lambda 定义有什么乐趣?

发布于 2024-08-22 21:29:13 字数 197 浏览 5 评论 0原文

没有让他们使用那么多,我不太确定所有的方法 可以使用 lambda 定义(除了 map/collect/do/轻量级本地函数语法)。对于有兴趣发布一些示例的任何人:

  • 提供解释以帮助读者了解如何使用 lambda 定义;

  • 示例的首选语言:Python、Smalltalk、Haskell。

Not having them used them all that much, I'm not quite sure about all the ways
lambda-definitions can be used (other than map/collect/do/lightweight local function syntax). For anyone interested in posting some examples:

  • provide explanations to help readers understand how lambda-definitions are being used;

  • preferred languages for the examples: Python, Smalltalk, Haskell.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

帅冕 2024-08-29 21:29:14

您可以用 lambda 构建函数式数据结构。这是一个简单的 - 一个函数列表 (Python),支持 addcontains 方法:

empty = lambda x : None

def add(lst, item) :
    return lambda x : x == item or lst(x)

def contains(lst, item) :
    return lst(item) or False

我只是为了好玩而快速编码 - 请注意,你不允许添加任何虚假值。它也不是尾递归,而良好的函数结构应该是尾递归的。供读者练习!

You can make a functional data structure out of lambdas. Here is a simple one - a functional list (Python), supporting add and contains methods:

empty = lambda x : None

def add(lst, item) :
    return lambda x : x == item or lst(x)

def contains(lst, item) :
    return lst(item) or False

I just coded this quickly for fun - notice that you're not allowed to add any falsy values as is. It also is not tail-recursive, as a good functional structure should be. Exercises for the reader!

潦草背影 2024-08-29 21:29:14

您可以使用它们来控制流程。例如,在 Smalltalk 中,“ifTrue:ifFalse:”方法是布尔对象上的方法,对每个 True 和 False 类都有不同的实现。该表达式

someBoolean ifTrue: [self doSomething] ifFalse: [self doSomethingElse]

使用两个闭包——块,在 Smalltalk 语法中的 [方括号] 中——一个用于 true 分支,一个用于 false 分支。 实例,“ifTrue:ifFalse:”的实现

ifTrue: block1 ifFalse: block2
    ^ block1 value

对于 True 类实例和 False 类

ifTrue: block1 ifFalse: block2
    ^ block2 value

是:这里的闭包用于延迟计算,以便可以做出有关控制流的决定,根本不需要任何专门的语法< /em> (除了块的语法之外)。

Haskell 有点不同,它的惰性评估模型在许多情况下有效地自动产生闭包的效果,但在Scheme 中你最终会大量使用 lambda 来控制流。例如,这里是一个从关联列表中检索值的实用程序,在该值不存在的情况下提供可选计算的默认值:

(define (assq/default key lst default-thunk)
  (cond
    ((null? lst) (default-thunk)) ;; actually invoke the default-value-producer
    ((eq? (caar lst) key) (car lst))
    (else (assq/default key (cdr lst) default-thunk))))

它将像这样调用:

