2011-02-10 8 views
13

Estoy trabajando en Project Euler, y encontré una omisión ligeramente sorprendente: No hay String#shift, unshift, push, o pop. Había asumido que una Cadena se consideraba un objeto "secuencial" como una Matriz, ya que comparten la capacidad de ser indexados e iterados, y eso incluiría la capacidad de cambiar fácilmente el principio y el final del objeto.¿Por qué no hay un String # shift()?

Sé que hay formas de crear los mismos efectos, pero ¿hay alguna razón específica por la que String no no tenga estos métodos?

+1

probablemente porque si la cadena tenía esos métodos, las personas utilizarían. Y eso sería algo malo. Ver también: "Pit of Success". Usted no quiere que la forma más fácil sea también la incorrecta. – Jimmy

+0

¿Por qué sería algo malo? – Zabba

+0

@Zabba: en muchos idiomas, las cadenas son algo inmutables. Esto te permite hacer trucos como tablas internas, pero también significa que si insistes en mutar mucho una cuerda, es tremendamente ineficiente. El ejemplo clásico es la pregunta de entrevista de .NET "gotcha" de todos los tiempos "¿Qué pasa con el siguiente código?" (es algo así como 'bar =" "; foreach (var foo in frob) bar + = foo;') – Jimmy

Respuesta

11

Las cadenas no hacer actuar como un objeto enumerable a partir de 1.9, porque se considera demasiado confuso para decidir de qué se trataría una lista de:

  • ¿Una lista de caracteres/puntos de código?
  • ¿Una lista de bytes?
  • ¿Una lista de líneas?
+0

. Ah, ese es un buen punto. ¿Hubo alguna vez una discusión en el núcleo sobre esto, o simplemente se decidió a medida que progresaban las cosas? – harbichidian

+0

Ver http://stackoverflow.com/questions/2266534/ruby-string-no-longer-mixes-in-enumerable-in-1-9/2266616#2266616 – Zabba

5

No siendo colaborador de Ruby, no puedo hablar de sus objetivos de diseño, pero por experiencia, no creo que las cadenas sean consideradas como objetos "secuenciales"; son mutables de maneras que sugieren un comportamiento secuencial, pero la mayoría del tiempo se tratan atómicamente.

Caso de ejemplo: en Ruby 1.9, String ya no se mezcla en Enumerable.

+0

Parece que el propio Matz eliminó' incluir Enumerable' de String en 2006, [según el espejo github] (https://github.com/ruby/ruby/commit/4e37427ee5ecabda3e59ffd3ad1a6c85d4d9327b) . – harbichidian

5
>> mystring = "abcdefgh" 
=> "abcdefgh" 
>> myarray = mystring.split("") 
=> ["a", "b", "c", "d", "e", "f", "g", "h"] 
>> myarray.pop 
=> "h" 
>> mystring = myarray.join 
=> "abcdefg" 

esto debe hacerlo, wouldhave para convertirlo en una matriz, y luego de vuelta aunque

ACTUALIZACIÓN:

uso String#chop! y Stirng#<<

>> s = "abc" 
=> "abc" 
>> s.chop! 
=> "ab" 
>> s 
=> "ab" 
>> s<<"def" 
=> "abdef" 
>> s 
=> "abdef" 
>> 
+0

Sé que puedes convertirlo en una matriz, así como usar #slice, # << y # + = para falsificar la funcionalidad; Estoy más preocupado sobre por qué Strings no tiene estos métodos en primer lugar. – harbichidian

+0

Como no deberían, son una cadena de caracteres, no una lista ni un objeto secuencial. Si necesita una lista o cola o dqueue o un objeto FIFO, use una matriz de caracteres. Si bien respaldan algunos métodos como ese, eso no significa que deban ser demandados así todo el tiempo. Ver la respuesta de Dan Cheail – loosecannon

2

Al menos en 1.9.2, puede manejar una cadena como una matriz.

ruby-1.9.2-p290 :001 > "awesome"[3..-1] => "some" 

Así que si usted quiere hacer una especie de personaje de desplazamiento a la izquierda, sólo tiene que utilizar [1 ..- 1]

ruby-1.9.2-p290 :003 > "fooh!"[1..-1] => "ooh!" 
Cuestiones relacionadas