¿Por qué una llamada a un método necesita ser desambiguada cuando en principio puede ser una constante?

Las llamadas a métodos generalmente pueden omitir el receptor y los paréntesis para los argumentos:

def foo; "foo" end foo # => "foo" 

En el caso anterior, foo es ambiguo entre la llamada al método y la referencia a una variable local potencial. En ausencia de este último, se interpreta como una llamada de método.

Sin embargo, cuando el nombre del método puede ser, en principio, un nombre constante (es decir, cuando comienza con una letra mayúscula y consiste solo en letras), parece que necesita desambiguación.

 def Foo; "Foo" end Foo # => NameError: uninitialized constant Foo Foo() # => "Foo" self.Foo # => "Foo" 

¿Por qué es este el caso? ¿Por qué una llamada a un método debe distinguirse explícitamente de una referencia a una constante incluso en ausencia de una constante con el mismo nombre?

El conjunto de variables locales que está dentro del scope en cualquier punto dado del progtwig se define de manera léxica y, por lo tanto, puede determinarse estáticamente, incluso tan pronto como el tiempo de análisis. Por lo tanto, Ruby sabe, incluso antes del tiempo de ejecución, qué variables locales están dentro del scope y, por lo tanto, puede distinguir entre un envío de mensajes y una desreferencia de variables locales.

Las constantes se buscan primero de manera léxica, pero luego a través de la herencia, es decir, dinámicamente. No se sabe qué constantes están en el scope antes del tiempo de ejecución. Por lo tanto, para desambiguar, Ruby siempre asume que es una constante, a menos que obviamente no lo sea, es decir, toma argumentos o tiene un receptor o ambos.

No hay una gran razón detrás de la diferencia. Solo quería que foo se comportara como foo (), si no hay una variable local foo en el ámbito. Pensé que era útil para crear DSL, etc. Pero no vi ninguna razón para hacer que Foo se comportara como Foo ().

Haces una gran pregunta. Como usted señala, Ruby quiere tratarlo como una constante y, por lo tanto, hacer una búsqueda constante.

Sin embargo, el siguiente fragmento de código muestra el comportamiento actual y, al modificar const_missing, parece que se obtiene el comportamiento deseado. Y a decir verdad, no puedo romper nada.

Mi conclusión es que esto fue como alguien ya sugirió, solo una decisión de diseño, pero es extraño porque en general ruby ​​favorece la convención frente a la aplicación.

O me estoy perdiendo algún caso donde las cosas se vuelven confusas y sucede algo incorrecto.