# , ` 是什么意思,不懂


#1

手册看几遍这一部分,英语渣,大部分看的懂. 反引号`,引用变量前加逗号或者@ 函数前加# 看不懂啊,要么是单词生僻,理解不了,要么是概念模糊,还是理解不了,有哪位大佬帮忙解释下,谢谢


#2
  • ` 必须和 , 配合使用. , 号后面的表达式会被求值

    比如 下面的表达式中后一个 (+ 3 4) 会被求值, 但是前一个不会,

    `(a (+ 3 4) , (+ 3 4))    ; =>    (a (+ 3 4) 7) 
    
  • ,@ 必须连在一起使用, ,@ 之后的表达式的结果必须是列表, 列表会被展开

    (setq  b '(1 2 3))
    `(a ,@ b c)  ; =>   (a 1 2 3 c)
    
    (setq b 1)
    `(a ,@ b c)  ; =>  Wrong type argument: sequencep, 1
    
  • #' 必须一起使用, #'foo(function foo) 等价, (# 号还有其他用途不过和这里没什么关系)

    function is a special form in ‘src/eval.c’.

    (function ARG)

    Like ‘quote’, but preferred for objects which are functions. In byte compilation, ‘function’ causes its argument to be compiled. ‘quote’ cannot do that.

    #'quote 基本一样, 只是在 byte-compile 的时候不一样


` 其实是一个宏 backquote 的别名 (backquote.el)

(defalias '\` (symbol-function 'backquote))

比如 `(1 2 3) 其实就是 (backquote (1 2 3))

在 backquote.el 里还定义了三个 symbol

(defconst backquote-backquote-symbol '\`
  "Symbol used to represent a backquote or nested backquote.")

(defconst backquote-unquote-symbol '\,
  "Symbol used to represent an unquote inside a backquote.")

(defconst backquote-splice-symbol '\,@
  "Symbol used to represent a splice inside a backquote.")

,,@ 其实是可以变成其他符号的


#3

看不明白什么问题。你的问题不完整、缺少上下文。


#4

谢谢,基本懂了,剩下的在参照手册,学吧。


#5

有点不明白的地方是,foo本身就是返回自己的函数引用,为何要写成(function foo),它们有区别吗?在scheme中,一般直接写foo,这是不是scheme与lisp的区别所在?

是不是,在elisp中,直接写foo,就从符号定义namespace查找,而(function foo)就是从函数定义namespace中查找的意思?


#6

如果没记错的话, elisp 里函数命名空间和变量命名空间是分开的,就说你可以定义名字是 foo 的函数, 同时也可以定义一个名字是 foo 的变量。 使用 foo 的时候除非是括号第一个位置, 其他位置默认成变量。


#7

刚试了一下

(defun fact (n)
  (if (= n 0) 1
    (* n (fact (1- n)))))

(defun test (fn n)
  (funcall fn n))

(test 'fact 3)   => 6
(test #'fact 3)  => 6 ;; byte compile

两者都能执行,#’ 第一次compile之后,以后执行应该快一些吧,compile之后的byte code保存在什么地方呢?若没保存的话,岂不是每次都compile。或者,compile之后缓存在自己的buffer里,一旦这个buffer关闭,再次打开的话,第一次遇到这个函数时compile一下。


#8

funcall会对它的参数求值。无论'foo或者#'foo求值的结果都是foo这个symbol。然后funcall会到foo的function slot寻找函数定义然后执行。

#' ' 没有实质性的区别。#'算是一个给字节码编译器的一个提示。如果字节码编译器发现#'foofoo在编译时没有函数定义。会报一个警。


#9

跟buffer没有关系的啊

(defun zx () (print (+ 90 90)))

(symbol-function 'zx)

(byte-compile 'zx)

(symbol-function 'zx)

(fset 'zxc (symbol-function 'zx))

(zxc)

#10

关于这个问题,我另起了一个主题[elisp 符号表 与 namespace]

关于本主题

为了使记号简洁,lisp 中有一个特殊的宏‘,称为 backquote。在这个宏里,所有的表达式都是引用(quote)的,如果要让一个表达式不被直接引用(也就是列表中要计算该表达式的值),需要在前面加 “,”,如果要让一个列表作为整个列表的一部分,可以用“,@”把它展开。

'(a list of ,(+ 2 3) elements) ; => (a list of 5 elements) 
(setq some-list ’(2 3))        ; => (2 3) 
'(1 ,some-list 4 ,@some-list)  ; => (1 (2 3) 4 2 3)

提个问题

(defmacro when (cond &rest body)
  (list 'if cond (cons 'progn body)))

; 按理说,是可以替换成
(defmacro when (cond &rest body)
  '(if ,cond (progn ,@body)))

; 但提示下面错误
Error running timer 'aggressive-indent--indent-if-changed': (void-function \,)
; 找不到名字为"\,"的函数

#11

macro when被使用的时候。负责处理lisp解释器解析后的backquote结构的backquote.el还没被加载呢


是你自己写的宏啊… 我还以为你动手改了subr.el呢。那你应该是写错字了。


#12

好的,谢谢。

不过,以我现在的水平,只看这段代码,看不出哪里写了backquote.el在when之后加载?


#13

写错了吧,应该是

`(if ,cond (progn ,@body))

不是

'(if ,cond (progn ,@body))

#14

我也看不懂。不过subr.el有不少宏都有类似的提示


#15

正解,非常感谢。


#16

好的,以后我也得仔细看代码和注释了。我感觉看他们的代码,在时间上有些吃不消,你是怎么做到的?

不过我这次的问题是‘ 和 `的问题