Fork me on GitHub
#clojure
<
2016-11-11
>
jasonjckn01:11:26

in the AOT compilation the top levels defs are evaled, but their value is discarded and recomputed again when I execute the jar file?

jasonjckn01:11:01

i was trying to read some ENV vars in my top levels defs, but the env vars are only set when i call java -jar, not lein uberjar

seancorfield01:11:29

Correct. Top-level def (and defn) forms are evaluated whenever the namespace is loaded. That happens when AOT occurs (it has to load the namespace to compile it) and it happens when you run the uberjar (again, it has to load the namespace in order to run the code).

seancorfield01:11:56

In general, you should avoid performing any computation in a def because of that.

seancorfield01:11:05

If you want to perform a calculation once and cache it, using (def my-sym (delay some-expression)), and then @my-sym to reference the value, will delay(!) the evaluation of some-expression until the first use of @my-sym at runtime.

seancorfield01:11:51

That’s a bit of a hack tho’… Computing global “state” once at application startup, called from your -main function, is better (and then passing it through function call chains). Stuart Sierra’s Component library is a reasonable approach.

seancorfield01:11:56

Oh, and if you go with the delay route, remember that (def my-other-sym @my-sym) will force a dereference at load time and thus you’ll be back in the situation you started in...

adambrosio03:11:47

@danielstockton maybe, but i find it helps if you have some pairs on the same line and others split

adambrosio03:11:10

that way you can train yourself to look for some common text to help you decipher a cond

adambrosio03:11:37

but i think i agree for most cases

roelofw06:11:34

hello, is first doing the clojure koans and then 4clojure a good way to learn clojure properly ?

jimmy06:11:15

I find it's a good way, even better if you are reading Programming Clojure on the way as well.

roelofw06:11:58

oke, I tried to learn clojure with the brave book but that one is way to fast for me.

roelofw06:11:16

The exercises/challenges were to difficult

roelofw06:11:09

@nxqd thanks, I found the book

roelofw07:11:29

Is this one good :

"When things cannot be equal, they must be different"
  (not= :true true)) 
the tests are green

danielstockton10:11:46

@adambros @cschep https://github.com/clojure-emacs/clojure-mode/issues/337 I found my answer. The indent spec can be a function, so pretty much anything is possible.

danielstockton10:11:09

The last comment worked perfectly for me.

borkdude13:11:49

Has anyone experience with AnalyzingInfixSuggester from lucene, in a REPL? I’m running into Lock obtain timed out: NativeFSLock when I want to rebuild an instance

borkdude17:11:22

I want to extend a Java class that needs a mutable field in Clojure. I chose defrecord. How should I model the mutable field, with an atom?

borkdude17:11:49

maybe deftype is better here

borkdude17:11:37

How do I combine a type hint with volatile-mutable?

Alex Miller (Clojure team)17:11:15

records can’t extend Java classes

Alex Miller (Clojure team)17:11:54

if you want a typed volatile field, just stack up the meta

Alex Miller (Clojure team)17:11:45

but note that the only “types” that actually matter are double and long

Alex Miller (Clojure team)17:11:05

all other fields are always constructed as Object type

Alex Miller (Clojure team)17:11:04

so like (deftype T [^:volatile-mutable ^long f]) for a type with a mutable long field

moxaj17:11:26

@alexmiller out of curiosity, why only double and long? Perhaps related to the ifn permutations?

Alex Miller (Clojure team)17:11:38

they are the only primitive types Clojure uses

Alex Miller (Clojure team)17:11:33

So ^long and ^double type hints typically do something more than any other type hint (they affect the code that’s generated, not just type inference on Java calls)

Alex Miller (Clojure team)17:11:00

in records and fields, they affect the field type. in functions, they affect the parameter types.

Alex Miller (Clojure team)17:11:32

so at the jvm level, the bytecode Clojure creates pretty much only cares about long, double, and Object. (hand-waving many details)

borkdude17:11:01

it turned out I was implementing an interface, not extending a class. so I’m good still with deftype\

hoppy17:11:22

does anybody have a good technique for picking up a package version (aka from lein defproject) in a way that works both in a repl, and in an uberjar? Also, this is in a library, and the library's version would be the one I'm after) from within the library code.

borkdude17:11:29

How do I add the following method: public BytesRef next() throws IOException I tried: (next ^BytesRef [this] …)

borkdude17:11:55

but I get the following error:

Method
   dre/index/terms_extra/TermIterator.next()Lorg/apache/lucene/util/BytesRef;
   is abstract

Alex Miller (Clojure team)17:11:53

is this using any of the new Java 8 stuff for default methods perhaps?

Alex Miller (Clojure team)17:11:15

you don’t need to type-hint that btw - just (next [this] …) should be sufficient

Alex Miller (Clojure team)17:11:39

you could also be running into something weird with generic bridge methods

Alex Miller (Clojure team)17:11:21

people seem to not like this advice, but sometimes the easiest thing to do is to just write a thin Java shim

