Feature #6483
closedparametric map
Description
I found very common use-case for map: map with parameters and &:meth syntax. For example:
matrix =[[1,2,3],[4,5,6]]
matrix.pmap(' ',&:join).join("\n") # => "1 2 3\n4 5 6
[1,2,3,4,5].pmap(2, &:to_s) # ['1', '10', '11', '100', '101']
[1,2,3,4,5].pmap(&:to_s) # ['1', '2, '3', '4', '5'] # empty parameter list behaves as usual map
Isn't it much better than ugly and verbose code:
matrix.map{|line| line.join(' ')}.join("\n")
I can write simple implementation
class Proc
def curry_except_self(*args)
Proc.new{|slf| curry[slf,*args] }
end
end
module Enumerable
def pmap!(*args,&block)
map! &block.curry_except_self(*args)
end
def pmap(*args,&block)
dup.pmap!(*args, &block)
end
end
Use-cases can be rewritten as tests (I can send my own unit-test if needed)
Also I've two related things to discuss.
- First is &-syntax. Is it possible to change ruby-interpeter in such a way that &:proc could be at any place. matrix.pmap(&:join,' ') is much prettier than matrix.join(' ',&:join) What is the reason behind this restriction? And if one can remove this restriction, we'd have new nice syntax.
- I'm not very experience in functional programming with curry etc, but it seems to me that currying proc without supplying first argument(self) can be common task when &:meth syntax is in play. If so, may be my curry_except_self(*args) also should be included in ruby.
Updated by prijutme4ty (Ilya Vorontsov) about 14 years ago
Also I propose similar approach for tap method.
So instead of
or
I can use
Updated by nobu (Nobuyoshi Nakada) about 14 years ago
Updated by prijutme4ty (Ilya Vorontsov) about 14 years ago
nobu (Nobuyoshi Nakada) wrote:
I proposed a different approach, symbol with arguments syntax.
And another proposed
Symbol#callin the same thread, instead.
Really cool syntax! I didn't even thought that about such a way. Second version I wrote like that:
class Symbol
def call(*args)
obj=Object.new.instance_exec(self,args){|sym,params| @sym=sym; @args = params; self}
obj.define_singleton_method :to_proc do
@sym.to_proc.curry_except_self(*@args)
end
obj
end
end
Unfortunately symbol isn't cloneable, so I used auxiliary object
In such a way one shouldn't define both tap and map and pleorth of other methods!
But first approach you suggested cannot be implemented in ruby yet. Hope sometimes ruby'll supply such a syntax! I propose it shouldn't even have parentheses for args
Updated by Eregon (Benoit Daloze) about 14 years ago
nobu (Nobuyoshi Nakada) wrote:
I proposed a different approach, symbol with arguments syntax.
And another proposed (({Symbol#call})) in the same thread, instead.
For info, this is http://bugs.ruby-lang.org/issues/show/4146 (I had a hard time finding it back).
Another syntax is proposed by Koichi (from what I can understand):
Which might be simplified to:
I really like that one.
Updated by trans (Thomas Sawyer) about 14 years ago
That's pretty neat. I wonder about its implementation, so basically & becomes a special object that returns a proc when method is called on it?
class Ampersand < BasicObject
def method_missing(s, *a, &b)
::Proc.new{ |x| x.public_send(s, *a, &b) }
end
end
& = Ampersand.new
This is also interesting in that it has an appearance similar to an anaphora (default block argument):
But despite appearances they are very different in nature.
Updated by prijutme4ty (Ilya Vorontsov) about 14 years ago
Eregon (Benoit Daloze) wrote:
Another syntax is proposed by Koichi (from what I can understand):
Which might be simplified to:
I really like that one.
It's fine, but in version with PM it look like a hack. However if it'll be implemented in second version - I'd take my words back.
Updated by mame (Yusuke Endoh) about 14 years ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
Assigning to matz.
Eregon (Benoit Daloze) wrote:
For info, this is http://bugs.ruby-lang.org/issues/show/4146 (I had a hard time finding it back).
Thanks Benoit! I added it as a related ticket.
--
Yusuke Endoh mame@tsg.ne.jp
Updated by prijutme4ty (Ilya Vorontsov) about 14 years ago
I've made a simple extension that allows one to use nested symbolic-procs like this:
Not to duplicate code - look at http://bugs.ruby-lang.org/issues/4146#change-26991
Updated by nobu (Nobuyoshi Nakada) about 14 years ago
Updated by prijutme4ty (Ilya Vorontsov) about 14 years ago
Updated by mame (Yusuke Endoh) over 13 years ago
- Target version set to 2.6
Updated by matz (Yukihiro Matsumoto) over 13 years ago
- Status changed from Assigned to Rejected
I reject the original idea of #pmap which might be read as 'parallel map' or 'parametric map' or something else.
The idea of adding parameter to block with argument specified e.g. a.map(&:to_s.(2)) is interesting,
but it must be proposed in separated issue.
Matz.