Fork me on GitHub
#clojure
<
2019-08-08
>
emccue01:08:28

should i catch ExceptionInfo or IExceptionInfo?

noisesmith01:08:27

maybe this answers the question

finops-recon.run=> (try (throw (ex-info "foo" {:a 42})) (catch clojure.lang.IExceptionInfo e (:a (ex-data e))))
Execution error (VerifyError) at java.lang.Class/getDeclaredConstructors0 (Class.java:-2).
Catch type is not a subclass of Throwable in exception handler 27
Exception Details:
  Location:
    finops_recon/run$eval23242.invokeStatic()Ljava/lang/Object; @27: astore_1
  Reason:
    Type 'clojure/lang/IExceptionInfo' (constant pool 61) is not assignable to 'java/lang/Throwable'

noisesmith01:08:58

as opposed to

finops-recon.run=> (try (throw (ex-info "foo" {:a 42})) (catch clojure.lang.ExceptionInfo e (:a (ex-data e))))
42

emccue01:08:40

yep im an idiot

emccue01:08:02

been reading clojure source today

danielcompton01:08:54

I've just put together a draft PR updating s3-wagon-private to use password instead of passphrase: https://github.com/s3-wagon-private/s3-wagon-private/pull/74. Feedback very welcome

danielcompton01:08:14

If you have any other complaints or breaking changes you'd like to make to s3-wagon-private, now would be a good time to suggest them

caleb.macdonaldblack03:08:53

Does a transducer exist like map but passes the previous result (or initialization) of the map fn into the current map fn?

caleb.macdonaldblack03:08:06

I could probably make one but this seems like it would be a solved problem

seancorfield03:08:38

@caleb.macdonaldblack Wouldn't that just be reduce?

caleb.macdonaldblack03:08:48

No I need collection back. I'm thinking reductions actually

caleb.macdonaldblack03:08:25

I think reductions is exactly what I need

caleb.macdonaldblack03:08:38

Actually no? I don't think reductions is a transducer

dominicm08:08:12

Check out cgrand/xforms you'll end up there if you're doing transducers, there's a reductions implementation

seancorfield03:08:36

Yeah, I think you'll have to write your own stateful transducer for that use case...

caleb.macdonaldblack03:08:59

This is what I ended up with. An improvement would be to have the init optional like reduce but I don't need that for my use case

caleb.macdonaldblack03:08:29

I don't plan on using this transducer this way with the + function. I know there are better ways to do that

caleb.macdonaldblack03:08:02

I actually need this to calculate battery charge and discharge over time

seancorfield03:08:16

Feels a bit weird to have the init value passed like that rather how it is with transduce, for example. I'd consider having (let [init (rf) prev (volatile! init)] (fn ([] init) (...) ...)) if that works for you?

seancorfield03:08:15

Although that doesn't quite match how transduce works either I guess.

caleb.macdonaldblack03:08:42

Is your feedback regarding the usecase where an init value is not provided and the transducer instead uses the first step value?

seancorfield03:08:05

@caleb.macdonaldblack It's mostly an unease about how/where the init value is provided for a transducer I think... and I'm not sure what the right answer is.

seancorfield03:08:42

What would happen if you tried to use your transducer above with transduce, which provides its own init value, for example?

hiredman03:08:24

it isn't the init for the reduce though, it isn't passed to rf

caleb.macdonaldblack03:08:35

The initialization value for transduce is passed into the reducing function right?

caleb.macdonaldblack03:08:25

I guess my transducer behaves more like map but with the previous value. Perhaps reductions-xform is not the best name

hiredman03:08:41

reductions can't really be an xform, it has to be a "reduce" (something that runs a reduce like loop), because if you make it an xform you end up with this weird circular thing

hiredman03:08:58

so yeah, not really reductions, but something similar

caleb.macdonaldblack03:08:13

So the init value for reductions-xform is the first value to use the the prev result to kick things off. When reducing this collection (possibly with transduce) the init value is used differently and used as the initital value to reduce the collection to a single value.

caleb.macdonaldblack03:08:30

but yeah, not a great name

caleb.macdonaldblack03:08:08

actually idk. The reductions core function behaves this way

hiredman03:08:30

an xform cannot assume that it is building a collection

hiredman03:08:21

reductions is a series of values, each one a step in a reduction process

hiredman03:08:32

so it inherently builds a collection

caleb.macdonaldblack03:08:50

I'm sorry if i'm getting confused with terminology. This is a stateful transducer.

