Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

crystal-lang

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?

like image 788
Martimatix Avatar asked Dec 19 '22 00:12

Martimatix


2 Answers

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"
like image 183
Jonne Haß Avatar answered Apr 01 '23 11:04

Jonne Haß


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.

like image 26
Johannes Müller Avatar answered Apr 01 '23 11:04

Johannes Müller