# <!-- rdoc-file=proc.c -->
# A `Proc` object is an encapsulation of a block of code, which can be stored in
# a local variable, passed to a method or another Proc, and can be called. Proc
# is an essential concept in Ruby and a core of its functional programming
# features.
#
#     square = Proc.new {|x| x**2 }
#
#     square.call(3)  #=> 9
#     # shorthands:
#     square.(3)      #=> 9
#     square[3]       #=> 9
#
# Proc objects are *closures*, meaning they remember and can use the entire
# context in which they were created.
#
#     def gen_times(factor)
#       Proc.new {|n| n*factor } # remembers the value of factor at the moment of creation
#     end
#
#     times3 = gen_times(3)
#     times5 = gen_times(5)
#
#     times3.call(12)               #=> 36
#     times5.call(5)                #=> 25
#     times3.call(times5.call(4))   #=> 60
#
# ## Creation
#
# There are several methods to create a Proc
#
# *   Use the Proc class constructor:
#
#         proc1 = Proc.new {|x| x**2 }
#
# *   Use the Kernel#proc method as a shorthand of Proc.new:
#
#         proc2 = proc {|x| x**2 }
#
# *   Receiving a block of code into proc argument (note the `&`):
#
#         def make_proc(&block)
#           block
#         end
#
#         proc3 = make_proc {|x| x**2 }
#
# *   Construct a proc with lambda semantics using the Kernel#lambda method (see
#     below for explanations about lambdas):
#
#         lambda1 = lambda {|x| x**2 }
#
# *   Use the [Lambda proc
#     literal](rdoc-ref:syntax/literals.rdoc@Lambda+Proc+Literals) syntax (also
#     constructs a proc with lambda semantics):
#
#         lambda2 = ->(x) { x**2 }
#
#
# ## Lambda and non-lambda semantics
#
# Procs are coming in two flavors: lambda and non-lambda (regular procs).
# Differences are:
#
# *   In lambdas, `return` and `break` means exit from this lambda;
# *   In non-lambda procs, `return` means exit from embracing method (and will
#     throw `LocalJumpError` if invoked outside the method);
# *   In non-lambda procs, `break` means exit from the method which the block
#     given for. (and will throw `LocalJumpError` if invoked after the method
#     returns);
# *   In lambdas, arguments are treated in the same way as in methods: strict,
#     with `ArgumentError` for mismatching argument number, and no additional
#     argument processing;
# *   Regular procs accept arguments more generously: missing arguments are
#     filled with `nil`, single Array arguments are deconstructed if the proc
#     has multiple arguments, and there is no error raised on extra arguments.
#
#
# Examples:
#
#     # +return+ in non-lambda proc, +b+, exits +m2+.
#     # (The block +{ return }+ is given for +m1+ and embraced by +m2+.)
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { return }; $a << :m2 end; m2; p $a
#     #=> []
#
#     # +break+ in non-lambda proc, +b+, exits +m1+.
#     # (The block +{ break }+ is given for +m1+ and embraced by +m2+.)
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { break }; $a << :m2 end; m2; p $a
#     #=> [:m2]
#
#     # +next+ in non-lambda proc, +b+, exits the block.
#     # (The block +{ next }+ is given for +m1+ and embraced by +m2+.)
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1 { next }; $a << :m2 end; m2; p $a
#     #=> [:m1, :m2]
#
#     # Using +proc+ method changes the behavior as follows because
#     # The block is given for +proc+ method and embraced by +m2+.
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { return }); $a << :m2 end; m2; p $a
#     #=> []
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { break }); $a << :m2 end; m2; p $a
#     # break from proc-closure (LocalJumpError)
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&proc { next }); $a << :m2 end; m2; p $a
#     #=> [:m1, :m2]
#
#     # +return+, +break+ and +next+ in the stubby lambda exits the block.
#     # (+lambda+ method behaves same.)
#     # (The block is given for stubby lambda syntax and embraced by +m2+.)
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { return }); $a << :m2 end; m2; p $a
#     #=> [:m1, :m2]
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { break }); $a << :m2 end; m2; p $a
#     #=> [:m1, :m2]
#     $a = []; def m1(&b) b.call; $a << :m1 end; def m2() m1(&-> { next }); $a << :m2 end; m2; p $a
#     #=> [:m1, :m2]
#
#     p = proc {|x, y| "x=#{x}, y=#{y}" }
#     p.call(1, 2)      #=> "x=1, y=2"
#     p.call([1, 2])    #=> "x=1, y=2", array deconstructed
#     p.call(1, 2, 8)   #=> "x=1, y=2", extra argument discarded
#     p.call(1)         #=> "x=1, y=", nil substituted instead of error
#
#     l = lambda {|x, y| "x=#{x}, y=#{y}" }
#     l.call(1, 2)      #=> "x=1, y=2"
#     l.call([1, 2])    # ArgumentError: wrong number of arguments (given 1, expected 2)
#     l.call(1, 2, 8)   # ArgumentError: wrong number of arguments (given 3, expected 2)
#     l.call(1)         # ArgumentError: wrong number of arguments (given 1, expected 2)
#
#     def test_return
#       -> { return 3 }.call      # just returns from lambda into method body
#       proc { return 4 }.call    # returns from method
#       return 5
#     end
#
#     test_return # => 4, return from proc
#
# Lambdas are useful as self-sufficient functions, in particular useful as
# arguments to higher-order functions, behaving exactly like Ruby methods.
#
# Procs are useful for implementing iterators:
#
#     def test
#       [[1, 2], [3, 4], [5, 6]].map {|a, b| return a if a + b > 10 }
#                                 #  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#     end
#
# Inside `map`, the block of code is treated as a regular (non-lambda) proc,
# which means that the internal arrays will be deconstructed to pairs of
# arguments, and `return` will exit from the method `test`. That would not be
# possible with a stricter lambda.
#
# You can tell a lambda from a regular proc by using the #lambda? instance
# method.
#
# Lambda semantics is typically preserved during the proc lifetime, including
# `&`-deconstruction to a block of code:
#
#     p = proc {|x, y| x }
#     l = lambda {|x, y| x }
#     [[1, 2], [3, 4]].map(&p) #=> [1, 3]
#     [[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2)
#
# The only exception is dynamic method definition: even if defined by passing a
# non-lambda proc, methods still have normal semantics of argument checking.
#
#     class C
#       define_method(:e, &proc {})
#     end
#     C.new.e(1,2)       #=> ArgumentError
#     C.new.method(:e).to_proc.lambda?   #=> true
#
# This exception ensures that methods never have unusual argument passing
# conventions, and makes it easy to have wrappers defining methods that behave
# as usual.
#
#     class C
#       def self.def2(name, &body)
#         define_method(name, &body)
#       end
#
#       def2(:f) {}
#     end
#     C.new.f(1,2)       #=> ArgumentError
#
# The wrapper `def2` receives *body* as a non-lambda proc, yet defines a method
# which has normal semantics.
#
# ## Conversion of other objects to procs
#
# Any object that implements the `to_proc` method can be converted into a proc
# by the `&` operator, and therefore can be consumed by iterators.
#
#     class Greeter
#       def initialize(greeting)
#         @greeting = greeting
#       end
#
#       def to_proc
#         proc {|name| "#{@greeting}, #{name}!" }
#       end
#     end
#
#     hi = Greeter.new("Hi")
#     hey = Greeter.new("Hey")
#     ["Bob", "Jane"].map(&hi)    #=> ["Hi, Bob!", "Hi, Jane!"]
#     ["Bob", "Jane"].map(&hey)   #=> ["Hey, Bob!", "Hey, Jane!"]
#
# Of the Ruby core classes, this method is implemented by Symbol, Method, and
# Hash.
#
#     :to_s.to_proc.call(1)           #=> "1"
#     [1, 2].map(&:to_s)              #=> ["1", "2"]
#
#     method(:puts).to_proc.call(1)   # prints 1
#     [1, 2].each(&method(:puts))     # prints 1, 2
#
#     {test: 1}.to_proc.call(:test)       #=> 1
#     %i[test many keys].map(&{test: 1})  #=> [1, nil, nil]
#
# ## Orphaned Proc
#
# `return` and `break` in a block exit a method. If a Proc object is generated
# from the block and the Proc object survives until the method is returned,
# `return` and `break` cannot work. In such case, `return` and `break` raises
# LocalJumpError. A Proc object in such situation is called as orphaned Proc
# object.
#
# Note that the method to exit is different for `return` and `break`. There is a
# situation that orphaned for `break` but not orphaned for `return`.
#
#     def m1(&b) b.call end; def m2(); m1 { return } end; m2 # ok
#     def m1(&b) b.call end; def m2(); m1 { break } end; m2 # ok
#
#     def m1(&b) b end; def m2(); m1 { return }.call end; m2 # ok
#     def m1(&b) b end; def m2(); m1 { break }.call end; m2 # LocalJumpError
#
#     def m1(&b) b end; def m2(); m1 { return } end; m2.call # LocalJumpError
#     def m1(&b) b end; def m2(); m1 { break } end; m2.call # LocalJumpError
#
# Since `return` and `break` exits the block itself in lambdas, lambdas cannot
# be orphaned.
#
# ## Numbered parameters
#
# Numbered parameters are implicitly defined block parameters intended to
# simplify writing short blocks:
#
#     # Explicit parameter:
#     %w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE
#     (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25]
#
#     # Implicit parameter:
#     %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
#     (1..5).map { _1**2 } # => [1, 4, 9, 16, 25]
#
# Parameter names from `_1` to `_9` are supported:
#
#     [10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 }
#     # => [120, 150, 180]
#
# Though, it is advised to resort to them wisely, probably limiting yourself to
# `_1` and `_2`, and to one-line blocks.
#
# Numbered parameters can't be used together with explicitly named ones:
#
#     [10, 20, 30].map { |x| _1**2 }
#     # SyntaxError (ordinary parameter is defined)
#
# To avoid conflicts, naming local variables or method arguments `_1`, `_2` and
# so on, causes a warning.
#
#     _1 = 'test'
#     # warning: `_1' is reserved as numbered parameter
#
# Using implicit numbered parameters affects block's arity:
#
#     p = proc { _1 + _2 }
#     l = lambda { _1 + _2 }
#     p.parameters     # => [[:opt, :_1], [:opt, :_2]]
#     p.arity          # => 2
#     l.parameters     # => [[:req, :_1], [:req, :_2]]
#     l.arity          # => 2
#
# Blocks with numbered parameters can't be nested:
#
#     %w[test me].each { _1.each_char { p _1 } }
#     # SyntaxError (numbered parameter is already used in outer block here)
#     # %w[test me].each { _1.each_char { p _1 } }
#     #                    ^~
#
# Numbered parameters were introduced in Ruby 2.7.
#
class Proc < Object
  def clone: () -> self

  # <!--
  #   rdoc-file=proc.c
  #   - prc.arity -> integer
  # -->
  # Returns the number of mandatory arguments. If the block is declared to take no
  # arguments, returns 0. If the block is known to take exactly n arguments,
  # returns n. If the block has optional arguments, returns -n-1, where n is the
  # number of mandatory arguments, with the exception for blocks that are not
  # lambdas and have only a finite number of optional arguments; in this latter
  # case, returns n. Keyword arguments will be considered as a single additional
  # argument, that argument being mandatory if any keyword argument is mandatory.
  # A #proc with no argument declarations is the same as a block declaring `||` as
  # its arguments.
  #
  #     proc {}.arity                  #=>  0
  #     proc { || }.arity              #=>  0
  #     proc { |a| }.arity             #=>  1
  #     proc { |a, b| }.arity          #=>  2
  #     proc { |a, b, c| }.arity       #=>  3
  #     proc { |*a| }.arity            #=> -1
  #     proc { |a, *b| }.arity         #=> -2
  #     proc { |a, *b, c| }.arity      #=> -3
  #     proc { |x:, y:, z:0| }.arity   #=>  1
  #     proc { |*a, x:, y:0| }.arity   #=> -2
  #
  #     proc   { |a=0| }.arity         #=>  0
  #     lambda { |a=0| }.arity         #=> -1
  #     proc   { |a=0, b| }.arity      #=>  1
  #     lambda { |a=0, b| }.arity      #=> -2
  #     proc   { |a=0, b=0| }.arity    #=>  0
  #     lambda { |a=0, b=0| }.arity    #=> -1
  #     proc   { |a, b=0| }.arity      #=>  1
  #     lambda { |a, b=0| }.arity      #=> -2
  #     proc   { |(a, b), c=0| }.arity #=>  1
  #     lambda { |(a, b), c=0| }.arity #=> -2
  #     proc   { |a, x:0, y:0| }.arity #=>  1
  #     lambda { |a, x:0, y:0| }.arity #=> -2
  #
  def arity: () -> Integer

  # <!--
  #   rdoc-file=proc.c
  #   - prc.binding    -> binding
  # -->
  # Returns the binding associated with *prc*.
  #
  #     def fred(param)
  #       proc {}
  #     end
  #
  #     b = fred(99)
  #     eval("param", b.binding)   #=> 99
  #
  def binding: () -> Binding

  # <!--
  #   rdoc-file=proc.c
  #   - prc.call(params,...)   -> obj
  #   - prc[params,...]        -> obj
  #   - prc.(params,...)       -> obj
  #   - prc.yield(params,...)  -> obj
  # -->
  # Invokes the block, setting the block's parameters to the values in *params*
  # using something close to method calling semantics. Returns the value of the
  # last expression evaluated in the block.
  #
  #     a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
  #     a_proc.call(9, 1, 2, 3)    #=> [9, 18, 27]
  #     a_proc[9, 1, 2, 3]         #=> [9, 18, 27]
  #     a_proc.(9, 1, 2, 3)        #=> [9, 18, 27]
  #     a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]
  #
  # Note that `prc.()` invokes `prc.call()` with the parameters given.  It's
  # syntactic sugar to hide "call".
  #
  # For procs created using #lambda or `->()` an error is generated if the wrong
  # number of parameters are passed to the proc.  For procs created using Proc.new
  # or Kernel.proc, extra parameters are silently discarded and missing parameters
  # are set to `nil`.
  #
  #     a_proc = proc {|a,b| [a,b] }
  #     a_proc.call(1)   #=> [1, nil]
  #
  #     a_proc = lambda {|a,b| [a,b] }
  #     a_proc.call(1)   # ArgumentError: wrong number of arguments (given 1, expected 2)
  #
  # See also Proc#lambda?.
  #
  def call: (*untyped arg0) -> untyped

  # <!-- rdoc-file=proc.c -->
  # Invokes the block, setting the block's parameters to the values in *params*
  # using something close to method calling semantics. Returns the value of the
  # last expression evaluated in the block.
  #
  #     a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
  #     a_proc.call(9, 1, 2, 3)    #=> [9, 18, 27]
  #     a_proc[9, 1, 2, 3]         #=> [9, 18, 27]
  #     a_proc.(9, 1, 2, 3)        #=> [9, 18, 27]
  #     a_proc.yield(9, 1, 2, 3)   #=> [9, 18, 27]
  #
  # Note that `prc.()` invokes `prc.call()` with the parameters given.  It's
  # syntactic sugar to hide "call".
  #
  # For procs created using #lambda or `->()` an error is generated if the wrong
  # number of parameters are passed to the proc.  For procs created using Proc.new
  # or Kernel.proc, extra parameters are silently discarded and missing parameters
  # are set to `nil`.
  #
  #     a_proc = proc {|a,b| [a,b] }
  #     a_proc.call(1)   #=> [1, nil]
  #
  #     a_proc = lambda {|a,b| [a,b] }
  #     a_proc.call(1)   # ArgumentError: wrong number of arguments (given 1, expected 2)
  #
  # See also Proc#lambda?.
  #
  def []: (*untyped arg0) -> untyped

  # <!--
  #   rdoc-file=proc.c
  #   - prc.curry         -> a_proc
  #   - prc.curry(arity)  -> a_proc
  # -->
  # Returns a curried proc. If the optional *arity* argument is given, it
  # determines the number of arguments. A curried proc receives some arguments. If
  # a sufficient number of arguments are supplied, it passes the supplied
  # arguments to the original proc and returns the result. Otherwise, returns
  # another curried proc that takes the rest of arguments.
  #
  # The optional *arity* argument should be supplied when currying procs with
  # variable arguments to determine how many arguments are needed before the proc
  # is called.
  #
  #     b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
  #     p b.curry[1][2][3]           #=> 6
  #     p b.curry[1, 2][3, 4]        #=> 6
  #     p b.curry(5)[1][2][3][4][5]  #=> 6
  #     p b.curry(5)[1, 2][3, 4][5]  #=> 6
  #     p b.curry(1)[1]              #=> 1
  #
  #     b = proc {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
  #     p b.curry[1][2][3]           #=> 6
  #     p b.curry[1, 2][3, 4]        #=> 10
  #     p b.curry(5)[1][2][3][4][5]  #=> 15
  #     p b.curry(5)[1, 2][3, 4][5]  #=> 15
  #     p b.curry(1)[1]              #=> 1
  #
  #     b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
  #     p b.curry[1][2][3]           #=> 6
  #     p b.curry[1, 2][3, 4]        #=> wrong number of arguments (given 4, expected 3)
  #     p b.curry(5)                 #=> wrong number of arguments (given 5, expected 3)
  #     p b.curry(1)                 #=> wrong number of arguments (given 1, expected 3)
  #
  #     b = lambda {|x, y, z, *w| (x||0) + (y||0) + (z||0) + w.inject(0, &:+) }
  #     p b.curry[1][2][3]           #=> 6
  #     p b.curry[1, 2][3, 4]        #=> 10
  #     p b.curry(5)[1][2][3][4][5]  #=> 15
  #     p b.curry(5)[1, 2][3, 4][5]  #=> 15
  #     p b.curry(1)                 #=> wrong number of arguments (given 1, expected 3)
  #
  #     b = proc { :foo }
  #     p b.curry[]                  #=> :foo
  #
  def curry: (?_ToInt arity) -> Proc

  # <!--
  #   rdoc-file=proc.c
  #   - prc.hash   ->  integer
  # -->
  # Returns a hash value corresponding to proc body.
  #
  # See also Object#hash.
  #
  def hash: () -> Integer

  # <!--
  #   rdoc-file=proc.c
  #   - Proc.new {|...| block } -> a_proc
  # -->
  # Creates a new Proc object, bound to the current context.
  #
  #     proc = Proc.new { "hello" }
  #     proc.call   #=> "hello"
  #
  # Raises ArgumentError if called without a block.
  #
  #     Proc.new    #=> ArgumentError
  #
  def initialize: () { (*untyped) -> untyped } -> void

  # <!--
  #   rdoc-file=proc.c
  #   - prc.lambda? -> true or false
  # -->
  # Returns `true` if a Proc object is lambda. `false` if non-lambda.
  #
  # The lambda-ness affects argument handling and the behavior of `return` and
  # `break`.
  #
  # A Proc object generated by `proc` ignores extra arguments.
  #
  #     proc {|a,b| [a,b] }.call(1,2,3)    #=> [1,2]
  #
  # It provides `nil` for missing arguments.
  #
  #     proc {|a,b| [a,b] }.call(1)        #=> [1,nil]
  #
  # It expands a single array argument.
  #
  #     proc {|a,b| [a,b] }.call([1,2])    #=> [1,2]
  #
  # A Proc object generated by `lambda` doesn't have such tricks.
  #
  #     lambda {|a,b| [a,b] }.call(1,2,3)  #=> ArgumentError
  #     lambda {|a,b| [a,b] }.call(1)      #=> ArgumentError
  #     lambda {|a,b| [a,b] }.call([1,2])  #=> ArgumentError
  #
  # Proc#lambda? is a predicate for the tricks. It returns `true` if no tricks
  # apply.
  #
  #     lambda {}.lambda?            #=> true
  #     proc {}.lambda?              #=> false
  #
  # Proc.new is the same as `proc`.
  #
  #     Proc.new {}.lambda?          #=> false
  #
  # `lambda`, `proc` and Proc.new preserve the tricks of a Proc object given by
  # `&` argument.
  #
  #     lambda(&lambda {}).lambda?   #=> true
  #     proc(&lambda {}).lambda?     #=> true
  #     Proc.new(&lambda {}).lambda? #=> true
  #
  #     lambda(&proc {}).lambda?     #=> false
  #     proc(&proc {}).lambda?       #=> false
  #     Proc.new(&proc {}).lambda?   #=> false
  #
  # A Proc object generated by `&` argument has the tricks
  #
  #     def n(&b) b.lambda? end
  #     n {}                         #=> false
  #
  # The `&` argument preserves the tricks if a Proc object is given by `&`
  # argument.
  #
  #     n(&lambda {})                #=> true
  #     n(&proc {})                  #=> false
  #     n(&Proc.new {})              #=> false
  #
  # A Proc object converted from a method has no tricks.
  #
  #     def m() end
  #     method(:m).to_proc.lambda?   #=> true
  #
  #     n(&method(:m))               #=> true
  #     n(&method(:m).to_proc)       #=> true
  #
  # `define_method` is treated the same as method definition. The defined method
  # has no tricks.
  #
  #     class C
  #       define_method(:d) {}
  #     end
  #     C.new.d(1,2)       #=> ArgumentError
  #     C.new.method(:d).to_proc.lambda?   #=> true
  #
  # `define_method` always defines a method without the tricks, even if a
  # non-lambda Proc object is given. This is the only exception for which the
  # tricks are not preserved.
  #
  #     class C
  #       define_method(:e, &proc {})
  #     end
  #     C.new.e(1,2)       #=> ArgumentError
  #     C.new.method(:e).to_proc.lambda?   #=> true
  #
  # This exception ensures that methods never have tricks and makes it easy to
  # have wrappers to define methods that behave as usual.
  #
  #     class C
  #       def self.def2(name, &body)
  #         define_method(name, &body)
  #       end
  #
  #       def2(:f) {}
  #     end
  #     C.new.f(1,2)       #=> ArgumentError
  #
  # The wrapper *def2* defines a method which has no tricks.
  #
  def lambda?: () -> bool

  # <!--
  #   rdoc-file=proc.c
  #   - prc.parameters(lambda: nil)  -> array
  # -->
  # Returns the parameter information of this proc.  If the lambda keyword is
  # provided and not nil, treats the proc as a lambda if true and as a non-lambda
  # if false.
  #
  #     prc = proc{|x, y=42, *other|}
  #     prc.parameters  #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
  #     prc = lambda{|x, y=42, *other|}
  #     prc.parameters  #=> [[:req, :x], [:opt, :y], [:rest, :other]]
  #     prc = proc{|x, y=42, *other|}
  #     prc.parameters(lambda: true)  #=> [[:req, :x], [:opt, :y], [:rest, :other]]
  #     prc = lambda{|x, y=42, *other|}
  #     prc.parameters(lambda: false) #=> [[:opt, :x], [:opt, :y], [:rest, :other]]
  #
  def parameters: (lambda: boolish) -> ::Array[[ Symbol, Symbol ]]

  # <!--
  #   rdoc-file=proc.c
  #   - prc.source_location  -> [String, Integer]
  # -->
  # Returns the Ruby source filename and line number containing this proc or `nil`
  # if this proc was not defined in Ruby (i.e. native).
  #
  def source_location: () -> [ String, Integer ]

  # <!--
  #   rdoc-file=proc.c
  #   - prc.to_proc -> proc
  # -->
  # Part of the protocol for converting objects to Proc objects. Instances of
  # class Proc simply return themselves.
  #
  def to_proc: () -> self

  # <!--
  #   rdoc-file=proc.c
  #   - prc.to_s   -> string
  # -->
  # Returns the unique identifier for this proc, along with an indication of where
  # the proc was defined.
  #
  def to_s: () -> String

  # <!-- rdoc-file=proc.c -->
  # Returns the unique identifier for this proc, along with an indication of where
  # the proc was defined.
  #
  def inspect: () -> String
end
