2017-10-11 4 views
0

Supposons que j'ai une fonction (remove-bad-nodes g) qui retourne une séquence comme ceci:Comment pouvez-vous déstructurer dans le REPL?

[updated-g bad-nodes] 

updated-g est un graphique avec ses mauvais noeuds supprimés, et bad-nodes est une collection contenant les noeuds enlevés.

Comme argument à une fonction ou à l'intérieur d'un let, je pouvais déstructurer comme ceci:

(let [[g bads] (remove-bad-nodes g)] 
    ...) 

mais qui ne définit les variables locales. Comment est-ce que je pourrais faire cela dans le REPL, de sorte que dans les futures commandes je peux me référer au graphique mis à jour comme g et les noeuds enlevés comme bads? La première chose qui vient à l'esprit est:

(def [g bads] (remove-bad-nodes g) 

mais cela ne fonctionne pas, parce def a besoin de son premier argument d'être un symbole.

Notez que je ne vous demande pas pourquoi def n'a pas la syntaxe comme let; il y a déjà a question à ce sujet. Je me demande quelle est la manière pratique et pratique de travailler dans le REPL avec des fonctions qui retournent des «valeurs multiples». S'il y a une raison pour laquelle, dans la pratique normale de Clojure, il n'y a pas besoin de déstructuration dans le REPL, parce que vous faites quelque chose d'autre, expliquant que cela pourrait apporter une réponse utile. J'y ai beaucoup couru dernièrement, c'est pourquoi je demande. Habituellement, mais pas toujours, ces fonctions renvoient une version mise à jour de quelque chose avec d'autres informations. Dans le code à effets latéraux, la fonction modifierait l'objet et ne renverrait qu'une seule valeur (les nœuds supprimés, dans l'exemple), mais évidemment, ce n'est pas la façon Clojurely de le faire.

+1

La réponse à la question liée répond également à la vôtre: "Si vous le souhaitez, vous pouvez écrire une macro (disons, def +) qui fait cela pour vous." – amalloy

+0

@amalloy Seriez-vous prêts à rouvrir cette question? Ce n'est pas super important, puisque [votre réponse à la question liée] (https://stackoverflow.com/a/8198215/1393162) me donne une idée utile (écrire une macro 'def +'), mais voici pourquoi je pense cette question doit être répondu séparément: (1) Il s'agit vraiment de quelque chose de différent: _how_ à déstructurer dans le REPL. (2) L'autre réponse mentionne tangentiellement une solution, pas nécessairement la seule. Peut-être qu'il y a toute une autre approche que je devrais utiliser - sans macro «def +». Je suppose que vous avez probablement une bonne raison d'appeler la macro brute! –

+0

Vous avez déjà des réponses à cette question, vous montrant différentes choses que vous pourriez appeler "déstructuration au REPL", principalement qu'en fait, il n'y a rien de spécial à propos de la REPL, juste une différence entre comment "laisser" et 'def' se comporte. Je ne vois aucune raison de rouvrir cette question telle quelle, mais bien sûr vous êtes libre de la modifier pour en améliorer la portée. – amalloy

Répondre

0

Il n'y a rien d'unique à propos de la déstructuration w/r/t du REPL. La réponse à votre question est essentiellement la même que this question. Je pense que vos options sont:

let:

(let [[light burnt just-right] (classify-toasts (make-lots-of-toast))] 
    (prn light burnt just-right)) 

def les valeurs individuelles:

(def result (classify-toasts (make-lots-of-toast))) 
(def light (nth result 0)) 
(def burnt (nth result 1)) 
(def just-right (nth result 2)) 

Ou écrire une macro pour faire def travail pour vous.

Vous pouvez également envisager une représentation différente si votre fonction renvoie toujours un vecteur 3-vecteur/par ex. vous pourriez aussi retourner une carte de classify-toasts:

{:light 1, :burnt 2, :just-right 3} 

Et puis, quand vous avez besoin d'une de ces valeurs, déstructurer la carte en utilisant les mots-clés où que vous soyez:

(:light the-map) => 1 
0

Observe:

user=> (def results [1 2 3]) 
#'user/results 
user=> (let [[light burnt just-right] results] (def light light) (def burnt burnt) (def just-right just-right)) 
#'user/just-right 
user=> light 
1 
user=> burnt 
2 
user=> just-right 
3 
1

Je pense que la façon de travailler avec de telles fonctions dans le repl est simplement de ne pas def vos résultats intermédiaires à moins qu'ils ne soient particulièrement intéressants; Pour des résultats intermédiaires intéressants, il n'est pas très compliqué de leur attribuer un seul nom, ou d'écrire plusieurs def dans un formulaire de déstructuration.

Par exemple, au lieu de

(def [x y] (foo)) 
(def [a b] (bar x y)) 

vous pouvez écrire

(let [[x y] (foo), 
     [x' y'] (bar x y)]) 
    (def a x') ; or maybe leave this out if `a` isn't that interesting 
    (def b y')) 

Un effet secondaire agréable est que le code que vous écrivez tout en jouant autour dans le rempl sera beaucoup plus semblable à le code que vous ajouterez un jour à votre fichier source, où vous ne serez sûrement pas à def encore et encore, mais plutôt en les déstructurant, en les passant aux fonctions, et ainsi de suite. Il sera plus facile d'adapter les informations que vous avez apprises au repl dans un vrai programme.