defconst 定义的 setq还是能修改。
不能zsbd
用closure或许能模拟常量,但是对于复合数据类型来说,还是可以修改内部结构
(defalias 'really-constant-var
(let ((x (list 1 2 3)))
(lambda () x)))
(really-constant-var)
;; => (1 2 3)
(setf (car (really-constant-var)) 3)
;; => 3
(really-constant-var)
;; => (3 2 3)
常量应该是在编译期确定/约束的,执行期在内存里怎么样都可以修改的。常见的动态语言里都没有常量这一概念吧。
26.1 之后可以这样:
(defvar const-var t)
(add-variable-watcher 'const-var #'const-var-watcher)
(defun const-var-watcher (sym _newval _op _where)
(error "assignment of read-only variable ‘%s’" sym))
(setq const-var nil) ;; error
(defvar const-var t)
(add-variable-watcher 'const-var #'const-var-watcher)
(defun const-var-watcher (sym _newval _op _where)
(error "assignment of read-only variable ‘%s’" sym))
(defvaralias 'alias-to-const-var 'const-var)
;; Error ???
可以先加一个判断
参数 op
可以区分操作类型是 set
还是 defvaralias
。
不想报错,就是想 setq 修改这个变量无效,还是原来的值。最多 warning 提示一下。用下面的好像并没有效果。
(defvar const-var t)
(add-variable-watcher 'const-var #'const-var-watcher)
(defun const-var-watcher (sym _newval _op _where)
(when (string= "set" _op)
(remove-variable-watcher 'package-archives #'const-var-watcher)
(setq const-var t)
(add-variable-watcher 'package-archives #'const-var-watcher)
;; (error "assignment of read-only variable ‘%s’" _op)
))
(setq const-var nil)
想要 const 又不报错。
就像是 try...catch
不处理,也不往上抛,静悄悄把问题掩盖起来。
本来 assign to constant
在byte-compile时就会报warning啊??
warning 只是附带,可有可无的,主要是setq 修改不要起作用。
本来想重新定义 setq ,定义一个列表包含所有不想被修改的变量,然后 setq 先判断变量是否在上面的列表内,然后分别处理,弄了两个多小时没弄出来。大神帮我看看。
(defvar var-list '())
(defmacro setq (&rest settings)
`(progn
,@(cl-loop for (var val) on settings by 'cddr
unless (member var var-list)
collect `(funcall #'set ',var ,val)
)))
不用 setq 命名这个宏,可以用。但是用 setq 命名的话,cl-loop 里也调用 setq 导致超出限制了。
我研究一下 try…catch
警告就改成:
(defun const-var-watcher (sym _newval _op _where)
(warn "assignment of read-only variable ‘%s’" sym))
我还是认为,既然是 const,就该报错。及早从源头杜绝错误,而不是把错误隐藏起来。
我是想在 site-start.el 里把 package-archives 里写死(还有其他一些变量).这样用其他的 emacs 配置就不用一个个设置了. warn 不能阻止修改值。
你前面知道改回去,这么快就忘了?
这个嘛,这个我试了没效果。
你说的 try…catch 应该可以,我查查。
请直接问这个问题. 不然别人会以为你在Elisp编程的时候出现了需要严格constant做约束的场景. (事实上你只是希望对不同配置pin一个变量)
答案是不能, 请自己分别找一下各个配置里允许你改package-archives
的地方改上.(或许可以用prin1
之类的东西批量生成)
-
这样改没啥用,
setq
并非set
语法糖. setq可以修改词法作用域的变量,set
则是专门用来修改全局变量的. 你用宏魔改setq,会破坏setq的语义,可能导致emacs整个都坏掉. -
对于编译的配置(比如doom)
setq
在编译时已经变成字节码, 再捣鼓setq
宏也不会有任何作用.
(byte-compile '(setq a 1))
;; => (byte-code "\301\211\207" [a 1] 2)
用宏改确实有问题,都不能启动了。直接改C代码的 setq 可以用了。 主要是 spacemacs 自己定义的很多变量,懒得看。 感谢各位。