0
votes

Récupération de la queue, comment éliminons-nous la déclaration de retour?

Voici un programme C # récursif de queue qui résume les carrés de 1 à 10. Cela fonctionne, à l'exception du dernier autre dans addsquares2 () code>. Cela ne fonctionne pas car c # semble exiger une déclaration de retour dans chaque chemin dans une méthode qui renvoie une valeur. Cependant, je n'aurais pas besoin d'une déclaration de retour dans une méthode récursive de la queue telle que celle-ci. Voir le commentaire.

est-ce juste une idiosyncrasie de C #? Ou existe-t-il un moyen de dire au compilateur que je sais ce que je fais ce que je fais et que je ne veux pas que chaque chemin retourne une valeur? P>

Voici mon programme: P>

 AddSquares(1, 10, 0)
    AddSquares(2, 10, 1)
    AddSquares(3, 10, 5)
    AddSquares(4, 10, 14)
    AddSquares(5, 10, 30)
    AddSquares(6, 10, 55)
    AddSquares(7, 10, 91)
    AddSquares(8, 10, 140)
    AddSquares(9, 10, 204)
    AddSquares(10, 10, 285)
    AddSquares(11, 10, 385)
      The total sum is 385
    AddSquares2(1, 10, 0)
    AddSquares2(2, 10, 1)
    AddSquares2(3, 10, 5)
    AddSquares2(4, 10, 14)
    AddSquares2(5, 10, 30)
    AddSquares2(6, 10, 55)
    AddSquares2(7, 10, 91)
    AddSquares2(8, 10, 140)
    AddSquares2(9, 10, 204)
    AddSquares2(10, 10, 285)
    AddSquares2(11, 10, 385)
      The total sum is 385


6 commentaires

Comment vous attendez-vous à une fonction de type INT pour ne pas renvoyer quoi que ce soit? Dans votre si ... des déclarations d'autre, la déclaration IF est vérifiée en premier. Si c'est vrai, il devrait renvoyer quelque chose d'autre s'il ne doit pas aussi retourner quelque chose. Peut-être que vous pouvez retourner 0 ou null.


HRMM, donc dans n'importe quelle autre langue (fonctionnelle ou non), que faites-vous, quelle est la valeur qui est renvoyée par cela d'autre, qu'advient-il de l'exécution du code, il disparaît juste?


Êtes-vous sous l'impression que la somme retour dans cette fonction se déroule de manière magique tous les appels précédents et retourner directement sur principal ?


Le sinon reste nécessaire de retourner une valeur à un moment donné lorsque la pile se déroule après la récursion et l'exécution frappe cette attelle de fermeture finale dans addsquares2 ... N'oubliez pas, l'exécution continuera après appeler cette méthode dans le bloc ele . Vous devez faire quelque chose avec la valeur de retour de l'appel récursif ou ne sera jamais envoyé à l'appelant.


Demandez-vous pourquoi vous devez utiliser le mot-clé "retour" et ne peut pas simplement le laisser simplement sortir et et juste avoir l'appel? Vous pensez que le compilateur doit déterminer implicitement que vous voulez avoir le résultat de l'appel renvoyé depuis dans ce scénario une optimisation de l'appel de la queue peut être effectuée . Ce n'est juste pas comment c # a été conçu. En laissant le mot-clé de retour ici est simplement un peu comme dit "ignorer les résultats de l'appel et ne le retourne pas explicitement"


Dans des lancuages ​​en vrac qui permettent de revenir en une seule des positions de la queue, vous obtiendrez une valeur non définie comme le résultat chaque fois que l'étape récursive a été utilisée. Ainsi, cela fonctionne, mais pas comme prévu.


3 Réponses :


1
votes

En bref, une méthode en C # doit avoir un retour sur tous les chemins d'exécution du code, vous ne l'aimerez peut-être pas, mais cela le fait. La même chose en maths toutes les fonctions ont un résultat, c'est ce que font les fonctions.

Maintenant, en disant que, le résultat peut être indéfini, l'infini, 0, null ou dans le cas de C # avec un type de retour d'un Int non nullable il peut être 0. Ce qui fait Sens parfait étant donné la signature.

