Lisp链接函数宏

时间:2010-01-29 14:40:22

标签: lisp macros common-lisp chaining piping

是否有现成的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 ,...来引用以前返回的值。

这是一个想法,确切的语法并不重要。

我知道这并不难写,但看起来非常有用,必须已经写好了。

5 个答案:

答案 0 :(得分:7)

这样的东西?

(defun chain-expander (forms)
  (cond ((null (cdr forms)) (car forms))
    (t `(let ((it ,(car forms)))
          ,(chain-expander (cdr forms))))))

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

(defmacro chain (&body forms)
  (chain-expander forms))

如果你喜欢_1,_2等可以使用的东西,只需调用CHAIN-EXPANDER来调用CHAIN-COUNTED-EXPANDER(用你喜欢的第一个号码,我建议0或1)。请注意,它明确地仅提供使用_ N 作为参考,但更改它以便它也为每个后续级别绑定_并不是很难。

答案 1 :(得分:4)

为什么不

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

或者把它变成一个函数?

答案 2 :(得分: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”,但如果需要,可以将其更改为“_”。 当然,您也可以将名称更改为 - >或者你想要的任何其他东西。

答案 3 :(得分:1)

通过On Lisp

答案 4 :(得分:0)

您可能会发现这个问题很有趣:Tacit programming in Lisp

我对这个问题的回答类似于Vatine对这个问题的回答,但没有计算;作为旁注,我认为计数是危险的 - 你可以在更新代码时引入重新排序错误。提供一种命名以前结果的方法可能更好 - 但在实践中,我很少需要除了最后一个之外的结果。如果你需要它们,也许你应该编写一个函数而不是链式表达式。