Ruby 请问 Ruby 中子方法如何访问父方法中的局部变量,类似 JavaScript 的闭包?

fenginsc · 2020年04月16日 · 最后由 alantsui 回复于 2020年04月29日 · 3773 次阅读
def method1()
    param = []
    def method2(x)
        param.push(x)
    end
    return method2
end
f = method1
f(10)

这样会报错 undefined local variable or method `param' for main:Object (NameError) 请问有什么解决方法吗?还是说 ruby 中必须用类来在外面包装一层?不能直接定义方法吗类似 javascript

关键字:作用域门

想实现闭包请使用 Proc

def method1()
  param = []
  method2 = proc { |x| param.push(x) }
  return method2
end
f = method1
f.call(10)
param = []
define_method(:method1) do
  define_method(:method2) do |x|
      param.push(x)
  end
  return method(:method2)
end

f = method1
f.(10)

p param

spike76 回复

好的,谢谢,似乎 ruby 中 def 定义的方法不能直接访问其他作用域中的局部变量

piecehealth 回复

谢谢,学习了,xxx.call(10) 可以写成 xxx.(10) 这是什么语法

fenginsc 回复

xxx.call(10)可以写成xxx.(10)或者xxx[10],都是语法糖,用多了讨人厌

楼主的函数嵌套写法,一看就是 python 过来的。 我就是受不了这样代码,才弃 python 而去。(还有就是 python 没有 end,感觉一个鞋子始终没落地,看着糟心)

我也是初学 Ruby,但 Ruby 似乎一般不会直接 return 另一个方法,而是 return 一个 proc 或 lambda。 二楼和三楼的写法都有问题:二楼的不能把 param 返回到最外,三楼的需要在方法外定义 param。 我试着写了一下: 用 lambda 代替 proc,就可以 return param; 把 param 作为参数传递给 method1,就解决方法外定义 param 的问题。 应该满足楼主的需求了:

def method1(param)
  lambda { |x| param.push(x); return param }
end
method2 = method1([])
p method2.call(1)
p method2.call(5)
p method2.call(10)
p method2.call(15)

# >[1]
# >[1, 5]
# >[1, 5, 10]
# >[1, 5, 10, 15]

用 proc 也可以,但不要写 return,顺便简化掉 call:

def method1(param)
  proc { |x| param.push(x); param }
end
method2 = method1([])
p method2.(1)
p method2.(5)
p method2.(10)
p method2.(15)

alantsui 回复

三楼的需要在方法外定义 param

不需要,写里面也一样。

piecehealth 回复

确实,def_method 可以共享上下文的作用域。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号