我正在尝试将Ruby 1.9.1用于嵌入式脚本语言,以便"最终用户"代码在Ruby块中编写.这个问题的一个问题是我希望用户能够在块中使用'return'关键字,因此他们不需要担心隐式返回值.考虑到这一点,这是我希望能够做到的事情:
def thing(*args, &block)
value = block.call
puts "value=#{value}"
end
thing {
return 6 * 7
}
Run Code Online (Sandbox Code Playgroud)
如果我在上面的例子中使用'return',我会得到一个LocalJumpError.我知道这是因为有问题的块是Proc而不是lambda.如果我删除'return',代码就可以工作,但我真的更喜欢在这种情况下使用'return'.这可能吗?我已经尝试将块转换为lambda,但结果是一样的.
def foo
f = Proc.new { return "return from foo from inside proc" }
f.call # control leaves foo here
return "return from foo"
end
def bar
b = Proc.new { "return from bar from inside proc" }
b.call # control leaves bar here
return "return from bar"
end
puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"
Run Code Online (Sandbox Code Playgroud)
我认为这个return
关键字在Ruby中是可选的,return
无论你是否请求它,你总是在想.鉴于这种情况,我觉得很奇怪,foo
并bar
有不同的输出由事实来确定foo
包含一个明确的return
在Proc …
可能重复:
Ruby中的proc和lambda有什么区别?
运行此Ruby
代码时:
def func_one
proc_new = Proc.new {return "123"}
proc_new.call
return "456"
end
def func_two
lambda_new = lambda {return "123"}
lambda_new.call
return "456"
end
puts "The result of running func_one is " + func_one
puts ""
puts "The result of running func_two is " + func_two
Run Code Online (Sandbox Code Playgroud)
我得到的结果如下:
The result of running func_one is 123
The result of running func_two is 456
Run Code Online (Sandbox Code Playgroud)
至于func_two
,第一个 的价值在哪里return
,也就是说,123
?
谢谢.
在Ruby中,Proc.new { 'waffles' }
和之间有什么区别proc { 'waffles' }
吗?我发现很少提到第二种语法.
从测试使用irb
,我没有发现任何明显的差异.第一个是第二个语法糖吗?
Joe Van Dyk 询问了Ruby邮件列表:
嗨,
在Ruby中,我猜你不能编组一个lambda/proc对象,对吗?在lisp或其他语言中这可能吗?
我想做什么:
l = lamda { ... }
Bj.submit "/path/to/ruby/program", :stdin => Marshal.dump(l)
Run Code Online (Sandbox Code Playgroud)
所以,我正在向BackgroundJob发送一个lambda对象,该对象包含要执行的操作的上下文/代码.但是,猜测这是不可能的.我最终编组了一个普通的ruby对象,其中包含程序运行后要执行的操作的说明.
乔
我是编程的新手,而ruby是我第一次真正的编程.我得到了块,但是procs看起来像一个简单的方法/功能概念 - 为什么要使用它们?为什么不直接使用方法呢?
谢谢你的帮助.
我希望能够在我的Ruby代码中编写lambda/Proc,将其序列化以便我可以将其写入磁盘,然后再执行lambda.有点像......
x = 40
f = lambda { |y| x + y }
save_for_later(f)
Run Code Online (Sandbox Code Playgroud)
后来,在另一个Ruby解释器的运行中,我想能够说...
f = load_from_before
z = f.call(2)
z.should == 42
Run Code Online (Sandbox Code Playgroud)
Marshal.dump不适用于Procs.我知道Perl有Data :: Dump :: Streamer,而在Lisp中这是微不足道的.但有没有办法在Ruby中做到这一点?换句话说,实施什么?save
_
for_
later
编辑:我的答案很好,但它不会关闭自由变量(如x
)并将它们与lambda序列化.所以在我的例子中......
x = 40
s = save_for_later { |y| x + y }
# => "lambda { |y|\n (x + y)\n}"
Run Code Online (Sandbox Code Playgroud)
...字符串输出不包含的定义x
.是否有一个解决方案考虑到这一点,可能是通过序列化符号表?你可以在Ruby中访问它吗?
编辑2:我更新了我的答案,以结合序列化局部变量.这似乎可以接受.
是否有可能将proc风味的Proc转换为lambda风味的Proc?
有点惊讶,这不起作用,至少在1.9.2:
my_proc = proc {|x| x}
my_lambda = lambda &p
my_lambda.lambda? # => false!
Run Code Online (Sandbox Code Playgroud) 在RoR的所有教程中,我看到编码器选择使用Proc.new的实例,看起来它既不必要又相当缺乏吸引力.
例如,这里是放置在模型中的回调,一个使用Proc.new,另一个可能做同样的事情:
class Order < ActiveRecord::Base
before_save :normalize_card_number,
:if => Proc.new { |order| order.paid_with_card? }
end
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => "paid_with_card?"
end
Run Code Online (Sandbox Code Playgroud)
那有什么区别?为什么要使用Proc?他们俩都不叫"paid_with_card"吗?方法?
提前致谢
我最近尝试做类似于此的事情:
a = "some string"
b = Proc.new{ upcase }
a.instance_eval b
Run Code Online (Sandbox Code Playgroud)
这给出了错误:
TypeError:无法将Proc转换为String
但这有效:
def b(&block)
"some string".instance_eval &block
end
b{ upcase }
Run Code Online (Sandbox Code Playgroud)
进一步了解这种方法:
def b(&block)
"some string".instance_eval block
end
Run Code Online (Sandbox Code Playgroud)
产生相同的Proc to String
错误.
所以...我对块的理解是它们只是触发器.但是这个&
&符号显然有一些特别之处......
谁可以给我解释一下这个?是否有可能将正常的proc转换成&block
对象的特殊之处?
刚刚想出了我的第二个问题,在前面加了一个&
...这很容易,但这是真的在做什么?