variable que paso parametros parametro otro metodos metodo manejo llamar importar dentro clases asignacion argumentos ruby syntax methods

que - ruby paso de parametros



Llamadas de método de operador Ruby vs. llamadas a métodos normales (5)

Me pregunto por qué las llamadas a los métodos del operador no requieren un punto? O más bien, ¿por qué no se pueden llamar a los métodos normales sin un punto?

Ejemplo

class Foo def +(object) puts "this will work" end def plus(object) puts "this won''t" end end f = Foo.new f + "anything" # "this will work" f plus "anything" # NoMethodError: undefined method `plus'' for main:Object


Debido a que Ruby tiene "azúcar sintáctica" que permite una variedad de sintaxis conveniente para situaciones preestablecidas. Por ejemplo:

class Foo def bar=( o ); end end # This is actually calling the bar= method with a parameter, not assigning a value Foo.new.bar = 42

Aquí hay una lista de las expresiones de operador que pueden implementarse como métodos en Ruby.


Debido a que la sintaxis de Ruby fue diseñada para parecerse más o menos a los lenguajes OO populares, y aquellos usan el operador punto para llamar a los métodos. El lenguaje del que tomó prestado su modelo de objetos, Smalltalk, no usaba puntos para los mensajes, y de hecho tenía una sintaxis bastante "extraña" que mucha gente consideraba ofensiva. Ruby ha sido llamado "Smalltalk con una sintaxis de Algol", donde Algol es el lenguaje que nos dio las convenciones de las que estás hablando aquí. (Por supuesto, en realidad hay más diferencias que solo la sintaxis de Algol).


La falta de llaves era una "ventaja" para ruby ​​1.8, pero con ruby ​​1.9 no puedes escribir method_0 method_1 some param que será rechazado, por lo que el lenguaje irá más bien a la versión estricta en lugar de freeforms.


La implementación no tiene la complejidad adicional que se necesitaría para permitir la definición genérica de nuevos operadores.

En cambio, Ruby tiene un analizador Yacc que usa una gramática estáticamente definida. Usted obtiene los operadores incorporados y eso es todo. Los símbolos ocurren en un conjunto fijo de oraciones en la gramática. Como ha notado, los operadores pueden estar sobrecargados, que es más de lo que ofrecen la mayoría de los idiomas.

Ciertamente no es porque Matz era flojo.

Ruby en realidad tiene una gramática diabólicamente compleja que está más o menos al límite de lo que se puede lograr en Yacc. Para ser más complejo, sería necesario utilizar un generador de compilador menos portátil o habría requerido escribir el analizador sintácticamente en C, y hacerlo habría limitado la portabilidad de la implementación futura a su manera, además de no proporcionar al mundo la entrada de Yacc. Eso sería un problema porque el código fuente de Yacc de Ruby es la única documentación de la gramática de Ruby y, por lo tanto, es "el estándar".


La respuesta a esta pregunta, en cuanto a casi todas las preguntas sobre el diseño del lenguaje es: "Solo porque". El diseño del lenguaje es una serie de intercambios principalmente subjetivos. Y para la mayoría de esas concesiones subjetivas, la única respuesta correcta a la pregunta de por qué algo es así es simplemente "porque Matz lo dijo".

Sin duda hay otras opciones:

  • Lisp no tiene operadores en absoluto . + , - , :: , > , = y así sucesivamente son simplemente nombres de funciones legales normales (nombres de variables, en realidad), al igual que foo o bar?

    (plus 1 2) (+ 1 2)

  • Smalltalk casi no tiene operadores. La única carcasa especial que tiene Smalltalk es que los métodos que consisten únicamente en caracteres de operador no tienen que terminar con dos puntos. En particular, dado que no hay operadores, todas las llamadas a métodos tienen la misma precedencia y se evalúan estrictamente de izquierda a derecha: 2 + 3 * 4 es 20 , no 14 .

    1 plus: 2 1 + 2

  • Scala casi no tiene operadores. Al igual que Lisp y Smalltalk, * , - , #::: y así sucesivamente son simplemente nombres de métodos legales. (En realidad, también son nombres legales de clase, rasgo, tipo y campo). Se puede llamar a cualquier método con o sin un punto. Si usa el formulario sin el punto y el método toma solo un argumento, también puede dejar de lado los corchetes. Sin embargo, Scala tiene prioridad, aunque no es definible por el usuario; simplemente está determinado por el primer carácter del nombre. Como un giro adicional, los nombres de los métodos del operador que terminan con dos puntos son invertidos o asociativos a la derecha, es decir, a :: b es equivalente a a :: b b.::(a) y no a a a.::(b) .

    1.plus(2) 1 plus(2) 1 plus 2 1.+(2) 1 +(2) 1 + 2

  • En Haskell, cualquier función cuyo nombre consiste en símbolos de operador se considera un operador. Cualquier función se puede tratar como un operador encerrándola en palos de atrás y cualquier operador se puede tratar como una función encerrándolo entre corchetes. Además, el programador puede definir libremente la asociatividad, la fijeza y la precedencia para los operadores definidos por el usuario.

    plus 1 2 1 `plus` 2 (+) 1 2 1 + 2

No hay una razón en particular por la cual Ruby no podría admitir operadores definidos por el usuario en un estilo similar al de Scala. Hay una razón por la cual Ruby no puede soportar métodos arbitrarios en la posición del operador, simplemente porque

foo plus bar

ya es legal, y por lo tanto, esto sería un cambio incompatible con versiones anteriores.

Otra cosa a considerar es que Ruby en realidad no fue completamente diseñado de antemano. Fue diseñado a través de su implementación. Lo que significa que en muchos lugares, la implementación se está filtrando. Por ejemplo, no hay absolutamente ninguna razón lógica por la cual

puts(!true)

es legal pero

puts(not true)

no es La única razón por la que esto es así es porque Matz usó un analizador LALR (1) para analizar un lenguaje que no es LALR (1). Si él había diseñado el idioma primero , nunca habría elegido un analizador LALR (1) en primer lugar, y la expresión sería legal.

La característica de Refinement actualmente se está discutiendo en ruby-core es otro ejemplo. La forma en que se especifica actualmente, hará que sea imposible optimizar las llamadas a métodos y los métodos en línea, incluso si el programa en cuestión no utiliza en absoluto Refinement s . Con solo un simple ajuste, puede ser tan expresivo y poderoso, y asegurar que el costo de la pesificación solo se incurra para los ámbitos que realmente usan Refinement . Aparentemente, la única razón por la que se especificó de esta manera, es que a) fue más fácil hacer prototipos de esta manera, yb) YARV no tiene un optimizador, por lo que nadie se molestó en pensar en las implicaciones (bueno, nadie excepto Charles Oliver Nutter).

Entonces, básicamente para cualquier pregunta que tengas sobre el diseño de Ruby, la respuesta casi siempre será "porque Matz lo dijo" o "porque en 1993 fue más fácil de implementar de esa manera".