Fork me on GitHub
#clojure
<
2017-10-06
>
kaosko05:10:39

my java/clj interop test is giving me: java.lang.ClassCastException: Cannot cast android.graphics.Point to android.graphics.Point at java.lang.Class.cast (Class.java:3369) clojure.lang.Reflector.boxArg (Reflector.java:427) clojure.lang.Reflector.setInstanceField (Reflector.java:282) I have this class in the classpath only once.. so this is a classloader issue? I'm trying to set a field in java class with clj

kaosko06:10:16

yeah, a classloader issue: point classloader from clj #object[clojure.lang.DynamicClassLoader 0x20c7622 clojure.lang.DynamicClassLoader@20c7622] , classloader for SurveyMap #object[sun.misc.Launcher$AppClassLoader 0x4554617c sun.misc.Launcher$AppClassLoader@4554617c] how the heck do you guys do clj/java interop development? Is there a trick to make all java classes load through DynamicClassLoader?

kaosko06:10:52

or perhaps it's the Virgil plugin I'm using (for reloading java) that causes the issue?

kaosko07:10:12

no, looks like this is at least somewhat of a known issue (e.g. https://github.com/xiongtx/lein-trampoline-aot). I don't have circular dependencies, I'm in control of loading my plain java classes so I feel like I should be able to instruct my clj to load them all through DynamicClassLoader

ajs10:10:11

why can i do (conj {} [\a \b]) but not (conj {} '(\a \b)) ?

ajs10:10:26

i'm guessing it's because maps require their entries to be vectors, not just sequences

genec10:10:43

;; When conjoining into a map, vector pairs may be provided: (conj {:a 1} [:b 2] [:c 3]) ;;=> {:c 3, šŸ˜› 2, :a 1} ;; Or maps may be provided, with multiple pairings: (conj {:a 1} {:b 2 :c 3} {:d 4 :e 5 :f 6}) ;;=> {:f 6, :d 4, :e 5, šŸ˜› 2, :c 3, :a 1} ;; But multiple pairings cannot appear in vectors: (conj {:a 1} [:b 2 :c 3]) ;;=> IllegalArgumentException Vector arg to map conj must be a pair... ;; And pairs may not be provided in lists: (conj {:a 1} '(:b 2)) ;;=> ClassCastException ...Keyword cannot be cast to ...Map$Entry...

bronsa10:10:51

vector pairs are map entries, lists aren't

genec10:10:42

you can always write a function to do it if you want

alex-dixon13:10:05

Why would a println affect something like evaluation order? Iā€™m getting a test that passes when I run a macro as a side effect wrapped with println, but fails without. Iā€™ve tried replacing with dorun and doall but still fails

alex-dixon13:10:10

Fails with eval also

the-kenny13:10:58

Do you use for or map for side effects?

sgerguri14:10:35

doseq or dorun

sgerguri14:10:36

If you have a side-effecting function that you want to apply consecutively to a lazy sequence use doseq.

bostonaholic15:10:07

@the-kenny for and map are both lazy, so the side effects wonā€™t happen until the results are realized

the-kenny15:10:28

bostonaholic: I know that.

bostonaholic15:10:27

then Iā€™m unsure of you question

bostonaholic15:10:42

ah, sorry. I just realized that

bostonaholic15:10:51

havenā€™t yet had my coffee

alex-dixon15:10:48

Itā€™s a thread last macro that threads the result of a macro through a filter and two maps

alex-dixon15:10:15

Thereā€™s a function in one of the map fns that does the side effect

the2bears15:10:55

@alex-dixon I'd run it in a repl, to see the result of the macro when it ends with the side-effecty call, to see if what comes back is what you expect.

alex-dixon15:10:45

Forgot to mention it works fine at a REPL without println or dorun or anything

jstew15:10:58

@alex-dixon you might be running into a chunking issue depending on the sample size. I would wager that your sample size in the repl is smaller than your data size outside of the repl.

alex-dixon15:10:13

!!!. @jstew Thank you! replaced map with run!, works and learned something šŸ™‚

danm15:10:06

run! is awesome. We've made extensive use of it

alex-dixon15:10:50

Didnā€™t know it existed

danm15:10:08

Neither did we until we found that exact article you were linked to above, after running into lazy-sequence processing issues šŸ˜‰

dominicm15:10:36

I am somewhat, yep

dominicm15:10:51

@zcaudate hangs out here sometimes too šŸ™‚

kingcode15:10:05

ok thx @sodominic Can you make sense of the sentence on the hara.event website which goes likeā€¦ ā€œIt can be noted that the try/catch paradigm can implement sections and . Other clojure restart libraries such as errorkit, swell and conditions additionally implement sections , and .ā€ , below section 5 - Strategies??

kingcode15:10:44

sorry, I meant ā€˜thx @dominicmā€¦

dominicm15:10:28

Looks like the references have been clobbered

kingcode15:10:19

okā€¦thx, thought I was missing something šŸ™‚

dominicm15:10:21

a few links are missing, or maybe sections were renamed

dbushenko19:10:06

do you guys use exceptions for something in your clojure code?

dbushenko19:10:19

for instance -- for code decoupling?

ghadi19:10:55

exceptions tend to couple code together

ghadi19:10:52

It makes code need to become aware of exception classes of any library, at any stack depth

dbushenko19:10:59

exceptions allow separating code from exceptions handling

ghadi19:10:22

clojure disagrees

dbushenko19:10:53

so if I want a single-responsibility function I don't wanna handle wrong cases inside the function, I just want to allow someone to handle this

ghadi19:10:04

People tend to turn errors into values/data, then act upon the data

dbushenko19:10:25

ok. how to separate main use case flow from alternative flows?

ghadi19:10:58

I will say exceptions are a way of life on the JVM, you can't avoid them. Usually I pick a spot in the code where I turn a specific concrete exception into a datastructure... then send the datastructure around the program

jstew19:10:19

exceptions are like side effects, IMO. Unintended side effects that make it hard to write pure functions.

ghadi19:10:21

Think of ring web responses -- you turn an exception into a {:status 400 ...}

dbushenko19:10:30

I think you don't get my question. let me explain

dbushenko19:10:32

lets say I have a use case "signup user". I have email, password and confirm password. Firstly I need to check that fields are filled, then -- password and its confirmation match. then I need to check that the same user does not exist yet in DB. Then, after creating user, that the user was successfully created

dbushenko19:10:42

see the point? lots, LOTS of branching

dbushenko19:10:48

I want to avoid that

dbushenko19:10:58

in Java I have exceptions, in Haskell -- Either moand

dbushenko19:10:05

how to do it in clojure?

jstew19:10:49

Usually I try to just use some-> if I don't care about which part of the process broke.

dbushenko19:10:31

and if I do care? I just want to separate the main flow of the use case from the alternative flows

dbushenko19:10:51

just read that

dpsutton19:10:10

{:user-info {:email ...} :reasons-preventing [:already-present :missing-email]} and then (if (seq (:reasons-preventing user-analysis)) (bad-response) (good-response (create-user user-analysis))

dpsutton19:10:16

something along those lines is what i do often

jstew19:10:38

If you have to branch n times you're doing it wrong. I've played with this too: http://funcool.github.io/cats/latest/

dbushenko19:10:53

ok, so you guys don't use exceptions?

dbushenko19:10:02

so what then? monads?

dpsutton20:10:13

i wouldn't trust anything beyond trivial usage of monads in a dynamic language. i would absolutely hate to pick up someone else's code like that

dbushenko20:10:58

@dpsutton same as me, monads are for static type system

dbushenko20:10:35

so I'm getting back to my question -- how to separate main flow and alternative flows without exceptions?..

dpsutton20:10:08

i like my example. build up an object with the inputs and analysis. you can put reasons preventing creating a user in the db, whatever. and then afterwards a function that takes that analysis object and has a simple cond statement examining the reasons-preventing the creation, and otherwise do the thing you want

dpsutton20:10:36

(def token-verification-functions [not-breeze-token?
                                   not-recent?
                                   not-verified?
                                   not-user-id?])

(defn- analyze-token*
  [decoded-token]
  (let [reasons (into []
                  (keep #(% decoded-token))
                  token-verification-functions)]
    {:valid?  (empty? reasons)
     :reasons reasons}))

dbushenko20:10:06

yeah, it looks like a bit more complex variant of monad Either

dbushenko20:10:14

i think Either should go here

dbushenko20:10:22

exceptions look alien to clojure

Shantanu Kumar20:10:32

Hi. Iā€™m trying to find a short macro expression for the following:

(-> x
  (foo a b)
  (foo c)
  (foo d e))
Any suggestions? I have the following in mind:
(foo-all x
  a b
  _ c
  d e)
or
(foo-all x
  [a b]
  c
  [d e])

jstew20:10:51

@dbushenko Off the top of my head I would try something like this:

(let [[result err] (-> [[:success, nil] {:name "name" :password "pw"}]
          validate-user
          check-exists
          create-user)])

jstew20:10:28

each fn returns a result and error and continues only if there's a good result.

jstew20:10:10

-> could also be some-> so that you don't have to check the input on each fn.

jstew20:10:55

The only kind of gross thing is having to return the [result err] seq in each fn.

jstew20:10:13

reminds me a little of the way that go handles errors.

noisesmith20:10:36

itā€™s basically a hand-rolled monad

jstew20:10:12

It pretty much is, and we've come full circle.

mseddon20:10:37

and you might as well implement Validation instead šŸ™‚

mseddon20:10:14

in fact. you did.

seancorfield20:10:38

I don't consider exceptions to be that evil, now that we have ex-info and ex-data.

seancorfield20:10:08

OTOH, if you can reduce all your steps you can short-circuit evaluation by returning (reduced {:fail ...})...

mseddon20:10:46

hmm- is there a good article or code that shows idiomatic usage of those?

jstew20:10:03

Hmm. That's a good use case for reduced that I haven't thought of.

mseddon20:10:42

it seems the idea is to just wrap your catches with them?

seancorfield20:10:04

(try (some complex pipeline that throws ex-info anywhere) (catch clojure.lang.ExceptionInfo e (ex-data e))) -- one top-level catch to return whatever data was thrown...

mseddon20:10:28

right. thanks!

seancorfield20:10:00

A bit like having transients inside a process and making them persistent to return the value šŸ™‚

mseddon20:10:21

i'm surprised it's not been covered in the book I'm reading so far

seancorfield20:10:00

(sorry if you said earlier and I missed it)

mseddon20:10:04

joy of clojure- although i'm only halfway through

mseddon20:10:07

ah, it is. chapter 12. still on my way there šŸ™‚

dbushenko20:10:16

@jstew have you ever heard about monad Either? šŸ˜‰

mseddon20:10:30

@dbushenko scala hacker? šŸ˜‰

seancorfield20:10:35

Page 304 onward and page 447 onward cover some good stuff about exceptions (assuming JoC 2nd Ed)

seancorfield20:10:47

It lives by my left hand šŸ™‚

mseddon20:10:03

@seancorfield it was the friendliest to common lisp refugees I found. šŸ™‚

dbushenko20:10:18

@seancorfield looks like ex-info/ex-data is a good workaround for my case

seancorfield20:10:23

@mseddon Yeah, JoC 1st Ed was my first Clojure book -- but I'd done Lisp and a fair bit of FP in various academic languages back in the early 80's.

mseddon20:10:56

Modern clojure/clojurescript is truly refreshing, I didn't think I'd be able to do this seriously. The community is doing an amazing job and I am in awe. Just wish I'd made the jump sooner!

mseddon20:10:47

I picked up clojure a bit early on, but it was rather fringe and iirc, there were some nasty bugs in maps that made me decide to sit it out for a while

seancorfield20:10:13

I picked up Clojure to play with in 2010, been doing it in production since 2011, and it became our primary back end language a few years ago.

dbushenko20:10:54

@seancorfield maybe you can give us a talk about it on our conference?

mseddon20:10:04

I've been very happy with ring, and it looks like spec will get me some way to functional dependant types without the pain of blowing up intellij you get with scala's shapeless šŸ™‚

seancorfield20:10:20

@dbushenko Pretty easy to mimic Either and related monads with first/`second` and vector for the values. A few def aliases for syntactic sugar and you're golden! šŸ™‚

mseddon20:10:47

and never underestimate the fearsome power of macros šŸ™‚

dbushenko20:10:06

yeah, but monad is about the syntactic sugar, otherwis it looks like even more complex solution than the problem it tries to solve

seancorfield20:10:43

Type systems are overrated šŸ™‚ (I've had a love/hate relationship with Haskell since it appeared and I worked with a number of its predecessors in the 80's)

mseddon20:10:29

Yeah, I'm in two minds with types, I think spec can hopefully find the middle ground. It looks so great until one of your nodes restarts and you goofed and push the rest of the cluster over. šŸ˜•

dbushenko20:10:29

@seancorfield can't agree with you more. I feel like I'm much more productive in Clojure than in Haskell and even in Java. But I don't know why

dbushenko20:10:57

sometimes I think that clojure just offers such simple solutions that we don't need to spend the time for investigating complex frameworks

mseddon20:10:01

that said i did some nodejs consultancy a few years ago and the scars drove me towards the Haskell/Scala camp šŸ™‚

dbushenko20:10:20

@mseddon what brought you to clojure?

Stefan Roex20:10:32

I hope someone can help me, for some reason I'm unable to get the (reset) working for a reloaded workflow. I've used this on multiple projects in the past two years now, but it always seems very unstable. Quite often I'm unable to use the reset-fn since it errors that a namespace isn't found... I have checked that the source-paths in project.clj are correct. Anyone with similar troubles?

seancorfield20:10:38

Ah, yes, JS can inspire a fear of dynamic languages / love of type systems šŸ™‚ I've managed to avoid JS almost completely...

seancorfield20:10:37

@stex There's a #component channel that may be able to give more specific advice. I must admit I've also had problems trying to use that workflow on projects...

mseddon20:10:02

@dbushenko initially I was a hairy undocumented sbcl hacker, so lisp is an old friend. My recent desire to learn it fluently is driven by discovering in production Scala is not delivering on types, and cemented by figwheel and general repl development

Stefan Roex20:10:29

@seancorfield Ah, thanks, didn't know that. Will ask it there šŸ‘.

mseddon20:10:36

@dbushenko some of what you get with CIDER repl development is 'meh' to a CL user, NASA literally debugged the pathfinder probe at the repl while it was on Mars using lisp- yet my initial forays into what clojure offers has wowed me, which just means I'm here to stay šŸ™‚

dbushenko20:10:59

nah, I've heard that 1000....0000 times

mseddon20:10:49

let's face it, it's going to be a while before the lisp communities are going to top that anecdote

mseddon20:10:04

@dbushenko but if you're of a scala/haskell persuasion, spec being able to emulate scalacheck/quickcheck and provide static checking seems like a massive step towards closing any gap there may be.

mseddon20:10:54

every point on the lambda cube has pain. it's nice to try other geometry

dbushenko20:10:18

Nice! And how do you emulate it without static type system?

mseddon20:10:36

clojure.spec.alpha šŸ™‚

mseddon20:10:19

it's dependent typing and structural typing in a common definition language, as far as i understand it (please anyone better qualified jump in at this point :))

hiredman20:10:12

spec isn't a type system at all

hiredman20:10:27

it is more like a contract system

hiredman20:10:41

there is no static checking

hiredman21:10:33

the only checking it does for functions is generative(generating inputs and checking outputs, no analysis of the code), which isn't suitable for use in production

mseddon21:10:34

but for example, it could easily be used to declare structural types, ala typescript, no?

mseddon21:10:23

the type system is obviously far to strong to be totally enforced at compile time, but ten years from now, couldn't we see linters using the common format to statically check certain aspects?

hiredman21:10:34

possibly, but unlikely, it allows arbitrary predicates

dbushenko21:10:27

As for me without lots of tests this specs are useless

mseddon21:10:33

absolutely, it would not even be possible to statically enforce the full level of specs

mseddon21:10:49

@dbushenko did you ever use property based testing?

mseddon21:10:25

hmm. come to think of it, specs structural language may be itself too powerful to do typechecking, predicates or no šŸ˜•

dpsutton21:10:20

is there a good collection compare for testing when order doesn't matter besides set, or this essentially what any collection compare would do anyways?

dpsutton21:10:44

i guess that would destroy duplicates in teh general case which doesn't affect me here but presumably this is a standard problem?

bfabry21:10:27

@dpsutton (= (frequencies col1) (frequencies col2))?

bfabry21:10:04

np, I love that function

mseddon21:10:11

bag=, i love it

bfabry21:10:15

it's so useful in so many surprising ways

dpsutton21:10:16

i like it and never thing to use it.

dpsutton21:10:06

@mseddon do you have bag= defn'd to the frequencies comparison bfabry showed?

mseddon21:10:05

@dpsutton no! but I will now šŸ™‚

dpsutton21:10:05

or have an alternative imp

dpsutton21:10:14

haha i was kinda thinking the same thing

mseddon21:10:27

it's the perfect bag= function. perfect for all your ISeq needs šŸ™‚

mseddon21:10:47

my naive answer would be coerce both args to sets, and now look, we don't handle bags šŸ™‚

dpsutton21:10:59

ticket closed for not being amenable to nice looking code

tjtolton22:10:59

question while I'm stuck at work late. Why doesn't clojure have a <- macro? something that takes the last form and puts it at the beginning

dominicm22:10:32

How would that be used?

tjtolton22:10:50

it would be really helpful for working with the other threading macros, like cond->/cond->>, some->/some->>, and as-> which require the in threaded value to be first. often you're working with a collection in a thread, so you're using map and filter (which are mostly worked with via the ->> macro), but you cant do anything conditionally with them, etc. You can easily hop from thread first to thread last, but you cant go the other direction. Let me give an example.

hiredman22:10:22

macros don't work like that

tjtolton22:10:44

that's what you think šŸ˜‚ check it out:

tjtolton22:10:29

so, this is not doable, because you're threading last

tjtolton22:10:34

it would be doable like this:

hiredman22:10:23

user=> (defmacro f [body] (prn 'f body))
#'user/f
user=> (defmacro g  [body] (prn 'g body) body)
#'user/g
user=> (g (f 1))
g (f 1)
f 1
nil
user=> 

noisesmith22:10:53

or (-> (retrieve...) (->> (map ...) (map ...)) (cond->> ...) (cond->> ...))

tjtolton22:10:11

right, you have nesting options that are less easy, like that @noisesmith. you could also do this (if you wanted to keep each step in the pipe easily re-orderable):

tjtolton22:10:29

you can use ->> to jump into a thread last at any point

tjtolton22:10:51

its just odd to me that there's no way to go the other direction.

hiredman22:10:05

you can also collapse the cond->>

tjtolton22:10:32

yes, you can šŸ™‚

dominicm22:10:33

It becomes complex to follow I think, with too many flow rewrites. I find nested -> a bit much at times

tjtolton23:10:55

right. do you kind of see how this would help to reduce nesting?

tjtolton23:10:21

without it, you have no choice but to nest to do the same thing.

noisesmith22:10:34

@hiredman only if show-inactive? doesnā€™t need data added by the condition side of show-internal-data?

hiredman22:10:51

cond->> will pass through all the true cases

noisesmith22:10:07

what I mean is if it needs the change the previous cond made

tjtolton22:10:17

I mean look, the point is to keep the whole thing flat

hiredman22:10:26

the condition doesn't have access to what is being threaded through

tjtolton22:10:31

if you just use ->> on each line, they become self contained steps

tjtolton22:10:17

likewise, if I had a symmetrical <-, I could have self contained filter steps thrown into the mix.

hiredman22:10:20

have you played with transducers?

tjtolton22:10:10

it just seems to me that, since there is no form of cond-> or some-> or as-> that can possibly be used in a thread last, the existence of a <- would be an obvious thing.

hiredman23:10:34

I may not know what there needs to be, I remember pasting a link to https://gist.github.com/hiredman/184831 in '#clojure' years ago and then ten days later '->>' showed up in core

hiredman23:10:33

jeez I still think of cond-> as being recent additions, but they are ancient

tjtolton23:10:07

oh yeah? possibly before ->?

hiredman23:10:44

no, I just mean they are from 2012 or so, which may as well be forever ago

tjtolton23:10:16

@seancorfield yeah, that's alright, but I really prefer my pipes to be flat, so I can reorder them easily as requirements change.

tjtolton23:10:45

maybe I want to filter earlier on to avoid running transforms on all the records, etc.

seancorfield23:10:34

If you think your code is too complex / hard to read, refactor it into smaller functions.

tjtolton23:10:23

I understand. I think that argument could be made for all of threading though.

seancorfield23:10:42

Yes, a lot of people combine too much code when threading.

tjtolton23:10:37

could be, but I happen to believe they are often a much better choice to represent a program, if you can keep them flat.

seancorfield23:10:51

Transducers are often an even better choice.

tjtolton23:10:24

well, anyway, I think my point is pretty well made here. when working with collections, it is often useful to use cond-> or some-> or as-> (insofar as it is useful to use those macros in any context). the existence of a <- would make that possible, without having to reorganize your thoughts around core's limitations.

noisesmith23:10:48

you should write <- then

tjtolton23:10:06

oh, I have. I was just wondering why it wasn't in core, and thought I'd make the case.

hiredman23:10:30

prismatic had a library for building processing graphs

hiredman23:10:37

you would give it transforms (as functions) and dependencies between transforms (as metadata on the function if I recall) and it would do the sorting and piping to give a function did what you wanted

noisesmith23:10:57

Iā€™ve been meaning to try plumatic/plumbing some day

hiredman23:10:24

data transforms are almost never linear, you end up wanting something more graph like

seancorfield23:10:47

(I was a bit surprised composing identity into the transducer pipeline worked)

hiredman23:10:45

I've got a version of that graph thing somewhere that expects all inputs to be seqs

noisesmith23:10:46

in this case clojure is evaluating show-internal-data? as a condition - I donā€™t think that is what was intended

noisesmith23:10:00

oh, never mind, it was

noisesmith23:10:02

I had misread

hiredman23:10:06

so you end up with some cross between that and a for comprehension it is very list monad

hiredman23:10:01

apropos as a way to build a processing pipeline/graph that isn't heavily nested