2024 Clojure 状态调查!中分享您的想法。

欢迎!请访问关于页面以获取更多有关如何使用本站的信息。

0
Clojure

我来Clojure语言时间不长,正试图通过deftype定义一个包含可变字段的类,以下是定义。

我的程序是单线程的,没有人会使用我的代码,我已经承诺了。我知道不可变性的优点,但这个程序有超过5亿次更新,所以垃圾收集器将是主要的行为者,而不是我的代码。我已经试过了。

我在运行时遇到了两个问题。

*1. ; Execution error (IllegalArgumentException) at layout.core.Individual/idivlCopy (core.clj:161).
    ; No matching field found: fitness for class layout.core.Individual

我明白deftype的字段不是公共的,但idivlCopy的代码在deftype内部。在我看来,运行时似乎知道(.fitness this),但不熟悉(.fitness that)。

  • 这种行为的理由是什么?我如何解决这个问题呢?
  • 我怎么从私有(即deftype)代码区域访问私有的受保护的字段(that)?!

`

*2. ; Execution error (ClassCastException) at layout.core.Individual/idivlSwap (core.clj:173).
           ; class clojure.core.Vec cannot be cast to class clojure.lang.IEditableCollection
           ;    (clojure.core.Vec and clojure.lang.IEditableCollection are in unnamed module of loader 'app')

`

  • 注释说明这两个字段都是volatile-mutable的。为什么染色体向量在运行时不了解这一点?为什么我不能以volatile-mutable染色体向量-of :char-{ 的形式进行(assoc!)操作?

(definterface IIndividual

  (idivlCopy [that])                      ; Copies that Individual to this
  (idivlSwap [^Integer xP, ^Integer xQ])) ; Swaps two genes in the chromosome
  ; and somme more.
)

(deftype Individual                ; An individual has a fitness value and a chromosome
  [^{:volatile-mutable true}  ^Integer fitness,       ; Integer
   ^{:volatile-mutable true}           chromosome]    ; vector-of :char
 
  IIndividual

	:
	.

  (idivlCopy         ; Copies that Individual to this
    [_, that] 
*1  (set! fitness    (.fitness    that))         ; (set! fitness  999) worked!!
    (set! chromosome (.chromosome that))
    nil)

  (idivlSwap         ; Swaps the genes in the chromosome at alleles P and Q
    [this,
     ^Integer iP,                 ; index of allele P
     ^Integer iQ]                 ; index of allele Q
    (let [gP (chromosome iP),     ; gene  at allele P
          gQ (chromosome iQ)]     ; gene  at allele Q
*2    (assoc! chromosome iP gQ)
      (assoc! chromosome iQ gP)
      nil))

    ; and some more
    :
	.
)

1 个回答

0

你所做的是一些你不熟悉的事情。

  • 几乎从不需要^Integer,通常它是^long
  • Clojure不知道that是什么,因为你没有为它标记IIndividual
  • assoc! 只在传递性集合上工作,并返回一个新的集合 - 你需要使用其返回值,但在这种情况下,你根本不需要 assoc!,你需要 set!assoc 的组合

这是一个工作版本

(definterface IIndividual
  (idivlCopy [that])
  (idivlSwap [^long xP ^long xQ]))

(deftype Individual [^:volatile-mutable ^long fitness
                     ^:volatile-mutable chromosome]
  IIndividual
  (idivlCopy [_this that]
    (let [^Individual that that]
      (set! fitness (.-fitness that))
      (set! chromosome (.-chromosome that))
      nil))

  (idivlSwap [_this ^long iP ^long iQ]
    (let [gP (chromosome iP)
          gQ (chromosome iQ)]
      (set! chromosome (assoc chromosome iP gQ iQ gP))
      nil)))

(let [i1 (Individual. 1 [:TP53 :TNF])
      i2 (Individual. 2 [:EGFR :VEGFA])]
  (.idivlCopy i1 i2)
  (.idivlSwap i1 0 1))

但是请注意,交换方法仍然使用一个不可变向量,这可能不是你想要的结果。如果你决定使用可变的长整型数组,你还需要更改复制方法,以便数组不仅是分配而是复制,以避免实例之间共享相同的数据。

此外,如果你的数据以任何方式可表示为列,那么在各个方面使用 Tablecloth 都会更好。顺便说一下,Clojure 在 Zulip 上有一个非常友好的数据科学社区,Tablecloth 的作者们在那里。

...