如何在 Ruby 中封送 lambda (Proc)?
Joe Van Dyk 询问 Ruby 邮件列表:
嗨,
在 Ruby 中,我猜你不能封送 lambda/proc 对象,对吧? 是 这在 Lisp 或其他语言中可能吗?
我想做什么:
l = lamda { ... }
Bj.submit "/path/to/ruby/program", :stdin => Marshal.dump(l)
因此,我向 BackgroundJob 发送一个 lambda 对象,其中包含 做什么的上下文/代码。 但是,我猜这是不可能的。 我 最终整理了一个包含指令的普通 ruby 对象 程序运行后要做什么。
乔
Joe Van Dyk asked the Ruby mailing list:
Hi,
In Ruby, I guess you can't marshal a lambda/proc object, right? Is
that possible in lisp or other languages?What I was trying to do:
l = lamda { ... }
Bj.submit "/path/to/ruby/program", :stdin => Marshal.dump(l)
So, I'm sending BackgroundJob a lambda object, which contains the
context/code for what to do. But, guess that wasn't possible. I
ended up marshaling a normal ruby object that contained instructions
for what to do after the program ran.Joe
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果proc被定义到一个文件中,你可以获取proc的文件位置然后将其序列化,然后在反序列化后使用该位置再次返回到proc
:
If proc is defined into a file, U can get the file location of proc then serialize it, then after deserialize use the location to get back to the proc again
after deserialize:
尝试 ruby2ruby
Try ruby2ruby
我发现 proc_to_ast 做得最好:https://github.com/joker1007/proc_to_ast。
在 ruby 2+ 中肯定有效,我已经为 ruby 1.9.3+ 兼容性创建了 PR( https://github.com/joker1007/proc_to_ast/pull/3)
I've found proc_to_ast to do the best job: https://github.com/joker1007/proc_to_ast.
Works for sure in ruby 2+, and I've created a PR for ruby 1.9.3+ compatibility(https://github.com/joker1007/proc_to_ast/pull/3)
如果您有兴趣使用 Ruby2Ruby 获取 Ruby 代码的字符串版本,您可能会喜欢 此线程。
If you're interested in getting a string version of Ruby code using Ruby2Ruby, you might like this thread.
曾几何时,这可以使用 ruby-internal gem (https://github.com/cout/ ruby-internal),eg:
有一些警告,但已经很多年了,我记不清细节了。 举个例子,如果一个变量在转储的绑定中是动态变量,而在重新绑定的绑定中是本地变量,我不确定会发生什么。 序列化 AST(在 MRI 上)或字节码(在 YARV 上)并非易事。
上面的代码适用于 YARV(最高 1.9.3)和 MRI(最高 1.8.7)。 没有理由不让它在 Ruby 2.x 上工作,只需付出少量的努力。
Once upon a time, this was possible using ruby-internal gem (https://github.com/cout/ruby-internal), e.g.:
There are some caveats, but it has been many years and I cannot remember the details. As an example, I'm not sure what happens if a variable is a dynvar in the binding where it is dumped and a local in the binding where it is re-bound. Serializing an AST (on MRI) or bytecode (on YARV) is non-trivial.
The above code works on YARV (up to 1.9.3) and MRI (up to 1.8.7). There's no reason why it cannot be made to work on Ruby 2.x, with a small amount of effort.
您无法封送 Lambda 或 Proc。 这是因为它们都被认为是闭包,这意味着它们围绕定义它们的内存封闭并可以引用它。 (为了编组它们,您必须编组它们在创建时可以访问的所有内存。)
正如 Gaius 指出的,您可以使用 ruby2ruby 来获取程序的字符串。 也就是说,您可以整理表示 ruby 代码的字符串,然后稍后重新评估它。
You cannot marshal a Lambda or Proc. This is because both of them are considered closures, which means they close around the memory on which they were defined and can reference it. (In order to marshal them you'd have to Marshal all of the memory they could access at the time they were created.)
As Gaius pointed out though, you can use ruby2ruby to get a hold of the string of the program. That is, you can marshal the string that represents the ruby code and then reevaluate it later.
你也可以只输入你的代码作为字符串:
然后用 eval 执行它
,它将返回一个 ruby lamda。
使用
%{}
格式转义字符串,但仅以不匹配的大括号结束。 即您可以像这样嵌套大括号%{ [] {} }
并且它仍然是封闭的。大多数文本语法荧光笔没有意识到这是一个字符串,因此仍然显示常规代码突出显示。
you could also just enter your code as a string:
then execute it with eval
which will return a ruby lamda.
using the
%{}
format escapes a string, but only closes on an unmatched brace. i.e. you can nest braces like this%{ [] {} }
and it's still enclosed.most text syntax highlighters don't realize this is a string, so still display regular code highlighting.