8
votes

Pourquoi la déclaration de rupture de Ruby se comporte-t-elle différemment lors de l'utilisation de proc.new v. Le signe AMPersand?

La déclaration de pause pour les blocs (selon Le langage de programmation de rubis ) est défini comme suit:

Il amène que le bloc retourne à son itérateur et à l'itérateur de retourner à la méthode qui l'a invoquée.

Par conséquent, lorsque le code suivant est exécuté, il en résulte un fichier localJumPerRor. xxx

tandis que le code suivant ne fait pas un localJumperror. Qu'est-ce qui est spécial sur le signe de l'ampersand? L'ampersand signe pas implicitement utiliser proc.new?<p> Enc. A quel point le comportement doit être identique à celui du premier code de code. xxx

Disclaimer : je suis newb Apprendre la langue (Ruby 1.9.2) et appréciera donc des références et un synopsis détaillé.


4 commentaires

Pas de temps pour une réponse appropriée, mais c'est tout à propos de la portée, pas autant un procédé ou de la Lambda étant spécial.


Lorsque vous obtenez du temps, veuillez visiter cette question à nouveau. J'apprécierais votre aperçu


Au lieu de proc.new essayez lambda .


C'est une question générale sur la langue; En mettant en œuvre, j'utiliserais une Lambda


3 Réponses :


3
votes

voici le Réponse .

ampersand est utilisé pour convertir un procédé à un bloc et un bloc à un proc.

J'ai changé l'exemple de manière à ce que votre cas: xxx comme Vous pouvez voir que cela n'a pas atteint l'accès «après Proc» xxx

dans votre deuxième exemple, vous avez une PROC en résultat, le PROC rompt depuis itérateur et retourne à test fonction. xxx


4 commentaires

Si j'ai cela correctement, dans le premier exemple, la déclaration de pause revient de proc.new (comme c'est un itérateur) et du bloc qui l'a enfermé. J'ai documenté la définition au début de la question que j'ai compris, pourquoi le premier a échoué. Mais, si dans le deuxième exemple, le signe AMPersand est Syntaxtic Sugar pour Proc.Nouveau, je ne comprends pas pourquoi ça ne marche pas là-bas


Donc, si un bloc a été converti en un PROC, la déclaration de pause ne devrait-elle pas fonctionner de la même manière que le premier extrait de code? Je veux dire, si nous sommes essentiellement enlignant un proc .New, pourquoi cela se comporte-t-il différemment d'un proc .New qui était dans une ligne distincte au-dessus de l'appel de la méthode?


"Le proc saute d'itérateur et retourne à la fonction de test." Si cela est vrai, la définition suivante de l'itérateur ne devrait pas échouer, mais fait: DEF Itérateur (p = proc.New {met "pénétrant" ponction "; pause}). Tout ce que je peux penser, c'est que proc.New est un itérateur et le signe d'ampersand, n'utilise pas la déclaration de rendement pour créer la proc.


Oui, mon explication n'est pas vraie. Maintenant, je pense que c'est à cause de «pause» mot-clé et non de proc. Mais ne peut pas trouver la description complète de ce mot clé.



0
votes

Cela concerne la différence entre les blocs, les Procs et les Lambdas - et leurs étendues respectives.

J'ai écrit un message à ce sujet en 2009 que vous pourriez trouver utile: http://www.leonardoborges.com/writings/2009/07/22/procs-lambdas-Blocks-Quels-the-Difence/

J'espère que cela aide.


7 commentaires

Le poste était clairement perspicace, mais étant donné que j'utilise un procédé dans les deux cas, je ne suis pas sûr de savoir pourquoi Ruby tente de donner un traitement spécial à un procédé sur un autre?


Cela concerne l'explication du mot clé de retour dans le poteau. La pause, telle que le retour dans ce cas, c'est une pause de la méthode d'appel, test dans ce cas. Cependant, vous ne pouvez pas faire la pause du test comme vous pouvez vérifier en mettant une pause juste après proc.new {...} qui est différent sur votre deuxième extrait car il reviendra de la méthode de l'appelant, Itérateur Dans ce cas, le contrôle de la nouvelle version du test.


Donc, si le test était enveloppé dans une méthode appelée test_test, la déclaration de pause dans Proc.New ne devrait pas échouer? Ici 'Comment je lis le bloc de la conversion de la Conversion def Itérateur (& Proc); #implicity appeler proc = proc.new {PROC}; ... fin auquel cas, le localJumperror devrait se produire, comme dans le test.


Cela l'appelle implicitement mais pas chez itérateur (& Proc) . La méthode obtient le Proc adopté par opposition à la créer en ligne.


Ensuite, pourquoi l'échec suivant def Itérateur (PROC) FIND ITERATOR PROC.NEW {met "PARTIS PERCE"; Pause }


mon point d'être que si le processus est adopté à l'itérateur, il devrait se comporter comme si une personne appelée Proc.New, à moins que et a reçu des privilèges spéciaux


@Salman, regarde la réponse que je viens de poster. Il explique pourquoi itérateur (& proc.new {break}) est différent de itérateur {break} .



8
votes

pause code> fait le bloc et em> l'appelant fort> du retour de bloc. Dans le code suivant: xxx pré>

"l'appelant" du bloc converti en un objet PROC est proc.New. Pause CODE> est censé rendre l'appelant du bloc de bloc, mais proc.New a déjà été retourné. P>

Dans ce code: P>

def iterator(&b); b.call; end
iterator { break }


2 commentaires

Je l'ai eu ... C'est la meilleure réponse. Cependant, tous les blocs ne sont-ils pas convertis en code exploitable via proc.new? Par conséquent, l'itérateur (& B) ne devient-il pas itérateur (B = proc.New b)?


et et proc.New ne sont pas les mêmes. & est la syntaxe de base; Proc.New est une méthode de la bibliothèque. Vous pouvez écrire votre propre proc.New comme ceci: Class Proc; DEF Self.Nouveau (& B); b; finir; fin . Mais il n'ya aucun moyen que vous puissiez mettre en œuvre votre propre syntaxe de base (en plus de pirater l'interprète, ou à l'aide d'un préprocesseur).