Pourquoi Ruby n’a-t-il pas un vrai SsortingngBuffer ou SsortingngIO?

J’ai récemment lu un article intéressant sur l’utilisation de SsortingngIO dans Ruby. Ce que l’auteur ne mentionne pas, c’est que SsortingngIO n’est qu’un “je”. Il n’y a pas de “O” Vous ne pouvez pas faire cela, par exemple:

 s = SsortingngIO.new s << 'foo' s < should be "foo\nbar" # => really is ''` 

Ruby a vraiment besoin d’un SsortingngBuffer comme celui de Java. SsortingngBuffers a deux objectives importants. Tout d’abord, ils vous permettent de tester la moitié de la production de Ruby’s SsortingngIO. Deuxièmement, ils sont utiles pour construire de longues chaînes à partir de petites pièces – ce que Joel nous rappelle encore et encore est très très lent.

Y a-t-il un bon remplacement?

Il est vrai que les chaînes de Ruby sont mutables, mais cela ne signifie pas que nous devons toujours compter sur cette fonctionnalité. Si les stuff sont volumineuses, les performances et la mémoire requirejses, par exemple, sont vraiment mauvaises.

 result = stuff.map(&:to_s).join(' ') 

La manière “correcte” de faire ceci en Java est:

 result = SsortingngBuffer.new("") for(Ssortingng s : stuff) { result.append(s); } 

Bien que mon Java soit un peu rouillé.

J’ai regardé la documentation SsortingngIO pour SsortingngIO , et on dirait que ce que vous voulez, c’est SsortingngIO#ssortingng , pas SsortingngIO#to_s

Ainsi, changez votre code pour:

 s = SsortingngIO.new s << 'foo' s << 'bar' s.string 

Comme d’autres objects de type IO dans Ruby, lorsque vous écrivez dans un IO, le pointeur de caractère avance.

 >> s = SsortingngIO.new => # >> s << 'foo' => # >> s << 'bar' => # >> s.pos => 6 >> s.rewind => 0 >> s.read => "foobar" 

Une autre façon de peler ce chat.

J’ai fait quelques tests et l’approche la plus rapide utilise la méthode Ssortingng#<< . Utiliser SsortingngIO est un peu plus lent.

 s = ""; Benchmark.measure{5000000.times{s << "some string"}} => 3.620000 0.100000 3.720000 ( 3.970463) >> s = SsortingngIO.new; Benchmark.measure{5000000.times{s << "some string"}} => 4.730000 0.120000 4.850000 ( 5.329215) 

La concaténation de chaînes à l'aide de la méthode Ssortingng#+ est l'approche la plus lente de plusieurs ordres de grandeur:

 >> s = ""; Benchmark.measure{10000.times{s = s + "some ssortingng"}} => 0.700000 0.560000 1.260000 ( 1.420272) >> s = ""; Benchmark.measure{10000.times{s << "some string"}} => 0.000000 0.000000 0.000000 ( 0.005639) 

Donc, je pense que la bonne réponse est que l’équivalent de SsortingngBuffer de Java utilise simplement Ssortingng#<< dans Ruby.

Votre exemple fonctionne dans Ruby – je l’ai juste essayé.

 irb(main):001:0> require 'ssortingngio' => true irb(main):002:0> s = SsortingngIO.new => # irb(main):003:0> s << 'foo' => # irb(main):004:0> s << 'bar' => # irb(main):005:0> s.ssortingng => "foobar" 

Sauf si je manque la raison pour laquelle vous utilisez to_s – qui ne fait que sortir l’identifiant de l’object.

Eh bien, un SsortingngBuffer n’est pas tout à fait aussi nécessaire dans Ruby, principalement parce que les chaînes de Ruby sont mutables … vous pouvez donc créer une chaîne en modifiant la chaîne existante au lieu de construire de nouvelles chaînes avec chaque concat.

Comme note, vous pouvez également utiliser une syntaxe de chaîne spéciale où vous pouvez créer une chaîne de caractères qui référence d’autres variables dans la chaîne, ce qui rend la construction de chaînes très lisible. Considérer:

 first = "Mike" last = "Stone" name = "#{first} #{last}" 

Ces chaînes peuvent également contenir des expressions, pas seulement des variables telles que:

 str = "The count will be: #{count + 1}" count = count + 1