English 中文(简体)
在使用特殊变量时使用宏观结果是错误的
原标题:Using a macro ends in error when using a special variable

SBCL

我想避免我这样作,因为我有许多变数(超过3个),想在他们之间插入一个分界线:

(format nil "~a;~b;~c;" var1 var2 var3)

预期结果:

"a;b;c;"

我确定了一个特殊的变量和一个宏观。

(defparameter *delimiter* ";")

(defmacro format-delimited (stream fmt delimiter &body vars)
   (let ((fmtstr ""))
    (dotimes (i (length vars))
      (setf fmtstr (str:concat fmtstr fmt delimiter)))
    `(format ,stream ,fmtstr ,@vars)))

这一呼吁成功地回归:

(format-delimited nil "~a" ";" "a" "b" "c")
"a;b;c;"

宏观收益1

(FORMAT NIL "~a;~a;~a;" "wolf" "golf" "rolf")

This call ends in error:

(format-delimited nil "~a" *delimiter* "a" "b" "c")

; Debugger entered on #<TYPE-ERROR expected-type: SEQUENCE datum: *DELIMITER*>

宏观尺度-1也差错。

错误的原因是什么?

问题回答

仅使用<代码>format已经提供的设施。 您可使用~{ ~}。 提出以下论点:

CL-USER> (format nil "~{~A;~}"  ("a" "b" "c"))
"a;b;c;"

If you want to omit the final semicolon, you can use ~^ to escape the iteration once the final argument has been processed:

CL-USER> (format nil "~{~A~^;~}"  ("a" "b" "c"))
"a;b;c"

你们可以利用这一想法来撰写一个宏观,例如:

(defmacro format-delimited (delimiter stream format-string &rest args)
  `(format ,stream
           ,`(concatenate  string "~{" ,format-string "~^" ,delimiter "~}")
           (list ,@args)))

I m not sure that writing a macro for this brings much advantage, but it is a little bit easier to use in simple cases:

CL-USER> (format-delimited ";" nil "~A" "a" "b" "c")
"a;b;c"
CL-USER> (let ((a 1) (b 2) (c 3))
           (format-delimited ";" nil "~A" a b c))
"1;2;3"
CL-USER> (let ((a  x) (b  y) (c  z))
           (format-delimited ";" nil "<~A>" a b c))
"<X>;<Y>;<Z>"

宏观法则对<条码>* 定义*表示进行评价;它符合该表述的源代码,即<条码>* 限制/代码。 页: 1

当争论为<代码>时,“,两者之间的区别因<代码>而消失;是一种自我评价的原子:<代码>的源代码”;和<代码>的操作时间价值”;相同。

如果您的宏观计算参数将不列入扩大范围,但必须加以评价,参数可以是任何表述(不仅如<代码>abc”、42(1 2)(引述名单),则您必须使用<代码>eval。

Let s change your &body to &rest because vars are not a progn-like body.

还要改变宏观参数的名称,以便提醒我们,它们是表述(来源代码),而不是价值观:

(defmacro format-delimited (stream-expr fmt-expr delimiter-expr &rest var-exprs)
  (let ((resulting-fmtstr "")
        (incoming-fmt (eval fmt-expr))
        (delim (eval delimiter-expr)))
    (dotimes (i (length var-exprs))
      (setf resulting-fmtstr (concatenate  string resulting-fmtstr incoming-fmt delim)))
    `(format ,stream-expr ,resulting-fmtstr ,@var-exprs)))

顺便提一下:

> (macroexpand  (format-delimited t "~a" ";" 1 2 3))
(FORMAT T "~a;~a;~a;" 1 2 3) ;
T
> (defvar *delimiter* "---")
*DELIMITER*
> (macroexpand  (format-delimited t "~a" *delimiter* 1 2 3))
(FORMAT T "~a---~a---~a---" 1 2 3) ;
T

Needless to say, the eval won t be happening in the apparent lexical environment. That does not exist until run time; at macro-expansion time, we are just processing source code.

The variable being referenced, *delimiter* will have to exist at macro-expansion time and have the right value.

<代码>format功能可做您之后的重述。 The syntax has a Much of bells and informs. 我不敢肯定,它是否能够篡改描述多种论点的格式,但可以用一个价值清单的论点来做到这一点。

You might be concerned that you don t want the format string to be interpreted at run-time.

普通图书馆有一个称为formatter的宏观,将格式说明变成代码(功能)。

如果是,

(format stream "whatever" args ...)

页: 1

(format stream (formatter "whatever") args ...)

编辑<代码>。 其结果是一种功能(如lambda >表述)。 当<代码>format的第二个论点是功能时,它只是从该功能的流体和论据手中。





相关问题
Lisp code called from Java

Long story: I am doing a project for my functional programing class, and I thought of writing an AI controller in Lisp, for the Mario AI competition. I was looking over frameworks/libraries/ways of ...

Emacs, Zen-Coding mode, and Putty

I use emacs via Putty and since Putty doesn t send certain key combinations to the remote console I generally need to re-bind them to other key combinations. After installing the amazing Zen-Coding ...

In Which Cases Is Better To Use Clojure? [closed]

I develop in Lisp and in Scheme, but I was reading about Clojure and then I want to know, in which cases is better to use it than using Lisp or Scheme? Thanks

lambda-gtk negative pointer

I was trying to write my own put-pixel on (Gdk) pixbuf in Lisp. When I finally realized how I can operate on C pointers in CL, new obstacle came along - (gdk:pixbuf-get-pixels pb) returns me negative ...

Is there a common lisp package naming convention?

I have created some of my own user packages and have run into a name clash. In Java, the naming convention is to use your domain name in the package name: e.g. import com.example.somepackage;. Are ...

SOAP request from within an AutoLISP/AutoCAD macro

We have built a webservice for a client that uses AutoCAD. They have a macro that runs in AutoCAD that builds a SOAP request. But they have not figured out how to actually send() the soap request to ...

热门标签