caleb.macdonaldblack03:08:08

Similar to partition-all

hiredman03:08:11

transducer, same thing

hiredman03:08:20

your reductions-xform ends up basically double reducing, once with the function you pass to it, and once with the actual reducing function (which builds the seq for eductions, and is + in your transduce snippet)

caleb.macdonaldblack03:08:20

In the snippet of code, I was demonstrating that It can be used with transduce. However the way I've used it is in the example not particularly useful

hiredman03:08:48

you don't get a sequence of values that are from the reduction steps of the reducing function

hiredman04:08:51

for transducers the reducing function is the thing building the result, so having a result that is a collection of the output of that doesn't work, so reductions-xform might be the closest you can get

caleb.macdonaldblack04:08:29

Ah okay I see what you mean now

borkdude07:08:03

if tools.deps supported npm deps, maybe this would also be useful for planck/plk which already can resolve deps using tools.deps

dominicm08:08:39

There's a jira for that

borkdude08:08:06

cool. I was referring to a conversation that happened on this channel yesterday

borkdude09:08:55

is there an extension for transit json files that is common? I personally have used .transit.json

👍 4
danieroux09:08:49

Anyone here have experience with Simulant? With notes on what to look out for? https://www.youtube.com/watch?v=N5HyVUPuU0E is very compelling

dominicm09:08:54

I think my colleague wrote a JUXT blog about it and was very positive.

jeroenvandijk10:08:28

@U9E8C7QRJ I've used it a long time ago. At the time I wasn't ready (i think). If you want to get the best out of it you need to structure your application/problem in a certain way so that it's experiments are repeatable (e.g. what is the influence of time or random number generation). Most applications aren't build with seedable random number generation or time manipulation in mind. I think the consequence is that you can only do useful tests around a set of core functions, which is not the same IMO

Alex Miller (Clojure team)12:08:59

I think the most important part of Simulant are the ideas.

👍 4
Anik Chowhdury10:08:47

hi everyone. I am newbie in clojure. I want to know how to halt future in clojure from executing functions before finishing future's processing?

Anik Chowhdury10:08:49

Dont want to cancel future, just to halt future from executing some dependancy functions before future's processing.

mdallastella10:08:18

So basically you want to wait for another condition to happen?

jumar11:08:08

I was a bit surprised (although not sure why 🙂 ) that (set! *warn-on-reflection* true) doesn't propagate to other threads (unless it's something like future):

(set! *warn-on-reflection* true)
true

user> (future (println *warn-on-reflection*))
true		

