Join_with

On 12/13/06, Nobuyoshi N. [email protected] wrote:

At Wed, 6 Dec 2006 19:40:03 +0900,
Martin DeMello wrote in [ruby-talk:228380]:

While golfing with the hex_ip thread, I realised that map takes no
argument, and join takes no block, leaving a vacuum for a combined
method:

Is it what is called “mapconcat” in Emacs Lisp?

Yes, just looked it up and it’s what I’m talking about. Might adopt
the name for consistency’s sake, though join_map has grown on me.

martin

On 12/13/06, [email protected] [email protected] wrote:

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

“Martin DeMello” [email protected] writes:

(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) ?

On Dec 13, 2006, at 3:56 PM, Christian N. wrote:

“Martin DeMello” [email protected] writes:

(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?

James Edward G. II

Hi –

On Thu, 14 Dec 2006, Christian N. wrote:

“Martin DeMello” [email protected] writes:

(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) :slight_smile: 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

Hi –

On Thu, 14 Dec 2006, Martin DeMello wrote:

It looks like Ruby >= 1.9 has this:
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 :slight_smile:

David

On Thu, 14 Dec 2006 [email protected] wrote:

I don’t particularly want to allow map(:anything) :slight_smile: 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! :wink:

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

Hi –

On Thu, 14 Dec 2006, James Edward G. II wrote:

On Dec 13, 2006, at 3:56 PM, Christian N. wrote:

“Martin DeMello” [email protected] writes:

(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

Hi –

On Thu, 14 Dec 2006, [email protected] wrote:

you confound me david! :wink:

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 :slight_smile:

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 :slight_smile:

David

On Dec 13, 2006, at 2:40 PM, [email protected] wrote:

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

Hi,

In message “Re: map taking an argument (was: Re: join_with)”
on Thu, 14 Dec 2006 01:58:15 +0900, [email protected] writes:

|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.

(a) noisier form works not only for map, but also for every method
that take a block.

(b) if we wanted to add same functionality for every iterator method,
we have to modify them all. besides that, some iterator methods
already take arguments that make less noisy form difficult.

© ampersand would serve as visual clue, which tells you that symbol
works as some kind of block. it is difficult to tell what :m
means in less noisy form. that could be a method name that map
based on instead of each, or some other thing.

Choose whichever you want.

						matz.

Hi –

On Fri, 15 Dec 2006, Yukihiro M. wrote:

|
|version and introducing the less simple one.
means in less noisy form. that could be a method name that map
based on instead of each, or some other thing.

Choose whichever you want.

I’ll take (a) and (b) :slight_smile: I understand © too, though.

David

On 12/14/06, [email protected] [email protected] wrote:

On Thu, 14 Dec 2006, [email protected] 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 :slight_smile:

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