join_with

M

Martin DeMello

There was an RCR a while back, rejected by Matz, that asked for:

enum.map:)m)

to be the same as:

enum.map {|e| e.m }

It looks like Ruby >= 1.9 has this:

enum.map(&:m)

which strikes me as the same thing, functionally, but visually noisier
and semantically more obscure.

I'm just wondering what the rationale is for rejecting the simple
version and introducing the less simple one.

The 1.9 version is nicely orthogonal, though - it hasn't added
anything to #map, since the Symbol#to_proc method is called eagerly,
*before* passing the resultant proc to #map. And #map has always been
able to take a proc:
(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

So this hasn't really changed anything, it's just added a convenience
method to symbol. There's actually considerably less magic going on
than, say, #join's automatically converting everything to strings, and
the complexity is a result of that lack of magic.

martin
 
D

dblack

Hi --

There was an RCR a while back, rejected by Matz, that asked for:

enum.map:)m)

to be the same as:

enum.map {|e| e.m }

It looks like Ruby >= 1.9 has this:

enum.map(&:m)

which strikes me as the same thing, functionally, but visually noisier
and semantically more obscure.

I'm just wondering what the rationale is for rejecting the simple
version and introducing the less simple one.

The 1.9 version is nicely orthogonal, though - it hasn't added
anything to #map, since the Symbol#to_proc method is called eagerly,
*before* passing the resultant proc to #map. And #map has always been
able to take a proc:
(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

So this hasn't really changed anything, it's just added a convenience
method to symbol. There's actually considerably less magic going on
than, say, #join's automatically converting everything to strings, and
the complexity is a result of that lack of magic.

Interesting -- I perceive it as quite magic, maybe because no matter
how long I stare at it, &:m doesn't say "block based on iteration with
method named 'm'" to me.

Mind you, there's *still* room for doing something with the argument
to map :)


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

dblack

Hi --

Martin DeMello said:
(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

David, do you want to allow (1..10).map:)*, 2) ?

I don't particularly want to allow map:)anything) :) I was just
somewhat surprised to see the idea return in a slightly new form,
since Matz had rejected it a while ago.

If I were designing map:)name), I don't think I'd want it to take
arguments. But I have no technical grounds for saying so, only
aesthetic ones.


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

dblack

Hi --

Martin DeMello said:
(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

David, do you want to allow (1..10).map:)*, 2) ?

Does the version currently in Ruby 1.9 support arguments?

I don't think so. I'm actually not sure where they'd go, since &:meth
is the block and not an argument.


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
A

ara.t.howard

Hi --

Martin DeMello said:
(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

David, do you want to allow (1..10).map:)*, 2) ?

I don't particularly want to allow map:)anything) :) I was just
somewhat surprised to see the idea return in a slightly new form,
since Matz had rejected it a while ago.

If I were designing map:)name), I don't think I'd want it to take
arguments. But I have no technical grounds for saying so, only
aesthetic ones.

you confound me david! ;-)

if you like 'e.map :m' how can you __not__ like

harp:~ > cat a.rb
class Array
def map *a, &b
m, *a = *a
super &(b || lambda{|o| o.send m, *a})
end
end

prefixes = %w( foo-bar bar-foo ).map :[], /^\w+/
p prefixes


harp:~ > ruby a.rb
["foo", "bar"]

?

-a
 
D

dblack

Hi --

Hi --

(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

David, do you want to allow (1..10).map:)*, 2) ?

I don't particularly want to allow map:)anything) :) I was just
somewhat surprised to see the idea return in a slightly new form,
since Matz had rejected it a while ago.

If I were designing map:)name), I don't think I'd want it to take
arguments. But I have no technical grounds for saying so, only
aesthetic ones.

you confound me david! ;-)

if you like 'e.map :m' how can you __not__ like

harp:~ > cat a.rb
class Array
def map *a, &b
m, *a = *a
super &(b || lambda{|o| o.send m, *a})
end
end

prefixes = %w( foo-bar bar-foo ).map :[], /^\w+/
p prefixes


harp:~ > ruby a.rb
["foo", "bar"]

?

I didn't say I liked e.map:)m); I said I wondered why it was rejected
and now the same functionality has returned in a noisier form :)

