在许多情况下,有两种实现选择:闭包和可调用类.例如,
class F:
def __init__(self, op):
self.op = op
def __call__(self, arg1, arg2):
if (self.op == 'mult'):
return arg1 * arg2
if (self.op == 'add'):
return arg1 + arg2
raise InvalidOp(op)
f = F('add')
Run Code Online (Sandbox Code Playgroud)
要么
def F(op):
if op == 'or':
def f_(arg1, arg2):
return arg1 | arg2
return f_
if op == 'and':
def g_(arg1, arg2):
return arg1 & arg2
return g_
raise InvalidOp(op)
f = F('add')
Run Code Online (Sandbox Code Playgroud)
在任何一个方向上做出选择时应该考虑哪些因素?
我能想到两个:
似乎关闭总会有更好的表现(不能想到一个反例).
我认为有些情况下关闭不能完成工作(例如,如果其状态随时间变化).
我在这些方面是否正确?还能添加什么?
功能编程..就像经典(马克吐温的类型).在阅读另一篇关于SICP的文章时,人们在谈论闭包对思维的影响,我得到了提醒,我读过很久以前
关闭是穷人的对象对象是穷人的关闭
(不记得确切的来源,但它是程序员,或编程的禅,或编程的tau ...谷歌已经变得如此拥挤,不能去原始来源)
所以共同编程人员......你有什么看法......关闭你总是缺少的东西......或者只是一些语法糖,这是一个预处理器可以做到的!
想象一个简单的(组成)语言,其中的函数如下所示:
function f(a, b) = c + 42
where c = a * b
Run Code Online (Sandbox Code Playgroud)
(说它是Lisp的一个子集,包括'defun'和'let'.)
还想象它包含看起来像的不可变对象:
struct s(a, b, c = a * b)
Run Code Online (Sandbox Code Playgroud)
再次类比于Lisp(这次是一个超集),假设像这样的结构定义将生成以下函数:
make-s(a, b)
s-a(s)
s-b(s)
s-c(s)
Run Code Online (Sandbox Code Playgroud)
现在,考虑到简单的设置,似乎很清楚,当您调用'f'或'make-s'时,幕后发生的事情之间存在很多相似之处.一旦在呼叫/实例化时间提供'a'和'b',就有足够的信息来计算'c'.
您可以考虑将struct实例化为类似于调用函数,然后存储生成的符号环境,以便在调用生成的访问器函数时供以后使用.或者您可以将一个函数评估为创建一个隐藏的结构,然后将其用作评估最终结果表达式的符号环境.
我的玩具模型是否过于简单,以至于没用?或者它实际上是一种有用的方式来思考真正的语言是如何工作的?是否有任何真正的语言/实现,没有CS背景但对编程语言感兴趣的人(即我)应该学习更多关于探索这个概念?
谢谢.
编辑:感谢您的答案到目前为止.为了详细说明,我想我想知道的是,如果有任何真正的语言,那么学习语言的人被告知例如"你应该认为对象基本上是闭包".或者,如果存在任何真正的语言实现,那么实例化对象并调用函数实际上共享一些常见的(非平凡的,即不仅仅是库调用)代码或数据结构.
我所做的类比,我知道其他人之前做过的,在任何实际情况下,是否比单纯的类比更深入?
我有一个Java类,我需要在F#中编写类似的类.如何在f#中定义public内的私有类?
public class KnownRuleGoals {
void record() {
knownParsingSet.add(new KnownParsing());
}
private class KnownParsing {
Rule [] knownParsing;
KnownParsing() {
...
}
void doWork() { ... }
}
}
Run Code Online (Sandbox Code Playgroud) 我越是读到关于lambdas的内容越多,我从人们那里听到它们只是伪装的函数对象/函子(除非它们没有捕获任何东西,在这种情况下它们只是自由静态函数.我想在本地写lambdas范围并将它们传递给一个通用事件处理程序,它根据需要调用它们,我开始注意到我几乎无法做任何传统函数对象允许我做的事情.如果我对此的理解是错误的,请告诉我.因为我已经评论过你可以用仿函数做的一大堆东西,据我所知,不能用lambdas:
#include <iostream>
#include <vector>
struct MyFunctorClass
{
// Custom constructor, can't do with lambda
MyFunctorClass(int& capturedVariable) : capturedVariable(capturedVariable)
{ std::cout << "I can do anything on construction.\n"; }
// Overloading constructors, different ways to initialise function object, can't do with lambda
MyFunctorClass(int& capturedVariable, int sizeOfBuffer) : capturedVariable(capturedVariable)
{ heapAllocation = new int[sizeOfBuffer]; }
// Custom destructor, can't do with lambda
~MyFunctorClass() { delete[] heapAllocation; }
void operator()() { std::cout << "Standard call\n"; }
void operator()(int arg) { std::cout << …Run Code Online (Sandbox Code Playgroud) 最近我一直在学习在Erlang中作为C和C#开发人员的长期编程.我对函数式编程很新.现在,我试图了解Scala等语言中的对象是如何工作的.我被告知OOP是关于使用其公共方法改变给定对象的状态.这些方法改变了公共财产和私人成员的状态.但现在我听说在函数式编程中,所有对象都应该是不可变的.好吧,我同意,一旦赋值变量(在给定函数中)应该保持指向同一个对象.但这种"不变性"是否意味着我无法使用公共方法更改给定对象的内部(属性,私有成员)?这使对象就像简单的数据容器一样.它提取了它们之外的所有功能.这使得对象更像C中的结构.这对我来说很奇怪.也许我错过了什么?是否有可能以旧式方式使用对象并仍将其视为函数式编程?
我从这个答案中理解为什么警告存在.但是,为什么它的默认值是2?在我看来,除了一个公共方法的类__init__是完全正常的!设置是否有任何警告
min-public-methods=1
Run Code Online (Sandbox Code Playgroud)
在pylintrc文件中?
closures ×2
oop ×2
python ×2
c# ×1
c++ ×1
class ×1
erlang ×1
f# ×1
function ×1
functor ×1
immutability ×1
imperative ×1
java ×1
lambda ×1
lisp ×1
object ×1
performance ×1
pylint ×1
python-3.x ×1
scala ×1