Clojure 计算持久数据结构的SHA
是否有一个库可以为持久数据结构计算某种类型的Clojure 计算持久数据结构的SHA,clojure,Clojure,是否有一个库可以为持久数据结构计算某种类型的SHA (sha(pr str))不起作用,因为有时打印时键的顺序不一样。这取决于您想要它做什么。对于最简单的用例,clojure.core/hash就可以了。但由于“数据结构”是一种比“字节序列”复杂得多的输入格式,所以指纹没有明显的通用概念——你必须决定它需要什么功能。这实际上取决于你想要它做什么。对于最简单的用例,clojure.core/hash就可以了。但由于“数据结构”是比“字节序列”复杂得多的输入格式,指纹没有明显的通用概念-你必须决定它
SHA
(sha(pr str))
不起作用,因为有时打印时键的顺序不一样。这取决于您想要它做什么。对于最简单的用例,clojure.core/hash
就可以了。但由于“数据结构”是一种比“字节序列”复杂得多的输入格式,所以指纹没有明显的通用概念——你必须决定它需要什么功能。这实际上取决于你想要它做什么。对于最简单的用例,clojure.core/hash
就可以了。但由于“数据结构”是比“字节序列”复杂得多的输入格式,指纹没有明显的通用概念-你必须决定它需要什么功能。我通过谷歌搜索发现了以下问题和讨论,即是否有一种加密强大的方法将无序集合元素的加密强散列值组合成整个集合的加密强散列,无视秩序。一个答案声称,将元素的散列值排序为一个位字符串,然后在该字符串上计算加密强散列,应该是强散列。XORing或将元素的散列添加在一起是不正确的。我没有阅读所有的回答,因此可能有更好的方法:通过谷歌搜索,我发现了以下问题和讨论,即是否有一种加密强大的方法可以将无序集合元素的加密强散列值组合成整个集合的加密强散列,而忽略顺序。一个答案声称,将元素的散列值排序为一个位字符串,然后在该字符串上计算加密强散列,应该是强散列。XORing或将元素的散列添加在一起是不正确的。我没有阅读所有的响应,因此可能有更好的方法:虽然它不是一个加密函数,clojure.core/hash unordered coll
将为您提供一个一致的哈希值,只要集合具有相同的内容,也许您可以利用它:
user=> (hash-unordered-coll (sorted-map :b 2 :a 1))
161871944
user=> (hash-unordered-coll {:b 2, :a 1})
161871944
user=> (hash-unordered-coll [[:b 2] [:a 1]])
161871944
请参见虽然它不是一个加密函数,
clojure.core/hash unordered coll
将为您提供一个一致的哈希值,只要集合具有相同的内容,也许您可以利用它:
user=> (hash-unordered-coll (sorted-map :b 2 :a 1))
161871944
user=> (hash-unordered-coll {:b 2, :a 1})
161871944
user=> (hash-unordered-coll [[:b 2] [:a 1]])
161871944
请参见该函数实现了一个可跨不同类型安全使用的比较器。您可以将其与按
排序的地图和按
排序的集相结合,以便将所有地图/集转换为始终以相同顺序打印的稳定版本。然后(sha(pr str XXX))
的技术就会起作用
上述逻辑已在函数中可用。该函数还执行它在tin上所述的操作。现在,最终的解决方案是:
(ns demo.core
(:require
[tupelo.core :as t]
[tupelo.misc :as tm] ))
(tm/str->sha (pr-str (t/unlazy XXX)))
其中,XXX
是任何Clojure集合。演示代码:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.core :as t]
[tupelo.misc :as tm]))
(dotest
(let [stuff {:hello "there"
1 [2 3 4]
"gooodbye" #{"cruel" :world}
'forever ['and "ever" :and #{"ever" 'more}]}
stuff-str (pr-str (t/unlazy stuff))
stuff-sha (tm/str->sha (pr-str (t/unlazy stuff)))]
(is= stuff-str
"{:hello \"there\", forever [and \"ever\" :and #{more \"ever\"}], 1 [2 3 4], \"gooodbye\" #{:world \"cruel\"}}")
(is= stuff-sha "af3ade069e7a33139f5ee1fd1d35fd82807e3b1c")))
该函数实现了一个可跨不同类型安全使用的比较器。您可以将其与按
排序的地图和按
排序的集相结合,以便将所有地图/集转换为始终以相同顺序打印的稳定版本。然后(sha(pr str XXX))
的技术就会起作用
上述逻辑已在函数中可用。该函数还执行它在tin上所述的操作。现在,最终的解决方案是:
(ns demo.core
(:require
[tupelo.core :as t]
[tupelo.misc :as tm] ))
(tm/str->sha (pr-str (t/unlazy XXX)))
其中,XXX
是任何Clojure集合。演示代码:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.core :as t]
[tupelo.misc :as tm]))
(dotest
(let [stuff {:hello "there"
1 [2 3 4]
"gooodbye" #{"cruel" :world}
'forever ['and "ever" :and #{"ever" 'more}]}
stuff-str (pr-str (t/unlazy stuff))
stuff-sha (tm/str->sha (pr-str (t/unlazy stuff)))]
(is= stuff-str
"{:hello \"there\", forever [and \"ever\" :and #{more \"ever\"}], 1 [2 3 4], \"gooodbye\" #{:world \"cruel\"}}")
(is= stuff-sha "af3ade069e7a33139f5ee1fd1d35fd82807e3b1c")))
我所知道的所有加密强散列函数都是位序列的函数。要使用其中之一,您需要为无序的持久数据结构选择一个可预测的顺序。对于作为集合元素/映射键的受限值集,例如整数或字符串,定义顺序很简单。对于不同类型的集合元素/映射键的任意混合,定义覆盖任意集合的总顺序并不容易。这里的Hacky部分代码:我所知道的所有加密强散列函数都是位序列的函数。要使用其中之一,您需要为无序的持久数据结构选择一个可预测的顺序。对于作为集合元素/映射键的受限值集,例如整数或字符串,定义顺序很简单。对于不同类型的集合元素/映射键的任意混合,定义覆盖任意集合的总顺序并不容易。黑客部分代码: