(I know Django is a thing, but that has always been in the shadow of Rails, and rightly so.)
I looked into Ruby and it struck me as being a truly aesthetically pleasing language, and since it espoused the "principle of least surprise" -- with caveats, naturally -- most Ruby code tended to be straightforward to read.
Python on the other hand, while clean -- I came from Perl -- had a fair bit of ugliness like the "self" argument in class methods, and the "dunders" in dunder methods (__init__). That said, the Python ecosystem, especially in the numerical computation space, was far ahead of Ruby's at the time, so I chose Python. It worked out really well and allowed me to accomplish what I needed to. To this day I have no regrets choosing Python.
Compared to many languages (like Haskell etc.) Python's design isn't the most aesthetically pleasing or orthogonal or clean. But being a Dutch design, at least initially, it was very pragmatic. And Python is by no means ugly on an absolute scale, on the contrary. It’s just not as beautiful as some others.
Python's main advantage is the energy behind it: to this day there are no converged alternatives to Numpy or Pandas on Ruby.
I can't help but wonder that if in an alternate universe/timeline, Travis Oliphant, Pearu Peterson, Wes McKinney and others happened to have encountered Ruby first, we might have a different de facto language for scientific computing and data science.
Also beginners don’t have to mentally blot out in their heads the self argument when calling a method (“you mean self isn’t the first argument?”). Debug messages are also more consistent (“the debug message says my method needs 1 argument. Isn’t self right there?”)
I accept Python’s explicit self for what it is (Python’s philosophy prefers explicit over implicit), and don’t have trouble with it but aesthetically it deviates from most OOP languages out there. It’s a valid choice for practical reasons but I would also say that an implicit “this” is an equally valid choice for aesthetic reasons.
Here’s a survey of this/self choices: https://en.m.wikipedia.org/wiki/This_(computer_programming)
At some point I read somewhere that the whole point of upvote and downvote on Reddit was for “contributed to conversation” (upvote) or doesn’t (downvote).
That, to me, makes sense.
Disagreeing is part of what promotes good, challenging discussions. It also buffers us from external influences controlling the crowd of “agree’ers”. By promoting and encouraging differences of opinion or view, we make it harder for someone to come in and sway the crowd.
btw, our little subthread here is off topic and may be downvoted for that. (rightfully as we aren't contributing to the actual topic)
How much of your like/dislike do you think comes down to familiarity with the language?
When I was first learning python, I definitely didn't like it as much because I was unfamiliar with some fairly basic syntax. Exactly the feeling that you're describing (I was coming from matlab). I've been using python for two years now and expressing most 'programs' feels like second nature. I.e. if I am to describe an algorithm on a whiteboard I may as well do it in python because then I don't have to worry about coming up with pseudo-code conventions on the fly, and there is little syntax getting in the way of me expressing semantics.
Based no the link, it seems like ruby is largely similar to python, but it has slightly different choices. I'm curious what someone who's experienced with both would have to say about the stylistic features of the languages (ignoring libraries).
Python does not feel natural at all. And I don't mean the indentation, that's in your face enough that it can be handled fast. But Python is just everywhere almost like you'd expect, only to still be different whenever it can. Dicts for example, why is that in there instead of a Hash or what I'd call a assiociative array? Using list instead of Arrays, as if it were a lisp, only that the list behaves like an array with different syntax, and Python is not lisp like at all. Null is of course not null (I already disliked ruby's nil), it's None. Compare how easy ruby makes range, and how inelegant Python makes that.
In the end none of that matters that much and discussing it too much probably only leads to a flame war. What mattered to me: My python program (an audio player for the tray) was completely unstable, it ran into multi-thread issues without me ever understanding why and how to solve them. My first ruby program was enough to pass my employer, my second one is still online (and one of my active projects linked in my profile).
If I want got get something done and have it work well, I use Ruby. Though fact of the matter for ML or even just statistics the ecosystem is way less nice and I will be forced to use Python next time, my try to use Ruby during my last encounter with ML just failed.
I looked up the select/filter syntax in ruby. I guess the main difference is that the name of the element you're iterating over is left implicit compared to comprehensions, but equivalent to filter.
details.select{ |item| item[:qty] != "" }
[item for item in details if item.qty != '']
filter(lambda item: item.qty != '', items)
I'm curious if the implicitness is cumbersome when you need to do a selection that combines multiple lists. How would you express the third line of the following in ruby? A = range(65,69)
B = ['A', 'B', 'C', 'D']
[a for a, b in zip(A, B) if b=='C'] A = (65..69).to_a
B = ['A', 'B', 'C', 'D']
A.zip(B).select{|x, y| y == 'C' }.map{|x, y| x }That looks equivalent to python without comprehensions.
As far as I can tell the difference in the expressiveness of `map/filter/reduce` is mainly about whether you like or don't like comprehensions. Do you have any examples where you believe ruby has cleaner syntax?
Comprehensions don't replace reduce, they are equivalent to a combination of map, filter, and flat_map. The difference is not just about comprehensions, since map/filter/reduce, and friends, in Python are functions, where in Ruby they are methods; so in Python when you can't do it all with comprehensions (reduce, zip, etc.), it's either imperative loops or functional notation (inside-out), while Ruby uses method call notation, which results in operations reading in the order of application.
I definitely like how method call notations can be read left-to-right rather than inside out.
Now I'm curious why python developers decided not to add these 'transformation methods' to all Iterables.
I never had a problem with ruby map/reduce, but any expression more complex than a simple loop becomes hard to write with list comprehensions.
On the plus side, python has type annotations and static type checking with the help of mypy.
It has async/await which was a good strategic move to give javascript users a sense of familiarity. Ruby is somewhat lacking in this aspect.
By design, at that point write a function or proper loop. This provides an opportunity for documentation.