4

是否有现成的 lisp 宏允许链接(管道)函数?我找不到一个。我将尝试用这个例子解释我的意思。

而不是像这样使用带有大量未使用的中间变量的 let* :

(let*
  ((var1 (f1 x y))
   (var2 (f2 x var1))
   (var3 (f1 var2 z)))
 var3)

我想把它写成这样:

(->
  (f1 x y)
  (f2 x _)
  (f1 _ z))

其中,显然_将是前一个表达式的返回值。一个优点是是否可以使用_1_2、 ... 来引用以前返回的值。

这就是想法,确切的语法并不那么重要。

我知道这并不难写,但似乎很有用,必须已经写好了。

4

5 回答 5

7

像这样的东西?

(defun 链扩展器(形式)
  (cond ((null (cdr forms)) (car forms))
    (t `(let ((it ,(car forms)))
          ,(扩链器(cdr 形式))))))

(defun chain-counted-expander (forms counter)
  (cond ((null (cdr forms)) (car forms))
    (t (let* ((name (format nil "_~d" 计数器))
          (回指 (or (find-symbol name) (intern name))))
         `(let ((,anaphora ,(car forms)))
        ,(chain-counted-expander (cdr forms) (1+ counter)))))))

(defmacro 链(&body 形式)
  (扩链器形式))

如果您更喜欢 _1、_2 等可用的东西,只需将对 CHAIN-EXPANDER 的调用替换为对 CHAIN-COUNTED-EXPANDER 的调用(使用您首选的第一个数字,我建议使用 0 或 1) . 请注意,它仅明确地迎合使用 _ N作为参考,但更改它以便它也为每个后续级别绑定 _ 并不是很难。

于 2010-02-01T23:46:43.957 回答
5

为什么不只是

(f1 (f2 x (f1 x y)) z)

?

或者把它变成一个函数?

于 2010-01-29T14:54:42.030 回答
2

您可以使用On Lisp中的 ablock 宏

(defmacro alambda (parms &body body)
  `(labels ((self ,parms ,@body))
     #'self))

(defmacro ablock (tag &rest args)
  `(block ,tag
     ,(funcall (alambda (args)
            (case (length args)
              (0 nil)    
          (1 (car args))
          (t `(let ((it ,(car args)))    ;; change it to _ 
            ,(self (cdr args))))))
       args)))

宏将前一个表达式的值绑定到“it”,但如果需要,您可以将其更改为“_”。当然,您也可以将名称更改为 -> 或您喜欢的任何其他名称。

于 2012-07-16T20:01:36.827 回答
1

通过在 Lisp 上

于 2010-01-30T03:54:54.700 回答
0

你可能会觉得这个问题很有趣:Tacit Programming in Lisp

我对这个问题的回答类似于 Vatine 对这个问题的回答,但没有计数;附带说明一下,我认为计数非常脆弱 - 您可以在更新代码时引入重新排序错误。提供一种命名先前结果的方法可能会更好——但实际上,除了最后一个结果之外,我很少需要其他结果。如果您需要它们,也许您应该编写一个函数而不是链接表达式。

于 2012-07-17T09:46:48.487 回答