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)代码区域访问私有受保护的字段(of 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。为什么染色体向量在运行时不知道这一点?为什么我不能(assoc! ) my volatile-mutable染色体向量-of :char -s?

(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))

但是请注意,交换方法仍然使用不可变向量,这可能不是您想要的。如果您决定使用longs的可变数组,您还必须更改copy方法,以确保数组不仅是分配,还要复制,以避免实例之间共享相同的数据。

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

...