6

I read the documentation on Procs in the Crystal Language book on the organizations’s site. What exactly is a proc? I get that you define argument and return types and use a call method to call the proc which makes me think it’s a function. But why use a proc? What is it for?

dkimot
  • 2,239
  • 4
  • 17
  • 25

3 Answers3

6

You cannot pass methods into other methods (but you can pass procs into methods), and methods cannot return other methods (but they can return procs).

Also Proc captures variables from the scope where it has been defined:

a = 1
b = 2

proc = ->{ a + b }

def foo(proc)
  bar(proc)
end

def bar(proc)
  a = 5
  b = 6
  1 + proc.call
end

puts bar(proc) # => 4

A powerful feature is to convert a block to Proc and pass it to a method, so you can forward it:

def int_to_int(&block : Int32 -> Int32)
  block
end

proc = int_to_int { |x| x + 1 }
proc.call(1) #=> 2

Also, as @Johannes Müller commented, Proc can be used as a closure:

def minus(num)
  ->(n : Int32) { num - n }
end

minus_20 = minus(20)
minus_20.call(7) # => 13
WPeN2Ic850EU
  • 995
  • 4
  • 8
  • 2
    The example about block forwarding is not really great because it doesn't actually use a Proc's unique features. You can do the same with a plain block (using `yield`). The power of a block is that it can be stored (for example in an instance variable) and forms a closure. – Johannes Müller Mar 15 '18 at 11:08
  • @JohannesMüller, thank you, I've updated the answer. – WPeN2Ic850EU Mar 15 '18 at 11:40
  • BTW, you can use a proc method as well, see: https://stackoverflow.com/a/46728999/7450793 – Faustino Aguilar Mar 17 '18 at 23:18
3

The language reference explains Proc pretty well actually:

A Proc represents a function pointer with an optional context (the closure data).

So yes, a proc is essentially like a function. In contrast to a plain block, it essentially holds a reference to a block so it can be stored and passed around and also provides a closure.

Johannes Müller
  • 5,581
  • 1
  • 11
  • 25
3

A Proc is simply a function/method without a name. You can pass it around as a variable, and it can refer to variables in it's enclosing scope (it's a closure). They are often used as a way of passing method blocks around as variables.

Stephie
  • 3,135
  • 17
  • 22