1

I have tried to use gen-and-load-class from clojure.core and then use custom class loader to call defineClass with generated bytecode, but when I call

(foo.bar.MyClass.)

I'm getting

CompilerExceptionjava.lang.NoClassDefFoundError: Could not initialize class foo.bar.MyClass

UPDATE:

So I used deftype as suggested by @Elogent :

(defprotocol Struct
  (getX [this path] "Get value")
  (setX [this ^long value path] "Get value"))
(deftype Foo 
  [
  ^{:tag long :unsynchronized-mutable true} a 
  ^{:tag long :unsynchronized-mutable true} b 
  ^{:tag long :unsynchronized-mutable true} c]
  Struct
  (getX
    [this [head & tail]]
    (let [field (condp = head
          'a a
          'b b
          'c c)]
      (if (empty? tail)
        field
        (getX field tail))))
  (setX
    [this value [head & tail]]

    (if (empty? tail)
        (condp = head
          (set! a (long value))
          (set! b (long value))
          (set! c (long value)))
        (condp = head
          (setX a value tail)
          (setX b value tail)
          (setX c value tail)))))

After AOT when I do javap Foo.class I got:

public final class struct.core.Foo implements struct.core.Struct,clojure.lang.IType {
  public static final clojure.lang.Var const__0;
  public static final java.lang.Object const__1;
  public static final clojure.lang.Var const__2;
  public static final java.lang.Object const__3;
  public static final clojure.lang.Var const__4;
  public static final clojure.lang.AFn const__5;
  public static final clojure.lang.AFn const__6;
  public static final clojure.lang.AFn const__7;
  public static final clojure.lang.Var const__8;
  public static final clojure.lang.Var const__9;
  public static final clojure.lang.Var const__10;
  public static final clojure.lang.Var const__11;
  public static final clojure.lang.Var const__12;
  long a;
  long b;
  long c;
  public static {};
  public struct.core.Foo(long, long, long);
  public static clojure.lang.IPersistentVector getBasis();
  public java.lang.Object setX(java.lang.Object, java.lang.Object);
  public java.lang.Object getX(java.lang.Object);
}

This is exactly what I need. Thank you @Elogent!

Lambder
  • 2,953
  • 1
  • 26
  • 20
  • 1
    What problem specifically are you trying to solve? In other words, for what purpose do you need this Java class that you are defining? – Sam Estep Nov 03 '15 at 17:30
  • I'm building prototype allowing to build succinct functional and cache oblivious data structures. For that I need to build equivalent of C strict, model data structures as arrays without using references etc. – Lambder Nov 04 '15 at 07:45
  • Why? What's wrong with [`defrecord`](http://clojuredocs.org/clojure.core/defrecord) or [`deftype`](http://clojuredocs.org/clojure.core/deftype) in this case? – Sam Estep Nov 04 '15 at 11:46
  • I need mutable primitive and array fields. – Lambder Nov 04 '15 at 11:47
  • `deftype` gives you that. – Sam Estep Nov 04 '15 at 11:49
  • Why do you need to get rid of the `const__*` fields? They're static, so they don't add to the size of each `struct.core.Foo` created. – Sam Estep Nov 05 '15 at 17:11
  • You are absolutely right. I managed to miss it somehow. Thank you – Lambder Nov 05 '15 at 17:14

1 Answers1

1

Unless you absolutely need all the flexibility of a Java class, I would advise that you use deftype instead. As explained here, deftype gives you access to lower-level constructs such as primitive types and mutability in an idiomatic way.

Sam Estep
  • 12,974
  • 2
  • 37
  • 75