代码之家  ›  专栏  ›  技术社区  ›  Marko

Lisp链接函数宏

  •  4
  • Marko  · 技术社区  · 14 年前

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

    不要将let*用于许多未使用的中间变量,如:

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

    我想这样写:

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

    显然,在哪里 γ 将是上一个表达式的返回值。一个优点是如果可以使用 Y1 , 二级 ,…引用以前返回的值。

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

    我知道这不是很难写,但似乎是如此有用,它必须已经写了。

    5 回复  |  直到 12 年前
        1
  •  7
  •   Marko    14 年前

    像这样?

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

        2
  •  4
  •   Christoffer Hammarström    14 年前

    为什么不只是

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

    ?

    或者把它变成一个函数?

        3
  •  2
  •   Erik Haliewicz    12 年前

    您可以使用ablock宏 On Lisp

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

        4
  •  1
  •   grettke    14 年前

    通过 On Lisp

        5
  •  0
  •   Community Ian Goodfellow    7 年前

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

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