Que diriez-vous de prétendre une seconde que nous pourrions simplement disparaître de l'exécution du code au point de votre part d'autre. Si la méthode d'appel s'appuie sur un résultat (et ils le font habituellement) et même si la méthode a fini par la manière dont vous proposez, alors quel est l'appelant va penser? Eh bien, il doit être capable de faire face à l'absence de valeur ou non.

Si vous avez vraiment besoin de savoir que votre autre ne produit pas de valeur, faites votre signature int? (nullable) et retourner null , donc l'appelant sait que l'appelant sait donc faire. Si c'est juste une absence d'un nombre pour la somme, faites-la 0, aucun mal fait


0 commentaires

1
votes

La seule façon dont vous pouvez "sortir avec" n'utiliser pas de retour est de lancer une erreur à la place. Il n'a pas de sens de le faire dans votre situation.

Vous pouvez également éviter d'utiliser un retour en ne fournissant pas de chemin de code (ne pas avoir de clause d'autre, dans cette situation)

Vous avez cependant fait la bonne chose en ce que vous avez renvoyé le résultat de l'appel de ADDSQures2 de récursivement. Si vous ne le faites pas, votre code pour AddsQuares2 ne se recueillera jamais et ne fonctionnera pas (vous devez donc retourner quelque chose après tout! Ahh).

Les méthodes récursives doivent avoir un point à l'intérieur de eux-mêmes où ils reviennent sans nous appeler (pour arrêter la récursion de partir pour toujours), ainsi qu'un point où ils s'appellent eux-mêmes (pour garder la récursion pendant un moment)

Probablement un exercice académique, mais peut-être la peine d'être mentionné que la récursivité est une forme de boucle que (AB) utilise la pile d'appels en fournissant une construction en boucle. Les méthodes récursives peuvent (et devraient, IMHO) être effectuées en utilisant des boucles normales


1 commentaires

Dépend de la langue. J'ai enseigné les Lisp communes pendant des années et nous avons utilisé la récursion presque partout, nous avions besoin de la répétition. IMHO, la récursivité vient naturellement et est plus facile à enseigner que l'itération.



1
votes

La question est correcte dans son affirmation qu'il n'aurait pas besoin de "retourner", mais cela dépend de votre sens de "retour". Dans un sens de bas niveau, si un appel de la queue est effectué, aucune instruction "RET" (une sorte d'instruction de type de nettoyage de pile standard) doit être effectuée à ce stade, car l'appel de la queue sera rendre l'exécution réelle se comporter d'équivalent à une boucle simple.

Cependant, c # n'est pas aussi proche du métal que cela. Lorsque nous écrivons C #, nous spécifions intention et laissez le compilateur (et / ou la gigue) s'occuper des optimisations telles que les appels de queue, l'allusion de la méthode et similaires. La présence du mot-clé C # RETURN n'implique pas nécessairement ou force un nettoyage de la pile. Au lieu de cela, cela indique la l'intention de programmeur .

Si nous vous permettons de laisser le "retour", il fait beaucoup plus de difficulté de comprendre votre intention de comprendre votre intention. Le programmeur a-t-il été au courant de l'optimisation qui se produirait et entend conceptuellement pour la méthode de "retour", ou a-t-il voulu dire explicitement rien faire avec le résultat. C # suppose ce dernier.

Maintenant, si vous craignez que le fait que vous ne puissiez pas quitter la déclaration signifie qu'un appel de la queue ne peut pas être effectué, ne vous inquiétez pas. Le compilateur et la gigue prennent soin de ces types d'optimisations automatiquement. Ils prennent votre intention et et les il est de la manière la plus optimisée possible. Et ils font presque toujours un meilleur travail de décider quoi et quand appliquer ces types d'optimisations que le programmeur.


2 commentaires

Le programme C # se comporte comme prévu. Cependant, d'autres langues (disent, python) ne nécessitent pas la déclaration de retour ici. Python est pathologique à sa manière. C # est aussi bien. Votre réponse est parfaitement logique. Merci.


Mais le résultat sans retour ne serait certainement aucun et pas un nombre?