I mean, Ruby is so much more elegant and consistent than Python, I'll never understand how Python became the more widely appreciated language of the two, especially with the effective head start that Ruby had through Rails' popularity.
1. Old history of using python for scripting linux, starting from mid-late 90ies, especially around clusters and HPC, i.e. where you find applied scientists in academia.
2. A full C API. Not especially good, but powerful enough. I don't think ruby is much different, but wrapping C with python, again for HPC (or GUI libs). Lua C API is definitely better.
3. Communities matter
4. Different people starting to talk to each other more and more, and right timings. First mid 90ies (numeric/numarray, use in astronomy, etc.), then early-mid 2000ies (NumPy/SciPy consolidation, matplotlib, ipython), then late 2000 with scikit learn, and pandas.
Also, while I know little about ruby, I fail to see how much better it is than python. Both are essentially the same w/ some minor syntactic differences, and different communities. I have never seen an example where ruby was much better than python or vice versa for non trivial code. I mean is RoR that much better than Django ? I doubt that stuff matters very much.
IMO syntax is a major factor. Python looks like pseudocode, while Ruby looks like Perl.
Regardless, I’ve always thought that Ruby is more like pseudocode because with Ruby, I’m able to worry less about syntax and more about what I’m trying to do. Maybe it’s just me?
I used to think it was significant indentation, but if you look at the pseudocode on e.g. Wikipedia, there is no significant preference for either whitespace or begin/end.
Therefore, it’s probably things like `if value in my_map` vs `if my_map.contains(value)` and `[x * 2 for x in my_list]` vs `my_list.map(x -> x * 2)`.
- `if my_map.contains(value)` is nice and consistent, easy to search for the code of the .contains method and figure out what it does
- `[x * 2 for x in my_list]` another ugly special case syntax, instead of general purpose higher order functions, even in Python while a `.map` method could've been easily added to dictionaries too, we had to wait years (decades?) for dictionary comprehensions to land in the language, and it's another damn special syntax one has to remember. ugh! - a sane solution not involving higher order functions usage would've been to make everything in the language an expression and have `for ...` expressions return lists or dictionaries or sets, still better than the fugly "list comprehension", I really can't comprehend why people like them
- `my_list.map(x -> x * 2)` nice, clean, and general. If I work with a weirder list like thingy and want to see the logic of mapping, I can easily jump to the definition of it's `.map` method
Most pseudocode is ugly and ambiguous and actually hard to read without special context from the text around it because you're never sure what something actually means, can't easily "jump to its implementation code and read it". Same like natural language, hard to non-ambiguously understand and ugly as hell in technical context where math and diagrams work 1000x times better.
I can't understand why people who are trained in math, physics and/or other sciences would ever choose something just because it "looks more like pseudocode"... To me pseudocode rhymes with... pseudoscience! It's never what you want when you can choose something better.
Also I think the mantra of "developer happiness is the #1 goal of ruby" kind of makes ruby seem a bit more fanciful and flowery than python.
These are just my personal anecdotes, though, I am assuming that most people (myself included) start eyeing seemingly superficial things like the attitude of the language author when a lot of other qualities of the language are similar.
I don't think I've ever seen a popular Rubygem with dense, nasty, Perl-like code.
That sort of style may have been more prevalent in the early days of Ruby, which I'm roughly defining as the days before Rails.
At first I rebelled against not having unnamed closures, but then you hit the first problem in a complex case, and the backtrace having sane names suddenly makes it all more than worth it.
NumPy, maybe? Lots of resources make it easy to get small impressive projects off the ground quickly.
A sort of Dutch Disease caused by Rails is probably the biggest one. When one killer feature drives the adoption of a language, everyone who is interested and good at the language is involved with that ecosystem, and it becomes self sustaining.
The other one (already alluded to elsewhere here) is the culture of monkey patching and meta-code. I worked professionally in Rails for years, and I really enjoy Ruby, but every time I had a problem or question that required digging into the Rails source I was tearing my hear out. Almost everything is a cascade of hundreds of single line methods built on an avalanche of DSL abstraction and depending on implicit monkey patching and other crazy stuff that's a nightmare to understand.
It's not a culture of readable code in sizeable projects, which is what you need if you want to be widely adopted by people who don't primarily write code for a living (scientific work, other general work). Ironic considering how expressive and beautiful Ruby can be.
I love Ruby, but when I started developing in it, I was surprised at how much the Windows experience lagged behind just about everything else I had tried up until that point (Java, Python, Perl, x86 Assembly, at least). Even today, it's not really easy to run for anything requiring native extensions. You have to set up a separate compiler* just to build those extensions because most gems don't push binaries out. That may be better for security, but I don't think that's the driving factor. You're better off just running JRuby, assuming WSL isn't an option.
* Granted, RubyInstaller makes this a lot easier nowadays.
But whatever floats people's boats. If I had to do numeric computation I would chose python as well, but personally I would become a grumpy fart that would complain way too much
I've been working with Elixir for the past three years and it's boring and predictable. I want that moving forward from my tools. I want boring and predictable.
Compared to Groovy and Java?
Ever worked with numpy, scipy, pandas etc. in Python? It's ALL about what you call "sweeping the details under the carpet", or what is generally called abstraction. When abstraction is well "swept under the rug", eg. "you can use it without understanding it much" it's called non-leaky abstraction, and is the best kind of abstraction.
Sure, there's languages like Go that are all about NOT sweeping things under the rug. But that's a different niche.
Is there such thing?
(I agree that math abstractions are less leaky than others, of course)
Those are just external libraries written in C/fortran/etc. Not monkeypatching.
I don't applaud ruby dark voodoo tricks, but I think it's the same spirit.
i, unlike GP, do not get a smile on my face when i read ruby code full of implicit tricks. even when i understand some of them, it is still annoying.
why don't people just write clear, explicit, maintainable code instead of trying to be clever. i am sure method_missing could be implemented in python using various tricks but nobody, afaik, is doing that.
You could probably implement method_missing in Python using either __getattribute__ or __getattr__.
I think this is a small example of why nobody is doing so. It’s not just culture - Python’s object model is so complex that it would be hard to get right.
> why don't people just write clear, explicit, maintainable code instead of trying to be clever
But that’s boring. Seriously, it always amazes me how many programmers allow their decisions to be guided by what’s best for their personal enjoyment rather than what’s best for the project.
Exactly! Python is flexible too... using module import hooks and AST transformations you can even implement common-lisp-style-macros... but the language and model is so darn messy and special-case-y that it would blow up in your face if you tried to use it in a real world project :|
Whereas in Ruby you can whip up a nice clean DSL in no time, and people can actually understand how it's implemented and read it's source without being gurus. Whereas the number of Python programmers who properly understand metaclasses and AST wrangling and other stuff you'd need to do DSL-like stuff and have it work correctly can be counted on not that many fingers...
But it didn't turn out that way. And since people using Python don't strike me as particularly stupid or anything, there must be something about that language I'm still missing, or it wouldn't have succeeded as it did.
I do insist, however, that the documentation is overseen by sadists. Half the time the first 10 hits are to the C interface. The others sometimes link circularly between two "see: x" declarations, etc.
See I can say the same thing in reverse. I suspect it's just frustrating that once you know one of the two well, the other just dosen't do enough different to be worth learning as much. They have plenty of differences in the specifics but they're incredible similar in the domains they shine in. Similarly between Java and C#.
Add to that the fact that Python is now so established and used so many domains that the package availability that it attracts so many more people as a first language.
That said, I do do have reasons I prefer python, though I doubt they're solely why it "won". Idiomatic Python is just much clearer and more straight forward for most. They explicitly spent time to minimize how many language concepts and constructs you need to get basic things done. Compare:
some_list.each do |this_item| puts this_time end
for this_item in some_list: print(this_time)
The syntax/grammar are often more regular, use keywords and fewer symbols, and optional bits. Python went through a heavy monkey-patching phase (that's all but rejected now) but never went full blown DSL-style like Ruby. I'd say they both gained popularity being fun to write languages but Python stayed a but more balanced in readability.
ps: parens are better on function calls. fight me.
> for this_item in some_list: print(this_time)
Just a nitpick:
for one liners you can write:
some_list.each { |this_time| puts this_time }
puts some_list
This works as puts implicitly does the equivalent of calling Array() on its arguments and then calls `to_s` on each one.`some_list.each ...` is somewhat more generic, as `puts some_list` requires `some_list` to respond to `to_ary` for it to work as expected, which is probably less common than implementing 'each'. (if you implement a collection class in Ruby, at least implement `each` and `to_ary`)
This is similar to a native-English speaker boldly asserting that Dutch is a 'clearer and more straight forward' and 'more regular' language than Japanese.
It might be absolutely true for your own experience and upbringing, but it's still completely subjective.
Maybe python just has a nicer API, leading to more people writing fast C libs for it instead of Ruby; and ultimately many people will just use the language with the fastest libraries for their domain (specially the kind of people that have some influence on their community).
Again, no idea if this is the case, but comparing the C APIs of Ruby and Lua, it's a huge difference.
As I just mentioned in this thread, there is a project called SWIG[0] which might be something you'd want to check out.
0 - http://swig.org/
No. I found bits and pieces scattered in blog posts and gists, and wildly different ways of making extensions.
It was incredibly vexing and I would've happily used Python - or anything else - at that moment. The number of times I find hardcoded paths in Ruby extensions is mind boggling. I guess "it works on my computer" is okay for some but to me it seems amateurish. I don't blame the library authors as much as the core team for this because the documentation and examples are so bad. Not a good look for a mature language.
I'm looking at learning Crystal and Elixir because they'll (hopefully in Crystal's case) fix a lot of the glaring-but-never-fixed problems in the Ruby ecosystem for me.
Ironically enough I've spent my afternoon fighting with a Ruby C-extension that won't install!
You might want to check out SWIG[0] then. It can definitely help integrate C/C++ libraries into Ruby (as well as a dozen other languages) without having to work directly with the host language's C API.
HTH
0 - http://swig.org/
> Ruby's C implementation is a mess of support for language-level flexibility. Python's C implementation is so clean you get the unsettling thought that you could probably write Python using C macros.
Now the community is scattered into different communities - JavaScript, Go, Python, Rust, Scala, Elixir, etc. Those communities are still quite good, but none of them is as great as the previous Ruby community, or at least, gives me the same feeling IMHO.
Without these it might be a a powerful tool, but it wouldn't be in the same niche as Python and R.
Also, having touched Scala once before, the complexity and learning curve, and the prerequisite of being knowledgeable about JVM ecosystem to be productive in it...
It's not the same as Python or R, you are right. There is complexity, but it's rewarding once you get past the initial curve. I felt similarity regarding the JVM, but again, it's not that bad. Plus with GraalVM you can compile binaries, which I love for so many reasons.
The language is nice though. I wouldn't vote for the everything is an object paradigm today.
Compared to Haskell, its performance is not good. Same with J for that matter.