我正在使用refs,我需要一些帮助。
我这里有2个银行账户,分别为:operations
(ref :name "bank"
:accounts
{12345678 (ref {:name "joey"
:account-number 12345678
:operations (ref {:desc "DESC1" :amount 100 :date "2017-01-10"]})
(ref {:desc "DESC2" :amount 200 :date "2017-01-11"]})
(ref {:desc "DESC3" :amount 300 :date "2017-01-12"]})})
{87654321 (ref {:name "paul"
:account-number 12345678
:operations (ref {:desc "DESC1" :amount 50 :date "2017-01-10"]})
(ref {:desc "DESC2" :amount 10 :date "2017-01-11"]})
(ref {:desc "DESC3" :amount 30 :date "2017-01-12"]})})
})
我需要从所有帐户中获取所有:operations
来构建这样的集合:
[{:desc "DESC1" :amount 100 :date "2017-01-10"]}
{:desc "DESC2" :amount 200 :date "2017-01-11"]}
{:desc "DESC3" :amount 300 :date "2017-01-12"]}
{:desc "DESC1" :amount 50 :date "2017-01-10"]}
{:desc "DESC2" :amount 10 :date "2017-01-11"]}
{:desc "DESC3" :amount 30 :date "2017-01-12"]}]
不要只是一个想法,我尝试使用map
和deref
,但仍然坚持。
答案 0 :(得分:1)
您的代码存在许多问题,需要对其进行整理。虽然clojure对并行/并发有很大的支持,但您需要首先获得正确的基础知识。处理多个活动线程很难并且试图解决这个问题,同时也试图弄清楚基本数据结构和核心功能如何工作将使它几乎不可能。
ref函数用法:(ref x) (ref x& options)创建并返回一个Ref,其初始值为x,零个或多个选项(按任意顺序):
:元元数据地图
:validator validate-fn
:min-history(默认为0):max-history(默认为10)
如果提供了元数据映射,它将成为ref的元数据。 validate-fn必须为nil或一个参数的无副作用fn, 任何状态变化都将通过预期的新状态。如果 新状态是不可接受的,validate-fn应返回false或 抛出一个例外。将在事务提交时调用validate-fn, 当所有裁判都有他们的最终价值时。
通常refs根据需要动态累积历史记录来处理 阅读要求。如果您事先知道,您将需要历史记录,您可以设置 :min-history以确保它在第一次需要时可用(相反 在读取故障之后)。历史有限,可以设置限制 with:max-history。在Clojure 1.0版中添加
您在开始时使用的两个关键字看起来可能正在尝试为ref定义元数据。在定义ref时你需要使用:meta选项(这是我对你的真实意图的猜测,可能完全不正确)。
ref的必需参数是初始值。这需要是一个有效的clojure'结构'或一个返回一个的函数。在您的情况下,您看起来像是想要一张地图。
我认为你不想要嵌套引用。从技术上讲,我认为你可以定义它们,这几乎肯定不是你真正想要的。阅读refs and transactions以了解为什么您可能不想这样做以及它对执行STM的影响。一般的经验法则是隔离确保管理所需的值。您需要细粒度的访问控制,并且您希望避免嵌套访问控制,因为它会使事情变得过于复杂,并且您的访问控制将变得粗略。考虑您的银行帐户操作。您只想在仅运行其中一个或两个银行帐户时锁定所有银行帐户 - 您只想锁定/控制所涉及帐户的更新。您可能想要的是refs的数组(向量)或者可能是普通的hash-map,其中一个键是帐户,值是ref,而ref又是一个地图,其中包含您需要确保更新的值一个事务(其他选项包括信号量或关键区域方法,因为ref是一个简单的标记/锁定,它确定交易是否可以继续或必须回收并再次尝试。
我认为您可能想要更多地考虑一下您的数据结构。稍微使用哈希映射并尝试嵌套结构。在这些基本和嵌套数据结构上使用核心函数(映射,过滤,减少,循环/重复,序列和懒惰等等)。获取正确的基本抽象,然后查看如何更改它以确保您的一致性数据,即如何确保您的事务是适当的原子,特别是当涉及多个帐户时。您当前的嵌套结构无效 - 例如,查看:操作值。这是什么值?它是事务引用的向量吗?如何clojure知道这是一个向量吗?你的应用程序将如何提取数据?最常见的操作是什么?将它们全部解压缩或提取单个事务?它们是否需要按日期顺序排列?获取数据是多么容易特定日期的交易?一旦你拥有成千上万笔交易的数百个账户等等,这是否会扩大规模。让你的抽象正确,简单的事情仍然很容易。弄错了,容易的事情会变得困难和艰难的事情ngs可能会更难。