2017-09-11 3 views
-1

Je suis les conférences SICP du MIT, et c'est ce que j'ai essayé de trouver l'approximation de racine carrée d'un nombre par la méthode de Héron d'Alexandrie. C'est la première fois que j'essaie un zézaiement, désolé de faire des erreurs. J'utilise Chicken scheme compiler pour imprimer ceci. Ceci est la sortie:Erreur: (/) mauvais type d'argument: # <unspecified> Poulet Scheme Approximation racine carrée

Error: (/) bad argument type: #<unspecified> 

    Call history: 

    1.a.SquareRootApproximation.scm:29: try 
    1.a.SquareRootApproximation.scm:17: goodEnough  
    1.a.SquareRootApproximation.scm:27: avg 
    1.a.SquareRootApproximation.scm:19: improve  <-- 

Mise à jour: J'ai changé mon approche face à ce problème en utilisant Lisp avec plus abstraction, mais je ne peux pas comprendre ce que cette nouvelle erreur veut impliquer. Des correctifs? Merci!

Répondre

1

La valeur #<unspecified> est fondamentalement "vide" dans d'autres langues. Il est utilisé comme valeur de retour chaque fois qu'une procédure n'a rien d'utile à retourner (par exemple, print retournera ceci). Il est également utilisé dans certaines situations comme valeur d'espace réservé temporaire, par exemple lors de la gestion d'un define.

Normalement, cet espace réservé temporaire ne doit pas être visible par l'utilisateur de la langue, mais il semble que vous ayez frappé un cas étrange dans la langue (félicitations, cela arrive rarement). L'erreur se produit car (define guess (avg guess (/ x guess))) dans la procédure improve définit simultanément une variable et utilise cette variable. Le comportement de faire cela n'est pas bien spécifié, et certaines implémentations Scheme feront ce que fait CHICKEN (Guile, Gauche, Gambit) alors que d'autres donneront un message d'erreur un peu plus significatif (MIT, Scheme48, Racket). La raison pour laquelle ceci est mal spécifié est liée au fait que define se développe en letrec, car cela permet de définir des procédures mutuellement récursives, mais cela crée un problème: que se passe-t-il par exemple pour (define a b) (define b a)?

Votre intention semble utiliser l'ancienne variable de deviner qui est transmis en entrée à la procédure, donc au lieu d'utiliser define vous pouvez utiliser let pour lier une nouvelle valeur pour guess (comment cela devrait se comporter est bien spécifié), ou il suffit d'utiliser un nom différent, comme new-guess.

+0

Je n'en ai pas encore entendu parler, je suis toujours sur la première conférence. Peut-être que la nouvelle supposition est la bonne façon d'y aller. Merci. Cela a fonctionné avec la nouvelle variable. –

+0

Il est très bien spécifié puisque dans R5RS et plus tôt 'define' dans' lambda' (et les formes dérivées) sont 'letrec' ne permettant aucune des variables d'être évaluées avant le corps et dans R6RS et plus tard c'est un' letrec * ' ce qui permet d'évaluer les variables déjà initialisées. Bien sûr, aucun de ceux-ci n'autorise l'évaluation d'une variable qui est ombrée par ** tout ** local 'define' dans le même' lambda'. 'letrec' et' letrec * 'permettent de faire des fonctions récursives et donc la liaison doit exister au moment de la création de la fermeture. – Sylwester

+0

Il est bien spécifié en ce sens que "c'est une erreur" de se référer directement dans les formulaires "" à la valeur de tout "". Cependant, cela signifie essentiellement que "la mise en œuvre est libre de faire ce qu'elle veut". En substance, il est similaire à "comportement indéfini" dans C. Tout ce qui "est une erreur" tombe en dehors de la spécification et les programmes qui causent une telle erreur peuvent ou non exécuter/compiler. Ceci est très dépendant de l'implémentation, comme vous pouvez le voir dans mon exemple: MIT, Racket et Scheme48 se comportent très différemment de CHICKEN, Guile, Gambit et Gauche. – sjamaan