如何从外部获得给定lambda的参数值,而不明确返回其“绑定”?

发布于 2025-01-25 10:56:14 字数 722 浏览 2 评论 0原文

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

我可以通过显式使lambda返回绑定,然后从此绑定中获取值:

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主体内部运行任何代码而获得这些值?即我可以做

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

,仍然可以从lambda外部以某种方式获得a a b 值吗?

(提供上下文 - 我问是因为我对于在此阶段自动分配的IVAR/读者实例化对象。

I want to be able to run a lambda and get at its argument values (the values of a and b below).

I can achieve this by explicitly having the lambda return a binding, and then getting the values out of this 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

Is it possible to get these values without running any code inside the lambda body? I.e. could I do

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

and still get the a and b values somehow from outside the lambda?

(To provide context – I'm asking because I've experimented with this as a shortcut syntax for instantiating objects with ivars/readers automatically assigned. At this stage I'm more curious about what's possible than what is advisable – so I invite any solutions, advisable or not…)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夢归不見 2025-02-01 10:56:14

我不确定这是多么可取,但是您可以使用 TracePoint 类: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)}"

这不是一个完美的解决方案,如果一个参数默认值之一输入一个块,则将失败(由于在:b_call事件之前对lambda发射默认值是在评估默认值的),但是可以在跟踪点处理程序中使用一些其他过滤修复。

I'm not sure how advisable this is, but you can use the TracePoint class with the :b_call event to grab the lambda's binding:

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)}"

This is not a perfect solution and will fail if one of the argument default values enters a block on it's own (since the default values are evaluated before the :b_call event is fired for the lambda), but that could be fixed with some additional filtering inside the TracePoint handler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文