Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.




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

Search: