Question

Je suis Structure et interprétation des programmes informatiques et en essayant de résoudre l’exemple 1.3, je suis arrivé au code suivant lors de ma première tentative:

(define (sumsq a b c)(
(define highest (if (> (if (> a b) a b) (if (> a c) a c)) (if (> a b) a b) (if (> a c) a c)))
(define second_h (if (> (if (> a b) b a) (if (> a c) c a)) (if (> a b) b a) (if (> a c) c a)))
(+ (* highest highest) (* second_h second_h)))

Cela ne fonctionnait pas et j'ai cherché la solution et je l'ai trouvée à l'adresse Wiki SICP

;; ex 1.3
;; implemented using only techniques covered to this point

(define (square x) (* x x))

(define (sum-of-squares x y)
  (+ (square x) (square y)))

(define (largest-two-of-three x y z)
  (if (>= x y)
      (sum-of-squares x (if (>= y z) y z))
      (sum-of-squares y (if (>= x z) x z))))

La différence était que j’utilisais plusieurs instructions pour définir des variables, puis pour additionner les carrés, alors que la méthode correcte consiste à définir chacune de mes lignes en tant que fonctions.

Existe-t-il des fonctions dans les liners du schéma un? Ou est-ce que tout me manque?

Était-ce utile?

La solution

Ce que vous avez écrit (moins un paren supplémentaire) est:

(define (sumsq a b c)
  (define highest
    (if (> (if (> a b) a b)
           (if (> a c) a c))
      (if (> a b) a b)
      (if (> a c) a c)))
  (define second_h
    (if (> (if (> a b) b a)
           (if (> a c) c a))
      (if (> a b) b a)
      (if (> a c) c a)))
  (+ (* highest highest) (* second_h second_h)))

Leur solution sépare les carrés et la somme des carrés en fonctions distinctes, mais je ne pense pas que ce soit l’important. Ne pas écrire (+ (* a a) (* b b)) va vous éviter d'avoir à nommer les deux valeurs que vous calculez, ce qui vous permettra d'écrire la fonction sous la forme d'une grande expression à la fin, mais vous devez vous inquiéter de choses plus importantes maintenant.

Je pense que le problème que vous rencontrez est que vos expressions (si ...) sont trop grandes pour être facilement comprises. Notez qu'il existe deux modèles qui apparaissent plusieurs fois: (if (> a b) a b) et (if (> a b) b a). Ce sont les fonctions max et min, il est donc utile de les définir comme telles:

(define (min a b) (if (< a b) a b))
(define (max a b) (if (< a b) b a))

Ainsi, vous pouvez réécrire votre solution comme suit:

(define (sumsq a b c)
  (define highest
    (if (> (max a b) (max a c))
      (max a b)
      (max a c)))
  (define second_h
    (if (> (min a b) (min a c))
      (min a b)
      (min a c)))
  (+ (* highest highest) (* second_h second_h)))

Simplifier à nouveau donne:

(define (sumsq a b c)
  (define highest
    (max (max a b) (max a c)))
  (define second_h
    (max (min a b) (min a c)))
  (+ (* highest highest) (* second_h second_h)))

Notez que cette écriture est beaucoup plus facile à raisonner, (max (max a b) (max a c)) est évidemment le maximum de a b et de c, et peut en fait être réécrit comme (max (max a b) c). En regardant second_h, cependant, il n’est pas évident que ce soit correct. Que se passera-t-il lorsque x sera la plus petite des trois valeurs?

Le truc qu’ils utilisent dans leur solution est d’abord de comparer y et x < y. si z, alors vous savez que y < x n’est pas le plus petit des trois, il est donc le plus élevé ou le deuxième plus élevé. L’autre nombre que vous souhaitez utiliser est le plus élevé de <=> et <=>, car le plus petit des deux sera le plus petit des trois, que vous souhaitez ignorer. Une logique similaire s'applique lorsque <=>.

Autres conseils

Vous devez utiliser le retrait approprié et les sauts de ligne pour obtenir un aperçu du flux de votre programme. Votre première proposition se lit alors comme suit:

(define (sumsq a b c)
  ((define highest 
     (if (> (if (> a b) a b)
            (if (> a c) a c))
         (if (> a b) a b)
         (if (> a c) a c)))
   (define second-h
     (if (> (if (> a b) b a)
            (if (> a c) c a))
         (if (> a b) b a)
         (if (> a c) c a)))
   (+ (* highest highest)
      (* second-h second-h)))

La première chose à noter: les parenthèses ne correspondent pas; il y en a un de plus ouvert que fermé. Une inspection minutieuse montre qu'une parenthèse d'ouverture dans la deuxième ligne est fausse. C'est d'ailleurs celui qui pendait à la fin de votre première ligne. Je suppose que lorsque vous avez essayé d'évaluer cela, rien ne s'est passé, le lecteur a attendu la fin de la déclaration.

Une bonne indentation est assez importante. Je pense que le SICP ne l'explique pas explicitement, bien que les exemples soient généralement faits de cette façon. J'ai trouvé un guide de style ici .

Deuxième constatation: vous vous répétez souvent. Dans toutes ces déclarations if imbriquées, je ne suis pas vraiment sûr que vous ayez réellement dégagé les bonnes valeurs. Regardez la solution que vous avez trouvée pour voir comment cela peut être grandement simplifié.

Vous avez essayé de casser la complexité en donnant des noms aux sous-résultats. Casser la complexité est une bonne chose, mais il est généralement préférable de ne pas nommer les résultats mais les concepts. Pensez à ce que vous faites, puis nommez ces activités. Ce sont des fonctions, et elles constituent le langage dans lequel vous résolvez finalement votre problème de façon presque triviale.

Une des idées de Scheme est bottom-up programming de créer une fonction pour chaque opération conceptuelle. C'est l'approche recommandée dans de nombreux langages de programmation fonctionnels.

Avec cette approche, de nombreuses petites fonctions implémentent une opération logique sur les arguments. De cette façon, votre code finit par être beaucoup plus modulaire et propre.

Votre solution présentait le formulaire suivant: (définir (func param) (définir ...) (définir ...))

Mais define nécessite ce formulaire: (define (func param) corps)

Le corps est l'implémentation de la fonction ... ce qu'il fait, ce qu'il retourne. Votre corps était juste plus de définitions, ne faisant jamais rien. Cela explique donc pourquoi votre solution n’a pas été acceptée par l’interprète Scheme.

Pour répondre à la question & "; les fonctions de schéma sont-elles simples? &"; vous devez rechercher le " commencer & le; form, qui ressemble à ceci: (begin (+ 1 1) (+ 2 2)) = > 4

Dans l'exemple ci-dessus, le résultat de (+ 1 1) est simplement jeté, vous pouvez donc voir que commencer n'a de sens que lorsque son contenu présente des effets secondaires.

Vous devez savoir que certaines parties de Scheme (notamment let et lambda) ont un début implicite autour de leur corps. Donc, ceci est valide:

  (let ((x 1))
    (+ 1 1)
    (+ 2 2))

même sans commencement. Cela simplifie l’écriture du code.

Enfin, pendant que vous continuez à apprendre Scheme, essayez toujours de trouver un moyen de faire quelque chose sans commencement ni effet secondaire. Surtout dans les premiers chapitres de la plupart des livres de Scheme, si vous pensez: & "Je veux définir cette variable, alors je veux le faire, alors ceci ... &"; vous êtes probablement pris au piège de votre ancienne méthode de programmation et ne le faites pas de manière schématique. Il n’ya aucun problème avec les effets secondaires, mais une utilisation intensive de ceux-ci signifie que vous ne programmez pas vraiment Scheme comme il fonctionne le mieux.

L'exercice 1.3 vous demande de définir une procédure utilisant trois nombres comme arguments et renvoyant la somme des carrés des deux plus grands nombres. Il est facile de définir une procédure comme celle qui utilise les procédures de schémas intégrées square, max et min, mais nous n’avons pas encore rencontré ces procédures dans le manuel, je les définirais donc. aussi bien.

(define (square x)
   (* x x))

(define (max x y)
   (if (> x y) x y))

(define (min x y)
   (if (< x y) x y))

(define (sum-of-highest-squares x y z)
   (+ (square (max x y))
      (square (max (min x y) z))))

La procédure sum-of-highest-squares consiste à ajouter le carré du maximum de x et y (le maximum de ces deux est éliminé du plus bas des trois) et le carré du maximum des deux restants (le minimum de x et y, quelle que soit la valeur restante de la première étape) et z.

Remarque: Ceci est tiré de mon article de blog Exercices SICP 1.1 - 1,5 . Il existe également des liens qui vous mèneront à de nombreuses autres solutions SICP.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top