2009-11-24 4 views
4

J'apprends SICP maintenant et faire le ex2.23 j'ai wrirten le code suivant:la différence entre si et cond?

(define (for-each proc items) 
    (if (null? items) 
     #t 
     ((proc (car items)) 
     (for-each proc (cdr items))))) 

mais lors de l'exécution, l'erreur de la cause: application procédure: procédure prévue, donnée: #; arguments étaient les suivants:()

je pense que je connais la raison: je l'appelle pour-chaque fonction récursive, tous appelé à-chacun voulait retourner la valeur

mais quand je l'ai modifié le code:

(define (for-each proc items) 
    (cond ((null? items) #t) 
     (else (proc (car items)) (for-each proc (cdr items))))) 

il fonctionne bien. Je ne comprends pas, pourquoi? dans cond, est-ce que chaque appelé pour-chacun pas besoin de retourner la valeur?

i utilisé DrScheme, et choisissez la langue SICP

je ne suis pas un locuteur natif de l'anglais, donc s'il y a qqch qui n'est pas décrit clairement, merci de me dire

Répondre

7

but when running, cause error: procedure application: expected > procedure, given: #; arguments were:()

i think i know the reason: I call the for-each function recursively, > every called for-each wanted to return value

Non, c'est parce que dans la clause alternative de if vous avez la combinaison ((proc (car items)) (for-each proc (cdr items))). Vous aviez l'intention d'évaluer les deux combinaisons (proc (car items)) et (for-each proc (cdr items)) de manière séquentielle, et à cette fin vous pensiez que les mettre dans une autre paire de parenthèses fonctionnerait. Mais en réalité, ce que vous avez spécifié est que le résultat de (proc (car items)) est une procédure à appliquer à l'argument qui est la valeur de retour de (for-each proc (cdr items)). Ce n'est pas le cas, et vous obtenez une erreur. Le point clé étant que les parenthèses dans Lisp ne sont pas pour le groupement, mais ont une signification définie.

Le problème est que if ne peut avoir qu'une seule combinaison dans cette position, alors que vous voulez avoir deux dans une rangée. D'autre part, cond ne souffre pas d'une telle restriction; vous pouvez mettre aussi longtemps une séquence de combinaisons individuelles dans la partie conséquente d'une clause cond que votre coeur désire. Cet état de choses est simplement comment la langue est définie pour fonctionner.

Vous pouvez tout aussi bien utiliser cond dans ces situations, mais si vous voulez toujours utiliser if, il y a quelques options pour empaqueter plusieurs combinaisons en une seule. Par exemple. vous pouvez créer une procédure lambda dont le corps est les deux combinaisons et le feu immédiatement hors tension:

 
(define (for-each proc items) 
    (if (null? items) 
     #t 
     ((lambda() 
      (proc (car items)) 
      (for-each proc (cdr items)))))) 

Ou vous pouvez utiliser begin qui est en fait destiné à être utilisé à cette fin:

 
(define (for-each proc items) 
    (if (null? items) 
     #t 
     (begin 
      (proc (car items)) 
      (for-each proc (cdr items))))) 
+0

merci beaucoup! très clairement – Vincent

+2

'begin' est la bonne chose à faire si vous voulez évaluer plusieurs instructions dans une clause' if' – newacct

+0

génial! tu m'as fait apprendre plus, merci – Vincent

Questions connexes