问题描述
我正在尝试构建一个函数(或宏),以简化哈希表深处的数据的获取和设置(意思是哈希内的哈希,哈希内的哈希等).我不认为我可以使用宏来实现,而且我不确定如何使用eval来实现.我希望能够执行以下操作:
I'm trying to build a function (or macro) to ease the getting and setting of data deep in a hash table (meaning, a hash within a hash, within a hash, etc). I don't think I can do it with a macro, and I'm not sure how to do it with eval. I'd like to be able to do the following:
(gethashdeep *HEROES* "Avengers" "Retired" "Tony Stark")
并返回钢铁侠"
所有哈希都是用以下方式创建的:
The hashes are all created with:
(setf hashtablename (make-hash-table :test 'equal))
并从那里填充.
我可以执行以下操作,但想对其进行抽象,以便可以以编程方式从任意深度提取值:
I can do the following, but would like to abstract it so I can programmatically pull a value from an arbitrary depth:
;;pulling from a hash that's 2 deep
(gethash "Tony Stark" (gethash "Avengers" *HEROES*))
更新-我要去做:
(defun getdeephash (hashpath h k)
(let* ((rhashpath (reverse hashpath))
(hashdepth (list-length hashpath))
(hashcommand (concatenate 'string "(gethash \"" k "\"")))
(loop for i from 1 to hashdepth
do (setf hashcommand (concatenate 'string hashcommand "(gethash \"" (nth (- i 1) rhashpath) "\"")))
(setf hashcommand (concatenate 'string hashcommand " " h (make-string (- hashdepth 0) :initial-element #\Right_Parenthesis) ")"))
(values hashcommand)))
推荐答案
它与访问权限库:
(ql:quickload "access")
我们定义 * heroes *
哈希表(如Xach的示例):
We define the *heroes*
hash table (as in Xach's example):
(defun table (&rest keys-and-values &key &allow-other-keys)
(let ((table (make-hash-table :test 'equal)))
(loop for (key value) on keys-and-values by #'cddr
do (setf (gethash key table) value))
table))
TABLE
(defparameter *heroes*
(table "Avengers"
(table "Retired" (table "Tony Stark" "Iron Man")
"Active" (table "Bruce Banner" "Hulk"))))
通常,我们使用 access:access
来一致地访问各种数据结构(alist,plist,哈希表,对象等).对于嵌套访问,我们使用 access:accesses
(复数):
Usually we use access:access
for a consistent access to diverse data structures (alist, plist, hash table, objects,…). For a nested access we use access:accesses
(plural):
(access:accesses *heroes* "Avengers" "Retired" "Tony Stark")
"Iron Man"
此外,我们可以 setf
:
(setf (access:accesses *heroes* "Avengers" "Retired" "Tony Stark") "me")
"me"
这是一个经过战斗验证的库,因为它是Djula模板库的核心,而Djula模板库是下载次数最多的Quicklisp库之一.
It is a battle tested library, since it is the core of the Djula template library, one of the most downloaded Quicklisp libraries.
我的博客文章: https://lisp-journey.gitlab.io/blog/generice-consistent-access-of-data-structures-dotted-path/
这篇关于Lisp:使用语法糖访问递归哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!