Reputation: 105
I have a nested array:
a = [[1, "Aldous Huxley"],
[3, "Sinclair Lewis"],
[2, "Ernest Hemingway"],
[4,"Anthony Burgess"]]
a.collect { |author| author.drop(1) }
outputs
[["Aldous Huxley"], ["Sinclair Lewis"], ["Ernest Hemingway"], ["Anthony Burgess"]]
while
a.collect(&:drop(1))
Gives me a sintax error.
SyntaxError: (irb):18: syntax error, unexpected '(', expecting ')'
a.collect(&:drop(1))
^
Is it possible to define my original block expression in a &: syntax?
Upvotes: 0
Views: 101
Reputation: 11090
The colon is part of a Symbol in Ruby, the &
is the magic that makes that syntax work, by calling to_proc
on the object and using that as a block. So, while you can't use a symbol like :drop(1)
, you can accomplish this without using a symbol in 2 ways:
1) Return a proc from a method and pass that in:
def drop(count)
proc { |instance| instance.drop(count) }
end
a.collect(&drop(1))
2) Pass in an object that responds to to_proc
:
class Drop
def initialize(how_many = 1)
@to_drop = how_many
end
def to_proc
proc { |instance| instance.drop(@to_drop) }
end
end
drop = Drop.new(1)
a.collect(&drop) # or, more succinctly
a.collect(&Drop.new(1))
In a simple case like this, defining methods that return procs or objects that respond to to_proc
is probably overkill and just passing a block to collect
is better, but there could be some use cases where it's not.
Update: Thinking about this more, the Symbol
class doesn't have a call
method, but that doesn't mean it can't:
module SymbolCall
def call(*args)
proc { |instance| instance.public_send(self, *args) }
end
end
class Symbol
include SymbolCall
end
a.collect(&:drop.(1)) # or
a.collect(&:drop.call(1))
Just make sure you don't forget that it's actually a method call :drop.(1)
not :drop(1)
.
Upvotes: 6
Reputation: 121010
No, this is impossible.
&
syntax is the syntactic sugar, that does literally the following:
Proc
instance, calling to_proc
on it;(&:foo)
works because Symbol.to_proc
exists.
(&:foo(arg))
just can not be parsed, since :
expects valid symbol chars afterwards, and opening parenthesis will raise a syntax error.
Upvotes: 6