#clojure logs

2017-06-28

00:41mgaareWhy don't specs implement IFn
00:43mgaareIt would be so nice to have something like, (s/spec a-bunch-of-predicate-logic-here :gen useful-generator) and have the result be callable as a normal pred
01:01amalloyaren't specs able to do a bunch of things? conform a thing, act like a predicate, produce an error report...which of those things should it do when called as a function?
01:03mgaareI think they should act like a predicate
01:04mgaareas it stands now, maybe I'ved missed it but I don't see a way to get the same functionality that, say, int? has. Where it can be used as a spec, can be called as a predicate function, and has a generator
01:04amalloymy point is, what if someone else disagrees? why should a predicate be the most interesting thing?
01:04amalloysuppose i think it would be far better if it produced an error report instead
01:05amalloyisn't it great that when i read your code, i can tell what you're using a spec for by what function you call on the spec?
01:06mgaareanother solution would be if spec supported adding generators to functions
01:07mgaareor I wonder if you could do that with fdef
01:07mgaarehmm
01:07mgaaredoesn't seem that way
01:09mgaareamalloy: and to your question, right now we both lose because they do nothing at all ;)
01:09amalloyno, i win because i actually think it's great to have named functions for doing things
01:11mgaareSo do I, but it seems like our predicates are destined to be second class citizens to the built-in clojure ones, as they get generator support and we have no apparent way to add it to ours
01:13amalloywhat's this about generator support for core functions? i haven't really kept up with development
01:17mgaarea whole slew of predicates in core have generators. So you can call s/gen on a variety of things like nat-int?, inst?, string? and so forth and it returns a generator. But the mechanism for this is a hard-coded list in clojure.spec.gen.alpha
01:23amalloyis it? i agree that that sounds pretty silly. i can't find the source for that, though
01:23amalloyi could easily be missing it, of course. as i said, i'm not current
01:34mgaareit's a little tricky to trace. `s/gen` calls down to `gensub` which calls `specize` on the predicate, which calls `spec-impl` for objects, that reifies a thing that will call spec.gen.alpha/gen-for-pred to get a generator, which is this here https://github.com/clojure/spec.alpha/blob/master/src/main/clojure/clojure/spec/gen/alpha.clj#L187 that gets the generator out of this map https://github.com/clojure/spec.alpha/blob/master/src/main/clojure/clojure/spec/
01:34mgaaregen/alpha.clj#L128
01:38amalloyhuh. confirmed, that seems lame
01:53dysfunspec is a bit crack
01:54TEttingera spec for crack though, now that woul be something
02:04TEttingerhm. thinking about https://github.com/rschmitt/dynamic-object and (de)serialization of hand-written values as opposed to machine-written ones
02:05TEttingerI love clojure's approach to writing data for prototyping, and I don't know if I have seen or used something better at that use
02:07TEttingerI don't know if there's any kind of way that homogeneous, no-types-declared collections will easily translate to Java, which is of course pretty strict on types if you want to get your IDE to do any work
02:22dysfunTEttinger: sure, List<String> is just List<Object> at runtime
02:23dysfunwell, it's more like List at runtime, really, but you get my point
02:24TEttingeryes, but the IDE won't be too helpful if you constantly cast each Object you get from a List to String in Java code
02:24dysfunoh well
02:24dysfunshouldn't rely on an IDE then
02:25TEttingeryou shouldn't rely on coffee then
02:25dysfuni shouldn't, you're right.
02:25TEttingerheh
02:25TEttingerunneeded performance boost!
02:26dysfunmeanwhile, i've given up trying to be polite in an email and left it at "call me"
02:26TEttinger, maybe
02:26clojurebot#error {\n :cause "Unable to resolve symbol: maybe in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: maybe in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6719]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: maybe in this...
02:26TEttinger,:maybe
02:26clojurebot:maybe
02:26TEttingerthere.
02:27dysfunhello, maybe
02:27TEttingerthis is your cousin, maybee
03:35WxckolHey
03:36TEttingerhello
03:36dysfunwotcha
03:39WxckolWhat does Clojure is for?
03:39dysfunit's a general purpose programming language
03:39Wxckolgeneral purpose like what?
03:39Wxckolim a general ignorant :D
03:39dysfunwell, in short, you can do most things with it
03:40WxckolWhat do you do with it?
03:40dysfunbuild websites mostly
03:40WxckolCan you show me something you built with it?
03:41dysfunhttps://github.com/irresponsible/anarchy is a simple business logic engine i built in clojure
03:42Para_"business logic engine" sounds horribly engineered solution looking for a problem
03:42WxckolMh, ok (thank you), but it's beyond my knowledge for now. What about a website, can you show me a website?
03:42Para_YMMV of course, rule engines have never appealed to me
03:42dysfunit's not a traditional rule engine
03:43dysfuni can show you a website, but that it's written in clojure will make no difference to your experience of it
03:43WxckolJust wanted to take a look you know
03:43dysfunthat's the thing about general purpose programming languages - they can all do much the same things, they just do them differently
03:43dysfunwell, https://bleeckerburger.co.uk/ is written in clojure, but what i said above
03:44WxckolSo you write all this with code? No gui at all
03:44Wxckol?
03:47dysfunyup
03:47dysfuni mean the html can be trivially edited in a gui if you want, but i choose not to
03:48dysfunwell, actually the template engine probably knackers gui editability
03:48dysfunbut it started as html and then i just edited the template in
03:49dysfunhttps://github.com/tonsky/datascript-chat # here is an example of a more dynamic app written in clojurescript
03:49dysfunthe burger site actually has a very shiny admin panel written in clojurescript too, but i can't show you that
04:25HanonimYop
04:25dysfunhiya
04:25Hanonimgood ?
04:26dysfunokay i guess, tired
04:29osfabibisiapparently Kafka think they have solved Exactly Once
04:30dysfunwell, they're presumably trying to compete with flink
04:30dysfun(flink claims exactly-once, so it's nice to know we've made such progress with the provably hard german tank commander problem
04:35Hanonimosfabibisi: only in special occasions
04:35osfabibisiso what's the flink-definition-of-exactly-once?
04:36dysfuni suspect "exactly once except when something goes wrong"
04:36osfabibisiah
04:36osfabibisiso "not exactly once"
04:37dysfunwell, we have a mathematical proof of the hardness of this problem, so...
04:38dysfunanyway, exactly once except in case of error is basically as good as you can get, it's what you do in the case of error that matters
04:39osfabibisiah ok
04:39osfabibisiand does that work out being better than at-least-once in practice?
04:39dysfunit depends what you're doing
04:40dysfunthere is also the other category - at most once
04:41dysfunat most once is what linkedin use for emails, because noone complains if they don't receive yet another fucking email
04:44TEttingerlinkedin can show restraint on emails???
04:44TEttingerhow surprising
04:44TEttingerI think they're just a spam council
04:45dysfunno, the outage of linkedin services can show restraint on emails
04:46Carr0tI wonder if they've done it by decoupling message sending from message sent checking. e.g. message is sent with UUID. Instead of resending on no ack you just keep asking "Have you got the message with UUID X" until you get either a yes or no. ON yes, mark as sent. On no, resend message with new UUID and start asking about *that* one
04:47dysfunah, but what happens if the machine receives it but then goes offline before it's done processing?
04:47osfabibisiah yes, I understood that better written down ;-)
04:49osfabibisiah yes, this is the thing that Paxos is meant to solve? (still not entirely sure what that is, I keep confusing it with the stock cube)
04:51dysfunpaxos and raft attempt to solve this problem, yes
04:52TEttingerthey just need to verify that they have received the message before the message was sent. a clear violation of causality, just like uber is a clear violation of taxi regulations
04:53torrent-of-ionsIs "Joy of Clojure" worth buying considering a) I'm a Common Lisper, and b) it's only v1.4 of Clojure?
04:53osfabibisiI liked JoC
04:54dysfunit depends on whether it's the sort of book you like to read
04:54TEttingerclojure's different enough from CL, so having a good book helps
04:54torrent-of-ionsOh, it's 1.6 actually
04:54TEttingernot very old huh
04:54TEttinger1.7 was transducers? or was that 1.6?
04:54torrent-of-ions1.7
04:54dysfun1.7
04:55TEttingerI still haven't used a transducer knowingly
04:55torrent-of-ionsI suppose those additions don't change the fundamentals
04:56torrent-of-ionsI'm still a bit unclear about fundamentals like names and symbols
04:56dysfunno, not at all
04:57dysfuni use transducers quite a lot, but i don't write new ones
04:58torrent-of-ionsAlso I hate buying technical books just before a new version comes out, but I can't find any news about a 3rd edition
04:58torrent-of-ionsI'll order it then
04:58dysfuni can't see a new edition this year
04:58dysfunor in the near future, generally
04:59dysfunnot with significant changes anyway, maybe a reprint
05:20osfabibisidysfun: are you back on Clojure, or just visiting? ;-)
05:21Hanonimit's weird, after quite a while with clojure, i start missing imperative langs
05:21dysfuni am writing clojure, but not contributing to it
05:21osfabibisiaha
05:22osfabibisicontributing to core? or to your irresponsible modules?
05:22dysfuncore. i am still doing irresponsible because i use them too
05:22osfabibisigood good
05:25dysfuni've stopped bothering with the site though
05:25deadghosthmm did dysfun jump langs?
05:25dysfunit will eventually turn into the irresponsible software guild and include stuff written in kotlin, or if i ever build the damn thing, kotlisp
05:26Hanonimso you've chosen kotlin for your lisp ?
05:26dysfunit's seeming likely, but it's not definite
05:27Hanonimbecause of the type system ?
05:28dysfuni use a lot of java libraries. using them is often a pain in clojure because it tries to have its two worlds thing, whereas kotlin just does java++
05:28osfabibisioh? we've found Java interop in clojure quite painless
05:28dysfunkotlin is not going to win any awards for outstanding revolutionary design, it's just java++, done quite wel
05:28dysfunwell*
05:29dysfunit is often painless, but equally often painful
05:50osfabibisiah, hehe
05:51dysfun:D i just talked a potential client into making an improved offer
05:51osfabibisiwoohoo
05:55audriusmhow will you improve the offer? :)
05:55dysfunwell i improved it by asking them to improve it
05:55dysfunand mentioned what their competition were offering
06:00osfabibisiis it a fun gig?
06:01dysfunno, but it's less un-fun that commuting 2 hours a day
06:01dysfunthan*
06:10osfabibisithis is true
06:13dysfungosh, there are engineers up the pylon i see out of my window. it's the most interesting thing i've seen this week
08:05MakisIs there a trick to using Himera and tryclj because I keep getting errors even when I use some existing examples?
08:28osfabibisiso the Clojure example in http://www.bradcypert.com/5-programming-languages-you-could-learn-from/
08:28osfabibisiwhy doesn't that blow it's stack? does lazy-cat do some magic there, even though it's not tail recursive?
08:43raekosfabibisi: yes. lazy-cat is a macro. the body of the lazy-cat form is wrapped up in a thunk and that thunk is returned immediately.
08:43dysfuni just looked at the source, it uses concat
08:43dysfunso if it's a very big list, and you realise it all at once, it likely *will* blow its stack
08:45raekoh, you're right. it calls concat immediately. but the arguments to concat are wrapped in lazy-seq which is the thing that delays the computation
08:46dysfunalso that quicksort assumes uniquity in the source collection
08:46raekso (lazy-cat e1 e2 ... e1000) becomes (concat (lazy-seq e1) (lazy-seq e2) ... (lazy-seq e1000))
08:46dysfunit will actually malfunction if an item goes twice by the looks of it
08:46raekdysfun: why would a big list blow the stack?
08:47dysfunraek: because each call to realise a new element adds a stack frame
08:48dysfunhaskell only gets away with pervasive laziness because the VM is built around it
08:48raekhmm right.
08:49raekif the partition is perfectly balanced the lazy sequences becomes nested at a depth of log2 n
08:49dysfunyes. in general we assume the stack size is log(heapsize)
08:50dysfunmuch garbage collection theory is based on that
08:51raekbut I suppose you could design a pathological input that makes all the partitions maximally unbalanced, so that the stack depth needed would indeed be proportional to n!
08:51dysfuneven with a perfect balance, it's vulnerable to large inputs
08:52dysfunperiodically someone turns up asking about a very strange stack overflow bug that appeared in production and it usually turns out it's concat's fault
09:33osfabibisiraek, dysfun: sorry, got called away after asking that question
09:33osfabibisiso essentially that function *will* blow its stack on large inputs?
09:34dysfunpretty much
09:34osfabibisicool. that was my guess, but I thought I'd ask in case I'd misunderstood ;-)
10:31dysfunso i spent an hour today tracking down a bug that would have been pointed out by even a half-arsed type system
10:31TMAwould it help if (lazy-cat e1 e2 ... e1000) were (concat (lazy-seq e1) (lazy-cat e2 ... e1000))?
10:32dysfunit might be less awful than the original in a large collection, but it still suffers the same basic flaw
10:32dysfunbut making it lazy seems rather pointless
10:36osfabibisiis there an existing function for (defn check [message predicate] (when (predicate message) message)) ?
10:36osfabibisie.g. you can (some-> thing (check some-predicate?) (...))
10:38dysfuner, isn't that... some-> ?
10:40osfabibisihmm, not exactly, some-> would just path the truthy value of the predicate
10:40osfabibisiit's a converter from truthy predicate into threading macro guard
10:40dysfuncond-> ?
10:41dysfunbut i think from your description not quite
10:43osfabibisiI can't figure out cond-> at all tbh ;-)
10:44osfabibisiI think the `check` definition should do for now, ta for suggestions
10:44dysfun,(for [i (range 10)] (cond-> i odd? #(* 2 %)))
10:45clojurebot(#object[sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45 0x23881a68 "sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45@23881a68"] #object[sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45 0x3c7db411 "sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45@3c7db411"] #object[sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45 0x60b8e71d "sandbox$eval40$iter__36__41$fn__42$fn__43$G__44__45@60b8e...
10:45dysfun,(for [i (range 10)] (cond-> i odd? (#(* 2 %))))
10:45clojurebot(0 2 4 6 8 ...)
10:46osfabibisi,(map #(* 2 %) (range 10))
10:46clojurebot(0 2 4 6 8 ...)
10:46osfabibisiI still don't understand your example
10:46osfabibisiif it's odd, it multiplies by 2? wouldn't that be (2, 6, 10, ...) ?
10:46dysfunwell, it's like -> except i inserted the predicate odd? in the middle
10:48dysfunto be fair, *i* was expecting to see something different as well
10:48osfabibisiyeah, I have no idea what it's doing though
10:48osfabibisiah, heh
13:05TimMcThing I'm really tired of in Clojure: Not being certain I can find all the places my code looks at a really generically named key in a datastructure.
13:05TimMcLike if I have something under :data in a map, there's no good way to grep for all references to that.
13:07osfameronhmm. that's a weakly typed issue in general isn't it?
13:07osfameronor possibly a hint that you should rename your map keys to something less generic
13:07dysfunnamespaced keywords (which rich has been banging on about a lot recently) *almost* solve that one
13:08dysfun(as in you need to substitute something that reads namespaces for grep in order to solve the typical case)
13:09osfameronit's interesting that Haskell just avoids having arbitrary maps of data and makes you model your structures up front
13:09osfameronI sometimes wonder if that trade-off would be worth it
13:09dysfunmichael snoyman said he'd quite like to remove tuples
13:09osfameronI mean, on larger-scale projects than I've worked on
13:10technomancyosfameron: you don't need haskell for that; racket encourages that too
13:10osfameronat least tuples are typed-ish, but yeah
13:10osfameronright, I should have said "e.g. Haskell" ;-)
13:10osfameronthe generic maps thing is Oh So Convenient for as long as you can actually remember and reason about what you're doing
13:10osfameron(which for me isn't very long, as I am a simple squirrel)
13:10dysfunit's really good for prototyping
13:11dysfunand it's very good for eliminating boilerplate
13:11dysfunbut as your code grows up, i don't think it scales
13:11osfameronright, I've not done sufficiently complex things in Haskell to worry about boilerplate tbh
13:11osfameronI should fix that...
13:11dysfuni got lost down the GHC.Generics hole a couple of months back
13:12dysfunthe other thing maps are good for is interop with json
13:12justin_smiththe compromise that works best for me is arbitrary hash-maps locally (eg. within one set of tightly coupled namespaces in one project) and schemas / defrecords between subsystems, enforcing specific keys or even using types instead of mappy things
13:13justin_smithkind of like how shorter names are OK in small scopes but as scope gets larger you want more and more description in a name
13:13TimMcosfameron: Yeah, weakly typed and some related stuff. If I had schemas on all this code, I could find references to the schemas...
13:13justin_smithplain-old-arbitrary-data is great in small scopes, more reification and validation of structures is good for things that crosses boundaries
13:14justin_smithhaha
13:14osfameronjustin_smith: interesthing - though again, at odds with dysfun's comment that it's the *weakly* typed stuff that is trivial to serialize and pass as JSON ;-)
13:14technomancyalso we need letrec
13:14osfameronthe French painter? ;-P
13:15dysfunno, we don't need letrec, we need letnonrec
13:15justin_smithosfameron: right, I think more structure at boundaries and less in the implementation is the path to sanity, not the opposite
13:15TimMcso we should use SOAP is what I'm hearing
13:15technomancydysfun: reference to https://news.ycombinator.com/item?id=8226934
13:15justin_smithoh man...
13:16osfameronTimMc: eeeeek!
13:18dysfunshouldn't you sit *on* the sofa to watch doctor who?
13:18justin_smithTimMc: SOAP is terrible, but I'd still want the type checking at the edges to be strictest - because that's where you get the real cascading problems, is stuff that comes from furthest away, because you need to read unrelated code to understand it, and the odds that no one dev read both parts of the codebase increase...
13:18technomancydysfun: you start out on the sofa and you end up behind the sofa once the daleks show up
13:18technomancyit's traditional
13:18justin_smithalso it's attention span friendly / uses human working memory nicely
13:19technomancyjustin_smith: starting to sound like grpc
13:19TimMcalso aparently everyone watches movies on their smartwatches or whatever these days so it's not like you need to be in any one place
13:19dysfunyeah, there's no better experience than watching a movie on a tiny tiny screen
13:20TimMcI pipe all YouTube videos to my NumLock light.
13:20justin_smithdysfun: I assume you've seen the classic David Lynch rant https://www.youtube.com/watch?v=wKiIroiCvZ0
13:20justin_smithtechnomancy: I'm unfamiliar... is it any good?
13:20technomancyjustin_smith: well... no? maybe? I don't know.
13:21technomancyit has some neat features, but protobufs are annoying.
13:21technomancygrpc alone is pretty nice; it gives you distributed tracing, cancellation of requests, automated backoff, etc
13:22technomancybut it's usually paired with protobufs which are efficient but extremely awkward to use from clojure
13:22technomancyI think grpc with edn or transit would be pretty nice
13:22dysfuns/to use from clojure// # FTFY
13:22technomancywith specs at the service boundaries, of course
13:22justin_smithof course
13:23technomancythe problem is if you use protobufs then people think that means you don't need spec, but protobufs are lame
13:23dysfunnah, you need to generate protocolbuffers from specs
13:23technomancyhm... now there's an idea
13:23dysfunbecause specs are better than types
13:24justin_smiththe system I have in development now uses transit event sourcing on kafka topics to build a state deterministically from a log, and all the job logic is driven by the state in a model derived from petri nets (pool of available workers, pool of jobs, join the two to represent an "in progress" object, etc.)
13:24technomancyis it common to keep specs for a service in a separate dependency artifact from any implementation?
13:24justin_smithwhere the jobs and workers and in progress tasks are all reified in a hash map that is guaranteed identical in every process
13:25dysfuntechnomancy: i haven't seen anyone do that yet
13:25justin_smithtechnomancy: I do this for things that talk to two separate codebases, I have app a, app b, and then schemas c which is referenced by a and b
13:25justin_smiththis was designed before spec though
13:26justin_smiththat seems likea pretty natural choice
13:26justin_smithI think spec is a bit too new for there to be real systems with N>1 apps in communication and specs in between
13:27hiredmanitym the tooling for protobufs is lame
13:27technomancysurely N=2 isn't that rare?
13:27justin_smithoh yeah, some people put their cljs in separate apps right
13:28technomancyhiredman: well sure, but what motivation to improve the tooling is there? even if it were decent it still isn't very compelling vs transit or msgpack
13:35hiredmanyeah, I am not sure for message passing kind of things, I am thinking more about storing data, I've had bad experiences processing lots of edn
13:36technomancyinteresting; yeah that's different
13:40gpkIs Clojure any good for small command line programs? I'm thinking that the jvm overhead would be too high
13:40justin_smiththe jvm overhead is fine! it's the clojure compiler that's too heavy for that
13:41justin_smiththough cljs + node for command line can work (see for example lumo which is a self hosting clojurescript you can install via npm)
13:41technomancyI would recommend racket or ocaml for small programs instead
13:41justin_smithyeah, ocaml is great for small things that have to start up quickly
13:41gpkI currently use python
13:41hiredmanit depends on what you find acceptable
13:41gpkOr C
13:42hiredmanI write a lot of command line stuff in clojure, but most of it is sort of fire in forget or it is a long running task anyway
13:44gpkjustin_smith: can one not compile clojure ahead of time?
13:45justin_smithyou can, but there's still a certain amount of bootstrapping of clojure itself
13:46gpkWhat's it like compared to SBCL binaries?
13:46gpkThose are actually fast enough even though they are huge
13:47justin_smithit's not the size, it's the amount of work done on startup, and there's nothing outside of experimental unofficial forks that eliminate that startup work
13:47gpkI'm wondering what project I'm going to rewrite to teach me clojure, by the way
13:50technomancysbcl just dumps its whole memory image, right?
13:50technomancyI don't think you can come close to that on the jvm
13:50gpkYeah
13:50gpkAs far as I understand
13:51technomancygpk: do you have a use case in mind or is this more of just a general question?
13:53gpkJust a general question... It would be nice to use Lisp instead of Python
13:53gpkBut I write a lot of tiny things
13:53technomancyIMO racket is a much better python replacement
13:54technomancyor hylang of course
13:54gpkUnfortunately racket is not cool...
13:54gpkSounds stupid, I know
13:55technomancyracket is h*ckin' cool; you take that back
13:55gpk*I* know it's cool
13:55technomancybut if it's not cool enough you could always try...
13:55technomancyrackjure!
13:55gpkUnfortunately nobody will pay me to write Racket
13:56technomancyhttp://docs.racket-lang.org/rackjure/index.html <- racket with sunglasses on
13:56gpk*won't
13:58gpkSo I think Clojure sits more where CL is
13:59gpkWhich is good because it does some things better than CL I think
13:59gpkI always thought it would be cool to get paid to write Lisp as well
14:05osfameron<dysfun> because specs are better than types <-- oh?
14:07dysfunosfameron: (not serious)
14:07dysfunit's one of my current pet peeves that people keep saying this when it blatantly isn't true
14:08osfameronah
14:09technomancyhuh; refactor-nrepl claims to be able to do slamhound-type things
14:09technomancythis looks pretty nice; does it work well?
14:11technomancyapparently not?
14:11dysfunyou may be overestimating how many people have tried it
14:12technomancyno, I mean I tried it and it doesn't work
14:12dysfunoh, heh
14:12technomancywhy the heck would a query for find-usages require a namespace/name *and* a filename, line number, and column number?
14:13Frozenlocktechnomancy: slamhound?
14:13Frozenlockoh https://github.com/technomancy/slamhound
14:14osfameron"Slamhound rips your ns form apart and reconstructs it. No Dutch surgeon required." (I have no idea what that means, which makes the description a little bit less useful than something, er, descriptive, but it sounds cool, I guess)
14:14dysfunosfameron: essentially it will rewrite your imports
14:15technomancythe "usage" section has a demo
14:17osfameronI think the first time I looked at the docs I gave up by then as I didn't know what problem it was trying to solve
14:23osfameronah I see, it's the "tidy up imports" function that some IDEs have
14:23osfameronI've occasionally wanted that, will try vim-slamhound
14:24osfameron(still don't think the project description sells it well though ;-)
14:26technomancyit's not quite like Java's "tidy up imports" because the implementation is a brute-force recompile-all-the-things, so I felt a metaphor of violence was appropriate
14:26Frozenlocktechnomancy: refactor-nrepl did pretty well when I left it 'guess' namespaces. Granted it was always with the canned solutions (str -> clojure.string) or with namespaces I was already using elsewhere in the project.
14:26TEttingerdysfun: depends on what types you mean. I'm sure specs are better than some type systems. JS' for instance...
14:27technomancyFrozenlock: I'm more interested in the find-usages
14:29technomancyso yeah... this just doesn't work as documented
14:29technomancytoo bad
14:42lxsameerwhich protocol is related to a derefable value ?
14:50justin_smithlxsameer: the easiest way to check is with supers
14:51justin_smitheg. (supers (class (future))) and (supers (class (atom nil)))
14:51technomancyboom; had lein refuse to download a transitive dependency that used a non-TLS repo which wasn't directly visible in project.clj
14:51technomancywoot
14:51justin_smithnice
14:52technomancycoincidentally nice that the first time this occurred I happened to be on coffee shop wifi
14:52lxsameerjustin_smith: thanks a lot man
14:54Frozenlocktechnomancy: living dangerously
14:55technomancyFrozenlock: it would be dangerous, if I weren't using this new version of lein that refuses to do idiotic things for me =)
14:55technomancyidiotic things which every actually-released version of lein will happily go ahead and do =(
14:58lxsameeris a custom type which defined with deftype
14:58lxsameermutable ?
14:58justin_smithtypes aren't mutable, but deftype fields can be
14:59justin_smithoptionally
14:59lxsameerjustin_smith: ow, thanks
15:39ridcully_osfameron: it also tries to do :refer etc. e.g. write >! somewhere, slamhound adds async with a refer. or use str/join and it will require clojure.string as str etc
15:49osfameronah, it has a catalogue of common functions?
15:49ridcully_dunno. i'd guess it just looks around
15:50ridcully_not sure, if it does the same thing for imports too
16:10octarinemolehello everyone! i have this strange question: why is (<= 0.1 1/10) true but all of (< 0.1 1/10), (= 0.1 1/10) and (> 0.1 1/10) are false?
16:11Para_Clojure has fractional type support.
16:11Para_Or rather, rational.
16:11Para_,(type (/ 1 3))
16:11clojurebotclojure.lang.Ratio
16:12octarinemole,(<= 0.1 1/10)
16:12clojurebottrue
16:12octarinemoleif that's true, shouldn't also one of the following be true?
16:12Para_"is equal" of that part matches
16:12octarinemole,(< 0.1 1/10)
16:12clojurebotfalse
16:12octarinemole,(= 0.1 1/10)
16:12clojurebotfalse
16:12Para_No.
16:12Para_That's not how that works in any language :)
16:13octarinemolewhy is that? (sorry, it just looks mathematically pleasing...)
16:13Para_It reads out loud "is equal OR smaller than"
16:13Para_so it's (or (< 0.1 1/10) (= 0.1 1/10))
16:13Para_,(or (< 0.1 1/10) (= 0.1 1/10))
16:13clojurebotfalse
16:13octarinemoleyes, so either (= 0.1 1/10) or (< 0.1 1/10) should be true as well, shouldn't it?
16:14Para_...well probably the other way around but anyhow
16:14octarinemolethere you go, you get
16:14ridcully_,(== 0.1 1/10)
16:14clojurebottrue
16:14octarinemole,(= (<= 0.1 1/10) (or (< 0.1 1/10) (= 0.1 1/10)))
16:14clojurebotfalse
16:14Para_,(or (= 0.1 1/10) (< 0.1 1/10))
16:14clojurebotfalse
16:14Para_Hum.
16:14Para_Well anyway. The <= is not decomposable.
16:15Para_< and = are not the same as <= in a sense; it goes into land of type coersions
16:15octarinemolei see...
16:15Para_Just read it out loud and don't think everything can be split into parts.
16:15Para_You're not Aristotle, atoms have already been discovered :)
16:15octarinemoleok, well, thanks
16:16TEttingerridcully_ had it
16:16ridcully_,(BigDecimal. 0.1)
16:16clojurebot0.1000000000000000055511151231257827021181583404541015625M
16:16Para_Yeah there's that.
16:16octarinemolethat is why i chose 0.1 in the first place...
16:16TEttingeroctarinemole: there's 0.1M for higher precision easily
16:16octarinemolei just expected some properties of the comparison operators which are apparently not there
16:16TEttingerbut yeah == is mathematical equality
16:17Para_Well it applies to all languages as well, if you care about fractions/ratios, make sure you work with compatible types at all points.
16:17TEttingerI believe <= is the or of < and ==
16:17technomancyPara_: most languages don't have ratios
16:17Para_,(or (== 0.1 1/10) (< 0.1 1/10))
16:17clojurebottrue
16:17Para_technomancy: That's their downfall :)
16:17octarinemole@TEttinger ok, thanks, i think that helps me a lot!
16:17TEttingersince <= is mathematical, not as general as =
16:17technomancyPara_: I would say that having decimal literals default to floats is the downfall
16:18technomancyit's much better to default to accuracy and opt-in to speed
16:18Frozenlockindeed
16:19FrozenlockMost people that first come to a computer won't have the reflex of saying "hmm, I wonder if the computer will lie to me and NOT register the number as I entered it."
16:19octarinemole:)
16:19Para_technomancy: That's why Groovy defaults to BigDecimals with actual accurate precision, as well.
16:19technomancyPara_: huh; that's the first sensible thing I've heard about it =)
16:19Para_Frozenlock: Well most people are really technically inept as well.
16:19Para_"WHERE IS THE FACEBOOK BUTTON"
16:20FrozenlockPara_: right, so we shouldn't make it harder.
16:20Para_They won't understand the difference or what it entails.
16:20Para_So don't waste your tiime.
16:34IamDrowsyI just had a look at the Clojure source and actually (= 0.1 1/10) resulting to false has nothing todo with 0.1 not being exact
16:34IamDrowsy,(= 1/2 0.5)
16:34clojurebotfalse
16:35IamDrowsyequal (=) check for the category of a number (Integer, Floating, Ratio, Decimal) and will always give false when it doesn't match
16:36technomancyIamDrowsy: depends how you define your terms; "inexact" is commonly used to describe types rather than values
16:36ridcully_,(= 1M 1)
16:36clojurebotfalse
16:37justin_smith(= 1N 1)
16:37justin_smith,(= 1N 1)
16:37clojurebottrue
16:39octarinemole,(== 0 (- 0.1 1/10))
16:39clojurebottrue
16:39octarinemole,(== 0 (- 0.1 (BigDecimal. 0.1)))
16:39clojurebottrue
16:39justin_smiththere's also zero?
16:39ridcully_,(= (BigInteger. "1") 1N)
16:39clojurebottrue
16:39octarinemolethese look a bit funny to me... it is like 0.1 can act as exactly one tenth, but also as "roughly" one tenth
16:40justin_smith,(zero? (- 0.1 1/10))
16:40clojurebottrue
16:40justin_smithoctarinemole: before you use a double in a calculation it's other because it's less precise, after you use it it is contagious, you get a double back
16:41technomancyjustin_smith: oh man that last one
16:41justin_smithyup
16:42octarinemoleso... in (- 0.1 1/10) I should get a non-zero double, shouldn't I?
16:43ridcully_,(+ 0.1 2/10)
16:43clojurebot0.30000000000000004
16:44octarinemoleit casts the fraction to a double and then does the operation?
16:46octarinemolefunny that
16:46octarinemole,(class (- 0.1 (BigDecimal. 0.1))
16:46clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
16:47octarinemole(class (- 0.1 (BigDecimal. 0.1)))
16:47octarinemole,(class (- 0.1 (BigDecimal. 0.1)))
16:47clojurebotjava.lang.Double
16:47octarinemoleso it also downgrades the bigdecimal to a double when possible
16:47dysfunwhen it doesn't make sense to keep it as a rational, it will convert it to a double
16:47octarinemole,(class (- 0.1M (BigDecimal. 0.1)))
16:47clojurebotjava.math.BigDecimal
16:48dysfunand in this case, you gave it a double first
16:48octarinemoleok, i think i'm starting to understand it enough
16:48octarinemole,(class (- (BigDecimal. 0.1) 0.1))
16:48clojurebotjava.lang.Double
16:48ridcully_i think order has nothing to do?
16:48dysfunah so it is
16:49octarinemolethanks everyone!
16:49ridcully_it will use double once one of those is there, since it gives the most wrong result
16:49octarinemole:-D
16:49dysfun"most wrong" really depends on how much of it's being used
16:49dysfuni would have said the logical approach would be to do the opposite
16:50technomancyusing a not-double would give the mistaken appearance of precision
16:50ridcully_is there even a way to get a Ratio from a double?
16:51dysfuni think "mistaken" depends heavily on what you're doing
16:52dysfuni can envision several useful scenarious for the behaviour i descirbe
16:52technomancywithout knowing about the context, using the less-exact representation is the only safe choice
16:56dysfuni don't know, it kind of offends me slightly because i've used so many languages that auto-upgrade to bignums
17:00octarinemoleridcully_: you can write a function that extracts the nominator and denominator from BigDecimal, then pass that to the Ratio constructor... maybe this should be built in?
17:01dysfunthat doesn't do a rario from a double
17:01technomancy(->> (for [...] (future ...)) (map deref) doall) ; <- is that even ... I mean
17:01technomancyyou're derefing every single future as it's constructed
17:02technomancyso... you're completely defeating the purpose of futures?
17:02justin_smithyeah, the doall should come first
17:02dysfunthere are infinite solutions for fractions, so the best you can do is multiply it until you've eliminated the point to get the numerator and denominator
17:02justin_smithunless you only want to work with (chunk size) futures at a time?
17:02technomancyI always try to come up with an explanation that isn't "whoever wrote this was very confused" but ...
17:02hiredmanit would make sense if the doall was before the map
17:03justin_smithtechnomancy: "I want either 1 or 32 futures to run at a time"
17:03hiredmanlazy creating futures -> forcing the lazily created futures -> waiting for them all to compute
17:04hiredmanthat is almost certainly what they meant to do
17:04technomancyyeah... and chunking accidentally makes it work sorta the way they meant?
17:04octarinemoledysfun: well, the double has finite precision, so you can definitely represent it as a fraction that way, and the methods on BigDecimal can help a lot
17:06justin_smithoh man, that's their only tweet
17:06justin_smithand they just made another one...
17:07technomancyit's like being around for a birth. such a magical moment.
17:07Frozenlockwith blood and shit everywhere
17:07Frozenlockmagical
17:09osfameronwhat's the big hex string on their first tweet?
17:20octarinemoleridcully_: found it:
17:20justin_smiththey're well typed Bröwer.
17:20octarinemole,(clojure.lang.Numbers/toRatio (BigDecimal. 0.1))
17:21clojurebot1000000000000000055511151231257827021181583404541015625/10000000000000000000000000000000000000000000000000000000
17:21justin_smithlol
17:22octarinemoleand somewhat embarassingly...
17:22octarinemole,(clojure.lang.Numbers/toRatio 0.1)
17:22clojurebot0/1
17:22justin_smithwell, it's a ratio
17:23octarinemoletrue :)
17:28justin_smith,(clojure.lang.Ratio. (biginteger 666) (biginteger 420))
17:28clojurebot666/420
17:29postpunkjustinsick ratio
17:30octarinemoleyeah, and then the equals method is a bit odd...
17:32octarinemolei don't think the constructor is meant to be invoked directly as it doesn't normalize the fraction...
17:32justin_smithyeah, I inferred the constructor wouldn't normalize when I saw the output for 0.1
17:33octarinemoleand then the equals method assumes they're normalized
17:33octarinemole,(== 12/14 (clojure.lang.Ratio. (biginteger 6) (biginteger 7)))
17:33clojurebottrue
17:33octarinemole,(== 12/14 (clojure.lang.Ratio. (biginteger 12) (biginteger 14)))
17:33clojurebotfalse
17:33octarinemoleso it's a no-no :)
17:35lxsameerhow can I get a function by name with out requiring the namespace ? in runtime
17:35justin_smithresolve finds it, if any other code caused the code to be loaded at least
17:36justin_smith,(resolve 'clojure.java.io/file)
17:36clojurebot#'clojure.java.io/file
17:36justin_smiththat finds the var
17:36justin_smithyou can call a var, or deref to get the actual thing out of it
17:39lxsameerjustin_smith: but what if there were no file requiring that ns ?
17:39technomancylxsameer: leiningen has a resolve-require function
17:40technomancy(defn resolve-require [x] (require (symbol (namespace x))) (resolve x))
17:40amalloylxsameer: why are you trying to do this? this is a weird thing to do
17:40lxsameertechnomancy: hmmm is that going to work on production ? i mean in a jar
17:40technomancylxsameer: yes, but it's better to have the call path known at compile-time if possible
17:40lxsameeramalloy: indeed it is.
17:42lxsameeramalloy: i'm trying to point to a function from an edn data
17:42Frozenlocklxsameer: is this to make plugins?
17:42amalloyhow much do you trust the source of this edn data? if you let them call arbitrary functions, they can do pretty much anything
17:43lxsameerFrozenlock: not a plugin but maybe concepts would be the same
17:43lxsameeramalloy: it's a trusted source
17:44justin_smithso this is effectively DI via edn?
17:45justin_smithwhat if a consumer passed you a function instead?
17:45lxsameerjustin_smith: some how yes
17:45lxsameerjustin_smith: over wire ?
17:45lxsameerjustin_smith: basically this happens on wire
17:46justin_smithOK - so they ask for some namespace, you might not have loaded it yet for whatever reason, but they trust you can find it if they ask for it?
17:46lxsameerjustin_smith: both side has several functions but i want to conditionally specify the callback
17:46lxsameerjustin_smith: yeah exactly
17:47justin_smithso it's a weird ad-hoc RPC thing
17:47lxsameerjustin_smith: yes
18:08technomancyad-hoc rpc isn't that weird
19:12assoc-inHas anyone called a jar from clojure? I have a jar for an external resource and it looks like I could clojure.java.shell to call it, but I am not sure how I would close it.
19:24justin_smithassoc-in: you could either invoke the jar's main from within your own vm, allowing you to access its api that hopefully has some way to shut it down or cancel it, or launch a shell script via shell/sh that runs it async and returns the pid (that you can later reference to kil it via shell )
19:24justin_smithor, you can also use ProcessBuilder to create a Process, which has a method to shut it down (and has a lot of useful options that shell/sh doesn't)
19:25justin_smiththere's a library called conch that wraps ProcessBuilder but I think using the real API is much less error prone
19:54assoc-inOkay I was able to get it to work with this. It looks like you need to call sh again. (shell/sh "sh" "-c" "java -jar ......")
19:54justin_smithshell/sh doesn't us sh (despite the name)
21:08llsouderhttps://pastebin.com/M8CAHhEG
21:08llsouderwhat is this argument? https://pastebin.com/M8CAHhEG
21:08llsouderdoh!
21:08llsouder[{{username "username" password "password" next "next"} :params
21:08llsouder session :session :as req}]
21:08llsouderthis is a vector with a map
21:09llsouderand the first key of the map is a map????
21:09llsouderwhy cant my evil brain parse this?!?!?
21:10llsouder(defn do-login
21:30llsouderso while I was waiting I found the :as which told me it is destructuring
21:31llsouderso not the session :session makes sense to me. the name session is bound to the value of the :session key
21:32llsouderso now*
21:32llsouderthat username stuff is still hurting my brains
21:38llsouderok, that took a while but I got it. "username" is a key and binds to username etc
21:39llsouderyeah, thanks for letting me work that out LOL! Clojure documentation test.... passed!
22:04assoc-injustin_smith:Yes quite odd behavior. I think the documentation could be more clear about that