Ruby 和 StackOverflow 新手在这里使用 Ruby 进行工作,并遇到了我的第一个主要障碍。我真的很难理解 Procs 和 Lambdas。这是我正在使用的代码。
def procBuilder(message)
Proc.new{ puts message; return}
end
def test
puts "entering method"
p = procBuilder("entering proc")
p.call
puts "exit method"
end
test
Run Code Online (Sandbox Code Playgroud)
按照设计,这是为了抛出 LocalJumpError,但我不明白为什么。如果我不得不猜测这是做什么的,我猜它最初会在 p = procBuilder("entering proc") 运行时打印“entering proc”,然后在 p.call 上抛出错误,因为 p.call 没有传递任何字符串,但显然我错过了这两行之间发生的一些关键事情。我也不完全理解为什么这适用于 lambda 而不是 proc,但我想理解错误也能解决该问题。
预先感谢您的澄清
我写了以下代码:
class Actions
def initialize
@people = []
@commands = {
"ADD" => ->(name){@people << name },
"REMOVE" => ->(n=0){ puts "Goodbye" },
"OTHER" => ->(n=0){puts "Do Nothing" }
}
end
def run_command(cmd,*param)
@commands[cmd].call param if @commands.key?(cmd)
end
def people
@people
end
end
act = Actions.new
act.run_command('ADD','joe')
act.run_command('ADD','jack')
puts act.people
Run Code Online (Sandbox Code Playgroud)
但是,当@commands哈希是一个类变量时,这是有效的,哈希中的代码不知道@people数组.
如何使@commands哈希成为类变量并仍然能够访问特定的对象实例变量?
其示例中的date_validator具有注释:
Using Proc.new prevents production cache issues
Run Code Online (Sandbox Code Playgroud)
这是否意味着,我的代码中的任何地方,我使用当前时间相关的方法(Time.now,1.day.since(Time.zone.now)等)我应该用Proc.new {}包围它们?
我不完全理解这一点,因为更换
time_now = Time.now.utc
Run Code Online (Sandbox Code Playgroud)
同
time_now = Proc.new { Time.now.utc }
Run Code Online (Sandbox Code Playgroud)
对我来说没有意义(返回新类型的对象).
那么,问题是,何时以及如何使用Proc.new与时间相关的方法?这仍然适用于最新版本的Ruby(1.92)和Rails(3.1)吗?
想从TCL专业人士那里获得最佳实践的建议.
假设您要使用proc构建包含特定数据的列表.现在哪种方式最好?
proc processList { myList } {
upvar $myList list_
#append necessary data into list_
}
proc returnList {} {
set list_ {}
#append necessary data into list_
return $list_
}
set list1 {}
processList list1
set list2 [returnList ]
Run Code Online (Sandbox Code Playgroud)
推荐哪种做法?
编辑:对不起,我无法理解回答这个问题的人的共识(和解释).
我在Project Euler上解决了一些问题,并且我提到我总是在proc函数中包含短方法.我问自己" 为什么? ".答案是" 我不知道.也许是因为它很短? ".
那么proc函数对普通方法有什么好处,除了它们很短:)
# Proc
is_prime = proc{|number| !((number%2 == 0) || (3..Math.sqrt(number).to_i).step(2).any?{|n| (number%n).zero?})}
# Ordinary method
def is_prime(number)
!((number%2 == 0) || (3..Math.sqrt(number).to_i).step(2).any?{|n| (number%n).zero?})
end
Run Code Online (Sandbox Code Playgroud) 我昨天在这里提出的问题的答案是以下一段Ruby代码:
def overlap?(r1,r2)
r1.include?(r2.begin) || r2.include?(r1.begin)
end
def any_overlap?(ranges)
ranges.sort_by(&:begin).each_cons(2).any? do |r1,r2|
overlap?(r1, r2)
end
end
Run Code Online (Sandbox Code Playgroud)
我明白了each_cons,但奇怪的&:begin记法是什么?救我脱离语法地狱!
谢谢!
我知道这段代码可能不太正确:
def print_string(&str)
puts str
end
print_string{"Abder-Rahman"}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行它时,这就是我得到的:
#<Proc:0x03e25d98@r.rb:5>
Run Code Online (Sandbox Code Playgroud)
这个输出是什么?
我想制作几个具有相同参数的对象,所以我尝试将它们存储在返回它们的proc中.但是解释器将返回结果评估为一个参数,而不是几个参数.我的过程是:
proc element_param {} {
return "-filled 1\
-visible 1\
-linewidth 1\
-linecolor yellow\
-fillcolor yellow\
-relief roundraised\
-linewidth 2"
}
Run Code Online (Sandbox Code Playgroud)
我用它:
$this/zinc add rectangle 1 [list "100" "100" "200" "200"] [element_param]
Run Code Online (Sandbox Code Playgroud)
如何将它们转换为几个不同的参数?
s = Proc.new {|x|x*2}
puts s.call(5)
-> 10
def foo(&a)
a.call(5)
end
puts "test foo:"
foo(s)
Run Code Online (Sandbox Code Playgroud)
当我尝试调用上面的proc时,我得到:
foo: wrong number of arguments (1 for 0) (ArgumentError)
Run Code Online (Sandbox Code Playgroud)
我的期望是,如果使用此类签名定义方法,我可以将proc传递给方法:
def foo(&a)
Run Code Online (Sandbox Code Playgroud)
然后我可以像这样执行proc insiide foo:
a.call(5)
Run Code Online (Sandbox Code Playgroud) 我正在遍历一个对象图,并希望传递一个块,该块将从一个方法运行在结构的每个节点上 - 让我们称之为访问.
在顶部,我将调用一个块,我想委托初始调用访问根对象以访问其他对象.我可以使用&last_parameter_name将块解压缩到本地proc中 - 但是如何在我委托的调用中将proc转回块?
这是一个简化的例子,我先调用(...)并希望将块委托给我的第二个调用(...)
def second(&block) # ... ? ...
block.call(72)
end
def first(&block)
puts block.class # okay - now I have the Proc version
puts 'pre-doit'
block.call(42)
puts 'post-doit'
second( ... ? ...) # how do I pass the block through here?
end
first {|x| puts x*x}
Run Code Online (Sandbox Code Playgroud)
注意:我需要在first()和second()上使用相同的约定 - 即它们需要采用相同的东西.
阅读并尝试了答案后,我想出了一个更全面,更有效的例子:
class X
def visit(&x)
x.call(50)
end
end
class Y < X
def visit(&x)
x.call(100)
X.new.visit(&x) …Run Code Online (Sandbox Code Playgroud)