3

Given that the following currently works in Ruby like a very limited version of Haskell's constructor pattern matching:

[[1,[2,3]]].map {|(x, (y, z))| x + y * z} #=> [7]

I wonder if it also supports a syntax for "as-patterns" (what Haskell calls them), which is basically putting multiple bindings on the same arguments, like so:

[[1,[2,3]]].map {|(x, yz@(y, z))| [x + y * z, yz]} #=> [7, [2,3]]

I tried @ and other symbols, but they all resulted in syntax errors.

JoL
  • 1,017
  • 10
  • 15
  • I don't think that ruby has such thing but I can't be sure, ruby does have some features from common functional languages but its main paradigm is the object oriented paradigm – niceman Jun 04 '18 at 21:03

2 Answers2

2

As far as I know, ruby does not currently (2018-06-04) have that feature.

There isn't a formal spec of the ruby language to refer to, but there is The Ruby Spec Suite. Check out language/block_spec.rb for some weird and unusual examples of block params.

Block arguments are surprisingly powerful, and support optional args, splats, post-args, destructuring, nested destructuring, keyword arguments, block-level variables. It's pretty impressive.

If you can read C (I can't) and you really want to dig into this further, you can find the definition of block arguments in the interpreter grammar at parse.y:2980.

Jared Beck
  • 16,796
  • 9
  • 72
  • 97
0

Not sure about the as-patterns but in ruby you can implement similar thing using lambda & proc

For 1st Pattern

2.3.1 :030 > pattern = Proc.new {|x, y, z| x + (y * z) }
 => #<Proc:0x007fa6fd5a2188@(irb):30> 
2.3.1 :031 > func = lambda { |arr| arr.map {|ar| pattern.call(*ar)} }
 => #<Proc:0x007fa6fddc1328@(irb):31 (lambda)> 
2.3.1 :032 > func.call([[1,2,3], [4,5,6]])
 => [7, 34] 

For 2nd Pattern

2.3.1 :033 > pattern = Proc.new {|x, y, z| [x + (y * z), [y, z]] }
 => #<Proc:0x007fa6ffba5150@(irb):33> 
2.3.1 :034 > func = lambda { |arr| arr.map {|ar| pattern.call(*ar)} }
 => #<Proc:0x007fa6fdd60aa0@(irb):34 (lambda)> 
2.3.1 :035 > func.call([[1,2,3], [4,5,6]])
 => [[7, [2, 3]], [34, [5, 6]]] 
Salil
  • 46,566
  • 21
  • 122
  • 156
  • The code I used for the first pattern already works as-is with ruby, so a workaround is not needed. The example you gave for the second pattern simply does `[y, z]`, so I guess the answer is no. – JoL Jun 04 '18 at 22:45