如何从外部获取给定 lambda 的参数值,而不显式返回其“绑定”?

How can I get argument values for a given lambda from the outside, without explicitly returning its `binding`?

我希望能够 运行 lambda 并获取其参数值(下面 ab 的值)。

我可以通过明确地让 lambda return 成为 binding,然后从此绑定中获取值来实现此目的:

fun = lambda { |a, b = Time.now| binding }
fun_binding = fun.call(123)
puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"
# Outputs e.g.: A is 123 and B is 2022-04-29 20:14:07 +0200

是否可以在没有 运行lambda 体内任何代码的情况下获得这些值? IE。我能做吗

fun = lambda { |a, b = Time.now| }
fun.call(123)

并且仍然以某种方式从 lambda 外部获取 ab 值?

(提供上下文——我问是因为我已经 experimented 将此作为实例化对象的快捷语法 ivars/readers 自动分配。在这个阶段我更好奇什么是可能的而不是什么是可取的——所以我邀请任何解决方案,无论是否明智……)

我不确定这是否明智,但您可以使用 TracePoint class 和 :b_call 事件来获取 lambda 的绑定:

fun = lambda { |a, b = Time.now| }

fun_binding = nil
TracePoint.trace(:b_call) do |tp|
    fun_binding = tp.binding
    tp.disable
end

fun.call(123)

puts "A is #{fun_binding.local_variable_get(:a)} and B is #{fun_binding.local_variable_get(:b)}"

这不是一个完美的解决方案,如果其中一个参数默认值自己进入一个块,将会失败(因为默认值是在为 lambda 触发 :b_call 事件之前评估的),但是这可以通过在 TracePoint 处理程序中进行一些额外的过滤来解决。