2011-03-29 2 views
3

Je réalise que c'est probablement une question vraiment stupide mais je n'ai aucune idée pourquoi ceci ne fonctionne pas et j'ai à peu près abandonné. Au fond, j'ai essayé:obtenir l'entrée standard et le stocker comme une chaîne dans le lisp

(setq answer (string (read))) 

et

(setq answer 0) 
(format answer "~s" (read)) 

et

(setq answer (read)) 

lorsque je tente d'évaluer

(if (stringp answer) 
    (princ "works") 
    (princ "failed")) 

sur l'un des tente au-dessus sort toujours échoué .

qu'est-ce que je fais mal?

Répondre

20

Ou vous pouvez simplement faire:

(setq answer (read-line)) 

Cela vous donne une chaîne là.

[1]> (setq answer (read)) 
3 
3 
[2]> (type-of answer) 
(INTEGER 0 16777215) 
[3]> (setq answer (read-line)) 
3 
"3" 
[4]> (type-of answer) 
(SIMPLE-BASE-STRING 1) 
[5]> 
5

Démarrer une nouvelle REPL, essayez de vérifier la valeur de retour de chacune de vos étapes:

T1> (read) 
foo 
FOO 
T1> (read) 
1 
1 
T1> (type-of (read)) 
foo 
SYMBOL 
T1> (type-of (read)) 
1 
BIT 

note maintenant que STRING ne fonctionnera pas sur tous les types d'entrée:

T1> (string 'foo) 
"FOO" 
T1> (string 1) 

également notez que, contrairement à setq, (format foo ...) ne foo, mais écrivez-lui, si c'est un stream ou un avec un fill-pointer. Jetez un oeil à son Documentation, et vous verrez:

Format destination contrôle chaîne & repos args => Résultat

[...]

destination --- nulle, t, un flux ou une chaîne avec un pointeur de remplissage.

[...]

Format

est utile pour produire un texte bien formaté, produisant Séduisant messages, et ainsi de suite. format peut générer et renvoyer une chaîne ou la sortie à destination.

Si la destination est une chaîne, un flux, ou t, le résultat est nul. Sinon, le résultat est une chaîne contenant `output '.

Essayez comme ceci:

T1> (setq *answer* 
      (with-output-to-string (s) 
      (format s "~s" (read)))) 
1 
"1" 
T1> *answer* 
"1" 

Ou comme ceci:

T1> (setq *answer* (make-array 20 :element-type 'character :fill-pointer 0)) 
"" 
T1> (format *answer* "~s" (read)) 
1 
NIL 
T1> *answer* 
"1" 

Ce sont les seules erreurs pertinentes que je pouvais trouver dans votre code.Cela revient certainement "works" dans tous conformes CL (vous pouvez aussi utiliser prin1-to-string):

T1> (defvar *answer*) 
*ANSWER* 
T1> (setq *answer* (format nil "~s" (read))) 
1 
"1" 
T1> (if (stringp *answer*) 
     (princ "works") 
     (princ "failed")) 
works 
"works" 

Sauf si vous êtes dans un paquet décoiffé (essayez (in-package cl-user) avant d'évaluer votre code) ou redéfinie fonctionnalités de base, cela fonctionnera. Donnez des descriptions d'erreurs plus exactes, si ce n'est toujours pas le cas.

ED:

Après avoir lu, je dois mentionner peut-être qui a correctement à read-line comme une solution plus courte, la réponse, Bill que je n'ai pas essayé de montrer les meilleurs, les approches les plus succincts, ou plus idiomatiques dans ma réponse , et que ceux-ci varient en fonction de ce que vous essayez vraiment de faire. (La solution la plus courte possible aurait été "works" :) Ce ne sont que des exemples qui devraient aider à expliquer pourquoi votre code a échoué.

Une autre chose que j'ai oublié de dire est que vous devez garder à l'esprit que toplevel setq s sur des variables non définies avec defvar ou defparameter sont généralement à éviter dans tout sauf barboter au REPL, car les conséquences ne sont pas définies. En outre, ces variables sont, par convention, enveloppées dans des astérisques (aussi appelés cache-oreilles) afin d'empêcher les bogues causés par des spéciaux confus avec des variables de portée lexicale.

Questions connexes