# Passing methods around

**URL:** <https://www.ruby-forum.com/t/passing-methods-around/54720>\
**Category:** Ruby\
**Created:** [March 13, 2006, 6:00pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720 "2006-03-13T18:00:51Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 6:00pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/1 "2006-03-13T18:00:51Z")

</div>

I’m a Ruby novice working my way through the pickaxe book, and I’ve got  
what should be an easy syntax question. On page 84 of chapter 6, the  
authors present the following program…

```
print "(t)imes or (p)lus: "
times = gets
print "number: "
number = Integer(gets)

if times =~ /^t/
  calc = lambda {|n| n*number }
else
  calc = lambda {|n| n+number }
end
puts ((1..10).collect(&calc).join(", "))

```

…Since everything is an object (right?), I thought I’d try a couple  
of different ways to tighten that up. The guts of the first thing I  
tried…

puts((1…10).collect{|n| n (times =~ /^t/ ? (\*) : (+)) number }.join(",  
"))

…results in syntax errors. Tossing in extra dots and ampersands in  
several places didn’t cure things for me. So, do I have just a simple  
syntax error there, or am I making a fundamental Ruby mistake? I also  
tried the following…

puts((1…10)  
.(times =~ /^t/ ? collect {|n| n\*number } : collect {|n| n+number })  
.join(", "))

…which doesn’t work either. Advice?

Thanks,

Greg Buchholz

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 6:34pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/2 "2006-03-13T18:34:42Z")

</div>

Haven’t tried it, but the “LHS (some\_dynamic\_method) RHS” syntax does  
seem a bit odd to me. You might try “LHS.send(some\_dynamic\_method,  
RHS)”. So something like:

puts (1…10).collect do |n|  
n.send( (times =~ /^t/ ? ‘\*’ : ‘+’), number )  
end.join(’, ')

Personally, I don’t like it though. You’re making a RegExp match on  
every iteration, when you only need the test once, and the Ternary  
operation in the middle of all that isn’t the easiest to read.

I’d recommend taking advantage of Ruby’s functional nature instead:

print "(t)imes or §lus: "  
times = gets  
print "number: "  
number = gets.to\_i

calc = if times =~ /^t/  
lambda { |n| n \* number }  
else  
lambda { |n| n + number }  
end

puts (1…10).collect(&calc).join(", ")

Other than that, I wouldn’t worry about making it “simpler”.

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 6:43pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/3 "2006-03-13T18:43:07Z")

</div>

Greg Buchholz wrote:

> I’m a Ruby novice working my way through the pickaxe book, and I’ve got  
> what should be an easy syntax question. On page 84 of chapter 6, the  
> authors present the following program…

[… program elided …]

> …Since everything is an object (right?),

Heh! Well, almost. I like to say that everything you can bind to a  
variable is an object. The problem is that you are playing games with  
syntax. You are trying to represent the operator of an expression with  
an expression. Since the operator itself is not a full expression, you  
can’t jam an expression in that place. You would get the same error  
from (the much simpler):

```
n (*) number

```

If you want to dynamically choose the operation, then “send” is your  
friend. For example:

```
n.send("*", number)

```

will work. Fixing your example to use send would be:

```
puts((1..10).collect{|n| n.send((times =~ /^t/ ? "*" : "+"), number) 

```

}.join(","))

–  
– Jim W.

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 9:40pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/4 "2006-03-13T21:40:22Z")

</div>

Greg Buchholz wrote:

> new functions in C at runtime, but you can do quite a bit with function  
> pointers). Does that sound about right?

I really like this explanation:

[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/179372](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/179372)

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 11:11pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/5 "2006-03-13T23:11:03Z")

</div>

Jim W. wrote:

> Fixing your example to use send would be:
> 
> ```
> puts((1..10).collect{|n| n.send((times =~ /^t/ ? "*" : "+"), number)
> 
> ```
> 
> }.join(","))

```
Just another data point. It looks like you can also use "method"

```

and “call”…

puts((1…10).  
collect{|n| n.method(times =~ /^t/ ? (:\*):(:+)).call(number) }.  
join(", "))

Greg Buchholz

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 13, 2006, 8:49pm UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/6 "2006-03-13T20:49:08Z")

</div>

Jim W. wrote:

> Heh! Well, almost. I like to say that everything you can bind to a  
> variable is an object. The problem is that you are playing games with  
> syntax. You are trying to represent the operator of an expression with  
> an expression. Since the operator itself is not a full expression, you  
> can’t jam an expression in that place.

OK. I’m trying to get aquinted with the terminology. Would we say  
that operators, methods, and messages aren’t first class entities?  
They’re second class citizens, like functions in C (you can’t create  
new functions in C at runtime, but you can do quite a bit with function  
pointers). Does that sound about right?

> puts((1…10).collect{|n| n.send((times =~ /^t/ ? “\*” : “+”), number) }.join(","))

Works like a charm.

Thanks,

Greg Buchholz

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 14, 2006, 8:21am UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/7 "2006-03-14T08:21:23Z")

</div>

Greg Buchholz wrote:

> OK. I’m trying to get aquinted with the terminology. Would we say  
> that operators, methods, and messages aren’t first class entities?  
> They’re second class citizens, like functions in C (you can’t create  
> new functions in C at runtime, but you can do quite a bit with function  
> pointers). Does that sound about right?

Nah. You’re confusing syntax with identity. The token “\*” there is not  
itself a method – you can’t assign it to a variable or anything. It  
just tells Ruby to call a method. But you can dynamically generate  
methods, and you can store a method in a variable – just not with that  
syntax.

Actually, Ruby is the opposite of C as far as what you can do at  
runtime. Ruby is all about runtime. For instance, when you’re defining  
a Person class and you write “attr\_accessor :shoe\_size”, you’re calling  
a method that dynamically creates (at runtime) the methods “shoe\_size”  
and “shoe\_size=” and defines them to get and set (respectively) the  
instance variable @shoe\_size. Some people have made classes that  
actually define methods as they’re called.

---

<div class="post-metadata">

**Author:** ![Greg\_Buchholz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a5b964/32.png) [@Greg\_Buchholz](https://www.ruby-forum.com/u/Greg_Buchholz)\
**Post date:** [March 14, 2006, 5:26am UTC](https://www.ruby-forum.com/t/passing-methods-around/54720/8 "2006-03-14T05:26:25Z")

</div>

> > “Would we say that operators, methods, and messages aren’t first class entities?”

No, the deal is that ‘+’, ‘\*’, etc aren’t some special “operator” type  
in Ruby, they’re just methods. The parser is what makes them look like  
traditional operators. So “x + y” is calling the ‘+’ method on ‘x’, and  
passing ‘y’ as a parameter.

So in saying “x some\_daynamic\_stuff y” you’re probably thinking “that  
should come out looking like ‘x + y’, so it should work.”.

The problem, is that to ruby it looks like: “Object1 some\_method  
Object2”

When you use symbols such as +, -, \*, /, etc, the parser just pretends  
you have a ‘.’ there, so to you ‘x + y’, but to Ruby, ‘x.+(y)’.

Except the parser can’t make this magic the way you’re trying, because  
you’re trying to execute it to see a result; something that happens  
_after_ parsing. So to ruby your method looks malformed. It’s easier to  
see if instead of a ‘+’ or ‘\*’ method, we use something else: ‘Greg’  
to\_i 16

See, ‘Greg’ isn’t the reciever for ‘to\_i’. There’s no ‘.’ to tell it  
so. This is what you’re ending up with. The ‘send()’ syntax mentioned  
earlier is a way to specify the reciever.

I would definitely consider methods “first-class” citizens in Ruby. The  
trick is that parenthesis in Ruby are optional. So unlike some  
JavaScript such as:

var meth = “Greg”.toString;

Which would assign the value of the toString member of “Greg” to a  
variable called “meth”, in Ruby this would actually execute the  
“toString” method. Because parens are optional. So to refer to a method  
without executing it, you’d use:

meth = ‘Greg’.method(:to\_s)

Which would return a BoundMethod, which has methods and attributes of  
it’s own. So they’re definitely objects. It’s just that getting a  
handle on the object is made a little difficult since accessing the  
member directly executes it, parens or no parens.

So you have a choice: Always force the use of parens for method calls,  
or have a helper for reflection so parens can be optional. Ruby chose  
the latter, (and I definitely think it was the right choice).

Sorry for going on so long…
