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

宏在定义时将关键帧视为true

  •  0
  • Rorschach  · 技术社区  · 7 年前

    使用时可以将密钥视为true cl-defmacro elisp中的s?例如

    (cl-defmacro mac (&key a b c)
      `(,@(if a "a" (if b "b" "c"))))
    
    (mac :a)
    "c"
    

    我可以在不需要给出的情况下将其评估为“a”吗 :a 像这样的值 (mac :a t )。我不知道相同的语义是否适用于公共lisp

    1 回复  |  直到 7 年前
        1
  •  3
  •   Dan Robertson    7 年前

    使用基础语言无法做到这一点。可以定义 defun 喜欢宏这样做。你愿意吗 只有 允许将这些值设置为true,或者您希望给出除 t (或 nil 是吗?第一种情况可以通过编写一些宏来完成。第二种情况不能很好地解决(特别是 (mac :a :b) a <- t; b <- t a <- :b ?)

    您可以为Common Lisp编写以下内容:

    (defmacro keyset-bind (keys-and-vars form &body body)
      (let (syms vars
            (keyv (gensym "KEY")))
        (loop for key in keys-and-vars
          for sym = (if (consp key)
                        (car key)
                        (intern (symbol-name key) "KEYWORD"))
          for var = (if (consp key) (cadr key) key)
          collect sym into symst
          collect var into varst
          finally (setf syms symst vars varst))
        `(let ,vars
            (loop for ,keyv in ,form
              do (case ,keyv
                   ,@(loop for sym in syms
                       for var in vars
                       collect `((,sym) (setf ,var t)))
                   (t (error "unrecognised keyword ~a" ,keyv))))
            ,@body)))
    

    然后你可以像这样使用它:

    (defun mac (&rest switches)
      (keyset-bind (a b (:t foo)) switches
        (list a b foo)))
    
    CL-USER> (mac :a)
    (T NIL NIL)
    CL-USER> (mac :b :t)
    (NIL NIL T)
    CL-USER> (mac :baz)
    ;; Error ...
    

    可以写一个替代方案 defun公司 已接受(例如a) &switch 参数类型,但您需要决定如何使其与其他参数类型和关键字交互,以及 &allow-other-keys :allow-other-keys t 。一般来说,所有这一切都是一个坏主意,不鼓励与上述内容混合使用(甚至使用),因为这样很难知道一个不熟悉的函数调用是被解释为普通关键字还是一组关键字。如果您想要一种支持这种类型的语言,请查看perl6,其中关键字是键值对类型,并且有特殊的语法 key => true key => false