(doto (Thread. #(println *warn-on-reflection*)) .start)
false

(.start (Thread. (bound-fn [] (println *warn-on-reflection*))))
Reflection warning, *cider-repl codescene-enterprise-project/empear-enterprise:localhost:58237(clj)*:451:15 - call to java.lang.Thread ctor can't be resolved.
true

Is there a way how to apply it globally to see all warnings even when the code is running in another thread?

jumar11:08:51

and a related one: is there any real difference between bound-fn and binding-conveyor-fn ?

jumar11:08:31

I tried setting the clojure.compile.warn-on-reflection system property in lein's project.clj but got nil as a result 😮

:jvm-opts ["-Dclojure.compile.warn-on-reflection=true"]

# run the repl
*warn-on-reflection*
nil

carkh12:08:24

isn't warn-on-reflection a compile time thing anyways ? do you do compilation in separate threads ?

jumar13:08:17

But shouldn't the system property work too?

jumar13:08:53

@U13RRNF2M I guess code is compiled "on the fly" (when it's loaded/required) - with that in mind I do "compilation" in separate threads (just running a big chunk of my code in a separate thread)

carkh13:08:51

hum no in a regular project it will be compiled when required

carkh13:08:17

hum actually i don't know

carkh13:08:27

but it's a lexical thing anyways

carkh13:08:46

the question is this : did you observe a different behavior ?

jumar06:08:39

So I was a bit puzzled when the things actually get compiled and now I can see that all the code (required namespaces) is actually compiled when the app is started (at least for the lein repl execution path) not "on demand" when the actual code is invoked - and all that compiled code is stored in memory, not in the class files in the target dir (only the AOTed main class is stored there). So when I use :global-vars {*warn-on-reflection* true as @U45T93RA6 suggested I can see that it's properly set and visible even in new threads. However, I'm still puzzled why I don't see reflection warnings in my code during the startup procedure although there are clearly some (they are reported by the lein check command). Perhaps the compilation happens before the var is set?

vemv06:08:31

if you have AOT configured for development, I'd disable it and clear target/. It tends to cache things, which is undesirable for development. > I'm still puzzled why I don't see reflection warnings in my code during the startup procedure your project's code isn't necessarily comprehensively required at startup. lein test and lein check do that , but not lein repl. Something like (clojure.tools.namespace.repl/refresh) is more certain to require all your code upfront, therefore giving you the warnings you seek

jumar06:08:58

We only have main ns AOTed for development. I tried cleaning target before but didn't seem to have any effect. I actually modified the compiler to print a message every time ObjExpr#compile is called and it seems that pretty much all my code is compiled (at least as far as I can tell from the limited debug info I got). E.g. one of my namespaces contains a reflection warning - I actually started the app and invoked the use case where the code is called (therefore it had to be compiled at some point - during the startup or later) but haven't seen any reflection warning in the console.

jumar06:08:36

(I only see that warning if I eval the ns file manually)

vemv06:08:56

> We only have main ns AOTed for development why? (it wouldn't surprise me if it transitively compiled more stuff) >I tried cleaning target before but didn't seem to have any effect. you can always rm. > aven't seen any reflection warning in the console. but are you using refresh? else you have no warrantee that all your code has been required

jumar06:08:43

The main ns is AOT-compiled because it contains the main method. find target/classes gives me just a list of few classes all related to the main ns. I tried lein clean before and now rm -rf target too -> same result. I don't use refresh (doesn't work on our project). I'm pretty sure the code has to be compiled at some point though because I actually invoke the code path by triggering the use case in the UI which calls the code containing a reflection call

vemv06:08:47

> The main ns is AOT-compiled because it contains the main method. These are unrelated concerns in principle - you can run lein run -m your.namespace and your.namespace's main method will be run - no AOT involved at all.

jumar06:08:18

Ok, but I don't think it's related to the problem, is it? 🙂

vemv06:08:52

Could as well be. Also I'd make sure (refresh) can work. Solving both could unmask some issues in your project

jumar06:08:26

The refresh issue might be related to the AOT compiled main ns - I'll look at that; thanks for pointing that out!

🙌 4
jumar06:08:43

btw. lein compile doesn't give me the warnings but lein compile :all does.

jumar07:08:06

Perfect, refresh works now! Although I still don't see the warnings if I don't use refresh, this is much bigger win for me 🙂 Thanks @U45T93RA6 a lot for your help!

vemv07:08:38

🍻 ! You can setup :init in your project.clj so it performs a refresh at startup

👍 4
knubie13:08:51

Does anyone know of a tool that will generate documentation from clojure specs?

Alex Miller (Clojure team)13:08:38

codox is probably most common

Alex Miller (Clojure team)13:08:04

autodoc does that but it's a pain to use

knubie13:08:33

thanks @alexmiller. Spec doesn’t support docstrings, right?

knubie13:08:33

Basically my use case is that I’m creating an import/export functionality for my app, and now I’m writing up documentation for the format (which is EDN)

knubie13:08:24

I could probably just post the raw specs, but might be a little dense for people unfamiliar with spec/edn

Alex Miller (Clojure team)14:08:15

there's some next level formatting/printing in there, which is probably not surprising given that Tom both wrote the cl-format/pprint stuff in Clojure and autodoc

carkh14:08:00

next level smileys _

dominicm16:08:51

I can't unsee that now

schmidt7318:08:56

what is the canonical way to do something like this in clojure? https://reference.wolfram.com/language/ref/NestWhile.html

schmidt7318:08:12

iterate and takewhile?

noisesmith18:08:13

that's precisely it, iterate and take-while

noisesmith18:08:53

@henri.schmidt I think this demonstrates chunking doesn't happen

user=> (let [calculated (take 2 (iterate #(doto (inc %) println) 0))] (dorun calculated) calculated)
1
(0 1)

noisesmith18:08:19

dorun realizes the entire thing eagerly, only the 1 println happens (the first element is the non-calculated init)

noisesmith18:08:44

without the let / dorun you get a messy output mixing prints with the data

noisesmith18:08:42

also the version where each step sees all results so far can be done easily with reduce and reduced, or loop

noisesmith18:08:43

user=> (reduce (fn [els e] (if (> (count els) 10) (reduced els) (conj els e))) [] (iterate inc 0))
[0 1 2 3 4 5 6 7 8 9 10]

subsaharancoder22:08:38

Hi, I need some help with lacinia

hiredman22:08:07

#graphql is a good place for that