如何将lambda实现为称为“lambda”的函数在Clojure? [英] How to implement lambda as a function called "lambda" in Clojure?

查看:329
本文介绍了如何将lambda实现为称为“lambda”的函数在Clojure?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Clojure中使用通用的Lisp语法来定义lambdas。例如:

I'd like to be able to define lambdas using common Lisp syntax, in Clojure. For example:

(lambda (myarg)
  (some-functions-that-refer-to myarg))

这需要产生相同的结果:

This needs to result in the same as:

#(some-functions-that-refer-to %)

在我的例子中,我知道我总是有一个arg,所以也许这简化了事情。 (但它可以被称为任何东西 - myarg或任何。)

In my case, I know I'll always have exactly one arg, so perhaps that simplifies things. (But it can be called anything -- "myarg" or whatever.)

我怀疑一个可行的解决方案是(defmacro lambda ...)我不知道最好的方式继续,如何干净地将arg名称转换为%?如何结束正确的函数?

I suspect a workable solution is to "(defmacro lambda ...". If so, I'm not sure of the best way to proceed. How to cleanly translate the arg name to %? And how to end up with the correct function?

或者,有一个更简单的解决方案比写我自己的宏,实际上重新实现Clojure的... lambda?

Or, is there a simpler solution than writing my own macro that actually re-implements Clojure's... lambda?

推荐答案

#(foo%)只是读者对(fn [arg](foo arg))的简写。扩展到#(...) ...)构造函数将立即展开为gensyms。

#(foo %) is just reader shorthand for (fn [arg] (foo arg)). There's no reason to write a macro that expands into #(...). All the %'s in a #(...) construct are expanded into gensyms right away anyways.

user> `#(foo % %1 %2)
(fn* [user/p1__1877 user/p2__1878] 
  (user/foo user/p1__1877 user/p1__1877 user/p2__1878))

如果你编写了一个宏来扩展以构建匿名函数,你可以将它扩展为 fn 表单自己。在你的情况下,你应该直接使用 fn 并跳过宏。 fn 是Clojure的 lambda

If you're ever writing a macro that expands to build anonymous functions, you might as well just expand them to fn forms yourself. In your case, you should probably just use fn directly and skip the macros. fn is Clojure's lambda.

code>(fn [] ...)和(lambda()...)类型比lambda短, fn 为其绑定采用向量,而 lambda 采用列表。如果你使用Clojure,你将不得不习惯这最终,因为向量总是用于绑定集合,在所有 do 表单和 for binding 等。我理解的背后的理由是列表用于函数调用或宏调用,用于不是调用的事情(例如,要绑定的符号列表)。可以说,它使得比起list-all-the-way-down来更容易地以可视化的方式扫描代码。 Clojure不是Common Lisp,如果你试图强制它是你会遇到疼痛。

The difference between (fn [] ...) and (lambda () ...) in this case is that "fn" is shorter to type than "lambda", and fn takes a vector for its bindings whereas lambda takes a list. If you're using Clojure, you will have to get used to this eventually, because vectors are always used for collections of bindings, in all the do forms and in for and binding etc. The rationale behind this as I understand it is that lists are used for function calls or macro calls, and vectors are used for things that aren't calls (lists of symbols to bind, for example). Arguably, it makes it easier to scan the code visually than lists-all-the-way-down. Clojure is not Common Lisp, and you will experience pain if you try to force it to be.

如果你真的,真的想这样做,只是说你做了:

If you really, really wanted to do this, just to say you did:

user> (defmacro lambda [args & body]
        `(fn ~(vec args) ~@body))
user> ((lambda (x) (println x)) "foo")
foo
nil


$ b b

这不允许你对你的函数放置一个docstring或元数据,等等。我不认为你会想在真正的Clojure程序中使用这个。

This doesn't let you put a docstring or metadata on your function, among other things. I don't think you would want to use this in a real Clojure program.

这篇关于如何将lambda实现为称为“lambda”的函数在Clojure?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