Clojure write constructors are not first class?

Apparently, you cannot call a request using the record constructor:

(defrecord Foo. [id field]) (apply Foo. my-list) 

does not work while reading because it does not expect Foo. in this place.

The only obvious workaround I thought of was to add a factory function:

 (make-foo [id field] (Foo. id field)) 

which can be applied, of course.

Did I miss something? I would expect this from C # / Java, but just thought it was a little disappointing in Clojure ...

+7
source share
3 answers

Going back to this post 1.3 ....

In Clojure 1.3, defrecord creates two generated constructor functions. Given:

 (defrecord Person [first last]) 

this will create a position constructor function ->Person :

 (->Person "alex" "miller") 

and map->Person map constructor function:

 (map->Person {:first "string"}) 

Since this is a map, all keys are optional and take the value nil in the constructed object.

You should use / use these functions from ns where you declare the record, but you do not need to import the record class in the same way as when using the Java class constructor.

More details:

+10
source

Foo. is a constructor for the Java class, so it has the typical limitations of how Java interacts with what you call it. Creating a constructor function is a general solution (this also means that you do not need to import Foo in another namespace).

+6
source

The problem is known, and much is said on the Clojure mailing list. Additional support is likely to be added in future versions of Clojure.

Now you should use your own functions or use https://github.com/david-mcneil/defrecord2 , which supports some functions, such as:

  • print in a form that is subject to change
  • provides Clojure function as a constructor
  • accept named parameters (maps) in the constructor
  • participate in the multi-method pre / post walk
+3
source

All Articles