如何在 Clojure 中编写 Java 对象的 public 字段?

How to write a public field of a Java object in Clojure?

This question 回答如何从 Java 对象读取 public 字段:

(let [p (java.awt.Point.)]
  (.x p))  ; <- returns 0

我想我可以用类似的方式写这个字段:

(let [p (java.awt.Point.)]
  (.x p 42))

但我收到以下错误:

IllegalArgumentException No matching method found: x for class java.awt.Point
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)

这在 Clojure - Java Interop:

(set! (. instance-expr instanceFieldName-symbol) expr)

Assignment special form.

When the first operand is a field member access form, the assignment is to the corresponding field. If it is an instance field, the instance expr will be evaluated [and assigned to the corresponding instance field].

另请注意在解析字段时使用“-”:

If the second operand [of (. instance-expr member)] is a symbol starting with -, the member-symbol will resolve only as field access (never as a 0-arity method) and should be preferred when that is the intent..."

因此:

(set! (. p -x) 42)

或者,“访问字段或方法成员的首选惯用形式” 略有不同,这种等效性显示在页面顶部的宏扩展中。

(set! (.-x p) 42)