Macros 如何在LISP中定义递归返回带引号列表的函数

Macros 如何在LISP中定义递归返回带引号列表的函数,macros,scheme,lisp,common-lisp,lisp-macros,Macros,Scheme,Lisp,Common Lisp,Lisp Macros,我的lisp解释器中的宏在JavaScript中有问题。此代码中存在问题: (define log (. console "log")) (define (alist->object alist) "(alist->object alist) Function convert alist pairs to JavaScript object." (if (pair? alist) ((. alist "toObject")))) (define (k

我的lisp解释器中的宏在JavaScript中有问题。此代码中存在问题:

(define log (. console "log"))

(define (alist->object alist)
  "(alist->object alist)

   Function convert alist pairs to JavaScript object."
  (if (pair? alist)
      ((. alist "toObject"))))


(define (klist->alist klist)
  "(klist->alist klist)

   Function convert klist in form (:foo 10 :bar 20) into alist
   in form ((foo . 10) (bar . 20))."
  (let iter ((klist klist) (result '()))
    (if (null? klist)
        result
        (if (and (pair? klist) (pair? (cdr klist)) (key? (car klist)))
            (begin
              (log ":::" (cadr klist))
              (log "data" (. (cadr klist) "data"))
              (iter (cddr klist) (cons (cons (key->string (car klist)) (cadr klist)) result)))))))




(define (make-empty-object)
  (alist->object '()))

(define empty-object (make-empty-object))

(define klist->object (pipe klist->alist alist->object))

;; main function that give problems
(define (make-tags expr)
  (log "make-tags" expr)
  `(h ,(key->string (car expr))
      ,(klist->object (cadr expr))
      ,(if (not (null? (cddr expr)))
           (if (and (pair? (caddr expr)) (let ((s (caaddr expr))) (and (symbol? s) (eq? s 'list))))
               `(list->array (list ,@(map make-tags (cdaddr expr))))
               (caddr expr)))))


(define-macro (with-tags expr)
  (make-tags expr))
(define (view state actions)
  (with-tags (:div ()
                   (list (:h1 () (value (cdr (assoc 'count (. state "counter")))))
                         (:button (:onclick (lambda () (--> actions (down 1)))) "-")
                         (:button (:onclick (lambda () (--> actions (up 1)))) "+")))))
我使用以下代码调用此宏:

(define log (. console "log"))

(define (alist->object alist)
  "(alist->object alist)

   Function convert alist pairs to JavaScript object."
  (if (pair? alist)
      ((. alist "toObject"))))


(define (klist->alist klist)
  "(klist->alist klist)

   Function convert klist in form (:foo 10 :bar 20) into alist
   in form ((foo . 10) (bar . 20))."
  (let iter ((klist klist) (result '()))
    (if (null? klist)
        result
        (if (and (pair? klist) (pair? (cdr klist)) (key? (car klist)))
            (begin
              (log ":::" (cadr klist))
              (log "data" (. (cadr klist) "data"))
              (iter (cddr klist) (cons (cons (key->string (car klist)) (cadr klist)) result)))))))




(define (make-empty-object)
  (alist->object '()))

(define empty-object (make-empty-object))

(define klist->object (pipe klist->alist alist->object))

;; main function that give problems
(define (make-tags expr)
  (log "make-tags" expr)
  `(h ,(key->string (car expr))
      ,(klist->object (cadr expr))
      ,(if (not (null? (cddr expr)))
           (if (and (pair? (caddr expr)) (let ((s (caaddr expr))) (and (symbol? s) (eq? s 'list))))
               `(list->array (list ,@(map make-tags (cdaddr expr))))
               (caddr expr)))))


(define-macro (with-tags expr)
  (make-tags expr))
(define (view state actions)
  (with-tags (:div ()
                   (list (:h1 () (value (cdr (assoc 'count (. state "counter")))))
                         (:button (:onclick (lambda () (--> actions (down 1)))) "-")
                         (:button (:onclick (lambda () (--> actions (up 1)))) "+")))))
应该扩展到几乎相同的代码:

(define (view state actions)
  (h "div" (make-empty-object)
     (list->array (list
                   (h "h1" (make-empty-object) (value (cdr (assoc 'count (. state "counter")))))
                   (h "button" (klist->object `(:onclick ,(lambda () (--> actions (down 1))))) "-")
                   (h "button" (klist->object `(:onclick ,(lambda () (--> actions (up 1))))) "+")))))
这个功能有效。我在使用调用main函数的宏进行扩展时遇到了问题,不知道LIPS在找到以下函数时应该如何操作:

(:onclick (lambda () (--> actions (down 1))))
在代码内部,您尝试按如下方式处理它:

,(klist->object (cadr expr))
现在,我的lisp可以将lambda标记为数据(将data flag设置为true,这是一种防止对宏中的某些代码进行递归计算的方法)和
klist->object
函数将lambda代码作为列表,而不是函数

这在Scheme或Common Lisp中应该如何工作?应该
klist->object
获取函数对象(lambda得到评估)还是以lambda作为第一个符号的列表结构?如果是第二种情况,那么我应该如何编写函数和宏来计算lambda,我应该使用eval(对我来说是一种攻击)

抱歉,我不知道如何使用更多无bug的LISP来测试这个

编辑:

我试图在guile中应用@jkiiski的提示(因为在我的lisp中它不起作用)

;;-*-舍姆-*-
(定义nil'())
(定义(键?符号)
“(钥匙?符号)
函数检查符号是否为键符号,以冒号作为第一个字符。“
(和(符号?符号)(等式?:“(子字符串(符号->字符串符号)01)))
(定义(键->字符串符号)
“(键->字符串符号)
如果符号是键,则将其转换为字符串-删除冒号。“
(如果(键?符号)
(子字符串(符号->字符串符号)1)
(定义(成对映射fn序列列表)
“(序列图fn列表)
函数调用列表中对的fn参数,并返回组合列表
从函数fn返回的值。它的工作方式与映射类似,但从列表中获取两项“
(让iter((顺序列表顺序列表)(结果“()))
(如果(空?序列列表)
结果
(如果(和(对?序列列表)(对?(cdr序列列表)))
(出租*((第一(汽车序列表))
(第二(cadr序列列表))
(值(fn第一秒)))
(如果为空值)
(iter(cddr序列列表)结果)
(国际热核实验堆(cddr序列列表)(cons值结果()()()())))
(定义(klist->klist)
“(klist->klist)
函数将形式为(:foo 10:bar 20)的klist转换为alist
以表格((第10章)(第20条))形式提交。”
(配对图(λ(第一秒)
(如果(钥匙?第一个)
(cons(键->字符串第一)第二)klist)
(定义(h支柱休息)
(展示道具)
(显示休息)
(犯人道具)(犯人休息)无)
(定义(使标记扩展)
`(h,(键->字符串(汽车出口))
(klist->alist(列表,@(cadr expr)))
,(如果(非空)(cddr expr)))
(如果(和(对)(caddr expr))(让((s(caaddr expr)))(和(符号s)(等式s列表)))
`(列表->数组(列表,@(映射生成标记(cdaddr expr)))
(caddr expr(()()))
(定义宏(带标记expr)
(制作标签expr))
(定义状态“((计数10)))
(定义xxx(带有标记(:div()
(列表(:h1()(cdr(关联计数状态)))
(:按钮(:onclick(lambda()(显示“向下”))“-”)

(:button(:onclick(lambda()(display“up”)“+”))”)
您正在使用逗号计算lambda表达式,因此它应该是一个函数对象,就像您编写了
(list:onclick(lambda…)
(引用
:onclick
,如果它在lisp中不是自计算的)@jkiiski在我的宏中不使用逗号表示lambda(
,(lambda…
),它是在原始代码中,我想尝试重写为宏,它是
,(klist->object(cadr expr))
并且它得到lambda作为列表结构。所以问题是宏当前没有扩展到您给出的示例扩展?看看
make tags
-函数,似乎您在宏扩展时调用
klist->object
,而不是返回它。如果我理解正确,您会希望它是这样的方法类似于
'(h…(klist->object(list,@(cadr expr)))…)
(一开始应该是一个倒勾,但我不知道如何在这里的注释中写一个).@jkiiski试图将您的解决方案应用于guile scheme,因为在我的代码中它不起作用,找到了我的lisp的修复程序,但还想知道这应该如何在scheme中实现。(guile的代码在折叠的代码段中)。guile中的关键字是编写的
:onclick
,而不是
:onclick
(我认为有一种方法可以让它也接受后者,但我对Guile/Scheme不太熟悉),因此它将
:onclick
视为一个变量,而不是一个自评估关键字。您使用逗号来计算lambda表达式,因此它应该是一个函数对象,就像您编写的
(列表:onclick(lambda…)
(引用
:onclick
,如果它不是lisp中的自评估)。@jkiiski在我的宏中不使用逗号表示lambda(
,(lambda…)
,我想尝试在原始代码中重写为宏它的
,(klist->object(cadr expr))
并且它得到lambda作为列表结构。所以问题是宏当前没有扩展到您给出的示例扩展?看看
make tags
-函数,似乎您在宏扩展时调用
klist->object
,而不是返回它。如果我理解正确,您会希望它是这样的方法类似于
'(h…(klist->object(list,@(cadr expr)))…)
(一开始应该是一个倒勾,但我不知道如何在这里的注释中写一个)@jkiiski试图将您的解决方案应用于guile scheme,因为在我的代码中它不起作用,找到了我的lisp的修复程序,但还想知道这应该如何在scheme中实现。(guile的代码在折叠的代码段中)。guile中的关键字是编写的
:o