在Ruby方法中,我应该创建proc还是方法?
我只是想问一下什么是正确的做法 我更喜欢使用procs,只是因为我认为在methods中定义方法有点不整洁,应该只在必要时进行。为了解决这个问题,我只需要使用procs 正确/更好的方法是什么?为什么?(除了proc访问在其自身之前定义的主方法变量的能力之外)在Ruby方法中,我应该创建proc还是方法?,ruby,methods,proc,Ruby,Methods,Proc,我只是想问一下什么是正确的做法 我更喜欢使用procs,只是因为我认为在methods中定义方法有点不整洁,应该只在必要时进行。为了解决这个问题,我只需要使用procs 正确/更好的方法是什么?为什么?(除了proc访问在其自身之前定义的主方法变量的能力之外) 在方法中定义方法是Ruby的一个特性,它可能有自己的用途。但有些事情告诉我,你问的是一个非常高级的问题,而你仍然是一个初学者。你知道默认定义是什么吗?如果没有 进程在Ruby中非常重要,但是新手倾向于使用它们,而不是在适当的对象中定义方法
在方法中定义方法是Ruby的一个特性,它可能有自己的用途。但有些事情告诉我,你问的是一个非常高级的问题,而你仍然是一个初学者。你知道默认定义是什么吗?如果没有 进程在Ruby中非常重要,但是新手倾向于使用它们,而不是在适当的对象中定义方法,这正是我从你的问题中得到的味道。在Ruby系列的OO语言中,通常的做法是在对象上定义方法:
class Foo
def bar *params
# do something with params
end
end
因为您不理解在方法中定义方法的含义,所以在接下来的6个月内不要这样做。一旦您了解了对象,就可以再次开始尝试这个非常高级的功能
附件:
既然您演示了intrest,那么让我向您演示在顶级使用def
中的def
是一件令人不快的事情。通常,当您在某个类上定义方法而不进行进一步修饰时,它将成为该类的公共实例方法:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
在def
中使用def
时,内部def的定义对象将是X
:
class X
def bar
def baz
"baz"
end
"bar"
end
end
执行上述代码时,实例方法#bar将在X上定义:
X.instance_methods.include? :bar
#=> true
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
但是#巴兹还没有:
X.instance_methods.include? :baz
#=> false
只有在调用#bar
至少一次后,该方法才会在X上定义:
X.instance_methods.include? :bar
#=> true
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
现在我想请你们理解刚才发生了多么可怕的事情:一个实例修改了它的母类。那是违法行为。这违反了OO设计的基本原则,我甚至不确定它是否有名字。这项技术对于模糊编码竞争非常有用,但在生产中,这是禁忌。Ruby给了你打破禁忌的自由,给了你自缢的绳索,但在任何正常情况下你都不会这么做
那么,还有什么比类定义中的def
内部的def
更糟糕呢?答案是,在顶层的def
内部有一个def
。让我告诉你为什么。通常,当您在顶级使用def
定义方法时,默认的定义对象是Object
,但顶级定义成为Object的私有实例方法。这是为了防止顶级def
s的意外后果,因为几乎所有Ruby对象都继承自Object
。例如,如果您定义:
class Object
def foo; "foo" end
end
现在,所有对象都将响应foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
当我们在顶层定义方法时,我们通常只打算在顶层使用该方法,而不希望每个对象都继承它。因此,顶级def
s变为私有:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
现在我们在顶层使用def
:
def hello; "hello" end
def bar
def baz; "baz" end
"bar"
end
我们可以看到,方法#hello
is并没有成为对象的实例方法:
Object.instance_methods.include? :hello
#=> false
神秘的是,它成了它的私人方法:
Object.private_instance_methods.include? :hello
#=> true
这样,我们就避免了为每个对象定义#hello
方法的意外后果。但是遗产就在那里。错误消息已更改:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
我们可以通过#send
强制调用该方法:
1.send :hello
#=> "hello"
hello
#=> "hello"
奇怪的是,在顶层,我们可以调用这个私有方法,而无需#send
:
1.send :hello
#=> "hello"
hello
#=> "hello"
现在,在顶层执行def
中的def
时会发生什么情况:
def hello; "hello" end
def bar
def baz; "baz" end
"bar"
end
您可以按照预期的方式定义私有实例方法Object#bar
。但是当你调用它时,唉,顶级魔法不再起作用,一个公共方法Object#baz
被定义:
bar #=> "bar"
这样,不仅是顶层,而且每个Ruby对象都被您的#baz
方法污染了:
1.baz #=> "baz"
Class.baz #=> "baz"
这就是为什么我告诉你不要使用这个成语,直到你从无意识的无能发展到有意识的无能。我建议您阅读更多信息。如果您想使用sub_func从其他方法的调用中封装它,您可以使用类将函数和sub_func分组在一起,并将sub_func设为私有。否则,如果要将此函数作为参数进一步传递,可以将其声明为lamda
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
不清楚您的具体用例是什么,但我肯定会选择procs或lambdas。动态定义proc或lambda时,开销较小,它们是可以通过的,因此如果需要,您可以返回它们,并且可以在函数外部使用它们
使用“def”将该方法公开为当前方法范围之外的实例方法(因此在包含类中,在您的情况下可能是Object
)。这可能是你想要的,也可能不是。如果要使用仅在本地作用域中可用的匿名函数,请使用lambda
还有Proc vs Lambda:我通常更喜欢使用Lambda,因为它们的行为更“可预测”,这意味着:正如您所期望的那样(检查传递的变量,只返回Lambda的返回,Proc从被调用的范围返回)。但是从你的例子很难推断出什么是适用的。我认为关键的区别在于:lambas是可以传递的,因此表现得更理智一点。如果这不是您的用例,请使用Proc
:)(一个不同点)。对您来说,听起来居高临下的只是我想带您去。另外,当你实际指的是一种方法时,不要使用理论术语“函数”,这两者在术语上有细微的区别。def
中的def
将在默认定义对象上定义。在顶层,默认的definee是Object,但是