abenga 8 hours ago

To a beginner who is used to ordinary imperative languages, that Ruby line is extremely difficult to understand. Is `.filter` a method or a property of `xs`? Is `{ |x| x.odd? }` an argument to a method or just a statement that comes after `xs.filter`? If it is passed to `.filter`, why does it not have parentheses around it but the `", "` passed to `join` does?

This all makes sense to a person who knows the language a lot, but wrinkles the brain of a newcomer. Too many concepts to juggle in order to understand. On the other hand, the Python one reads quite easily, even if you may have to go right to left.

3
usrbinenv 8 hours ago

The only difficulty in Ruby code is the block notation. Even then, it is very similar to constructs in JavaScript, Go, D and a number of other languages -- the only difference form JS would be that instead of `(x) => ...` you write `{ |x| ... }`.

Questions such as

> why does it not have parentheses around it but the `", "` passed to `join` does?

would be exactly the same for JavaScript, Go or D. Ruby has the best syntax with regards to blocks/lambdas/closures.

Qem 50 minutes ago

> Ruby has the best syntax with regards to blocks/lambdas/closures.

A bit of Smalltalk shining through Ruby.

abenga 7 hours ago

I don't know much Ruby outside of a few toy examples I wrote a long time ago. For most languages, there would be parentheses around objects you pass to functions, like `.filter({|x| x.odd? })`. This lends some consistency and makes it easy (for me at least) to understand that an anonymous function is passed to `filter`. Just separating it using spaces feels like Bash, something I find difficult to write anything slightly complicated in.

creata 5 hours ago

Lua, Haskell, ML, plenty of other languages where one-argument functions don't need parentheses. I think it makes a lot of code more readable.

abenga 5 hours ago

All not-exactly-popular languages.

creata 5 hours ago

Maybe relative to juggernauts like C or Java. But Lua is pretty widely used.

Defletter 1 hour ago

Kotlin too

kouteiheika 7 hours ago

> To a beginner who is used to ordinary imperative languages, that Ruby line is extremely difficult to understand.

I don't understand this argument. You are a beginner only for a tiny fraction of your time using a given programming language. Why are we optimizing a programming language for people who don't know it, instead of optimizing it for people who actually program in it?

abenga 4 hours ago

> Why are we optimizing a programming language for people who don't know it, instead of optimizing it for people who actually program in it?

Everyone who actually programs in a language was once a person who didn't know it. Languages which optimize for succinct terseness might be powerful once you master them, but they will never enter mainstream use, which I guess is not necessarily the aim.

creata 5 hours ago

The Ruby syntax doesn't seem that different to many other languages. For example:

    xs.filter(x => x & 1).sort().join(", ") // JavaScript

    xs & filter odd & sort & map show & intercalate ", " -- Haskell
Python seems to be the odd one out. Imo, its list comprehensions are confusing as hell to "newcomers". For example, when a list comprehension has multiple `for`s, what order are they nested in?

quietbritishjim 1 hour ago

> ... confusing as hell to "newcomers". For example, when a list comprehension has multiple `for`s, what order are they nested in?

I get that this is just a rhetorical question to make a point about newcomers, and I do agree it's not immediately obvious, but for the record: you can imagine any "if"s and "for"s in a list comprehension are nested statements in the same order. So, for example, this:

   l = [
      y.foo()
      for x in my_list
      if x.blah() > 7
      for y in x.ys()
   ]
Is equivalent to this:

   l = []
   for x in my_list:
       if x.blah() > 7:
           for y in x.ys():
               l.append(y.foo())
So the least comprehension is basically in left to right order with the one exception of the actual expression to be added to the list (like y.foo() in the example above).

creata 58 minutes ago

Yeah, I know, I know. But I imagine many people would mentally want to bracket [e for x in xs for y in ys] like [(e for x in xs) for y in ys] and thus conclude that y is the outer loop.

abenga 5 hours ago

Those both seem a little bit more consistent than the Ruby example, however. To understand the JS example for example, you only need know that to call a method on an object, you do `object.method(arguments)`, and this is chained in a straightforward manner, with methods called on the returned values left to right. Ditto for the Haskell example. Maybe the Ruby one does the same thing, but even in this extremely simple example, we still have two different ways of doing the same thing.

For Python, you don't really have to use list comprehensions in the place of multiple for loops, you can sacrifice the brevity afforded to write the same thing in a more easily understandable fashion.