Dynamic languages allow dispatching with and invoking on values from variables whose values are only known at run-time. Contrasting examples in Perl:
class names
constant
Foo::Bar->some_method Foo::Bar::->some_method 'Foo::Bar'->some_method
These are all identical, except the first one is an edge case. If there's a subroutine defined in scope with that name, the dispatch happens on its return value, which leads to difficult to understand bugs. The quoted versions are always safe.
dynamic
my $class_name = 'Foo::Bar'; $class_name->some_method
method names
constant
Some::Class->foo_bardynamic
my $method_name = 'foo_bar'; Some::Class->$method_name
function names
constant
foo_bar; (\&foo_bar)->()dynamic
my $function_name = 'foo_bar'; (\&$function_name)->()
I wonder, how do languages whose variable names have no sigils (normally, or at all) deal with these problems, specifically how did their language designers disambiguate the following?
- resolving class name
FooBar.some_methodwhere classFooBarmight be name literal or a variable whose value is a class name - dispatching to
SomeClass.foo_barwhere methodfoo_barmight be name literal or a variable whose value is a method name - invoking
foo_barwhere the function might be a name literal or a variable whose value is a function
I'm primarily interested in the three languages mentioned in this question's tags, but if you know a different dynamic language with no sigils, you can answer too.
In python and js (my ruby is a bit rusty) it's not possible to use a string in the name context. If you attempt to do so, that would be interpreted as an operation on the string itself:
The string should first be resolved by looking up in the context/scope dictionary:
or
Python provides both global and local dicts, js only the global one, so there's no way, apart from ubiquitous "eval", to obtain a local value from its name.
The same applies to methods: you look up a method using
getattr(python) or the indirect reference operator[...](js):Javascript code is slightly more complicated, because, unlike python, the returned method pointer is unbound:
Without
bindyou won't get the correctthisin a method:To put it more formally, the dot operator
.(equivalent to php's::and->) in python/js requires an identifier on the right, and allows for arbitrary expressions on the left. Since everything is an object, if the left-hand expression returns a string, the dot applies to that string, not to a variable whose name this string happens to be equal to.(As a side note, it's technically feasible to allow expressions on the right of the dot as well, so that
foo.('bar' + 'baz')would resolve tofoo.barbaz. I'm not aware of languages that support this syntax, but it looks like a nice alternative togetattrand similar methods).Similarly, the call operator
()allows for complex expressions on the left, additionally this expression must resolve to a "callable" object. Therefore,"someString"()doesn't make sense, since strings are normally not callable (unless you hack them somehow so that they are).That is, if you have a string the contains a variable name, you have to explicitly resolve it before use. There's no magic in the language that does that for you behind the scenes.