But the broader answer is: because I don't think about Ruby design
questions as a matter of one thing leading inexorably to another.
Liking e.map:)m) would not imply liking anything else.

I suppose I've answered my own question, in a sense: Matz's dislike of
map:)m) does not imply disliking anything else, including map &:m.
That principle is so important. I'm even willing to pay the price of
&:m to see it upheld :)


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
M

Michael Judge

Hi --

(1..10).map &lambda {|i| i*2}
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
David, do you want to allow (1..10).map:)*, 2) ?

Does the version currently in Ruby 1.9 support arguments?

I don't think so. I'm actually not sure where they'd go, since &:meth
is the block and not an argument.

David

A few days ago, I modified Dr. Nic's MapByMethod gem (locally) to
attempt to handle arguments. The results were interesting.

Scroll down for some examples.

#
# --copy into irb--
#

module FindByMethod
def method_missing method, *args, &block
begin
method_missing_handler method, *args, &block
rescue
super
end
end

FIND_BY_REGEX = /^(all|any|collect|detect|find_all|find|
first_match|grep|group_by|map|none|partition|reject|select|sort_by)_?
(by|where)?_([\w_]+\??)$/

QUERY_ITERATORS = ["all","any","none"]

def method_missing_handler method, *args, &block
unless method.to_s.match FIND_BY_REGEX
raise NoMethodError
end

iterator = $1
selector = $2
callmethod = $3

iterator += "?" if QUERY_ITERATORS.include? iterator

self.send(iterator) do |item|
if selector == "where"
# Arguments used in boolean comparison
if args.length == 1
args.first == item.send(callmethod)
else
args.include? item.send(callmethod)
end
else
# Arguments fall through
item.send(callmethod,*args)
end
end
end
end

Array.send :include, FindByMethod

#
# ---stop---
#

#
# Examples!
#

[1,2,3].map_by_succ
# => [2, 3, 4]
# -- equivalent to [1,2,3].map { |x| x.succ }

[1,2,nil].select_by_nil?
# => [nil]
# -- equivalent to [1,2,nil].select { |x| x.nil? }

#
# Now lets try some arguments.
# (Normally they're passed right to the method.)
#

[2,4,6].map_by_div(2)
# => [1, 2, 3]

["1","one"].select_by_match(/\d/)
# => ["1"]

#
# If you've gotten ahead of me, you're probably wondering
# how you would pull off a rails-like magic finder:
#
# users.find_by_name("charlie")
#
# I struggled with that one for a long time, before settling
# on using 'find_where' instead of 'find_by' where you need
# it to equal an argument rather than pass through an argument.
#

[1,2,'a'].select_where_class(Fixnum)
# => [1, 2]
# -- equivalent to [1,2,'a'].select { |x| x.class == Fixnum }

#
# You can use most enumerable methods as well.
#

[1,2,3].partition_where_to_f(3.0)
# => [[3], [1, 2]]

#
# Some special cases though are .any?, .none?, and .all?
#
#They work, but you need to omit the question mark or ruby
# throws up all over her prom dress.
#

[1,2,3].any_by_nil?
# => false

#
# Keep in mind that it's easy to mix up 'where' and 'by'.
# Compare these two identical sounding method calls.
#

[1,2,'a'].select_where_kind_of?(Fixnum)
[1,2,'a'].select_by_kind_of?(Fixnum)

# Can you guess which works and which crashes?
#
# _by_ works as it translates into:
# x.kind_of?(Fixnum)
#
#_where_ raises an exception because it becomes gibberish:
# x.kind_of? == Fixnum
#
# I had to run it to figure out the difference too. There's something
# seriously wrong with the words I chose to distinguish between
# passing an argument from equaling an argument.
#
# - Mike
 
M

Martin DeMello

On Thu, 14 Dec 2006, (e-mail address removed) wrote:

I didn't say I liked e.map:)m); I said I wondered why it was rejected
and now the same functionality has returned in a noisier form :)

It hasn't really returned - it's just a small "hack" being officially
blessed. Indeed, it's almost exactly like adding to_a to Enumerable
makes *(1..10) work.

martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,220
Messages
2,571,128
Members
47,744
Latest member
FrederickM

Latest Threads

Top