borkdude17:11:36

yes, that’s what I had, but it didn’t play nice with my boot project ...

borkdude17:11:54

I think I’m going to carve it out into its own project...

Alex Miller (Clojure team)17:11:05

what interface are you implementing here?

Alex Miller (Clojure team)17:11:48

dunno, not obvious to me why that wouldn’t be feasible

borkdude17:11:00

Dependencies:

[org.apache.lucene/lucene-core "4.9.1"]
[org.apache.lucene/lucene-suggest "4.9.1"]

borkdude17:11:34

I suppose you can redefine deftypes in the REPL right?

borkdude17:11:33

ah it worked

borkdude17:11:46

REPL state I think

Alex Miller (Clojure team)17:11:06

I’d get rid of the type hint. and I don’t see the need for the current field?

Alex Miller (Clojure team)17:11:29

you could just reify this impl too, you don’t even need a deftype afaict

borkdude17:11:08

the current field is used in the payload method which I had to implement still

Alex Miller (Clojure team)17:11:24

ah, was wondering about that

borkdude17:11:25

do you mean reify, because I only need one instance?

Alex Miller (Clojure team)17:11:35

no, b/c I didn’t see anything stateful

Alex Miller (Clojure team)17:11:01

which you could still do with reify even, by just closing over a volatile

borkdude17:11:45

I’m wondering about the ‘constructor’, I guess just a normal function and then calling (TermIterator. x nil)?

Alex Miller (Clojure team)17:11:15

my personal preference is to always use the generated constructor (->TermIterator x nil)

Alex Miller (Clojure team)17:11:50

the fact that it’s generating a Java class is an implementation detail (and different in CLJS)

Alex Miller (Clojure team)18:11:02

reify version would be like:

Alex Miller (Clojure team)18:11:04

(defn term-iterator [iter]
(let [current (volatile nil)]
  (reify InputIterator
    (weight [this] 0)
    (payload [this] @current)
    (hasPayloads [this] true)
    (context [this] nil)
    (hasContext [this] false)
    (next [this]
      (when (.hasNext iter)
        (vreset! current (.next iter))
        (BytesRef. (.getBytes ^String (:term @current))))))))

Alex Miller (Clojure team)18:11:04

if you don’t need a type (and I don’t think you do), then I wouldn’t make one - it complicates everything about compilation, work at the repl, etc

borkdude18:11:12

cool, it worked:

(suggest s "heart att" 5) ;; (#dre.index.terms_extra.Term{:uri "x", :term "heart attack”})

borkdude18:11:02

this is very useful for me, because now I have my REPL experience back with this piece of code 🙂

jasonjckn18:11:58

@seancorfield thank you, that's very helpful

borkdude19:11:41

(never mind, was just a typo, context should be contexts)

borkdude19:11:50

Is there a common supertype that I can use to get rid of the reflection warning, as long it’s a seq/collection-ish thing? (.iterator items)

borkdude19:11:00

it seems not

borkdude19:11:05

Both vectors and lazy seqs do return iterators though

luxbock19:11:42

is there such a thing as test/simulation driven optimization, where you write generative tests or something similar for the performance sensitive parts of your code, and the compiler is able to figure out the hoth code paths and generate efficient code based on those?

luxbock19:11:03

kind of like a JIT, but the code would be AOT compiled based on the profiling info gained from running the tests

bja19:11:46

@luxbock I don't think anything like that exists for clojure, mostly because almost all clojure runs in JIT'd environments..

luxbock19:11:22

in theory could you somehow instruct the JIT to cache its optimizations during this step, and then get code that starts up and finds its hot code paths faster than otherwise?

Alex Miller (Clojure team)20:11:36

@luxbock they are working on AOT Java which maybe would be something like that

borkdude20:11:53

eh yes, that works! 😊

Alex Miller (Clojure team)20:11:08

although I guess that compiled binary would not be optimized for any particular profile and it could still recompile later. I don’t know.

Alex Miller (Clojure team)20:11:22

would help startup time to provide Clojure core jar in that mode though

mikeb22:11:14

@alexmiller top comment about JEP 295 on https://news.ycombinator.com/item?id=12807906 says "No dynamic byte code (Lambda Expressions, Dynamic Classes, etc.)". Would clojure need dynamic bytecode?

mikeb22:11:31

Also it mentions that this wouldn't have much if any effect on startup time, because it only bypasses the interpreted phase before the 10k invocations number is hit to trigger a compile, but it might help clojure because has to read/load so many vars.

Alex Miller (Clojure team)22:11:03

Clojure does not currently use any of those features

ghadi22:11:06

I believe they (JDK stewards) are still in early research phase on how to handle some of the late binding aspects of Java bytecode

ghadi22:11:21

(e.g. invokedynamic, which powers Lambda Expressions)

ghadi22:11:18

"ConstantDynamic"

idiomancy22:11:01

is hickory the industry standard for parsing html in clojure?