Fork me on GitHub
#clojure
<
2017-03-14
>
yonatanel00:03:39

So, with socket server I could examine internal state of a running clojure server in production?

ag01:03:56

if I have a macro that creates bunch of defs, something like:

(defmacro multidef
  [table-names]
  `(do ~@(for [t table-names]
           `(def ~(symbol t) (str ”def-” t)))))
if used: (multidef [”foo” “bar”) it will create my-ns/foo and my-ns/bar and now I also want them to be in a vector where each element of is reference to defs, e.g. (def tables [foo bar]) how do I do that?

hiredman01:03:24

You can do that, but an alternative, which knowing nothing about your macro, I think would be superior, would be to get your macro out of the def business altogether. Have your macro expand to a vector, def the result if you must

ag01:03:17

I need to be able to refer to each thing individually and through another “shared” def

hiredman01:03:24

If you expand to vector, you can bind that vector to any name you like, in whatever scope

hiredman01:03:11

If you bake in global name definition in your macro, it can only be used to create global names

hiredman01:03:25

(which seems like a common pitfall when writing macros)

hiredman01:03:57

(def foo [a b c]) you can refer to each part of the vector without naming them

hiredman01:03:20

(nth foo 1)

ag01:03:12

ok, let me dig from the other side: let’s say I have bunch of defs in the namespace, eg: (def a 1) (def b 2) (def c 3)… how do I “collect” all into one vector?

hiredman01:03:35

Have you not tried [a b c]?

hiredman01:03:54

[~@(for [n syms] n)]

hiredman01:03:03

Anyway, whatever system you are creating, I encourage consideration of objects bound to local names, or objects not bound to a name at all

tbaldridge01:03:55

Also, if I read your code I now need to understand what a multidef is. So that's more work on the part of the reader, for the gain of a bit less typing on your part. Often it's better to structure code for the ease of use of the people that come after you as we tend to read code much more often than we write it.

tbaldridge01:03:28

(also true of all macros, not just ones that def something)

seancorfield01:03:29

TL;DR: use macros very sparingly 🙂

hiredman01:03:01

Spec might be a good case study, it has more macros than I would like, but it at least distinguishes spec construction from binding to a name

martinklepsch07:03:28

Logging question: I have a logback.xml with specific appender that I want to enable in production only. Is there any way around using conditionals in the xml file? Some one-liner to enable a named appender or something?

mpenet07:03:54

Dont think so. You can do it with interop tho

mpenet07:03:36

There's also a lib, unilog that wraps this stuff

martinklepsch07:03:37

I figured out a way to get the appender via Interop now just need to find the on-off switch 😄

martinklepsch08:03:14

ha, .start & .stop

martinklepsch08:03:42

@mpenet thanks for the pointer but I think I’ll stick to these for now, Java logging is a bit overwhelming...

martinklepsch08:03:54

Ended up trying unilog anyways but I needed a custom Syslog appender (Papertrail) and that seemed a bit more involved @mpenet

martinklepsch08:03:59

pretty nice otherwise 👍

karol.adamiec09:03:39

@martinklepsch i get away with java logging by just dumping to stdout and stderr. it is the environment responsibility to process that however you would like

thheller12:03:18

@martinklepsch FWIW I have a srv/dev/log4j.properties and src/production/log4j.properties where only src/production is included in the uberjar but never in dev

thheller12:03:47

seperates the entire logging config easily

mpenet12:03:36

juxt/aero + unilog make it quite similar, but in edn format

Shantanu Kumar16:03:54

Is there a built-in fn (or alternative) to do this more concisely? (reduce #(%2 %1) {} fns)

Shantanu Kumar16:03:12

@martinklepsch In the XML you may want to wrap the appender definition with

<if condition=‘p(”logback.appender.syslog.enabled”).equalsIgnoreCase(”true")'><then>
   …appender-config-here...
</then></if>

Shantanu Kumar16:03:47

but you need a system property logback.appender.syslog.enabled defined to make it work

martinklepsch16:03:42

@kumarshantanu I looked into that but then I needed another depenency for it and also XML CONDITIONALS? 😄

Shantanu Kumar16:03:08

The XML config is well documented and searchable, but it’s weirdly evolved 😬

mobileink17:03:50

@martinklepsch have you considered using a boot task with edn and stencil to gen xml config files? works great for boot-gae.

rauh17:03:57

@martinklepsch I created this a while ago: https://gist.github.com/rauhs/129a1fbca375ef8972902161e594bc39 , maybe it'll help you. It's nothing fancy.

martinklepsch17:03:38

@mobileink this project doesn’t use boot unfortunately so I wanted to avoid any build-time-solutions for now. That’s probably what I’ll go for later though.

martinklepsch17:03:29

@rauh looks pretty similar to unilog 🙂

curlyfry17:03:12

@kumarshantanu Do you have an example of what you use (reduce #(%2 %1) {} fns) for?

Shantanu Kumar17:03:42

@curlyfry I am trying roll an init-map (empty in the beginning) through a bunch of initializer fns

jeff.terrell17:03:52

@kumarshantanu - If you know the fns at code-writing time, you can use ->. Otherwise, not sure how I'd improve that.

jeff.terrell18:03:05

@hiredman - Wouldn't the order of application be different with comp?

jeff.terrell18:03:18

Might still work, if the order of application doesn't matter.

hiredman18:03:29

or just call reverse

jeff.terrell18:03:26

So to summarize: ((-> fns reverse comp) {}).

jeff.terrell18:03:52

Right, good catch.

jeff.terrell18:03:01

Try 2: ((->> fns reverse (apply comp)) {}). I think it just got longer than the original. :-)

Alex Miller (Clojure team)18:03:53

as a bonus, it’s also harder to understand

jeff.terrell18:03:08

@alexmiller - Agreed. For the sake of legibility I might say:

(letfn [(step [m f] (f m))]
  (reduce step {} fns))

joshjones18:03:26

no need for thread macro @jeff.terrell .. ((apply comp (reverse fns)) {}) ... but i think the original reduce is also easier to understand as @alexmiller said

hiredman18:03:01

it depends a lot on the context

jeff.terrell18:03:02

Yeah…I tend not to use comp very often because I always have to stop and think about the order of application, so to me, the reduce is clearer. But then, I also had to stop and think about the order of application to the reducing function (and even initially got it wrong in my "legible" snippet above), so I guess YMMV.

Alex Miller (Clojure team)18:03:39

I like the step version

Alex Miller (Clojure team)18:03:21

seems like there has to be an iterate version of this too?

Alex Miller (Clojure team)18:03:37

I guess not as the function changes

hiredman18:03:22

you have to combine the list of functions and the seed value, and iterate taking a function and applying it to the seed value, then returning a new combination of the rest of the functions and the new seed value

Alex Miller (Clojure team)18:03:32

@hiredman iterate requires that f must be free of side effects, so shouldn’t be stateful

Alex Miller (Clojure team)18:03:00

this is actually the same idea as that one transducer ticket

dpsutton18:03:02

@alexmiller when spec is finalized, will it be a package that must be imported in a project.clj file (think core.match) or will it just be referenced similar to clojure.string or set?

dpsutton18:03:15

or at least is there a road map for this?

dpsutton18:03:23

even if its not commited to yet?

dpsutton18:03:42

we had a good discussion in #clojure-spec

Alex Miller (Clojure team)18:03:43

it will be a required part of Clojure in either case

dpsutton18:03:48

about how to write tooling

Alex Miller (Clojure team)18:03:55

either it will be in core or core will depend on it

Alex Miller (Clojure team)18:03:21

separating it would allow spec to rev faster than core and that would be the reason to separate

dpsutton18:03:29

so we won't need to version it? ie cider-nrepl has spec 0.2 and your project has spec 0.4

Alex Miller (Clojure team)18:03:37

we do not intend to make it independent or backport it

dpsutton18:03:06

thanks for the information

dpsutton18:03:20

and as always, "is subject to change, it's alpha 15"

hiredman18:03:36

user=> 
(take-while :value
            (iterate
             (fn [{:keys [fns value]}]
               (when (seq fns)
                 {:fns (rest fns) :value ((first fns) value)}))
             {:fns [inc inc inc] :value 0}))
({:fns [#object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"] #object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"] #object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"]], :value 0} {:fns (#object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"] #object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"]), :value 1} {:fns (#object[clojure.core$inc 0x4df5bcb4 "clojure.core$inc@4df5bcb4"]), :value 2} {:fns (), :value 3})
user=> 

Alex Miller (Clojure team)18:03:40

I think there is some missing thing in this area, but I have not sorted through all the stuff on that page enough to have an opinion on it

favila18:03:56

This is a head-scratcher to me. Why doesn't this fail?

favila18:03:08

(defprotocol SetA (seta [x a]))
=> SetA
(defrecord X [a]
  SetA
  (seta [this newa] (set! (.a this) newa)))
=> user.X
(def x (->X 0))
=> #'user/x
x
=> #user.X{:a 0}
(seta x 1)
=> 1
x
=> #user.X{:a 1}

favila18:03:47

The best I can guess is that "final" is only a compile-time concept in java and does not exist in the jvm?

bronsa18:03:51

that shouldn't work :|

favila18:03:25

(set! a newa) (in protocol impl) fails at compile-time

favila18:03:31

this does not

favila18:03:54

But I assumed JVM would protect

bronsa18:03:20

I would've assumed that too

bronsa18:03:53

I'll look into why this is not failing at compile time

favila18:03:25

Oh this is clj 1.8 btw, I didn't try with 1.9

bronsa18:03:33

yeah i can repro on master

favila18:03:52

I assumed it was a java gotcha I didn't know about, but this is actually surprising?

bronsa18:03:09

surprising that the jvm doesn't throw a verifyerror

Alex Miller (Clojure team)18:03:20

I echo bronsa’s surprise

bronsa18:03:23

the clj side is likely a bug

Alex Miller (Clojure team)18:03:35

unless record fields aren’t marked final!?

favila18:03:50

@alexmiller I verified via reflection, they are

favila18:03:09

That was my first thought too

bronsa18:03:37

public final java.lang.Object a;
    descriptor: Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_FINAL
public java.lang.Object seta(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: checkcast     #2                  // class test/X
         4: aload_1
         5: aconst_null
         6: astore_1
         7: dup_x1
         8: putfield      #18                 // Field a:Ljava/lang/Object;
        11: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Ltest/X;
            0      11     1  newa   Ljava/lang/Object;
      LineNumberTable:
        line 5: 0
        line 7: 7

bronsa18:03:52

how does that putfield even compile

bronsa18:03:03

time to dig into the jvm manual

favila18:03:14

I seem to be running into the bad ones recently

favila18:03:34

first the CLJS stack-overflow, now this

Alex Miller (Clojure team)18:03:07

I mean depending on the JDK version, it is possible to modify final fields

Alex Miller (Clojure team)18:03:21

(subject to security policy)

Alex Miller (Clojure team)18:03:38

but I didn’t think you could do that ^^

bronsa18:03:10

I think I know what's causing the compile-time check to not fail for (.a this) but it is for a

favila18:03:11

I'm running Oracle 1.8.0_121-b13 on linux if it matters

bronsa18:03:52

>>> The HotSpot VM did not implement the new checks until JDK-8157181. However, the changes by JDK-8157181 have introduced the checks only for class files with version 9 and onwards.

favila18:03:30

clj generates 6, right?

Alex Miller (Clojure team)18:03:39

well, needless to say, don’t do that :)

favila18:03:55

no argument from me!

Alex Miller (Clojure team)18:03:21

if someone wants to file a ticket, it might be useful to a future person that runs into it. I guess we could probably enhance the compiler to detect that the field is final and this should fail, but I’m not sure if the effort is worth it.

bronsa19:03:07

@alexmiller I'm working on that patch, should be relatively straightforward

bronsa19:03:01

attached patch

bronsa19:03:51

amusingly, this was not an issue before because set! was broken for that use case pre 1.8 http://dev.clojure.org/jira/browse/CLJ-1226

ghadi19:03:57

it is weird for a AssignableExpr to have a method canAssign()

ghadi19:03:11

hot-take-code-review

bronsa19:03:20

should we rename AssignableExpr to MaybeAssignableExpr? :)

bronsa19:03:32

PotentiallyAssignableExpr

bronsa19:03:52

half joking, prior art in MaybePrimitiveExpr

ghadi19:03:06

how about checking explicitly for target being a final field before AssignExpr is constructed at the top of the diff?

bronsa19:03:34

the check is parmetric on the Expr type

dpsutton19:03:50

should it not be put into analyze? so that analyze won't return an AssignableExpr if it's not in fact assignable?

dpsutton19:03:11

not sure how invasive that is though

ghadi19:03:24

if(!assignable(target))

ghadi19:03:10

instanceof checks seem better here than polymorphism

bronsa19:03:35

meh. an AssignableExpr is already potentially non assignable at runtime

bronsa19:03:50

(set! (.nonExistentField foo) 1)

hiredman19:03:11

yeah, to determine if a field is final, you have to know the type of the object, which clojure doesn't always

dpsutton19:03:14

ah. and if it wasn't, you would need a type that would hold this notion of an NonAssignableExpr, right?

dpsutton19:03:24

which would get invasive

dpsutton19:03:12

but i am not familiar with it, just reading the patch

bronsa19:03:47

or even at compile time -- in (deftype a [x] Foo (bar [this] (set! x 1))) x is AssignableExpr but fails at compile time already

dpsutton19:03:20

well i'll keep thinking about what color the bike shed should be 🙂

yonatanel19:03:38

Is there a changelog for clojure 1.9.0-alpha15?

Alex Miller (Clojure team)20:03:17

Not a big delta, but more stuff moved behind that for the next alpha too

jasonjckn22:03:50

is it a convention in clojure to name :private functons with - prefix, e.g. defn ^:private -my-private-defn

yonatanel22:03:46

@jasonjckn there's the defn- shortcut

jasonjckn22:03:06

yah i realize, i'm just curious what's the naming convention around - prefix

yonatanel22:03:10

I think the prefix makes the function static

hiredman22:03:15

- doesn't do anything

jasonjckn22:03:24

what's the naming convention for

hiredman22:03:12

gen-class by default looks for functions that provide the implementation for methods by prefixing with '-' but, if I recall that is configurable, but people rarely change it

bronsa22:03:33

yeah you can change prefix if you want

yonatanel22:03:44

Good to know

hiredman22:03:11

-main may actually be special cased in gen-class

hiredman22:03:38

but - as a prefix by itself doesn't do anything

bronsa22:03:31

nah not even -main is special cased

bronsa22:03:43

you can use $$$$$$$$main if you want

hiredman22:03:50

bronsa: I mean, generating a static main method for classes must be special cased in someway

bronsa22:03:41

main is special cased by the jvm, the prefix is irrelevant

hiredman22:03:44

oh, right, it defaults to generating a main, the default name for the function is "main" plus the prefix

bronsa22:03:22

(i wish genclass and proxy had never existed)

dpsutton22:03:45

what don't you like about proxy

bronsa22:03:08

what genclass/proxy compile to is really gross

bronsa22:03:23

and has tons of limtiations/performance issues

jasonjckn22:03:39

so you wish it compiled differently? or that no interop existed in this way

bronsa22:03:49

plus, genclass's interface is a beast of complexity

bronsa22:03:05

no, I'm ok with that type of interop existing

bronsa22:03:19

but deftype/reify style interop is much nicer than genclass/proxy

hiredman22:03:26

make users deal with asm themselves 🙂

hiredman22:03:24

I remember there being a reason proxy isn't a java Proxy, but I cannot remember it now

bronsa22:03:39

redeffing?

bronsa22:03:18

altho I don't know if that even works with genclass so maybe that's not it

mobileink22:03:04

gen-class is unjustly maligned. it's beautifully designed to serve its purpose. simple_smile

bronsa22:03:03

I disagree

mobileink22:03:06

try doing servlets without it.

bronsa22:03:20

it's barely useful and vastly overcomplex

bronsa22:03:29

I'd rather write java to do that interop than using genclass

hiredman22:03:36

pedestal does it great

hiredman22:03:49

it has a java class that implements a servlet taking a clojure var

mobileink22:03:00

it may be poorly documented, but that's a separate issue.

bronsa22:03:08

documentation isn't the issue

hiredman22:03:12

(or did, it has been a long time)

bronsa22:03:58

it's also impossible to avoid some reflection if you're using gen-class

hiredman22:03:59

the way ring-jetty-adapter does it is super gross

hiredman22:03:05

actually the way ring-jetty-adapter does it may be fine

mobileink22:03:05

@hiredman you prefer that java mess over gen-class? de gustibus non disputandem, but i don't see it.

hiredman22:03:22

I am thinking of the way lein-ring does it

hiredman22:03:53

I would take that java, compile it to bytecode, and use it without remorse

bronsa22:03:23

@mobileink how's that java a mess? it's very simple and clean

bronsa22:03:11

it's much simpler than gen-class and has way less gotchas/limitations

mobileink22:03:27

compared to same in clojure?

bronsa22:03:35

compared to same in gen-class

mobileink22:03:46

well let's not get religious, i just genuinely do not see the problem with gen-class. i've use it to great effect, never with more than a few lines of code.

hiredman22:03:50

not to mention, to use gen-class you have to aot compile, which is terrible

hiredman22:03:38

aot compilation is a huge source of maintenance headaches because it tends to break things in weird ways that show up far from the cause of the breakage

mobileink22:03:18

all that stuff in the java code is easily done in clojure. re: aot, how do you use java without compiling? i don't get it.

hiredman22:03:37

what do you mean?

hiredman22:03:56

clojure work just fine without aot

hiredman22:03:18

you can compile java to classes without aot compiling clojure

mobileink22:03:19

so just aot compile your gen-class stuff. i don't see why this is any more of a problem than javac.

hiredman22:03:49

because clojure makes it difficult to just aot compile gen-class stuff

hiredman22:03:02

because anything else you load while aot compiling is also aot compiled

mobileink22:03:12

you don't need to aot compile everything just because you have one gen-class.

bronsa22:03:28

anything that that gen-class loads will be aot compiled

mobileink22:03:55

so don't load stuff in gen-class. ?

bronsa22:03:08

anything that reloads that gen-class ns will likely break stuff

mobileink22:03:02

sure, but why would you reload gen-class? you reload the impl-ns.

hiredman22:03:06

no one is disputing that it can be done, but in practice it always breaks, the amount of times people have come in here or on irc with an issue that ultimately comes down to a problem with aot is huge

mobileink22:03:26

i think you may need to think more diabolically about gen-class. you don't use it to implement anything, only as a kind of bridge.

bronsa22:03:47

@mobileink sure, but then you start limiting what you can do if you're using gen-class, at that point just don't use it at all, avoid potential headaches, write a few lines of java and be done with it

hiredman22:03:12

if you look through the clojure jira for issues related to aot compilation it is like a game of whack a mole

mobileink22:03:15

well, i dunno, but i'm guessing folks tend to misuse gen-class.

hiredman22:03:23

that is the point

hiredman22:03:42

aot compilation is a loaded gun pointed at your feet

bronsa22:03:45

there's a lot you need to know and that's easy to fuck up with gen-class, that's exactly the point

hiredman22:03:59

sure you can use it, but most people shoot themselves in the foot

mobileink22:03:08

right, documentation.

bronsa22:03:12

why would you want to risk it if it's super easy to just write 10 lines of java that do the same w/o the incidental complexity

bronsa22:03:23

nah, it's not documentation. it's inherent to how genclass works

mobileink22:03:09

all i can say is i use it all the time for servlets, and it's a total non-issue.

mobileink23:03:07

it's just for stubs, effectively, so the servlet container can find some bytecode on disc. that generalizes to for example alexa.

bronsa23:03:40

try writing something like clojure.lang.ExceptionInfo using gen-class, making sure it doesn't use any reflection and include it in a project that uses something like reloaded

bronsa23:03:49

have fun when everything breaks as soon as you reload your project

mobileink23:03:13

i might not do that. but that has nothing to do with the virtues of gen-class. just because it's not the right tool for your task does not mean it sucks in general.

mobileink23:03:33

after all, the reason it's there is interop.

bronsa23:03:09

I can't speak for Rich but I seriously doubt gen-class would be included in clojure if he was to make that decision now

bronsa23:03:56

there are simpler ways to do interop. writing a java class is often vastly simpler and more powerful than gen-class

mobileink23:03:03

use it when the execution env. requires bytecode on disk. then it works fantastically well.

Alex Miller (Clojure team)23:03:51

I think it would but he considers it low level

mobileink23:03:06

writing java: matter of taste. i prefer not, and have tried both.

bronsa23:03:42

hah, I consider it too high level/abstracted for what interop should do :)

mobileink23:03:59

peoperly used, in the right circumstances, gen-class is perfect.

bronsa23:03:23

that could be said for anything

mobileink23:03:30

misused, not ao much. 😉

Alex Miller (Clojure team)23:03:47

I prefer to use Java in most cases, but then I have 20 years of familiarity with it

mobileink23:03:06

@hiredman so don't aot compile all nss. I'm genuinely puzzled here. gen-class, esp. with :impl-ns, works absolutely perfectly for my use cases.

hiredman23:03:26

puzzled about what?

hiredman23:03:42

you say aot compilation works perfectly for you, that is 1, I am saying I see people have issues with it here or on irc about once a week

hiredman23:03:23

to the point where I have a pr on the clojure-site to explain how to launch a clojure program without aot compiling anything, because people are mostly aot compiling just for a launcher

mobileink23:03:16

i'm puzzled as to why people think gen-class is bad.

mobileink23:03:05

so you do not aot, but you do javac?

hiredman23:03:11

gen-class has a number of issues, but for me, the nail in the coffin is aot, because aot causes more weird issues

hiredman23:03:33

the code base I am working on now doesn't use either javac or aot

hiredman23:03:47

I worked on a large code base that was aot compiled

hiredman23:03:31

as that company grew and the code base started to be broken up, aot compilation caused issues, so I ripped aot out and replaced the parts that needed to be replaced with java

mobileink23:03:20

ok just to make sure we don't talk past each other: i isolate my gen-class code. that makes it easy to only aot that. of course it depends on your build tooling.

noisesmith23:03:52

that addresses hiredman’s concerns but not bronsa’s I think

mobileink23:03:21

plus i have the lux of not working on legacy code! simple_smile ymmv

hiredman23:03:04

it addresses my concerns in a shallow way. when you move on to another job and another programmer takes over, or you hire someone new that isn't aware this section of code is an isolated garden, boom

noisesmith23:03:10

@mobileink a hacky implementation that needs to use reflection

noisesmith23:03:03

it sounds like you aren’t trying to use gen-class for anyting perf critical anyway

hiredman23:03:20

why would you use something that requires being wrapped in caution tape?

hiredman23:03:09

this is the same argument you see everytime there is a high profile buffer overflow

hiredman23:03:46

"stop writing software in languages that permit buffer overflows" "I write in languages that permit buffer overflows and have never had a problem"

mobileink23:03:08

well, maybe i'm misunderestimating sth. why would we need gen-class, ever? i'm assuming because the runtime env (a container of some kind?) needs to find code on disk. if not, just use def*. but maybe my view is overly narrow? i know that when that is the case, gen-class works very well.

noisesmith23:03:48

@mobileink you can use gen-class without making class files on disk, you can create class files on disk without gen-class

hiredman23:03:02

that is not correct

hiredman23:03:07

gen-class requires aot

bronsa23:03:14

gen-class is strictly AOT (for no good reason)

hiredman23:03:16

gen-class is a noop without aot

hiredman23:03:27

the reason is classloaders are weird

hiredman23:03:51

before gen-class existing clojure had gen-and-load-class (or whatever it is classed)

bronsa23:03:07

I think as of current clojure, gen-class could be used to JIT

bronsa23:03:24

not that I would care if it did

bronsa23:03:29

unless what you're talking about is the potential issue of dyn classes being GC'ed before use?

bronsa23:03:36

that might still happen

mobileink23:03:49

@noisesmith regarding performance critical stuff, true, i do not think of gen-clasd in those terms. i might go with java for that. but my point is there are many cases where gen-class works perfectly well.

mobileink23:03:21

so it should not be denigrated. poor gen-class!

hiredman23:03:19

bronsa: no, I don't know the exact reasoning, but gen-and-load-class got replaced with gen-class when aot was introduced. I suspect because gen-and-load-class would always define a new class in a dynamic classloader, anything using the system classloader would get the wrong class

mobileink23:03:36

@noisesmith how do you create bytecode on disk without gen-class?

bronsa23:03:28

@hiredman i don't see how AOT/JIT gen-class would have differnt issues thatn AOT/JIT deftype?

noisesmith23:03:49

clojure.core/compile can do that - it doesn’t give you something directly loadable by a java program though, for that I use clojure.core

hiredman23:03:49

yeah, I am not sure

mobileink23:03:58

i mean without aot-ing everything.

hiredman23:03:50

I've used asm directly https://github.com/hiredman/jenkins-clojure-injector/blob/master/src/leiningen/jpi.clj I think for that there was some reason gen-class wouldn't work, but I forget what it was

bronsa23:03:39

i never quite understood why gen-class just does writeClassFile and doesn't also (.defineClass ^DynamiClassLoader Compiler/LOADER ..) like definterface does

hiredman23:03:24

dear rich; why??????????????; regards, etc

noisesmith23:03:36

clearly it’s a conspiracy against inheritence

bronsa23:03:49

might actually be to discourage people from using gen-class, for real

noisesmith23:03:41

just imagine the terrible code from java users newly trying clojure and defining everything via gen-class

devn23:03:46

(defn load [gzip-input-stream]
  (let [rdr (transit/reader gzip-input-stream :json)
        eof :_EOF_]
    (loop [res []]
      (let [chunk (try (transit/read rdr)
                       (catch Exception e
                         eof))]
        (if (= chunk eof)
          (walk/keywordize-keys res)
          (recur (into res chunk)))))))

devn23:03:14

For some reason I cannot catch EOFException or IOException in that catch. Why?

bronsa23:03:37

they're not automatically imported

hiredman23:03:42

are you sure that is what is being thrown?

devn23:03:42

I've imported them

hiredman23:03:00

like what does (println (type e)) show?

devn23:03:08

@hiredman unless there's another kind of EOFException, it's an EOFException

devn23:03:16

@hiredman will take a look

hiredman23:03:50

I wonder if it is some other type of exception, with an EOF as the cause, and you have some tooling that is unwrapping to the root-cause

hiredman23:03:48

says it throws a runtime exception

devn23:03:20

@hiredman right you are

devn23:03:34

2. Unhandled java.lang.RuntimeException
   java.io.EOFException

1. Caused by java.io.EOFException

devn23:03:04

Makes me think I shouldn't be using try/catch for this anyway

devn23:03:42

So I guess my actual question is, with a gzip input stream, what should I do to avoid using try/catch in the first place