Reputation: 1137
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.
Upvotes: 3
Views: 77
Reputation: 47522
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]]]
Upvotes: 0
Reputation: 17538
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.
Upvotes: 2