SmallTalk a la base: -Message mis en œuvre par récursivité (dans Visualworks) ou par l'inflexion de compilateur (dans Squeak / Pharo). Existe-t-il un moyen de définir une telle méthode sans utiliser l'un d'entre eux? Sinon, y a-t-il une preuve pour cette aviable quelque part? P>
4 Réponses :
Je propose la solution suivante: au lieu d'utiliser des tours de récursivité et de compilateur, le code ci-dessus utilise la réflexion sur la pile d'exécution. Avant que la boucle ne commence la méthode stocke le compteur de programme actuel dans une variable temporaire et la réinitialise à la fin pour revenir au début de la méthode. Dans certaines implémentations de SmallTalk, une telle approche pourrait être lente car certaines dialectes de SmallTalk réindiquent la pile à la demande uniquement, mais à Pharo / Squeak, cette astuce est assez pratique. P> Remarque, le code ci-dessus ne répond pas au résultat de La dernière activation du bloc en tant que mise en œuvre initiale de #Quitre: fait. Il devrait être assez facile de résoudre ce problème. P> p>
Dans ce cas, la restauration du contexte est fondamentalement l'équivalent de goto
Sans récursivité infinie, sans nombre infini de déclaration et sans la capacité de reprendre un contexte, il semble impossible.
Vous pouvez également utiliser un gestionnaire d'exception pour le faire revenir au début, mais cela pourrait compter comme tricher si le code de manipulation des exceptions utilisait un élément essentiel: ou une autre construction de boucle quelque part. Ainsi, fondamentalement, la question se résume si vous pouvez mettre en œuvre une boucle sans aller à l'emploi ni à la récursivité, et je pense que la réponse est non. Donc, si la récursion est interdite, vous êtes laissé à essayer de gaver un goto de techniques telles que définir la méthode PC ou en utilisant une exception. P>
WhileRue: & Tandurlied: retournez toujours nul. par exemple. S'il y a une définition récursive normale:
ContextPart methods for controlling label ^{ pc. stackp } goto: aLabel "N.B. we *must* answer label so that the top of stack is aLabel as it is when we send label" pc := aLabel at: 1. self stackp: (aLabel at: 2). ^aLabel BlockContext>>myWhileTrue: aBlock | label | label := thisContext label. self value ifFalse: [^nil]. aBlock value. thisContext goto: label BlockClosure>>myWhileTrue: aBlock | label | label := thisContext label. ^self value ifTrue: [aBlock value. thisContext goto: label]
juste faire: p>
Blockclousure >> WhileRue: Ablock P>
Valeur de soi Iftrue: [ Valeur Ablock. CeciContext Redémarrer. "Redémarrez sur Pharo, réinitialiser sur VW"] P>