Passing params to Map method

Hi and thanks in advance for your help.
I have been pounding every Ruby and Rails book I can find, desperately
attempting to move beyond newbie status.My latest foray has taken me
into the native 2.0.2 Rails::Info module. I am reading what I think is
native ruby code but I can’t seem to figure out what is being passed
to map and find. Could someone please explain (name, ) in the
following code?

Thanks again.

module Rails
module Info
mattr_accessor :properties

class << (@@properties = [])
  def names
    map {|(name, )| name}
  end

  def value_for(property_name)
    find {|(name, )| name == property_name}.last rescue nil
  end
end

Hi –

On Tue, 25 Mar 2008, Ruby F. wrote:

module Rails
end
end

find and map are not being passed any arguments; rather, they’re being
given code blocks, and those blocks are being passed arguments.
(name,) is block parameter syntax for grabbing one element of an array
and putting it in name.

David

Thank you David,
I stand corrected (actually I’m sitting)

So… I have been re-reading the best darn Ruby/Rails book on the
planet (Ruby for Rails of course! which I already read cover to cover
once) and I am still a bit confused but it’s getting better.
Maybe someone could be so kind as to critique my comments below about
what I think is happening. I have been studying this little bit code
for about 6 … no 8, hours and hopefully, I have most of it correct.
(personally I find it irritating when people ask questions without
putting any personal effort into finding the answers themselves)

module Rails
module Info
mattr_accessor :properties #module level property
assessor (getter and setter)
class << (@@properties = []) #Open up Array class def to
add methods (class << object), object == an Array
def names #define
Array.properties.names method
map {|(name, )| name} #read code block to return
array comprised of first half of [name, value]
end

  def value_for(property_name)       #define

Array.properties.value_for(“name param”) method
find {|(name, )| name == property_name}.last rescue nil
#return value part of [name, value] for sent name param
end
end #close Array class def

class << self #:nodoc:               #open "Info" class def to add

methods
def property(name, value = nil) #define property “setter”
except the yield makes it a “getter”
value ||= yield #if value is nil, yield name
to code block in names and value_for
properties << [name, value] if value #push [name, value]
array into @@properties array
rescue Exception #ignore error?
end

What I think is happening is the new “Info.properties” accessor is
cleverly leveraging self.property as a method to both set a new
property into @@properties and to return (yield) just the name when
the parameter passed to the code block is just the first half of the
array (name, ). Just understanding that after 8 months and thousands
of hours and reading thousands of pages of books is really exciting
for me.

I am a little iffy on the “class << (@@properties = [])” opening up
the Array object, but it fits the rule.(class << object)

if that is true, it is pretty cool code. (it’s pretty cool even if I
am wrong) Ruby has quite a learning curve, especially for a VB guy.

Thanks again.

On Mar 24, 11:57 pm, “David A. Black” [email protected] wrote:


find and map are not being passed any arguments; rather, they’re being
given code blocks, and those blocks are being passed arguments.
(name,) is block parameter syntax for grabbing one element of an array
and putting it in name.

From your description “block parameter syntax”, someone might conclude
that this is something specific to blocks, but it’s more generally the
syntax for destructuring an array. For example:

(x,) = [7,8,9] # x => 7
(x,y,z) = [7,8,9]

or even

x, = [7,8,9]

In the OP’s example, I think map {|a| a[0] } is clearer, but if the
parameter is used multiple times, e.g. map {|a,| “#{a}-#{a}” }, then
assigning to ‘a’ initially is more concise.

2008/3/26, Ruby F. [email protected]:

What I think is happening is the new “Info.properties” accessor is
cleverly leveraging self.property as a method to both set a new
property into @@properties and to return (yield) just the name when
the parameter passed to the code block is just the first half of the
array (name, ). Just understanding that after 8 months and thousands
of hours and reading thousands of pages of books is really exciting
for me.

Yep. Methods #names and #values_for are defined for the one instance
of Array only that is referenced by @@properties. So these are not
general methods. But they rely on methods defined in Array and
Enumerable to do their job. Basically they seem to rely on the fact
that @@properties contains arrays with exactly two elements - the
first one used as property name and the second one as property value.
During iteration (i.e. map, find) on the array only the first is
assigned a block parameter (small optimization because the second one
is not needed). That’s it basically. This is the usual pattern
matching that Ruby applies to multiple assignments:

irb(main):001:0> (a,(b,c),d)=1,2,3,4,5
=> [1, 2, 3, 4, 5]
irb(main):002:0> a
=> 1
irb(main):003:0> b
=> 2
irb(main):004:0> c
=> nil
irb(main):005:0> d
=> 3
irb(main):006:0> (a,(b,c),d)=1,[2,3],4,5
=> [1, [2, 3], 4, 5]
irb(main):007:0> a
=> 1
irb(main):008:0> b
=> 2
irb(main):009:0> c
=> 3
irb(main):010:0> d
=> 4

What makes this a bit hard to read is that assignment to @@properties
and the class<<@@properties are lumped into one statement.

I am a little iffy on the “class << (@@properties = [])” opening up
the Array object, but it fits the rule.(class << object)

if that is true, it is pretty cool code. (it’s pretty cool even if I
am wrong) Ruby has quite a learning curve, especially for a VB guy.

Yeah, it seems VB is a bad place to start learning to program. :slight_smile:

Kind regards

robert