File: //usr/lib/ruby/gems/3.2.0/gems/rbs-2.8.2/core/proc.rbs
# <!-- 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](doc/syntax/literals_rdoc.html#label-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.
#
# 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 -> array
# -->
# Returns the parameter information of this proc.
#
# prc = lambda{|x, y=42, *other|}
# prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
#
def parameters: () -> ::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