la différence entre si et cond?
Question
j'apprends maintenant SICP et faire la ex2.23 J'ai wrirten le code suivant:
(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: la procédure prévue, donnée: #; arguments étaient les suivants: ()
Je crois que je connais la raison: je l'appelle pour-chaque fonction récursive, tous appelés for-each 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? cond , fait tous appelé à-chaque pas besoin de retourner la valeur?
i utilisé DrScheme et choisir 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
La solution
mais lors de l'exécution, erreur Cause: application procédure: attendue> procédure, donnée: #; arguments étaient les suivants: ()
Je crois que je connais la raison: je l'appelle pour-chaque fonction récursive,> tous appelé for-each voulait retourner la valeur
Non, c'est parce que dans la clause alternative de if
vous avez la ((proc (car items)) (for-each proc (cdr items)))
combinaison. Vous l'intention d'évaluer les deux combinaisons (proc (car items))
et (for-each proc (cdr items))
séquentiellement, et à cette fin que vous avez pensé de les mettre dans une autre paire de parenthèses travailleraient. 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. La clé étant de point entre parenthèses dans Lisp ne sont pas pour le regroupement, mais ont une signification précise.
Le problème est que if
ne peut avoir qu'une seule combinaison dans cette position, alors que vous voulez avoir deux fois de suite. 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 de cond
que votre coeur désire. Cet état de choses est tout simplement la façon dont la langue est définie au travail.
Vous pouvez tout aussi bien utiliser cond
dans ces situations, mais si vous voulez continuer à utiliser if
il y a quelques options pour bourrer multiples combinaisons en un seul. 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)) )) ))
Vous pouvez aussi 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)) ) ))