Hacker News new | past | comments | ask | show | jobs | submit login
Pattern Matching in Ruby 2.7 (2019) (speakerdeck.com)
137 points by brudgers on Jan 9, 2020 | hide | past | favorite | 106 comments



I personally love pattern matching (one of the best features of Elixir and Erlang for my taste) and would be screaming in enjoyment if something similar would be introduced to Ruby but I'm kind of meh about the whole ordeal.

This is experimental. Even when we upgrade production systems to 2.7 I'm still going to refute usage of pattern matching in the code (and it still boggles my mind why add experimental feature to a public release of such mature language as Ruby) since there is no guarantee we won't have to rewrite everything back in 2.7.4 or 2.8

The other issue I'm having with it is that it is connected to a case statement. It might be just me, but I'd dream of having this in function header definition instead of a statement which I rarely see in code and am not too comfortable to use as well (this might be connected to the crowd I'm usually working with).


Kind of tangential but I really appreciate seeing this cross inspiration of Elixir and Ruby. Ruby taking inspiration from the pattern matching and pin operator of Elixir, and Elixir taking the initial direction from Ruby. I look forward to the future developments of both.


Refinements was also at some point marked as "experimental", and jruby maintainers have at some point declared not wanting to support it. It's 2020, refinements are still here, and jruby supports them, even with all its imperfections.

I'm wondering: how would you showcase an experimental feature to the community? Cuz if you're saying "3rd party library", there were already 3/ 4 different pattern matching libraries.


> how would you showcase an experimental feature to the community?

How do other languages do it? Python has the PEP process for discussing design on paper, but I don’t know how they handle experimental implementations.


Standard library packages can be declared "provisional": https://www.python.org/dev/peps/pep-0411/

The PEP says "A provisional package is one which has been deliberately excluded from the standard library's backwards compatibility guarantees."

But there's no equivalent for language features, AFAIR.


The aim, from memory, is to gemify most of the standard library so why not release it as a "blessed" gem?

Edit: I see there is already the pattern-match gem [1], released as a proof of concept, although obviously it has slightly different syntax. Still, the reason why `case` is chosen (because `match` cannot be used) seems very thin.

Should've stayed as a gem, IMO.

[1] https://rubygems.org/gems/pattern-match


> in function header definition

Hmmm, I can kind of see it, but then you'd also need function overloading, right? With this you'd just do outer/inner functions, where the outer determines the pattern match and dispatches along to the appropriate inner function.

If you want to just make sure the function only accepts arguments that match a pattern, you're basically talking a guard pattern. Maybe a `return unless foo in <pattern>` syntax would then be nice (or some other one-liner), but it's not like it'd be hard to do it using this feature, you'd just use a few more mostly empty lines.


You mean that guards + destructuring would effectively be the same as pattern matching in function's params? Pattern matching would allow matching against more complex data structures more comfortably though.


The === operator is used by case statements, and can be used to implement pattern matching if you write objects which match in the way you want. It's how regexes match strings and ranges match numbers, etc.

What it doesn't have is destructuring combined with pattern matching, though it does have some destructuring assignments.


I hope... this is not another feature that is added to Ruby at the sake of the functional programming trend.

Rubycop’s author criticized[0] Ruby 2.7 for losing a direction/vision where Ruby should go (which sparked controversial operators that were quickly removed).

Most of them looks like, at least to me, trying to fit a functional programming features in an inherently object-oriented language to be ‘hip’. Like... the pipeline operator which had strange semantics.

I hope this isn’t one.

[0] Ruby, Where do We Go Now?: https://metaredux.com/posts/2019/12/06/ruby-where-do-we-go-n...


Hmmm. I'm definitely in favor of more functional programming features / capabilities, particularly in a language like Ruby that allows for pretty effective mixing of OOP/functional paradigms. Right tool for the job, where the job is usually "communicating with other programmers what this code should do".

I've always found Ruby to be an amazing mix of functional & OOP already, what with blocks, and that class definitions are also (actually?) functions themselves. And don't forget being able to drop parens!

I've also always felt like Ruby had mostly clear vision - arguably better than a perfectly clear one, since it leaves more room for play, exploration, and other people's contribution - even if it's not one that's able to be put into words. Every time I came across something surprising in Ruby, once I learned what was going on, it made sense in that larger whole.


Ruby blocks are another example of something that looks like a functional programming feature but is actually not. As in Java 8 and C++11, which also added lambdas, it doesn't have much in common with FP lambdas. These are essentially syntax sugar for an ad-hoc function that's too small to factor our and give a name. FP lambdas are the most elementary unit of computation. You're supposed to be doing absolutely everything with lambdas even addition, theoretically (head in the clouds academic BS), and the other syntax (like `do` in Haskell) is sugar for lambdas.

So basically Ruby is far from FP. It sticks to OOP, which has actually been proven to work.


From CS point of view, I miss the point you are trying to make.

No mainstream FP language is doing pure lambda calculus.


IIRC the main distinguishing feature of ruby blocks from regular anonymous functions is that you can break out of a containing scope from within them.


> [Java 8 and C++11 lambdas] are essentially syntax sugar for an ad-hoc function

that's what a lambda is pretty much anywhere, FP or not :)

> [in FP] you're supposed to be doing absolutely everything with lambdas even addition

in imperative programming, are you supposed to be doing everything by writing symbols to a moving tape, a la Turing? there's more to FP than pure lambda calculus, even if it was the starting point.

sure, natural numbers and other types can be implemented with lambdas. no serious FP language actually does that.


> functional programming features

What features?

Smalltalk-80 already had lambdas and LINQ, they were just called blocks and collection methods instead.

Pattern matching in OOP languages was a path pursued by BETA, Simula's successor by the same authors, where even classes are instances of patterns as concept.


You got any links to share on this? I'm doing a bit of academic study on the subject of pattern matching in OOP.


BETA programming language, https://beta.cs.au.dk/

Chapter 3, Objects and Patterns

Oberon-2 type guards, which are basic but still have the same idea somehow, https://cseweb.ucsd.edu/~wgg/CSE131B/oberon2.htm

Modula-3 type case, https://www.cs.purdue.edu/homes/hosking/m3/reference/typecas...


Thanks!


Definitely agree regarding the strange semantics recently like the pipeline[0] or `.:` method reference[1] operators. I do think those kind of functional features would be handy if they behaved correctly and had a more Ruby-like syntax instead of introducing foreign looking operators.

Luckily this new pattern matching feature appears to behave like expected and feels pretty natural - just a new `in` keyword and some variable binding syntax to familiarize ourselves with (which we already kind of use with statements like `rescue`).

Awhile back we experimented with an alternative Ruby pipe operator proof of concept[2] that is "operator-less" and looks just like regular old Ruby blocks with method calls inside of it. Maybe there's still a chance for something like this now that those other implementations have been reverted!

  # regular inverted method calls
  JSON.parse(Net::HTTP.get(URI.parse(url)))

  # could be written left to right
  url.pipe { URI.parse; Net::HTTP.get; JSON.parse }

  # or top to bottom for even more clarity
  url.pipe do
    URI.parse
    Net::HTTP.get
    JSON.parse
  end
[0] Revert pipeline operator: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/...

[1] Revert method reference operator: https://bugs.ruby-lang.org/issues/16275

[2] Experimental "operator-less" Ruby pipe operator proof of concept: https://github.com/lendinghome/pipe_operator


Why can't pattern matching fit in OOP? It's not really functional, despite being in most functional languages. It's just sugar for more lengthy imperative conditionals and unpacking.


It's typical in statically typed functional languages to match against Algebraic data type value constructors. These ADTs have a fixed amount of variants, which makes it suitable to do a clean pattern match.

ADTs don't exist in OOP. It gets more complicated to do matches against classes whose abstractions are not really decomposable so easily.


Indeed, Objective Caml is a multi-paradigm language with pattern matching.


And Scala. The poster child of oop + functional


Because part of the OOP mindset is to never dig into an object and only interact with a flat interface. From the few that I remember from OO articles in the 00s.

Now technically yes all FP idioms are just simple operations below that can be used. And they are.. python, js have destructuring which is a first stage pattern matching.


Destructuring ("digging into" a type) makes little sense with open records and sums, which OOP introduced into common use. The "closed" ('final', 'sealed' etc.) case where destructuring makes sense was disregarded for some time because it was thought that extensibility was always the appropriate choice.

Today, "open" extensibility mechanisms are considered a bit problematic because it's never really clear what invariants they should preserve, so maintaining correctness is an issue. A "closed" interface makes it essier to specify related invariants.


Yes! This is fantastic! And, in typical Ruby fashion, I've learned more about pattern matching from these slides than anything else trying to explain it that I've encountered before.

I'd definitely vote in favor of the pinned expressions. One of the things I like about Ruby is how pretty much everything is an expression, and you can replace pretty much any symbol with an expression.


I mean I get it - but, it doesn't feel like ruby to me. It lacks clarity. Maybe it's just me, but i'm not psyched to see this. It feels like a scope creep of some sort.


The ^ operator is maybe a bit confusing, and that Hashes need to use symbol keys to work here is just another example that symbols are a mess. But did you see the JSON-matching example in the slides? That made it totally clear to me how this is supposed to work and what the advantage of having this would be. Very powerful, very useful, and the code in that scenario is much clearer.


Lacking clarity is a good word for it, it was my feeling as well, but I've not used Ruby extensively. My feeling trying to hack existing Ruby code was always that Ruby favoured the arcane abit too much. This is from a perspective of me not bothering to learn Ruby at all. I remember thinking the same about C and Python before I bothered learning them.

I guess that feeling is always present when you try languages that are new, or our ignorance of pattern matching/Ruby?


Is it just me or does the syntax seem very confusing? Compared to other languages with pattern matching (ex OCaml) it seems a little clunky. I'm not familiar with Ruby though, does this syntax mesh with the rest of the language though?


It mostly does, but they talk about part of that actually, and why they had to use and extend `case` rather than introducing a new reserved word (like match).

And to your point, I think... Some of these features like pipes are really cool to see in languages like Ruby or JavaScript, but holy shit without true immutability some of this seems like a nightmare to emulate (like not being able to match on method calls if I remember correctly) in an traditional OOP runtime/vm.

Fuck my life, and this is strictly IMHO, but pipes seem totally worthless when you have to worry about the object and not the data...


In a language like Ruby and most imperative mutable ones pipelines could be a nice syntactic sugar for constructs like this

  a = f1()
  a = f2(a)
  a = f3(a, b)
  a = f4(a, c)
It becomes (let me use Unix pipes)

  a = f1()
    | f2()
    | f3(b)
    | f4(c)
OO idiomatically handles that by making each method return an object with the status and at least the next method to be called

  a = f1().f2().f3(b).f4(c)
However unless the class of that object is something standard and already available like (example) Ruby's Enum, it's a pain to code it (and understand it later on) and people go for the shortcut of writing the code at the beginning of my reply.


It kind of meshes with but I agree it's clunky. I'd like to have full pattern matching like we have in Elixir or at least in method definition. But that's going to turn Ruby into something different. I'm not sure it's worth it.


...semi off-topic, but man, how I wish Ruby had won the hearts of data-science and machine-learning practitioners instead of Python or R! It looks like such a wonderful and extensible and programmer friendly language compared to all the others in the "multi-purpose dynamic 'scripting' languages class". Every time I read Ruby code it almost puts a smile on my face, it seems such a joy to write and think in, so sad it didn't break out of its niche much :(


Same! I never used Rails much but did learn Ruby and used it a lot for the kind of stuff people tend to use Python for nowadays. Data crunching, prototyping, sciency stuff.. It's excellent for that.

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.


I don't have any data to back this up, but I suspect solid Windows support was a big driver of that. I used to do a fair bit of Python before Ruby and there was a nice MSI installer for the runtime and plenty of libraries had precompiled Windows installers available. This was important because we were working with some software that necessitated running Windows.

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.


> I’ll never understand how Python became the more widely appreciated language

IMO syntax is a major factor. Python looks like pseudocode, while Ruby looks like Perl.


You can write Ruby that looks like Perl, but in my experience (6 years of fulltime Ruby) this is very rare in the wild.

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.


Genuinely curious, what makes Python look more like pseudocode? The use of colons?

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?


> Genuinely curious, what makes Python look more like pseudocode? The use of colons?

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 value in my_map` is a one off special case - ugly, nasty, hard to figure out how to extend it (what if I invented my_map to have special logic for `in` ...I need to search the docs for a magic method called for that operator ...if I even know for what keywords to search, ugh)

- `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.


List comprehension in python it’s absolutely hideous. It’s reversed and you have to define first the function and after where it is applied. The code completion it’s completely broken in that way since it has no idea on which elements you are operating. And also are you saying that “list.include? 2” doesn’t look more like English than “2 in list”?


Ah, yeah. In that regard, I agree, Ruby could use some improvement.


Just as someone who got on the Ruby bandwagon back in the mid 00's there was definitely a feel of Ruby being a "Japanese import language" and at the time for myself, comparing Matz and van Rossom the latter felt like a little bit more of a scientist/engineer than the former who seemed very humanity focused.

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.


It’s your point of view. From my point of view ruby looks much more like pseudo code than python. It reads almost like English. And the closures syntax is way better and much more powerful given that it’s not sillily limited to one expression.


On the closure front, you are assuming that `lambda` is the only way of writing a closure in Python. That is not true. You can write a named function (`def blah():`) in the same place, pass it around (within that scope the name is now `blah`), and it will still have access to the variables in the original scope. So it is a closure, just a named one.

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.


I can think of two reasons:

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'll never understand how Python became the more widely appreciated language of the two

NumPy, maybe? Lots of resources make it easy to get small impressive projects off the ground quickly.


I guess the answer is - Google. As it used Python and the word was out. Also, Python had been released a few years earlier and so was adopted by universities.


Google had little influence on scientific python. I agree python did not have technically much advantage over ruby, but:

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.


From my perspective, it was the was the ipython notebook (now jupyter) that was the killer app leading to Python being adopted for data science.


I'd say python was pretty big in academic circles even before that if memory serves.


I wrote Ruby as my primary language professionally for over 10 years. These last few years though I write more python and javascript than anything else, but damn do I miss the joy of full time Ruby - what a beautiful, pleasant, productive language it is!


As someone who sometimes steps out of the comfort of writing scheme, I agree with you. I spent a lot more time writing python than I did ruby, but with ruby I can just jump right in and things work like I expect them to. With python there is always small semantic things that moves the whole experience into slightly uncomfortable territory.

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


Ruby was fun while I worked with it professionally but now I don't really like it or reach for it. It's a combination of monkey patching, imports being affected by their filesystem location, games of is this a function or a variable. I don't miss it.

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.


That's why I actually do a lot of my data science work with Groovy. I just find Python awkward, frustrating and way underpowered as a language (both in terms of language itself but, of course performance as soon as you need to implement anything and not just glue other things together). Groovy + JVM accessible numerical libraries (Smile, ND4J etc) actually make a pretty good combination, even if you do not have access to the state of the art stuff that is going on in R / Python.


>I just find Python awkward, frustrating and way underpowered as a language (both in terms of language itself but, of course performance as soon as you need to implement anything and not just glue other things together).

Compared to Groovy and Java?


Groovy absolutely. Java is .... Java.


I shudder to think what datascience code would look like if a language with a culture of monkeypatching/metaclassing had won. Clear code is nice, but not when the price is sweeping all of the details too deeply under the carpet.


> sweeping all of the details too deeply under the carpet

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.


imo, python won because the community does not condone monkey-patching and dark magic tricks. it's totally possible, yes, but it is frown up. i just realized how important language communities are, actually!

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.


> 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.


> It’s not just culture - Python’s object model is so complex that it would be hard to get right

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...


>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.

Those are just external libraries written in C/fortran/etc. Not monkeypatching.


I never looked at the source but it seems that there's an object layer with a lot of meta-programming to turn the oo syntax into more pleasant ergonomics.

I don't applaud ruby dark voodoo tricks, but I think it's the same spirit.


"it's called non-leaky abstraction"

Is there such thing?


Sure. Math based abstractions are non-leaky. This is one of the main thing FP people rave about. Eg. map works without bias on all functors regardless whether the concrete thing is a list or a tree or an IO action, etc...


For example, different implementations may have different performance characteristics depending on the object they are operating on. This way implementation details leak out through the time or space complexity, or through the constant factor.


Have you heard of “divide by zero?” ;)

