1
votes

La fonction Lisp renvoie NIL lorsqu'elle est utilisée dans une fonction de menu mais fonctionne autrement

J'ai écrit une fonction pour interroger un petit programme de base de données que j'écris pour l'école. Cette fonction recherche par nom. Lorsque j'exécute la fonction seule, cela fonctionne. Lorsque je l'exécute dans le menu, cela ne fonctionne pas (il renvoie NIL). Voici tout ce qui est pertinent:

(defun prompt-read (prompt)                                                    
  (format *query-io* "~a: " prompt)                                            
  (force-output *query-io*)                                                    
  (read-line *query-io*)) 

(defun search-name (name)                                                      
  (remove-if-not                                                               
   #'(lambda (cat) (equal (getf cat :name) name)) *db*))                       

(defun input-name ()                                                           
  (search-name                                                                 
   (prompt-read "Name")))

(defun search-menu ()                                                          
  (print "1) Search Name")                                                     
  (print "2) Search Color")                                                    
  (print "3) Search Min. Weight")                                              
  (print "4) Search Min. Experience")                                          
  (print "5) Search Min. Length")                                              
  (setf choose (read))                                                         
  (cond ((= choose 1)(input-name))                                             
        ((= choose 2)(print "Color"))                                          
        ((= choose 3)(print "Weight"))                                         
        ((= choose 4)(print "XP"))                                             
        ((= choose 5)(print "Color"))                                          
  )                                                                            
  NIL                                                                          
)  

Pour le moment, je travaille uniquement à faire fonctionner la recherche par nom, le reste du menu n'est que des espaces réservés. Lorsque j'exécute "input-name" (qui utilise search-name) par lui-même, il renvoie le résultat correct. Lorsque j'essaie la première option du menu de recherche (qui exécute également "nom-d'entrée"), elle renvoie NIL. Je me demande pourquoi lorsque je l'exécute tout seul fonctionne, mais pas lorsqu'il est utilisé avec ce menu. Si quelqu'un a besoin d'autres informations, n'hésitez pas à demander. Je ferai de mon mieux pour le fournir. De plus, je suis un débutant, alors pardonnez-moi.


3 commentaires

Je ne comprends pas la question. Vous devrez peut-être nous montrer une interaction. Comme la fonction search-menu est actuellement, elle renvoie toujours NIL , puisque c'est la dernière valeur explicitement dans votre code - voir l'avant-dernière ligne de search- menu . Comment peut-il renvoyer autre chose que NIL ?


De plus: la variable choose n'est pas définie dans votre code. setf ne définit pas les variables - il ne fait que les définir.


Astuce: essayez de comprendre la différence entre imprimer quelque chose dans une fonction , renvoyer une valeur d'une fonction et imprimer le résultat de l'évaluation dans un READ-EVEL-PRINT- BOUCLE .


3 Réponses :


-1
votes

J'ai fini par trouver une solution qui fonctionne en utilisant simplement print dans la fonction input-name. Cette fonction n'a qu'à afficher les résultats donc cela fonctionne très bien.

(defun input-name ()                                                           
  (print                                                                       
  (search-name                                                                 
   (prompt-read "Name")))) 

Même fonction qu'avant mais avec une impression ajoutée. Maintenant, cela fonctionne également dans le menu.


4 commentaires

Mais maintenant, lorsque vous exécutez la fonction seule, le résultat est imprimé deux fois. Comprends-tu pourquoi?


@RainerJoswig ouais, c'est bien. Ce n'est qu'un projet pour débutant et tout ce que j'ai à faire est d'afficher les bons résultats à l'écran.


La question était: comprenez-vous pourquoi il est imprimé deux fois?


Et j'ai dit «ouais».



2
votes

Si vous voulez une sortie dans un programme, alors vous devez imprimer quelque chose.

(defun foo ()
  (let ((bar 10))    ; define BAR
    (print bar)      ; BAR is defined
    (setf bar 20)    ; BAR is defined
    (print bar)))    ; BAR is defined

La fonction ci-dessus n'imprime rien. Il renvoie juste un nombre.

Si nous l'appelons dans la boucle read-eval-print-loop:

(defun foo ()
  (setf bar 10)  ; <- BAR is undefined
  (print bar)    ; <- BAR is undefined
  (setf bar 20)  ; <- BAR is undefined
  (print bar))   ; <- BAR is undefined

Vous voyez que 1000 est imprimé. Mais pourquoi?

Nous l'exécutons dans le READ-EVAL- PRINT -LOOP. La boucle read, eval, PRINT .

Signifie: le système Lisp imprime la valeur renvoyée de l'évaluation, mais pas votre code.

Maintenant nous ajoutons un appel print :

CL-USER 138 > (defun call-the-example ()
                (example)
                (values))
CALL-THE-EXAMPLE

CL-USER 139 > (call-the-example)

1000 

Il est imprimé deux fois!

CL-USER 137 > (example)

1000     ; <- the function example prints 
1000     ; <- the read-eval-print-loop prints the result

Donc notre fonction imprime maintenant quelque chose lui-même, car il appelle PRINT.

Maintenant cela fonctionne:

CL-USER 136 > (defun example ()
                (print 1000))
EXAMPLE

CL-USER 137 > (example)

1000 
1000

Nous pouvons appeler le exemple , la fonction imprime quelque chose et le REPL n'imprime rien.

Le REPL n'imprime rien, puisque call-the-example ne renvoie rien. Il ne renvoie aucune valeur.

Vous devez donc ajouter un appel PRINT

Vous avez raison d'ajouter un appel d'impression, mais la raison est simplement qu'avant vous n'avez pas imprimé et l'appel à (nom-d'entrée) ne s'est pas imprimé. Vous appeliez (input-name) dans la READ-EVAL-PRINT-LOOP, qui imprime ensuite le résultat. Pas votre code, mais le REPL a produit la sortie.

Style: variable non définie

CL-USER 134 > (defun example ()
                1000)
EXAMPLE

CL-USER 135 > (example)
1000

Écrivez ceci à la place - en utilisant LET pour définir une variable locale:

(defun example ()
  1000)


0 commentaires

0
votes

search-menu ne fait rien avec la valeur de retour de input-name . Une fonction renvoie la valeur de la dernière expression qu'elle exécute, et la dernière expression dans search-menu est NIL , c'est donc ce qu'elle renvoie.

Si vous voulez pour renvoyer la valeur de l'expression cond , supprimez NIL de la fin.

Vous devez également utiliser let pour déclarer une variable locale, plutôt que d'affecter la variable non définie choose.

(defun search-menu ()
  (print "1) Search Name")
  (print "2) Search Color")
  (print "3) Search Min. Weight")
  (print "4) Search Min. Experience")
  (print "5) Search Min. Length")
  (let ((choose (read)))
    (cond ((= choose 1) (input-name))
          ((= choose 2) (print "Color"))
          ((= choose 3) (print "Weight"))
          ((= choose 4) (print "XP"))
          ((= choose 5) (print "Color")))))


0 commentaires