使用变量定义可选参数
Use a variable to define an optional argument
我不知道我在做什么或术语是什么。我只知道我想使用一个变量(?)来避免在几个地方重复一个值。但是我无法使用该变量 (?) 的值 (?) 将其传递给 emacs lisp 中的可选(关键字?)参数。
使用文字值有效:
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory "projects/notes"
:base-extension "org"
:publishing-directory "html"
...
)
))
使用变量无效:
(setq my-base-directory "~/projects/notes")
(setq my-publising-directory "html")
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory
...
)
))
我收到一个错误:
byte-code: Wrong type argument: stringp, my-base-directory
这也不起作用:
(let (
(my-base-directory "~/projects/notes")
(my-publising-directory "html")
)
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory
...
)
)))
我想知道为什么在 emacs 中访问变量如此困难?这些变量被定义了(我可以打印它们),但是它们不能被可选参数访问(那些前面有冒号的东西叫做可选参数或关键字参数吗?)
我尝试了无数其他变体,包括 (quote ...)
和使用引号 '
:
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory 'my-base-directory
:base-extension "org"
:publishing-directory 'my-publishing-directory
...
)
))
在这种情况下,我得到:
byte-code: Wrong type argument: stringp, (quote my-base-directory)
我只需要使用变量来设置可选参数。我怎样才能做到这一点?我是否需要对可选参数使用与正常使用不同的语法?
示例:
反引号列表:
ELISP> (let ((foo "Foo")) `(,foo bar))
("Foo" bar)
函数LIST
:
ELISP> (let ((foo "Foo")) (list foo 'bar))
("Foo" bar)
示例:
(setq
org-publish-project-alist
`(("my-notes"
:base-directory ,my-base-directory
:base-extension "org"
:publishing-directory ,my-publishing-directory
; ...
)))
我看到你已经有了一个有效的答案,但在你的评论中表达了一些困惑;我会尝试更彻底地解释它。
当你引用某些东西时(通过使用 (quote foo)
或 'foo
),你是在告诉 lisp 解释器不要计算 foo。这通常用于输入数据而不是代码;在这种情况下,您正在创建一个适度复杂的列表结构以用作数据,而不是用作要评估的代码。
您的代码有 '(("my-notes" :base-directory my-base-directory))
,这是一个列表的引用列表。内部列表将包含关键字 :base-directory
和符号 my-base-directory
。它不包含 my-base-directory 变量的值,因为开头的引号告诉 lisp 不要对它求值。
解决这个问题的两种方法都涉及不引用整个表达式。
第一个也是最简单的选择是使用 list
;这是一个函数,它接受任意数量的参数和 returns 包含这些值的列表。例如:
(list 1 2 3) => '(1 2 3)
(let ((x 42)) (list x x)) => '(42 42)
因此,您可以像这样构建代码:
(setq org-publish-project-alist
(list (list "my-notes" :base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory)))
您会发现必须调用 list
函数两次,结构的每个级别一次。随着结构变得更加复杂,这可能会变得乏味;引用的发明是为了让您免于乏味。
(另请注意,关键字和字符串对其自身求值,因此当它们用作参数而不是引用列表的成员时不需要任何特殊处理。)
另一种选择是使用反引号(或偶尔称为语法引号)而不是正常的 quote
。反引号是不寻常的,因为它可以使用逗号运算符撤消:
(setq org-publish-project-alist
`(("my-notes" :base-directory ,my-base-directory
:base-extension "org"
:publishing-directory ,my-publishing-directory)))
反引号告诉 lisp 不要计算表达式,就像普通引号一样,但后面的逗号让您改变主意,让 lisp 最终计算一些表达式。
反引号有点像 Python 的字符串插值,不同之处在于它们适用于整个 lisp 语法,而不仅仅是双引号字符串。
此外,您可以在逗号后放置任意 lisp 表达式,就像您可以在引号或反引号后放置任意 lisp 表达式一样:
`(("my-notes" :base-directory ,(concat my-projects-directory "notes")))
请特别注意 `(("my-notes" :base-directory, my-base-directory)) 不起作用;您的评论之一表明您可能尝试过这样的事情。逗号的这种用法对于来自其他语言的程序员来说确实很陌生!并不是只有您认为这是一种非常奇怪的书写方式,但一段时间后它开始变得有意义了。将逗号视为一种倒置的反引号会有所帮助。
我不知道我在做什么或术语是什么。我只知道我想使用一个变量(?)来避免在几个地方重复一个值。但是我无法使用该变量 (?) 的值 (?) 将其传递给 emacs lisp 中的可选(关键字?)参数。
使用文字值有效:
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory "projects/notes"
:base-extension "org"
:publishing-directory "html"
...
)
))
使用变量无效:
(setq my-base-directory "~/projects/notes")
(setq my-publising-directory "html")
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory
...
)
))
我收到一个错误:
byte-code: Wrong type argument: stringp, my-base-directory
这也不起作用:
(let (
(my-base-directory "~/projects/notes")
(my-publising-directory "html")
)
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory
...
)
)))
我想知道为什么在 emacs 中访问变量如此困难?这些变量被定义了(我可以打印它们),但是它们不能被可选参数访问(那些前面有冒号的东西叫做可选参数或关键字参数吗?)
我尝试了无数其他变体,包括 (quote ...)
和使用引号 '
:
(setq
org-publish-project-alist
'(
("my-notes"
:base-directory 'my-base-directory
:base-extension "org"
:publishing-directory 'my-publishing-directory
...
)
))
在这种情况下,我得到:
byte-code: Wrong type argument: stringp, (quote my-base-directory)
我只需要使用变量来设置可选参数。我怎样才能做到这一点?我是否需要对可选参数使用与正常使用不同的语法?
示例:
反引号列表:
ELISP> (let ((foo "Foo")) `(,foo bar))
("Foo" bar)
函数LIST
:
ELISP> (let ((foo "Foo")) (list foo 'bar))
("Foo" bar)
示例:
(setq
org-publish-project-alist
`(("my-notes"
:base-directory ,my-base-directory
:base-extension "org"
:publishing-directory ,my-publishing-directory
; ...
)))
我看到你已经有了一个有效的答案,但在你的评论中表达了一些困惑;我会尝试更彻底地解释它。
当你引用某些东西时(通过使用 (quote foo)
或 'foo
),你是在告诉 lisp 解释器不要计算 foo。这通常用于输入数据而不是代码;在这种情况下,您正在创建一个适度复杂的列表结构以用作数据,而不是用作要评估的代码。
您的代码有 '(("my-notes" :base-directory my-base-directory))
,这是一个列表的引用列表。内部列表将包含关键字 :base-directory
和符号 my-base-directory
。它不包含 my-base-directory 变量的值,因为开头的引号告诉 lisp 不要对它求值。
解决这个问题的两种方法都涉及不引用整个表达式。
第一个也是最简单的选择是使用 list
;这是一个函数,它接受任意数量的参数和 returns 包含这些值的列表。例如:
(list 1 2 3) => '(1 2 3)
(let ((x 42)) (list x x)) => '(42 42)
因此,您可以像这样构建代码:
(setq org-publish-project-alist
(list (list "my-notes" :base-directory my-base-directory
:base-extension "org"
:publishing-directory my-publishing-directory)))
您会发现必须调用 list
函数两次,结构的每个级别一次。随着结构变得更加复杂,这可能会变得乏味;引用的发明是为了让您免于乏味。
(另请注意,关键字和字符串对其自身求值,因此当它们用作参数而不是引用列表的成员时不需要任何特殊处理。)
另一种选择是使用反引号(或偶尔称为语法引号)而不是正常的 quote
。反引号是不寻常的,因为它可以使用逗号运算符撤消:
(setq org-publish-project-alist
`(("my-notes" :base-directory ,my-base-directory
:base-extension "org"
:publishing-directory ,my-publishing-directory)))
反引号告诉 lisp 不要计算表达式,就像普通引号一样,但后面的逗号让您改变主意,让 lisp 最终计算一些表达式。
反引号有点像 Python 的字符串插值,不同之处在于它们适用于整个 lisp 语法,而不仅仅是双引号字符串。
此外,您可以在逗号后放置任意 lisp 表达式,就像您可以在引号或反引号后放置任意 lisp 表达式一样:
`(("my-notes" :base-directory ,(concat my-projects-directory "notes")))
请特别注意 `(("my-notes" :base-directory, my-base-directory)) 不起作用;您的评论之一表明您可能尝试过这样的事情。逗号的这种用法对于来自其他语言的程序员来说确实很陌生!并不是只有您认为这是一种非常奇怪的书写方式,但一段时间后它开始变得有意义了。将逗号视为一种倒置的反引号会有所帮助。