ventajas tutorial sirve rails que para documentacion desventajas descargar ruby

tutorial - ¿Por qué los setters de Ruby necesitan calificación "self" dentro de la clase?



ruby wikipedia (3)

Bueno, creo que la razón por la cual este es el caso es porque qwerty = 4 es ambiguo: ¿estás definiendo una nueva variable llamada qwerty o llamando al setter? Ruby resuelve esta ambigüedad diciendo que creará una nueva variable, por lo tanto, el self. es requerido.

Aquí hay otro caso donde necesita self. :

class A def test 4 end def use_variable test = 5 test end def use_method test = 5 self.test end end a = A.new a.use_variable # returns 5 a.use_method # returns 4

Como puede ver, el acceso a la test es ambiguo, por lo que el self. es requerido.

Además, esta es la razón por la que el ejemplo de C # no es realmente una buena comparación, porque se definen las variables de una manera que no sea ambigua desde el uso del setter. Si había definido una variable en C # que tenía el mismo nombre que el descriptor de acceso, debería calificar las llamadas al descriptor de acceso con this. , al igual que el caso Ruby.

Los establecedores de rubíes, ya sean creados por (c)attr_accessor o manualmente, parecen ser los únicos métodos que necesitan self. calificación cuando se accede dentro de la misma clase. Esto parece poner a Ruby solo en el mundo de los idiomas:

  • Todos los métodos necesitan self / this (como Perl, y creo que Javascript)
  • Ningún método requiere self / this es (C #, Java)
  • Solo los setters necesitan self / this (¿Ruby?)

La mejor comparación es C # contra Ruby, porque ambos lenguajes admiten métodos de acceso que funcionan sintácticamente al igual que las variables de instancia de clase: foo.x = y , y = foo.x C # los llama propiedades.

Aquí hay un ejemplo simple; el mismo programa en Ruby y luego C #:

class A def qwerty; @q; end # manual getter def qwerty=(value); @q = value; end # manual setter, but attr_accessor is same def asdf; self.qwerty = 4; end # "self." is necessary in ruby? def xxx; asdf; end # we can invoke nonsetters w/o "self." def dump; puts "qwerty = #{qwerty}"; end end a = A.new a.xxx a.dump

quitar el self.qwerty =() y falla (Ruby 1.8.6 en Linux y OS X). Ahora C #:

using System; public class A { public A() {} int q; public int qwerty { get { return q; } set { q = value; } } public void asdf() { qwerty = 4; } // C# setters work w/o "this." public void xxx() { asdf(); } // are just like other methods public void dump() { Console.WriteLine("qwerty = {0}", qwerty); } } public class Test { public static void Main() { A a = new A(); a.xxx(); a.dump(); } }

Pregunta: ¿Es esto cierto? ¿Hay otras ocasiones además de instaladores donde el yo es necesario? Es decir, ¿hay otras ocasiones en que un método de Ruby no se puede invocar sin uno mismo?

Ciertamente, hay muchos casos en que el yo se vuelve necesario. Esto no es exclusivo de Ruby, solo para ser claro:

using System; public class A { public A() {} public int test { get { return 4; }} public int useVariable() { int test = 5; return test; } public int useMethod() { int test = 5; return this.test; } } public class Test { public static void Main() { A a = new A(); Console.WriteLine("{0}", a.useVariable()); // prints 5 Console.WriteLine("{0}", a.useMethod()); // prints 4 } }

La misma ambigüedad se resuelve de la misma manera. Pero mientras sutil estoy preguntando sobre el caso donde

  • Se ha definido un método, y
  • No se ha definido ninguna variable local, y

Nos encontramos

qwerty = 4

que es ambiguo: ¿se trata de una invocación a un método o una nueva asignación de variable local?

@Mike Stone

¡Hola! Entiendo y aprecio los puntos que ha hecho y su ejemplo fue grandioso. Créanme cuando digo, si tuviera suficiente reputación, votaría su respuesta. Sin embargo, todavía estamos en desacuerdo:

  • en una cuestión de semántica, y
  • en un punto central de hecho

Primero, afirmo, no sin ironía, que estamos teniendo un debate semántico sobre el significado de "ambigüedad".

Cuando se trata de analizar y programar la semántica del lenguaje (el tema de esta pregunta), seguramente admitiría un amplio espectro de la noción de "ambigüedad". Solo adoptemos una notación aleatoria:

  1. ambiguo: ambigüedad léxica (lex debe ''mirar hacia el futuro'')
  2. Ambiguo: ambigüedad gramatical (yacc debe diferir para analizar el árbol de análisis)
  3. AMBIGUO: ambigüedad sabiendo todo en el momento de la ejecución

(y hay basura entre 2-3 también). Todas estas categorías se resuelven reuniendo más información contextual, mirando cada vez más a nivel global. Entonces cuando dices,

"qwerty = 4" es UNAMBIGUOSO en C # cuando no hay una variable definida ...

No podría estar mas de acuerdo. Pero por la misma razón, estoy diciendo

"qwerty = 4" no es ambiguo en ruby ​​(como ahora existe)

"qwerty = 4" es ambiguo en C #

Y aún no nos estamos contradiciendo. Por último, aquí es donde realmente estamos en desacuerdo: o Ruby podría o no podría implementarse sin ningún lenguaje adicional construye de tal manera que,

Para "qwerty = 4", ruby ​​INVITA UNAMBIGUOAMENTE un setter existente si hay
no hay una variable local definida

Dices que no. Yo digo si; podría existir otro rubí que se comporte exactamente igual que la corriente en todos los aspectos, excepto que "qwerty = 4" define una nueva variable cuando no existe ningún setter y no existe local, invoca el setter si existe, y lo asigna al local si existe. Acepto completamente que podría estar equivocado. De hecho, una razón por la que podría estar equivocado sería interesante.

Dejame explicar.

Imagine que está escribiendo un nuevo lenguaje OO con métodos de acceso que parecen instancias vars (como ruby ​​y C #). Probablemente comenzarías con gramáticas conceptuales como:

var = expr // assignment method = expr // setter method invocation

Pero el compilador del analizador (ni siquiera el tiempo de ejecución) vomitará, porque incluso después de que se haya asimilado toda la información, no hay forma de saber qué gramática es pertinente. Te enfrentas a una elección clásica. No puedo estar seguro de los detalles, pero básicamente Ruby hace esto:

var = expr // assignment (new or existing) // method = expr, disallow setter method invocation without .

es por eso que no es ambiguo, mientras que C # hace esto:

symbol = expr // push ''symbol='' onto parse tree and decide later // if local variable is def''d somewhere in scope: assignment // else if a setter is def''d in scope: invocation

Para C #, ''más tarde'' todavía está en tiempo de compilación.

Estoy seguro de que Ruby podría hacer lo mismo, pero ''más tarde'' tendría que ser en tiempo de ejecución, porque como señala ben no sabes hasta que se ejecute la declaración que caso aplica.

Mi pregunta nunca tuvo la intención de decir "¿realmente necesito el ''yo''?" o "¿qué posible ambigüedad se está evitando?" Más bien, quería saber por qué se hizo esta elección en particular? Tal vez no es el rendimiento. Tal vez simplemente hizo el trabajo, o se consideró que era mejor permitir siempre que un local de 1 línea anulara un método (un requisito bastante raro) ...

Pero estoy sugiriendo que el lenguaje más dinámico podría ser el que posponga esta decisión por más tiempo, y elija la semántica en función de la información más contextual: así que si no tiene local y definió un setter, usaría el setter . ¿No es por eso que nos gusta ruby, smalltalk, objc, porque la invocación al método se decide en tiempo de ejecución, ofreciendo máxima expresividad?


Lo importante que hay que recordar aquí es que los métodos de Ruby pueden (no) definirse en cualquier momento, por lo que para resolver de forma inteligente la ambigüedad, cada asignación debería ejecutar código para verificar si hay un método con el nombre asignado en ese momento de asignación.


Porque de lo contrario sería imposible establecer variables locales dentro de los métodos. variable = some_value es ambiguo. Por ejemplo:

class ExampleClass attr_reader :last_set def method_missing(name, *args) if name.to_s =~ /=$/ @last_set = args.first else super end end def some_method some_variable = 5 # Set a local variable? Or call method_missing? puts some_variable end end

Si no se requiriese self para los setters, some_method levantaría NameError: undefined local variable or method ''some_variable'' . Como está, el método funciona según lo previsto:

example = ExampleClass.new example.blah = ''Some text'' example.last_set #=> "Some text" example.some_method # prints "5" example.last_set #=> "Some text"