(assq/default 'mykey my-alist (lambda () (+ 3 4 5)))

这里的关键是使用 lambda 来延迟默认值的计算,直到实际知道需要它为止。

另请参见延续传递风格,它将这种风格发挥到了极致。例如,Javascript 依赖连续传递风格和闭包来执行其所有阻塞操作(如睡眠、I/O 等)。

预计到达时间:我上面所说的闭包,是指词法作用域闭包。通常,词法范围是关键。

You can use them for control flow. For example, in Smalltalk, the "ifTrue:ifFalse:" method is a method on Boolean objects, with a different implementation on each of True and False classes. The expression

someBoolean ifTrue: [self doSomething] ifFalse: [self doSomethingElse]

uses two closures---blocks, in [square brackets] in Smalltalk syntax---one for the true branch, and one for the false branch. The implementation of "ifTrue:ifFalse:" for instances of class True is

ifTrue: block1 ifFalse: block2
    ^ block1 value

and for class False:

ifTrue: block1 ifFalse: block2
    ^ block2 value

Closures, here, are used to delay evaluation so that a decision about control flow can be taken, without any specialised syntax at all (besides the syntax for blocks).

Haskell is a little different, with its lazy evaluation model effectively automatically producing the effect of closures in many cases, but in Scheme you end up using lambdas for control flow a lot. For example, here is a utility to retrieve a value from an association-list, supplying an optionally-computed default in the case where the value is not present:

(define (assq/default key lst default-thunk)
  (cond
    ((null? lst) (default-thunk)) ;; actually invoke the default-value-producer
    ((eq? (caar lst) key) (car lst))
    (else (assq/default key (cdr lst) default-thunk))))

It would be called like this:

(assq/default 'mykey my-alist (lambda () (+ 3 4 5)))

The key here is the use of the lambda to delay computation of the default value until it's actually known to be required.

See also continuation-passing-style, which takes this to an extreme. Javascript, for instance, relies on continuation-passing-style and closures to perform all of its blocking operations (like sleeping, I/O, etc).

ETA: Where I've said closures above, I mean lexically scoped closures. It's the lexical scope that's key, often.

〃安静 2024-08-29 21:29:14

您可以使用 lambda 创建 Y Combinator,该函数接受另一个函数并返回它的递归形式。这是一个例子:

def Y(le):
    def _anon(cc):
        return le(lambda x: cc(cc)(x))
    return _anon(_anon)

这是一个思想大棒,值得更多解释,但不要在这里重复它,请查看此博客条目(上面的示例也来自那里)。

You can use a lambda to create a Y Combinator, that is a function that takes another function and returns a recursive form of it. Here is an example:

def Y(le):
    def _anon(cc):
        return le(lambda x: cc(cc)(x))
    return _anon(_anon)

This is a thought bludgeon that deserves some more explanation, but rather than regurgitate it here check out this blog entry (above sample comes from there too).

美人迟暮 2024-08-29 21:29:14

它是 C#,但我个人每次读到这篇文章时都会感到很兴奋:

Building Data out of Thin Air - Lisp 的 cons、car 和 cdr 函数在 C# 中的实现。它展示了如何完全使用 lambda 函数构建简单的堆栈数据结构。

Its C#, but I personally get a kick out of this article every time I read it:

Building Data out of Thin Air - an implementation of Lisp's cons, car, and cdr functions in C#. It shows how to build a simple stack data structure entirely out of lambda functions.

你爱我像她 2024-08-29 21:29:14

它与 haskell 等中的概念并不完全相同,但在 C# 中,lambda 构造具有(可选)编译为表示代码的 objcet 模型的能力(表达式树)而不是代码本身(这本身就是 LINQ 的基石之一)。

这反过来又可以带来一些非常具有表现力的元编程机会,例如(这里的 lambda 表示“给定一个服务,你想用它做什么?”):(

var client = new Client<ISomeService>();
string captured = "to show a closure";
var result = client.Invoke(
    svc => svc.SomeMethodDefinedOnTheService(123, captured)
);

假设有一个合适的 Invoke 签名)

这种类型的东西有很多用途,但我用它来构建一个不需要任何运行时代码生成的 RPC 堆栈 - 它只是解析表达式树,找出调用者的意图,将其转换为 RPC、调用它、收集响应等(更多讨论此处)。

It isn't really quite the same concept as in haskell etc, but in C#, the lambda construct has (optionally) the ability to compile to an objcet model representing the code (expression-trees) rather than code itself (this is itself one of the cornerstones of LINQ).

This in turn can lead to some very expressive meta-programming opportunities, for example (where the lambda here is expressing "given a service, what do you want to do with it?"):

var client = new Client<ISomeService>();
string captured = "to show a closure";
var result = client.Invoke(
    svc => svc.SomeMethodDefinedOnTheService(123, captured)
);

(assuming a suitable Invoke signature)

There are lots of uses for this type of thing, but I've used it to build an RPC stack that doesn't require any runtime code generation - it simply parses the expression-tree, figures out what the caller intended, translates it to RPC, invokes it, gathers the response, etc (discussed more here).

∞琼窗梦回ˉ 2024-08-29 21:29:14

Haskell 中使用数值近似计算单变量函数导数的示例:

deriv f = \x -> (f (x + d) - f x) / d
  where
    d = 0.00001

f x = x ^ 2
f' = deriv f -- roughly equal to f' x = 2 * x

An example in Haskell to compute the derivative of a single variabled function using a numerical approximation:

deriv f = \x -> (f (x + d) - f x) / d
  where
    d = 0.00001

f x = x ^ 2
f' = deriv f -- roughly equal to f' x = 2 * x
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文