(I agree that math abstractions are less leaky than others, of course)


I'm confused: how is dividing by zero an example of a leaky abstraction in mathematics?


I don't think OP is talking about metaprogramming, but more about syntax and how ergonomic Enumerable chains are, which I can see being really nice in data wrangling.


Agreed... I can write typical data-wrangling code at close to the speed of typing in ruby. In Python it takes forever, and I notice how every fibre of my soul tries to avoid even looking at it, much less enjoying and wanting to learn.

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.


> I can write typical data-wrangling code at close to the speed of typing in ruby. In Python it takes forever, and I notice how every fibre of my soul tries to avoid even looking at it, much less enjoying and wanting to learn.

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.


> 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. [...] The syntax/grammar are often more regular, use keywords and fewer symbols, and optional bits.

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.


I know! That's why the sentence right before it was: That said, I do do have reasons I prefer python, though I doubt they're solely why it "won".


> some_list.each do |this_item| puts this_time end

> 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 }


If each element of some_list responds to to_s with something sensible, which it would need to in order for puts to work in the first place, you can just write:

   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`)


I don't really know much about python, but how is the C API? Because as nice as Ruby may be as a language, I wouldn't want to touch the C API with a laser pointer.

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.


I wouldn't say I'm a C programmer at all though I did manage to struggle through producing a very simple C-extension for Ruby once. Recently, I had to debug one that wouldn't install. Could I find well written, up to date documents?

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!


This is a big use case for me. I really want to use Perl but I favour Python because the CPython API vs XS, it's a no brainer. I haven't really looked into the Ruby C API but if it's sane I would use it as well.


Perhaps Raku is an alternative for you with its Perl roots and its NativeCall support: https://docs.raku.org/language/nativecall Also see this recent blog post for interfacing with C++ and Fortran from Raku: https://andrewshitov.com/2020/01/08/calling-cpp-and-fortran-...


Nice thank you. The last time I looked at Raku a few years ago when it was still called Perl 6 I hadn't considered native bindings. Will take a look.


> I really want to use Perl but I favour Python because the CPython API vs XS, it's a no brainer.

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/


Thank you. I've heard of it and read about it a few times but haven't seriously considered it, but I will.


> I don't really know much about python, but how is the C API? Because as nice as Ruby may be as a language, I wouldn't want to touch the C API with a laser pointer.

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/


As one of my favorite HN comments of all time said:

> 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.

https://news.ycombinator.com/item?id=682364


And also, a decade before the Ruby community was the most inspiring community. One can really learn a lot from others, every day. It was like a hacker sanctuary while most programmers are still debating Java vs C++/C#.

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.


Does Julia scratch that itch now?


I agree with this. I did rails for a long time and honestly became pretty disenchanted on Ruby as a web services platform. But now that I interact with data analyses in Python fairly regularly (because they are everywhere) I really miss Ruby. I wish Ruby had landed on a different killer app!


It's not on the same level as the R Python ecosystem, but you should check out Scala. It has the power and flexibility, but also a fairly solid backbone of data science libs.


Does it have (1) a RELP, (2) jupyter support and/or smth like it, (3) interpreted mode or a compiler fast enough that I can pretend it does not exist?

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...


1) yes: https://docs.scala-lang.org/overviews/repl/overview.html 2) yes: https://almond.sh/, there are other options as well 3) The compile times don't bother me. I just set up sbt to watch for files saves and run tests. I'd say the dev cycle is faster than python due to compile time type checking.

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.


Marv, yarv - how is the most downloaded standard implementation called before the language cops bite - is just so unbearably slow for anything besides gluing things together. After that many years it still leaves me baffling how such a mediocre implementation is still actually accepted by it's community.

The language is nice though. I wouldn't vote for the everything is an object paradigm today.


Python may be faster than Ruby, but it's not "C" faster. It's the language extensions like NumPy that do the heavy lifting, and those are usually written in compiled languages like, say, C.


> Every time I read Ruby code it almost puts a smile on my face, it seems such a joy to write and think in

Compared to Haskell, its performance is not good. Same with J for that matter.


I'm 80% in favour of this change. JSON parsing is tedious and this looks like it will help pretty cleanly on something that rubyists do quite frequently. I could also see myself using this pretty frequently elsewhere.

That said, I do see some minor drawbacks:

1. I personally find the case statement in ruby confusing. It uses === which I find hard to use without stopping and thinking.

2. I don't understand why the bitwise or operator is being used for the pattern matcher or. Was it not possible to just use `or` itself?

3. Deconstruct keys reads a bit weird. Easy enough to understand and remember, but I can imagine being new to ruby or programming and finding the pattern matching pretty hard to follow.


Do we have something similar in python, if not I am going to make one.



This project is just someone wrote a proposal or something. Here is actually implemented pattern matching as a library https://github.com/santinic/pampy


IIRC Guido himself is planning on adding a `match` statement to Python.


I used both Python and Ruby extensively for a while, love both, but Ruby was just nicer to code in. The problem for me was the much smaller ecosystem, especially for anything numerical/data related. Numpy was, pre Pandas days, the killer library for the type of work I do.


Is pattern matching implemented sequentially in order of declaration in other languages? My naive brain took the pattern resolution to be based on some kind of map of types and values to implementation.


It is, from top to bottom.


ML is changing the world.


Wrong thread?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: