4 ms·
What you're telling me sounds reasonable, but I thought about it some more, and these rules are so syntactically ambiguous, writing a Ruby parser should be just
by csense 13y ago
What you're telling me sounds reasonable, but I thought about it some more, and these rules are so syntactically ambiguous, writing a Ruby parser should be just plain impossible!
If you can call 0-ary functions (functions which take zero arguments) without parentheses, how does Ruby know what a statement as simple as "a = b" does? It must expand internally to something like this (in Python notation):
a = b() if b.is_function else b
But then if the b() call itself returns a function, then is that function auto-called as well? So we'd have something like this as the Python translation:
a = b
while a.is_function:
a = a()
This can't be right.
And then you get syntactic ambiguities. For example, is the Python translation of the expression x = h-3 (in Ruby) equivalent to (in Python):
(A) x = h-3
(B) x = h(-3)
(C) x = h()-3
(D) x = h()()-3
(E) x = (h-3)()
(F) x = (h()-3)()
Maybe different whitespace, different compile-time definitions, or different run-time values will change the answer! And since the talk says you can monkey-patch Ruby's integer data type, you could even presumably make integers callable so things like "x = (h()-3())()" would be possible!
And then the overloading of the colon and question mark.
Is the expression "k:v" in Ruby a dictionary containing a single key, "k", which is mapped to the value "v"? Or is it a function call of a function called "k" with a single argument, ":v"?
And the ternary operator uses colons too! "a?b:c" could translate as a function called "a?b" being called with a single argument, ":c". Or a dictionary with a key "a?b" which maps to value "c". Or of course the ternary operator! And that's assuming none of the sub-expressions involved are 0-ary functions which are automagically called!
And then what if you want to disable the automagic calling and pass a function object around? Do you have to decorate it with an initial ampersand or something every time you use it? What if you have code like this that puts either a function object or an integer into a variable:
h = flag ? (&my_function) : 5
Then you want to copy h to the variable y. If you say "y = h" then it does the wrong thing when h is a function, because then h would be auto-called. But if you use the ampersand, you do the wrong thing when h is an integer, because then you would be taking &5 and (in C notation) this would change y from being of type "int" to type "int*". Good grief!
Which all reinforces my original point: Ruby syntax is aggravating! This language is impossible to deal with!
(Sorry for the double reply, but I feel like this comment is different enough from my other reply to merit its own space.)
- relix 13y agoIt's a common joke that Ruby is designed to make it as hard as possible for parsers. For the code samples going forward, keep in mind that in ruby you don't need a literal return statement to return a value from a method. Just whatever value is last, is returned: def val 5 end That method would always return 5. > But then if the b() call itself returns a function, then is that function auto-called as well? No, the only way to pass a method is by using method(method_name_here), which returns a Method object. To execute a Method object, you need to call call on it: def a end method(:a).call So if you have a method that returns a method, it should not be automatically called, so there's no loop necessary: def b method(:a) end z = b Then z is a Method object, namely a. Some experiments to answer your questions (I admit I wasn't sure for all of them what the outcome would be). IRB is Ruby's repl: irb(main):001:0> def a irb(main):002:1> 5 irb(main):003:1> end irb(main):019:0> {a: 1} => {:a=>1} irb(main):020:0> {a(): 1} SyntaxError: (irb):20: syntax error, unexpected ':', expecting tASSOC irb(main):009:0> def h(num = 10) irb(main):010:1> num irb(main):011:1> end irb(main):012:0> h => 10 irb(main):013:0> h-3 => 7 irb(main):014:0> h -3 => -3 irb(main):015:0> h - 3 => 7 irb(main):001:0> a?b:c NameError: undefined local variable or method `c' for main:Object
- csense 13y agoThis is really interesting. I guess some of my examples were relying on using a similar lexer as C -- which you probably couldn't in Ruby. I'll have to think some more about what a Ruby lexer would look like... But again, it steepens the learning curve -- it's so different from other languages that it's actually kind of hard to immediately see all the implications of "well Ruby's lexer is different than C's lexer".