Scheme 字典操作
Scheme dict operations
我想了解 lisp 中的一些 hashmap 代码,并使用 python 作为参考。
下面两个是不是大致一样?如果是这样,我怎样才能看到我的字典对象是什么样子的?
# create dict
>>> my_dict = dict()
> (define my_dict (make-hash-table))
# add keys
>>> my_dict['a'] = 1
>>> my_dict['b'] = 2
> (hash-set! my_dict 'a 1)
> (hash-set! my_dict 'b 2)
# get values
>>> my_dict.get('a')
> (hash-ref my_dict 'a)
# print the values?
print (my_dict)
> ??? How can I see what my hashmap contains in scheme?
Are the following two roughly the same?
当然可以,但是我会通过参考 Python.
来学习 Scheme 或任何 Lisp。
请注意,R6RS Scheme has hash tables 和散列 table 过程是标准库的一部分; R5RS 方案并非如此。因此,早期的 Scheme 实现通常有自己的 hash table 实现。 Guile Scheme 确实支持 R6RS 哈希 tables 和过程,但似乎也保持对旧过程的支持。我最熟悉的Scheme Chez Scheme也是如此。 Chez Scheme 用户指南 说包含旧式过程主要是为了与旧的 Chez Scheme 实现兼容,但在未来的版本中可能会放弃对它们的支持。我不知道 Guile 对此的立场是什么,但我建议尽可能使用标准 Scheme 过程以获得最大的可移植性并防止未来在您的实现中发生此类变化。
撰写本文时,Guile 已达到 v3.0.2; OP 版本是 v2.0.9,据我所知目前已有 5 年历史。 Guile 2.0.14 supports R6RS hashtables,所以我怀疑 Guile 2.0.9 也是如此。不管怎样,我都会用R6RS Standard Scheme来回答;如有必要,适应旧的 Guile 实施应该是微不足道的。
R6RS Standard Library没有make-hash-table
,而是有make-hashtable
、make-eq-hashtable
、make-eqv-hashtable
。 make-hashtable
过程需要一个测试键等价性的过程,而 make-eq-hashtable
测试与 eq?
的等价性,make-eqv-hashtable
测试与 eqv?
.
而不是 hash-set!
,标准库有 hashtable-set!
,它采用与 OP 对 hash-set!
.
相同的参数
而不是 hash-ref
,标准库有 hashtable-ref
。这与 OP hash-ref
的不同之处在于它需要第三个参数来指定找不到键时的默认 return 值。
跟随 OP 的脚步,可以创建和查询哈希 table:
Chez Scheme Version 9.5
Copyright 1984-2017 Cisco Systems, Inc.
> (define my-dict (make-eq-hashtable))
> (hashtable-set! my-dict 'a 1)
> (hashtable-set! my-dict 'b 2)
> (hashtable-set! my-dict 'c 3)
> (hashtable-set! my-dict 'd 5)
> (hashtable-set! my-dict 'e 7)
> (hashtable-set! my-dict 'f 11)
> (hashtable-set! my-dict 'g 13)
> (hashtable-ref my-dict 'e #f)
7
> (hashtable-ref my-dict 'h #f)
#f
> my-dict
#<eq hashtable>
How can I see what my hashmap contains in scheme?
可能最简单的做法是从散列 table 创建一个关联列表。 R6RS 中没有执行此操作的标准程序,但是 是 一个旧的 SRFI (SRFI-69) that included exactly such a procedure: hash-table->alist
。Guile 的 OP 实现可能包含这样一个程序,但它是使用 R6RS 标准方案易于实施:
(define (hashtable->alist ht)
(let-values (((ks vs) (hashtable-entries ht)))
(vector->list (vector-map cons ks vs))))
这里,hashtable-entries
过程采用散列 table 和 return 的两个值:键向量和对应值向量; let-values
用于绑定两个 return 值,以便它们可以使用。 vector-map
return 是将 ks
和 vs
的元素与 cons
的元素组合而成的向量,vector->list
从该向量创建一个列表。
> (hashtable->alist my-dict)
((f . 11) (e . 7) (c . 3) (b . 2) (a . 1) (g . 13) (d . 5))
诡计:为了完整性
上面的解决方案在Guile中是可行的,但是很多R6RS程序在Guile中默认不被识别。要使上述解决方案在 Guile 中工作,首先需要如下内容:
(import (rnrs hashtables (6)) ; for R6RS hash tables
(rnrs base (6))) ; for R6RS let-values
在查看 Guile 2.0.14 参考手册 后,另一个非 portable 解决方案显而易见。手册中没有描述 hash-table->alist
过程,但是 the documentation describes 如何使用 hash-map->list
过程从散列 table 创建关联列表:
(hash-map->list cons my-dict)
这只能用于使用 Guile 的特定实现哈希 table 构造函数(例如 make-hash-table
)创建的哈希 table,并且可能不适用于哈希 tables 使用 R6RS 构造函数创建(例如 make-eq-hashtable
)。再次注意这个解决方案应该在 Guile 中工作(没有任何导入),但不是 portable.
我想了解 lisp 中的一些 hashmap 代码,并使用 python 作为参考。
下面两个是不是大致一样?如果是这样,我怎样才能看到我的字典对象是什么样子的?
# create dict
>>> my_dict = dict()
> (define my_dict (make-hash-table))
# add keys
>>> my_dict['a'] = 1
>>> my_dict['b'] = 2
> (hash-set! my_dict 'a 1)
> (hash-set! my_dict 'b 2)
# get values
>>> my_dict.get('a')
> (hash-ref my_dict 'a)
# print the values?
print (my_dict)
> ??? How can I see what my hashmap contains in scheme?
Are the following two roughly the same?
当然可以,但是我会通过参考 Python.
来学习 Scheme 或任何 Lisp。请注意,R6RS Scheme has hash tables 和散列 table 过程是标准库的一部分; R5RS 方案并非如此。因此,早期的 Scheme 实现通常有自己的 hash table 实现。 Guile Scheme 确实支持 R6RS 哈希 tables 和过程,但似乎也保持对旧过程的支持。我最熟悉的Scheme Chez Scheme也是如此。 Chez Scheme 用户指南 说包含旧式过程主要是为了与旧的 Chez Scheme 实现兼容,但在未来的版本中可能会放弃对它们的支持。我不知道 Guile 对此的立场是什么,但我建议尽可能使用标准 Scheme 过程以获得最大的可移植性并防止未来在您的实现中发生此类变化。
撰写本文时,Guile 已达到 v3.0.2; OP 版本是 v2.0.9,据我所知目前已有 5 年历史。 Guile 2.0.14 supports R6RS hashtables,所以我怀疑 Guile 2.0.9 也是如此。不管怎样,我都会用R6RS Standard Scheme来回答;如有必要,适应旧的 Guile 实施应该是微不足道的。
R6RS Standard Library没有make-hash-table
,而是有make-hashtable
、make-eq-hashtable
、make-eqv-hashtable
。 make-hashtable
过程需要一个测试键等价性的过程,而 make-eq-hashtable
测试与 eq?
的等价性,make-eqv-hashtable
测试与 eqv?
.
而不是 hash-set!
,标准库有 hashtable-set!
,它采用与 OP 对 hash-set!
.
而不是 hash-ref
,标准库有 hashtable-ref
。这与 OP hash-ref
的不同之处在于它需要第三个参数来指定找不到键时的默认 return 值。
跟随 OP 的脚步,可以创建和查询哈希 table:
Chez Scheme Version 9.5
Copyright 1984-2017 Cisco Systems, Inc.
> (define my-dict (make-eq-hashtable))
> (hashtable-set! my-dict 'a 1)
> (hashtable-set! my-dict 'b 2)
> (hashtable-set! my-dict 'c 3)
> (hashtable-set! my-dict 'd 5)
> (hashtable-set! my-dict 'e 7)
> (hashtable-set! my-dict 'f 11)
> (hashtable-set! my-dict 'g 13)
> (hashtable-ref my-dict 'e #f)
7
> (hashtable-ref my-dict 'h #f)
#f
> my-dict
#<eq hashtable>
How can I see what my hashmap contains in scheme?
可能最简单的做法是从散列 table 创建一个关联列表。 R6RS 中没有执行此操作的标准程序,但是 是 一个旧的 SRFI (SRFI-69) that included exactly such a procedure: hash-table->alist
。Guile 的 OP 实现可能包含这样一个程序,但它是使用 R6RS 标准方案易于实施:
(define (hashtable->alist ht)
(let-values (((ks vs) (hashtable-entries ht)))
(vector->list (vector-map cons ks vs))))
这里,hashtable-entries
过程采用散列 table 和 return 的两个值:键向量和对应值向量; let-values
用于绑定两个 return 值,以便它们可以使用。 vector-map
return 是将 ks
和 vs
的元素与 cons
的元素组合而成的向量,vector->list
从该向量创建一个列表。
> (hashtable->alist my-dict)
((f . 11) (e . 7) (c . 3) (b . 2) (a . 1) (g . 13) (d . 5))
诡计:为了完整性
上面的解决方案在Guile中是可行的,但是很多R6RS程序在Guile中默认不被识别。要使上述解决方案在 Guile 中工作,首先需要如下内容:
(import (rnrs hashtables (6)) ; for R6RS hash tables
(rnrs base (6))) ; for R6RS let-values
在查看 Guile 2.0.14 参考手册 后,另一个非 portable 解决方案显而易见。手册中没有描述 hash-table->alist
过程,但是 the documentation describes 如何使用 hash-map->list
过程从散列 table 创建关联列表:
(hash-map->list cons my-dict)
这只能用于使用 Guile 的特定实现哈希 table 构造函数(例如 make-hash-table
)创建的哈希 table,并且可能不适用于哈希 tables 使用 R6RS 构造函数创建(例如 make-eq-hashtable
)。再次注意这个解决方案应该在 Guile 中工作(没有任何导入),但不是 portable.