【问题标题】:how to use structure member types for hashing?如何使用结构成员类型进行散列?
【发布时间】:2018-08-14 16:28:49
【问题描述】:

我正在为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、无符号字节、有符号字节类型的类型位。
  • 类型大小推断!!有符号和无符号的
  • 类型使用类型层次结构,所以我不能有唯一类型。

我只使用类型来散列结构(etypecasesubtypep

我读过Xdr-Binding-to-Lisp,但我不明白他们如何使用casetypecase 来区分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" 以在接收/发送时正确读取数据。如果我有一个结构。 st:

(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 结构有一个带有数字 say: 5 的槽,如何让 lisp 将 5 种类型唯一地理解为 sint8/uint8/sin16/uint16,但不能只适合所有这些类型?
  • 如何使用 lisp 散列数据类型(自定义)?
  • 如果我必须存储类型 def.那么有什么选择呢?我正在考虑使用gensym 构建一个哈希表,但是这个哈希表会四处浮动!!
  • 如何使数据类型结构隔离?或者更好的设计?
  • 示例会很棒。

提前致谢

【问题讨论】:

  • 我认为你应该定义你自己的结构定义宏,它也会为结构生成一个散列函数
  • 这是我所做的,但我想看看是否有比浮动哈希表更好的。
  • 这句话没有任何意义。您能否也调整一下您的问题,以举例说明您已经拥有或想要获得什么。
  • 没有。什么是lcm型?什么是期权?你在哪里做任何哈希?我所看到的只是一个哈希表。我不明白你想要什么?
  • etypecasesubtypep 与散列有什么关系?

标签: data-structures encoding lisp common-lisp static-typing


【解决方案1】:

这里有一个例子说明你可以如何做到这一点:

(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 的宏,它知道字段,可以根据声明的类型生成合适的方法。第二种方法是在运行时检查对象的类,但相比之下会很慢,编译器可能根本无法优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    相关资源
    最近更新 更多