gpt4 book ai didi

lisp - 使用 gensym 和 macrolet 构建哈希表

转载 作者:太空宇宙 更新时间:2023-11-03 18:50:15 25 4
gpt4 key购买 nike

我正在尝试在读取时构建哈希表(以及其他操作)。我不希望散列表具有全局范围(目前),所以我使用宏和 gensym 来实现。在宏 x 中,我定义了一个宏 s,它类似于 setf,但在哈希表中定义了一个条目,而不是定义某处的一个符号。它爆炸了。我想我理解了错误消息,但我该如何让它发挥作用?

代码:

#!/usr/bin/clisp -repl

(defmacro x (&rest statements)
(let ((config-variables (gensym)))
`(macrolet ((s (place value)
(setf (gethash 'place ,config-variables) value)))
(let ((,config-variables (make-hash-table :test #'eq)))
(progn ,@statements)
,config-variables))))

(defun load-config ()
(let ((config-file-tree (read *standard-input*)))
(eval config-file-tree)))

(defun load-test-config ()
(with-input-from-string (*standard-input* "(x (s fred 3) (s barney 5))")
(load-config)))

(load-test-config)

输出:

*** - LET*: variable #:G12655 has no value
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of #:G12655.
STORE-VALUE :R2 Input a new value for #:G12655.
SKIP :R3 skip (LOAD-TEST-CONFIG)
STOP :R4 stop loading file /u/asterisk/semicolon/build.l/stackoverflow-semi

最佳答案

只是猜测 Bill 可能真正想要什么。

假设他想要从一些键到一些值的映射作为文件中的配置。

这是程序的方式。

  • 打开数据流
  • 把它读成一个s-expression
  • 遍历数据并填充哈希表

示例代码:

(defun read-mapping (&optional (stream *standard-input*))
(destructuring-bind (type &rest mappings) (read stream)
(assert (eq type 'mapping))
(let ((table (make-hash-table)))
(loop for (key value) in mappings
do (setf (gethash key table) value))
table)))

(defun load-config ()
(read-mapping))

(defun load-test-config ()
(with-input-from-string (*standard-input* "(mapping (fred 3) (barney 5))")
(load-config)))

(load-test-config)

使用:

CL-USER 57 > (load-test-config)
#<EQL Hash Table{2} 402000151B>

CL-USER 58 > (describe *)

#<EQL Hash Table{2} 402000151B> is a HASH-TABLE
BARNEY 5
FRED 3

优点:

  • 没有宏
  • 数据没有在源代码和生成的源代码中编码
  • 无需通过 EVAL 进行评估(安全!)
  • 没有目标代码因扩展为更大代码的宏而膨胀
  • 功能抽象
  • 更容易理解和调试

或者,我会为 { 编写一个读取宏,这样 {(fred 3) (barney 5)} 将直接作为哈希表读取。


如果你想要计算值:

(defun make-table (mappings &aux (table (make-hash-table)))
(loop for (key value) in mappings
do (setf (gethash key table) (eval value)))
table)

CL-USER 66> (describe (make-table '((fred (- 10 7)) (barney (- 10 5)))))

#<EQL Hash Table{2} 4020000A4B> is a HASH-TABLE
BARNEY 5
FRED 3

把它变成一个宏:

(defmacro defmapping (&body mappings)
`(make-table ',mappings))

(defmapping
(fred 3)
(barney 5))

关于lisp - 使用 gensym 和 macrolet 构建哈希表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8629565/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com