Martimatix
Martimatix

Reputation: 1643

How to get the name of the arguments passed into a block?

In Ruby, you can do this:

prc = lambda{|x, y=42, *other|}
prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]

In particular, I'm interested in being able to get the names of the parameters which are x and y in the above example.

In Crystal, I have the following situation:

def my_method(&block)
  # I would like the name of the arguments of the block here
end

How would one do this in Crystal?

Upvotes: 4

Views: 138

Answers (2)

Johannes Müller
Johannes Müller

Reputation: 5661

To expand on the great answer by Jonne Haß, the equivalent of the Ruby parameters method would be something like this:

macro block_args(&block)
  {{ block.args.map &.symbolize }}
end
p block_args {|x, y, *other| } # => [:x, :y, :other]

Note that block arguments are always required in Crystal and can't have default values.

Upvotes: 5

Jonne Haß
Jonne Haß

Reputation: 4857

While this already sounds weird in Ruby, there's no way to do it in Crystal since in your example the block already takes no arguments. The other problem is that such information is already lost after compilation. So we would need to access this at compile time. But you cannot access a runtime method argument at compile time. However you can access the block with a macro and that then even allows arbitrary signatures of the block without explicitly giving them:

macro foo(&block)
  {{ block.args.first.stringify }}
end

p foo {|x| 0 } # => "x"

Upvotes: 6

Related Questions