2010-12-06 27 views
3

En this answer to a separate question, je dit que si vous faitesComment puis-je suivre la création de chaînes dans Ruby?

name = "Rohit " "Sharma" 

vous ne créez deux String objets avec le contenu "Rohit " et "Sharma" qui se combinent pour créer un nouvel objet String avec le contenu "Rohit Sharma", mais que vous créez seulement un seul objet String pour commencer.

Mais c'est seulement un livre qui me dit cela, plutôt que de le vérifier manuellement.

Comment seriez-vous en mesure d'enregistrer la création d'une chaîne?

J'ai essayé d'utiliser

set_trace_func proc { |event, file, line, id, binding, classname| 
    printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname 
} 

string = "Insert content here" 

Mais seulement obtenu

c-return -:3 set_trace_func Kernel 
    line -:5 

et "Programmation Ruby 1.9" (la Pioche) dit que la modification Class#new ne fonctionnerait pas pour les chaînes, car ils sont construits sans utiliser new.

Répondre

0

Cela ne veut pas trace la création de la chaîne en tant que telle, mais ce qui suit suggère que l'enchaînement se produit avant que les objets chaîne sont créés:

Ce qui suit (je lis à ce sujet dans la Pioche, dans la section « Derrière la rideau: le Ruby VM ") fonctionne dans YARV - Je ne pense pas que ça fonctionne dans toutes les autres implémentations de Ruby:

irb(main):003:0> uncompiled_code = 'name = "Rohit " "Sharma"' 
=> "name = \"Rohit \" \"Sharma\"" 
irb(main):004:0> code = RubyVM::InstructionSequence.compile(uncompiled_code) 
=> <RubyVM::InstructionSequence:<compiled>@<compiled>> 
irb(main):005:0> puts code.disassemble 
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) 
[ 2] name 
0000 trace   1            ( 1) 
0002 putstring  "Rohit Sharma" 
0004 dup 
0005 setlocal   name 
0007 leave 
=> nil 
3

Vous ne pouvez pas vous connecter, car cette concaténation ne se produit pas au moment de l'exécution. Cela arrive au moment de l'analyse. En d'autres termes: quel que soit le code que vous écrivez pour l'enregistrer, la concaténation aura eu lieu bien avant que votre code ne soit exécuté.

En d'autres termes encore: vous avez confiance qu'il n'y a qu'un seul objet chaîne a créé de la même façon que vous faites confiance que 42 ne crée un objet Fixnum avec la valeur 42, pas 42 Fixnum objets avec la valeur 1: Ruby ISO Spécification du langage dit ainsi, et le code source de chaque implémentation Ruby existante le dit, et chaque livre Ruby jamais écrit le dit.

+1

Je suis d'accord que l'enchaînement se passe au moment de l'analyse, mais ne la création de l'objet Chaîne concaténée se produit lors de l'exécution? –

+2

@Andrew Grimm: Probablement. Notez cependant que la création d'objet n'est pas l'un des 8 événements que vous pouvez tracer. Vous pouvez uniquement suivre l'appel d'une méthode Ruby, revenir d'une méthode Ruby, appeler une opération native (fonction C dans MRI, YARV, méthode C++ dans Rubinius, etc.), retourner d'une opération native, début d'une définition de module, fin de une définition de module, levant une exception et exécutant une ligne. –