【问题标题】:Lisp chaining functions macroLisp 链接函数宏
【发布时间】:2010-01-29 14:40:21
【问题描述】:

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

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

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

【问题讨论】:

  • 出于好奇,您最终是否经常使用此代码? (f1 (f2 x (f1 x y)) z) 而不是 let* 的级联通常看起来更易读。

标签: lisp macros common-lisp chaining piping


【解决方案1】:

这样的?

(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 作为参考,但更改它以便它也为每个后续级别绑定 _ 并不是很难。

【讨论】:

  • 谢谢。这正是我想要的。
【解决方案2】:

为什么不直接

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

?

或者把它变成一个函数?

【讨论】:

  • 嗯,第二种方法似乎更具可读性,尤其是对于较长的函数序列。
  • 其实我觉得这更容易理解。使用管道版本,我尝试在我的脑海中重建价值流。这里的版本更清楚。管道版本需要“势在必行”的心态。
【解决方案3】:

你可以使用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”,但如果需要,您可以将其更改为“_”。 当然,您也可以将名称更改为 -> 或您喜欢的任何其他名称。

【讨论】:

    【解决方案4】:

    通过On Lisp

    【讨论】:

    • 此链接已损坏。
    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多