6 ms·
I don't understand why Ruby's syntax is seen as so elegant. It's ambiguous and a nightmare to parse. http://programmingisterrible.com/post/42432568185/how-to-
by davexunit 11y ago
I don't understand why Ruby's syntax is seen as so elegant. It's ambiguous and a nightmare to parse.
http://programmingisterrible.com/post/42432568185/how-to-parse-ruby http://programmingisterrible.com/post/42432568185/how-to-par...
- john2x 11y agoYeah, the Ruby-like syntax of Elixir made me stop looking into it more. I remember reading an article (or was that a chapter in a book), which basically said something like "ok, these parentheses are optional, but only for this case. For other cases, parentheses are required." Which is a shame, since the tooling built for it is the most amazing I've ever seen. I know syntax shouldn't matter, but personally I think consistency is very important.
- Reefersleep 11y agoI think syntax matters a lot - if it incurs development costs through inconsistencies, for example. I'm going to a meetup in a couple of days where Elixir and Phoenix will be presented, I think I'll keep your comment in mind and maybe ask about inconsistencies in the syntax, as I wasn't aware of this. What I know of the syntax relation to Ruby is that it is only superficial - the semantics are very different.
- Lrigikithumer 11y agoElegant to program with. Not write a parser for.
- davexunit 11y agoAn ambiguous syntax is not elegant to program with. Is this a variable reference? Is it a method call? I dunno!
- JoeAltmaier 11y agoWait - are we talking C/C++ here? where a function call, a variable declaration, an expression cast all look identical?
- spdionis 11y agoNo, C/C++ have bad syntax too, imo.
- mbel 11y agoYou are probably talking about C++, not C, unless those look identical to you: foo(); int foo; (int)foo;
- JoeAltmaier 11y agothe cast can equally be int(foo); or (int)(foo); The parenthesis are allowed and optional. The method can be declared (int) foo(int(x), int(y)); which can also be an invocation. etc.
- therealdtscode 11y agoI wouldn't really say they are optional. The two do different things. (int) foo (or (int)(foo)) is a c-style cast. int(foo) isn't a cast. Instead it invokes the int constructor with the argument foo.
- mbel 11y agoint(foo) and (int) foo(int(x), int(y)) are not legal syntax in C. However, they are in C++ [0], which is my whole point. [0] your method declaration has a small problem, it apparently cannot have parenthesis around returned type.
- jacques_chester 11y ago> Is this a variable reference? Is it a method call? I dunno! Neither. It's a message sent to an object. The object decides how to respond to that message. Caring about the implementation of the message receiver breaks information hiding. If you have to distinguish between .message and .message(), you already know more than you need to know to interact with that object. Every language is confusing until you understand the mental model (even if you disagree with the utility of that model). If you come to Ruby thinking in Java/C++/C terms, you'll be unhappy, because the mental model is very different. For Ruby, the book to read is The Well-Grounded Rubyist, which makes the language quite obvious.
- davexunit 11y agoI've been programming in Ruby for years, and the inherent ambiguity proven by the complexity of the parser isn't made better by telling me I'm not thinking right. Variables and methods are treated differently. I can't pass arguments to a variable, I can't even write foo(), but if it were a method I could. I can't treat variables like any other object because they have different rules applied.
- jacques_chester 11y ago> I can't pass arguments to a variable I'm confused -- if you're knowingly invoking a method, why are you unsure whether it's a method or a variable? I programmed for years in Ruby too. I just accepted a whole bunch of stuff as mysterious and shrugged. It didn't mean the language was ambiguous, I just didn't have any idea of what the actual model was.
- dragonwriter 11y agoActually, you're wrong. The syntactic ambiguity between local variable references and implicit self method calls us not accurately resolved by thinking of it as message sends because it's only a message sends if it is a self method call, not it is a local variable reference. This is a real syntactic ambiguity in Ruby.
- 11y ago
- Confusion 11y agoBoring arm chair language criticism. I have programmed professionally in Ruby for 5 years and it has never been a problem. You may as well complain that the ability to import an identifier leads to confusion about which identifier from which namespace you are calling when you reference one. I have 99 gripes about Ruby, but this ain't one.
- snake117 11y agoI just started working with Ruby on Rails a few weeks ago and I think the so-called "elegant" syntax is the reason why I went with it. That and the fact that Rails is a joy to work with.
- kentt 11y agoHave you written Ruby often and still felt like this? I'm asking because I'm newer to Ruby and this does come up a fair bit, but I was assuming that with time the ambiguity would disappear.
- Jweb_Guru 11y agoI have written Ruby for many years now. The ambiguity never disappears, and the delight at how "expressive" the syntax is quickly turns to loathing. YMMV, of course.
- adamlett 11y agoAmong people who like Ruby, this is seen as a feature, not a bug. It makes refactorings easier when you change something from a local variable to a method call and don't have to search for all the places you would have to add parentheses in a language like Java. Granted, you could argue that your IDE should take care of that for you with automatic refactorings, but to a Rubyist this is a crutch and also something that forces her to use a particular IDE instead of her favorite editor.
- asterite 11y agoI don't think it matters much that it's hard to parse: very few are going to write a parser for that language compared to the ones that are going to write programs in the language. It goes the same for everything else in a language: prefer a fast compiler rather than an elegant (compiler) but slow one. Ruby's syntax is very short and concise if you compare it to other languages. To know if "x" is a variable or a method you just need to see if "x" was assigned a value in the method, that's all.
- dragonwriter 11y agoLots of people find it elegant in actual use because of the same features that make it hard to parse; this is much the same thing that is true of natural languages.
- atmosx 11y agoI don't understand what parsing has to do with elegance in this context. There are some 'best practices' but I don't see the different syntax support as a bug. I feel that it's a trademark of a modern language. Let's take rust as a counter example. IMHO this is ugly: fn foo() {...} To make it elegant I should be able to remove the parenthesis because there's no argument inside: fn foo {...} But this will come up with an error: "expected one of `(` or `<`, found `{` ...", which is fine. It's easy to parse, but it is not elegant IMHO. Elegance != easy parsing.
- kibwen 11y agoIt's not just about making parsing easy (which is usually motivated by the promise of better tooling), it's about making costs explicit. `foo.bar` with no trailing parentheses is always a field access in Rust, and a field access is basically the fastest thing one can do: take a known offset from a memory location. In comparison, `foo.bar()` has a relatively tremendous cost, depending on various factors. It's for this same reason that Rust requires you to write `(foo.bar)()` if you want to call a function stored in a struct. This isn't a tradeoff worth making in all languages. But it is a tradeoff, and not a rejection of elegance.
- waj 11y ago`foo.bar` is always a call in Crystal. If `bar` is just an accessor, then the method will be inlined and there is no extra cost compared to make an explicit field access.
- MrBra 11y agoTry to build a class with it and you will understand.
- davexunit 11y agoI've built many a class in Ruby.
- MrBra 11y ago> I've built many a class in Ruby. I see..... Anyway, this is elegant to me: sum ||= (1..100000).to_a.inject(:+) Maybe you have a different aesthetical sense than the rest of us. That's perfectly fine, we don't have to like the same things. But since you questioned, now I'm curious and I would like to ask you: what language in your opinion has the most elegant syntax? Also if you have 2 extra minutes free, would you mind to code that same one-liner above in that language so we could compare the two?
- giovannibajo1 11y agoIn Python it's x = sum(range(100000)). You might say that's cheating because there is a specific sum function, but having smart builtins covering common programming cases is exactly what an elegant language offers.
- sandbags 11y agoHaving migrated to Clojure I prefer: (reduce + (range 1 100001)) but you can make yours a little nicer by relying on a Range being enumerable, hence: (1..100000).inject(:+)