我正在为 XDR 移植哈希代码通信,所以它需要散列数据类型才能发送。类型应为 uint8 sint8、uint16、sint16、...、sint64
;; lisp types -- byte := bit
(deftype uint8 () '(UNSIGNED-BYTE 8))
(deftype sint8 () '(SIGNED-BYTE 8)) ;
(deftype uint16 () '(UNSIGNED-BYTE 16))
(deftype sint16 () '(SIGNED-BYTE 16))
(deftype uint32 () '(UNSIGNED-BYTE 32))
(deftype sint32 () '(SIGNED-BYTE 32))
(deftype uint64 () '(UNSIGNED-BYTE 64))
(deftype sint64 () '(SIGNED-BYTE 64))
“我正在使用 SBCL”
数据存储在指定类型的结构中
问题:
- 当数据为 0 或 1 时,它获得适合所有 -fixnum、unsigned-byte、signed-byte- 类型的类型位。
- 类型大小推断!!签名和未签名
- 类型使用类型层次结构,所以我不能有唯一的类型。
我只使用类型来散列结构(etypecase
,subtypep
)
我已阅读 Xdr-Binding-to-Lisp ,但我不明白他们如何使用 case
或 typecase
来区分 uint8 和 sint8。 drx on github使用 encode_int、encode_array、...
我想要的:
(defstruct example
(x 0 :type lcm:sint32)
(y "blablabla" :type string)
(z 1.8d0 :type double-float))
使用(etypecase
, subtypep
)快速散列结构槽信息。
编辑:
我想对 lisp-structure TYPE SLOTS
“string sint8 float array”进行哈希处理,以便在接收/发送时正确读取数据。如果我有一个结构。圣:
(typecase st
(structure-object (recursive do this))
(sint8 (do this))
(string (recursive do this))
(uint8 ( do this))
...
我使用 typecase 递归地转换类型信息。 ---> 整数
结构体定义代码如下:
(defvar *struct-types* (make-array 0
:adjustable t
:fill-pointer 0))
(defmacro deflcmstruct (name options &rest slots)
"Define a struct"
(let ((slot-types '()))
`(progn
(defstruct (,name (:include lcm-type options))
,@(mapcar (lambda (slot)
(destructuring-bind (slot-name slot-type &rest slot-args)
slot
()
(declare (ignore slot-type))
`(,slot-name ,@slot-args)))
slots))
,(vector-push-extend *struct-types* name)
,(vector-push-extend *struct-types* (make-hash-table))
问题:
- 如果 lisp 结构有一个带数字的槽:5 如何让 lisp 将 5 类型唯一地理解为 sint8/uint8/sin16/uint16,但不能只适合所有这些类型?
- 如何使用 lisp 散列数据类型(自定义)?
- 如果我必须存储类型定义。那么有什么选择呢?我正在考虑使用
gensym
构建一个哈希表,但是这个哈希表会四处 float !! - 如何使数据类型结构隔离?或者更好的设计?
- 例子会很棒。
提前致谢
最佳答案
以下是您可以如何操作的示例:
(defgeneric generic-hash (object))
(defmethod generic-hash ((x integer))
(error “GENERIC-HASH does not work on integers as it does not know what size field to put them in.”))
(defun hash-for-type (type)
;; could also be done with a hash table
(case type
(uint8 'hash-uint8)
;; ...
(otherwise 'generic-hash)))
(defun hash-function-for-struct-definition (var name slots)
(flet ((access (sym)
(intern (concatenate 'string (symbol-name name) "-" (symbol-name sym)) (symbol-package sym))))
(let ((hashed-slots
(loop for slot in slots collect
(let ((type (etypecase slot (symbol t) (cons (or (getf :type slot) t))))
(name (if (consp slot) (car slot) slot)))
(list (hash-for-type type) (list (access name var)))))))
(reduce (lambda (a b) (list 'combine-hash a b)) hashed-slots))))
(defmacro my-defstruct (name &rest slots)
(let* ((var (gensym)) (hash (hash-function-for-struct-definition var name slots)))
`(progn
(defstruct ,name ,@slots)
(defmethod generic-hash ((,var ,name))
,hash))))
诀窍在于,虽然您无法通过字段中的值判断字段的类型,但您确实在结构定义时获得了类型,因此您可以定义自己的类似 defstruct 的宏,知道类型字段,可以根据声明的类型生成合适的方法。第二种方法是在运行时检查对象的类,但相比之下这会很慢,而且编译器可能根本无法优化它。
关于data-structures - 如何使用结构成员类型进行散列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51845973/