#clojure log - Apr 06 2016

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:00 Lewis: amalloy: sorry im multitasking. My fault

0:01 ,(doc next)

0:01 clojurebot: "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil."

0:02 Lewis: (next [ 1 2 3 4])

0:02 ,(next [ 1 2 3 4])

0:02 clojurebot: (2 3 4)

0:04 Lewis: ,(not [1 2 3])

0:04 clojurebot: false

0:05 Lewis: (not [])

0:05 ,(not [])

0:05 clojurebot: false

0:05 Lewis: ,(doc not)

0:05 clojurebot: "([x]); Returns true if x is logical false, false otherwise."

0:06 Lewis: wow I don't think today. I've been working all day it might not help

0:06 i even for got what not* was lol

0:35 dorian: hey can anybody tell me why lein-bin keeps trying to put the generated binary into a target/base+system+user+dev (which doesn't exist)?

0:40 oh i see, boilerplate made :target-path "target/%s" which presumably gets formatted in something

0:40 tolstoy: Yeah, I always delete that line. Can't remember what it messed up for me.

0:41 dorian: i kiiiinda understand what it's doing, i just don't understand why the dir doesn't get made

2:14 Lewis: ,(doc max)

2:14 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."

2:14 Lewis: ,(doc max-key)

2:14 clojurebot: "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."

5:43 ulrichschinz: hey there, I'm learning clojure and plain around... i dont understand why this is not working, mybe someone can explain....

5:43 (reduce (fn [aggr field] (if field (when (:pn field) (println (:pn field)) (conj aggr (:pn field))))) [] column))

5:43 returns nil

5:43 whereas column is a vec of maps

5:43 println prints the right thing

5:44 but it returns nil, i would expect to get a vec of str-entries

5:51 Kneiva: ulrichschinz: println returns nil

5:51 ridcully: ulrichschinz: field is most likely always true, so this branch always gives you nil

5:51 ulrichschinz: either the when gives you nil or the print

5:52 Glenjamin: one way to help with debugging, is to extract the function outside the reduce, and try it with different values to see if it does what you expect

5:52 ridcully: or use doto

5:59 ulrichschinz: ok

6:00 so println inside a reduce always results in a nil?

6:02 same thing without println returns nil as well

6:06 ridcully: a println always returns nil

6:56 aptablips: Hi. Quick Clojure question: How do you do an inexact numerical comparison? For example, I'd like this to come out true: (= (+ 0.1 0.2) 0.3)

7:06 tdammers: aptablips: not a clojure specific question really; you can't do that with floats in any language

7:06 what you want is "epsilon comparison"

7:06 i.e., compare against a tiny range

7:07 gon__: one way (= (+ 0.1M 0.2M) 0.3M)

7:07 dmsnell: (< (- 0.3 (+ 0.1 0.2)) epsilon)

7:07 ^^^ really need absolute value

7:07 but I wrote that to clarify

7:07 where epsilon is small

7:08 jaaqo: (= (+ (rationalize 0.1) (rationalize 0.2)) (rationalize 0.3))

7:08 tdammers: also note that because floating-point precision decreases with growing absolute values, there is no single "ideal" epsilon; you have to pick one that works well enough for your domain

7:10 dmsnell: fun fact, JavaScript just introduced this as a language construct -> Number.EPSILON

7:10 "the difference between one and the smallest value greater than one that can be represented as a Number."

7:10 tdammers: which makes it suitable for numbers between -1 and 1

7:11 or actually not

7:11 Glenjamin: ,2.220446049250313e-16 ; the value in my version of firefox

7:11 clojurebot: 2.220446049250313E-16

7:11 tdammers: ,(+ 1.0 2.220446049250313E-16 -2.220446049250313E-16)

7:11 clojurebot: 1.0

7:11 tdammers: \o/

7:12 ,(+ 1.0 2.220446049250313E-16)

7:12 clojurebot: 1.0000000000000002

7:12 tdammers: ,(+ 1.0 2.220446049250312E-16)

7:12 clojurebot: 1.0000000000000002

7:12 tdammers: ,(+ 1.0 2.2204460492503E-16)

7:12 clojurebot: 1.0000000000000002

7:12 tdammers: hmm

7:14 cwgem|mac: Is there something like this ( https://github.com/liebke/cljr ) that's not 6 years old? It seems like I have to create a temp lein project just to automate package downloads and install.

7:14 dmsnell: tdammers: -1 to 1 is very useful for floating-point numbers

7:14 tdammers: dmsnell: agree.

7:17 Glenjamin: ,(def epsilon 2.220446049250313E-16)

7:17 clojurebot: #'sandbox/epsilon

7:17 Glenjamin: ,(< (- 0.3 (+ 0.1 0.2)) epsilon)

7:17 clojurebot: true

7:17 MJB47: i think if i saw that code in a project

7:18 i would become angry

7:18 dmsnell: MJB47: Clojure is a LISP, so this would normally be a macro if needed

7:18 MJB47: i mean it works

7:18 but holy magic number batman

7:18 Glenjamin: i'd probably do something like (float= x y)

7:18 dmsnell: (~= (+ 0.1 0.2) 0.3)

7:19 MJB47: ye i more meant the def than anything :P

7:19 Glenjamin: oh, i'd have added a docstring i expect, better than a bare use in-place :D

7:20 MJB47: sure but

7:20 3E-16

7:20 would be better (with a comment)

7:20 imo

7:21 or 2E-16

7:21 w/e

7:22 dmsnell: MJB47 that value is specifically chosen to be "the smallest value for which two floats could be different"

7:22 MJB47: i know

7:22 dmsnell: so in that sense, it's a "discrete" value and changing it to look better for a human would disturb its mathematical value

7:23 MJB47: but that also means you need to explain why that is the case to every intern that comes through

7:23 dmsnell: like PI, why not PI=3?

7:23 MJB47: or have a mother of all comments

7:23 dmsnell: it _is_ surprising this doesn't appear to be baked into Clojure, I'll give you that

7:23 MJB47: w/e im just nitpicking

7:31 someone1: hi

7:31 Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath.

7:31 what error is this?

7:31 clojure is in my classpath

7:35 mavbozo: someone1, did you try to run clojure repl?

7:41 someone1: mavbozo: no, use clojure from jython

7:49 dysfun: you probably want clojure.lang.RT

7:49 and clojure.lang.* generally

7:57 prohobo: we need some closure

9:29 TimMc: someone1: clojure.core is a Clojure namespace, not a Java package. See above advice.

9:29 hmm, looking again, I'm not even sure what exactly you did to provoke that

9:31 jondot: what's the best way to contact rich hickey?

9:31 Empperi: sacrifice your soul to the lambda god

9:31 someone1: TimMc: I think its a classloader problem

9:31 Empperi: really, I'm guessing it's not that easy to just contact him - except he hangs around here every now and then

9:32 TimMc: someone1: What did you do to get that error?

9:32 It will be very hard to help you without that info.

9:32 Empperi: although less recently, guess he got to be a too big a celebrity

9:32 Glenjamin: most reliable way is to work in the same office as him afaik

9:32 Empperi: when he was a normal programmer kinda guy he used to be here too :)

9:33 jondot: yes i remember when he was here

9:33 but seriously then, is there any way to contact him? we'd like to get him to speak on a keynote for a conference

9:34 Glenjamin: i'd suggest probably cognitect is your best port of call for that

9:34 someone1: TimMc: https://nopaste.me/view/c5826bad#mXhyfNTGjnIRRfhTg9W7qUMi4gDzGbHS

9:35 TimMc: someone1: That's a big block of base64

9:35 someone1: should I feel proud that I talked with Rich in 2008 over IRC? :D

9:35 jondot: someone1: yes!

9:35 Glenjamin: someone1: http://clojure.org/reference/java_interop#_calling_clojure_from_java

9:37 someone1: Glenjamin: is this somehow build in in JRuby? Because with JRuby, all works like expected

9:38 builtin*

9:38 Empperi: jondot: yeah, contact cognitec

9:38 Glenjamin: no idea i'm afraid

9:38 Empperi: with luck you *might* get him as a speaker

9:38 be prepared though to not get him unless your conference is a big one

9:38 jondot: Empperi: you think that's impossible?

9:38 Empperi: he is kinda busy, he chooses the conferences

9:38 jondot: right

9:38 Empperi: so definitely not impossible

9:39 but that is a very real possibility that he refuses

9:39 jondot: sure i can understand

9:39 Empperi: but if your conference isn't totally insignificant you should be able to get someone from cognitec as a speaker

9:39 jondot: you think info@congnitect.com is good? or should i use a better email for such a cold call?

9:39 someone1: best way is to build a competitive lisp language and take his market shares

9:39 Empperi: they do have a lot of brilliant guys after all

9:39 jondot: that's true

9:40 Empperi: Rich Hickey is the Big Gun and the most wanted speaker, so there's a lot of demand for him

9:40 jondot: damn.

9:41 Empperi: I personally haven't tried to get him as a speaker but I do know some people who did :)

9:41 it was one of the largest software conferences in Finland which was centered around clojure that year, didn't interest mr Hickey

9:41 not significant enough

9:41 I totally understand though

9:42 but they did get Stuart there and he was awesome

9:45 jondot: Empperi: so i have something close. Stockholm

9:46 any other notable speakers you think of? clojure isn't a focus, but someone with a mind-opening point of view like Rich

9:46 Empperi: JFokus would definitely be big enough for Mr Hickey :)

9:46 I really like David Nolen's talks

9:46 dnolen: your welcome for the compliment

9:46 ;P

9:47 dnolen: Empperi: ha! thx :)

9:47 jondot: dnolen: ah!

9:47 dnolen: would it be appropriate to approach you on this perhaps? :)

9:48 Empperi: Om Next style is the future of web development and would definitely be a "mind-opening" kinda of talk

9:49 I personally am trying to do something similar to Om Next but in a slightly different way for different usage scenarios

9:49 I'll talk about it later if I get it to something properly working :)

9:49 jondot: yep, we love Om, didn't realize dnolen is here

9:50 someone1: jondot: me neither

9:50 Empperi: suprisingly large portion of significant Clojure people are here or have been here

9:50 someone1: he destroyed pedestal

9:50 dnolen: jondot: if you're looking to get in touch with anyone at Cognitect yes I would use that email.

9:50 someone1: little joke

9:51 jondot: dnolen: I mean, get in touch with you :)

9:52 someone1: just watched a talk from him, first comment "Many different interesting ideas, however Clojure looks so strange and difficult to parse."

9:52 dnolen: jondot: sure send me an email https://github.com/swannodette. Note I may or may not respond for various reasons yadda yadda.

9:52 someone1: the last part in the sentence is really true :)))))))

9:53 jondot: dnolen: thanks :)

9:55 sdegutis: I wrote a bunch of macros. :(

9:55 ToxicFrog: yay macros

9:55 someone1: at least you can

10:11 sdegutis: But I did :/

10:19 Well, it's done.

10:26 https://gist.github.com/sdegutis/4112dd4989fe7be17326d57d57b3ca6b

10:26 ,(defmacro some-let [bindings body] (let [[x y & rest] bindings] `(if-let [~x ~y] ~(if (empty? rest) body `(some-let ~(vec rest) ~body)))))

10:26 clojurebot: #'sandbox/some-let

10:26 sdegutis: ,(some-let [a 1, b (inc a), c (inc b)] [a b c])

10:26 clojurebot: [1 2 3]

10:26 sdegutis: ,(some-let [a (prn :a!), b nil, c (prn :b!)] [a b c])

10:26 clojurebot: :a!\n

10:27 sdegutis: Very handy. I may use this every day.

10:27 Glenjamin: multi-clause if-let?

10:28 sdegutis: Glenjamin: similar, yeah

10:28 Glenjamin: it's basically a nested if-let

10:28 Glenjamin: it'll short-circuit and return nil if any of the bindings are nil along the way

10:30 Glenjamin: i imagine useful has something similar, although the api docs appear to have gone missing

10:30 sdegutis: It should probably use when-let though rather than if-let

10:30 Glenjamin: I looked in amalloy_'s useful and didn't see anything like it

10:32 Glenjamin: similar-ish to cond-> i guess, but more flexible with how you use the args

10:34 sdegutis: Glenjamin: im not seeing how some-let is similar to cond->

10:35 Glenjamin: well i was thinking you'd often chain values as you went with some-let

10:37 sdegutis: Glenjamin: the purpose I created it for was so that I can create bindings that are based on other bindings, but short-circuit if any are nil

10:38 Glenjamin: right, that's sort of what cond-> does, but without the bindings

10:39 similar sort of "drilling down" effect

11:09 sdegutis: Glenjamin: ah

11:50 back

11:53 Good morning. Is there a built-in way to create a record that conforms to a protocol purely by its keys?

11:53 ,(do (defprotocol Foo (bar [this])) (defrecord RealFoo [bar] Foo) (bar (RealFoo. "foo")))

11:54 clojurebot: #error {\n :cause "sandbox.RealFoo.bar()Ljava/lang/Object;"\n :via\n [{:type java.lang.AbstractMethodError\n :message "sandbox.RealFoo.bar()Ljava/lang/Object;"\n :at [sandbox$eval68 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval68 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval68 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n [clojure.lang.C...

11:54 sdegutis: I'd like to be able to do something like that.

11:54 Kind of like Ruby's #attr_accessor or whatever it's called.

11:54 Or must I write my own macro to do this?

11:55 The problem I'm trying to solve is to have some kind of type-safety on keys on what is currently just a map.

11:55 I end up typing (:email-service env) and hoping I didn't make a typo, and writing a unit test if I need to prove that I didn't.

11:56 Whereas I'd like to just have it fail at compile-time if it's not a valid key, like (env/email-service env)

11:56 I suppose I can just create functions that are the keys, such as (do (ns myapp.env) (def email-service :email-service))

11:56 Then I can access env/email-service knowing for sure it's legit.

11:57 Okay, thanks, I'll do that.

11:57 Good morning justin_smith.

12:00 Lewix: ,(conj nil 0)

12:00 clojurebot: (0)

12:01 sdegutis: how are you luma

12:01 Lewix: ,(conj '(1) 0) ;; added in the most natural way ok?

12:01 clojurebot: (0 1)

12:01 Lewix: ,(conj '(0) 1) ;; added in the most natural !? no way

12:01 clojurebot: (1 0)

12:03 Lewix: so no matter what it adds it after the number in this instance

12:03 (class '(:foo))

12:03 ,(class '(:foo))

12:03 clojurebot: clojure.lang.PersistentList

12:04 Glenjamin: Lewix: conj always adds in the most efficient way

12:04 ,(doc conj)

12:04 clojurebot: "([coll x] [coll x & xs]); conj[oin]. Returns a new collection with the xs 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type."

12:04 Glenjamin: that's not very helpful

12:09 sdegutis: wow I guess everyone else is productive today

12:09 well that's good I suppose

12:17 justin_smith: I'm much more productive now that I only IRC on the mobile (which I have connected to a bluetooth kvm)

12:19 sdegutis: justin_smith: nice

12:19 justin_smith: on one hand I really enjoy socializing in #clojure (anything more than that is too much socialization for me)

12:19 justin_smith: on the other hand, I feel bad like I'm dragging everyone else here's productivity down with me

12:19 justin_smith: so its good to see you're being more productive with a clever solution

12:41 Phew, we're a lot less stringly-typed now.

12:53 tolstoy: For some reason, I rarely have an issue with fat-fingered keywords, etc, etc.

12:53 Not sure why.

12:53 I used to.

12:54 I bet I use maps (and so on) in a much more temporary way than I used to.

12:54 Like Clojure has taught me to be the designer it prefers.

12:59 spieden: i habitually use the cursive keyword completion and check the "find usages" popup

12:59 also use namespaced keywords much more lately

13:00 keyword indexing can lag behind though it seems

13:01 cfleming: should that be the case?

13:02 tolstoy: I imagine another technique is that outside a concern, the data blobs are largely opaque.

13:03 (create-email {:to "blah" :from "blah" :smtp "whatev"})

13:03 Then (email/send email "nub@example.com").

13:03 So, it's only in the email namespace I ever have to track keywords or worry about types more complicated than strings.

13:04 spieden: tolstoy: do you use prismatic plumbing's fnk, et al?

13:05 tolstoy: Nope.

13:06 I'm guessing most of the problems I work on are pretty simple.

13:07 I do read a config.edn and validate it with schema, then just assume it's valid when I pass a sub-map to a component.

13:07 When I get data from a websocket (say), I use schema to validate it.

13:07 But those are the two pain points.

13:08 spieden: tolstoy: i like the fnk destructuring forms a lot

13:08 tolstoy: I think if it were all painful to me, I'd just move on to a Haskell of some sort.

13:08 spieden: .. but yeah, schemas for the entrypoints of data

13:09 tolstoy: Esp. if other people are going to use it.

13:09 I've had people send me a JSON doc that was just wrong, but get a cryptic error back and just assume I was a crappy programmer and start digging around in my code.

13:10 Maybe I am a crappy programmer!

13:10 But a nice "missing key" error sure cuts down on people having to be disappointed in me. ;)

13:11 sdegutis: tolstoy: we all are

13:12 tolstoy: Yeah. It's never my fault your lib doesn't work! You clearly don't know what you're doing! ;) Oh, wait. Sorry. <--- programmer mindset

13:14 sdegutis: tolstoy: what do you use instead of maps now?

13:15 tolstoy: I use maps like everyone else, for the most part.

13:15 sdegutis: yeah but how is that?

13:15 tolstoy: I'm just trying to piece together why I don't get into as much trouble with them anymore.

13:16 sdegutis: tolstoy: I've started passing around an "env" map that has keys like :email-service, :env-name, :host-name, :db-connection, stuff like that which changes based on environment

13:16 I pass it to all my (defn routes [env] [...]) functions, which just return a vector of compojure routes, that capture the env via lexical scope

13:16 tolstoy: Well, for instance, I like websockets. So, I get a message like [:some/thing {:map "of stuff"}]. Then I destructure, and validate the map, then call a function based on the first word in the tuple, and then the map is over.

13:16 sdegutis: and they pass it to whatever functions need to send emails or change the DB, etc

13:17 tolstoy: ahh I see

13:17 tolstoy: The map is just good for that message, not meant to represent a domain object.

13:17 sdegutis: right

13:17 hmm yeah I use it for inter-function communication sometimes too

13:18 tolstoy: I don't think I do that much any more (just evolved to be that way), which I'm guessing is why things seem smoother for me.

13:19 Lately, I get a message in [:topic msg-map] and I've been casting it to a record (map->SaveUser msg-map).

13:19 sdegutis: tolstoy: ah

13:19 tolstoy: Then I have protocols for that.

13:19 sdegutis: thanks for ur feedback

13:19 tolstoy: (if (satisfies? IMutate msg) (protcol/mutate msg db) ...)

13:20 Also, (when (satisfied? Validatable msg) (protocols/validate! msg)) and so on.

13:20 sdegutis: tolstoy: I've found protocols & records to be very handy, but only for services which could change depending on whether you're in a test environment (i.e. deftest), development, or production, such as EmailService, LiveEmailService, and MemoryEmailService

13:20 tolstoy: Then I have a single file "validate" that handles that concern for all (or most) messages.

13:21 sdegutis: That's what I use them for too. I have a Publisher component, for instance (def record) which I can re-instantiate with different topics. But they all implement the send! protocol.

13:22 sdegutis: hmm interesting

13:22 tolstoy: sdegutis: The advantage of converting a message or data item to a record is you can hang protocols on it. No matter what the message is, you can call "validate" on it, for instance.

13:22 sdegutis: tolstoy: do you work on a clojure app full time btw?

13:23 tolstoy: I'm freelance at the moment, so, yes and no: quick and dirty apps, for the most part.

13:23 sdegutis: tolstoy: hmm interesting, re: "validate" & protocols

13:23 tolstoy: not sure I fully understand, but..

13:23 tolstoy: sdegutis: It's overkill on a small app, but starts to work out well (I think) for a big app.

13:25 sdegutis: hmm

13:25 tolstoy: Think of a validate namespace (myapp.lib.validate ...), and then (extend-protocol Validatable m/UserCreate (validate [_] ...) m/UserEdit (validate [_] ...) m/AccountDelete (validate [{:keys [id auth]}] ...)). All your "validation" is in that one file, and dispatched based on the type of message.

13:26 sdegutis: tolstoy: ahh, that's an interesting way to do it

13:26 tolstoy: With a web socket, there's just one end point, so instead of a giant case statement for each type of message, I have a "process!" function that tests which protocol a given message implements, then invokes the right function.

13:27 All the database query stuff is in one file, the database mutate in another, all based on the type of message.

13:27 Downside: Stuff starts to get spread out. You have to edit four files for ever new message you want to process.

13:28 Upside: your one file isn't 1000 lines long. ;)

13:28 Oy.

13:28 ANYWAY, what I don't do is pass maps from one component to another, to seems. ;)

13:28 sdegutis: tolstoy: I see this making a lot of sense when you have a single entry-point into the system

13:28 tolstoy: Yeah.

13:29 sdegutis: tolstoy: in our case we handle them on a case-by-case basis, for better or worse, since we just use plain-jane HTTP

13:29 unrelated, there should be a one? function

13:29 ,(defn one? [x] (= 1 x))

13:29 clojurebot: #'sandbox/one?

13:29 sdegutis: ,(map (juxt neg? pos? zero? one?) (range 10))

13:29 clojurebot: ([false false true false] [false true false true] [false true false false] [false true false false] [false true false false] ...)

13:30 tolstoy: Heh. We already have zero?. So, zero? one? a-few? a-lot? tons? webscale?

13:30 sdegutis: I too often wanna check if there's only one item in a collection.

13:30 Like, 4 times so far..

13:30 so that's about.. once per year

13:31 rcassidy: several?

13:31 tolstoy: a-scosh?

13:31 smidgen?

13:32 TimMc: (defn big-data? [n] (< 40 n))

13:32 sdegutis: haha

13:32 TimMc: If you don't think 40 is a big number, I challenge you to eat 40 hot dogs in a sitting.

13:33 sdegutis: TimMc: thats an interesting way to look at it

13:33 TimMc: I would have done (> n 40)

13:33 TimMc: sdegutis: Yeah but then your number line is backwards. :-P

13:34 <---39-40-41---n--->

13:35 sdegutis: TimMc: interesting

13:53 bendlas: hi, are there read-cond flags for cljs macros?

14:05 TMA: actually, 40 was established as value of infinity in ancient middle east

14:25 sdegutis: ha

14:33 ane: well, it's more than 39

14:41 rcassidy: http://www.therobotsvoice.com/wp-content/uploads/2011/03/lexluthorcakes.jpg

14:59 jjmalina: rcassidy where is that from

15:02 TimMc: So many!

15:02 TMA: Seems implausible. :-)

15:10 TMA: TimMc: it does: https://en.wikipedia.org/wiki/40_%28number%29#In_religion

15:16 Empperi: you must have edited that page just before pasting the link, spent the last hour typing that stuff in

15:16 lmao

15:17 TimMc: TMA: Eh, that's not infinity, that's "large number"

15:26 TMA: TimMc: that's nitpicking :) the English word "forever" is too understood as a "long time" not as "infinite time" in day-to-day contexts; likewise "infinite" is "too large number to count" -- “It seemed like forever ago, like we've had this brief but still infinite forever. Some infinities are bigger than other infinities.” ― John Green, The Fault in Our Stars

15:31 rcassidy: jjmalina: http://knowyourmeme.com/memes/lex-luthor-took-forty-cakes

15:33 gganley: Hi, I'm starting a project that needs a connection to an IRC server. I've never made a program that uses the network this way but I've worked on a lot of Cisco routers so I have plenty of knowlage of the protocol itself. I'm just looking for some advice on how to start in network programming. it doesnt have to be clojure specific but i would like if it was

15:36 Empperi: you insist on doing the IRC stuff yourself?

15:36 or do you want to use a library for that

15:41 gganley: in my mind its a good learning opertunity but I'm not opposed to using a library

15:42 Empperi: this is an old java library but it works for irc communication http://www.jibble.org/pircbot.php

15:42 Deraen: gganley: You could take a look at https://github.com/Raynes/irclj for IRC impl

15:43 Aleph might also be interesting if you want to do async TCP/UDP stuff

15:45 gganley: I just found aleph also

15:46 it uses the manifold library which im havent heard of

15:51 ane: manifold is great

16:10 asdf12z_: if i have a program (server) running using clojure, and i repl into it to update some code, will it crash if my updated code throws? is there a way to make it just fallback

16:10 ane: depends if it's the main thread

16:54 Lewis: what does it mean to thread an expression through a variable number of forms?

16:55 ridcully: ,(-> 1 inc inc inc)

16:55 clojurebot: 4

16:56 luma: ,(-> 1 (+ 2) (* 3) (+ 4))

16:56 clojurebot: 13

16:56 luma: ,(+ (* (+ 1 2) 3) 4)

16:56 clojurebot: 13

16:56 luma: those forms are the same thign

16:59 yottabyte: is it difficult to add a clojure class to a java web application and have it work with other java classes

17:00 rcassidy: the double arrow threads in last position so you can do things like

17:00 hiredman: depends what you mean

17:00 amalloy: yottabyte: it's easier to instead use a clojure function (or functions), and write a java wrapper class that acts as a facade for it

17:00 rcassidy: ,(->> "abcdef" (.toUpperCase) (take 3) (reverse))

17:00 clojurebot: (\C \B \A)

17:00 hiredman: clojure doesn't have something called a 'class'

17:00 yottabyte: amalloy: can you show me an example of that?

17:01 amalloy: https://github.com/amalloy/thrift-gen

17:10 jbrhbr: hey guys. i've been trying to learn clojure and have been doing some of those codewars kata. i have a solution that's mathematically correct but i think i'm getting an ob1 error due to precision rounding or something with respect to sqrt's behavior with bigints. would anyone mind taking a look at what i have and letting me know if you see anything funny? https://gist.github.com/jerryhebert/ecf54d3c33faa0c0c4d9a19efd5d1199

17:11 trying to avoid writing it some other way since this one is basically just a math problem

17:12 the issue is (find-nb 10252519345963644753026N) yields the solution 450010N, but verifying 450010N yields 10252519345963644753025N (off by 1)

17:13 luma: Math/sqrt takes and returns a double

17:14 that's where a precision error probably comes fro

17:14 jbrhbr: yeah

17:15 it's all i can see too, i guess i was just hoping it was overloaded for bigints or something

17:15 luma: nope

17:16 jbrhbr: i'm honestly surprised it's this close if it isn't doing something near-correct tho

17:16 rcassidy: you might just need to implement bigint sqrt logic yourself

17:19 jbrhbr: it's actually producing the correct value for 20250148500407250495000225N, somehow. guess i'll have to poke around some more

17:20 and that one is way more than 64bits

17:21 thanks for the input

17:33 i discovered this today: (number? (Math/sqrt -1)) => true

17:33 i'm sure there's a good reason for it but NaN being a number is pretty funny :p

17:36 rhg135: ,(Math/sqrt -1)

17:36 clojurebot: NaN

17:36 hiredman: you may be confusing math with computers

17:37 rhg135: I is dissapoint. that's i/j

17:38 hiredman: ,(type NaN)

17:38 clojurebot: #error {\n :cause "Unable to resolve symbol: NaN in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: NaN in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: NaN in this conte...

17:38 hiredman: ,(type Double/NaN)

17:38 clojurebot: java.lang.Double

17:38 hiredman: ,(supers (type Double/NaN))

17:38 clojurebot: #{java.lang.Comparable java.io.Serializable java.lang.Number java.lang.Object}

17:38 jbrhbr: a NaN type could be its own class that isn't a number, for less language asymmetry

17:40 hiredman: NaNs exist as part of floating point standards, so just don't do floating point

17:40 jbrhbr: and then the return type of Math/sqrt is either double or whatever NaN is

17:41 jbrhbr: sure

17:41 hiredman: and of course, Math/sqrt doesn't return an Object anyway, it returns primitive

17:41 jbrhbr: i'm not denying there are good explanations

17:42 but the english "not-a-number is a number" is funny

17:42 that seems like a jvm oddity to me though

17:42 hiredman: it isn't it is built right in the hardware

17:43 jbrhbr: it's a design choice

17:43 alternative: raise an exception when your function is cornered into making a weird type choice

17:44 amalloy: jbrhbr: seems like a pretty reasonable alternative is: "follow the IEEE spec everyone else follows"

17:46 hiredman: the fp spec folds nan values and floating point valus in to the same bit space, the fpu instructions all take those bit patterns and produce them

17:47 jbrhbr: amalloy: that spec doesn't define a language type system

17:47 sorry if i offended you guys, it was meant to be a joke

18:09 aptablips: Hi. Quick Clojure question: How do you do an inexact numerical comparison? For example, I'd like this to come out true: (= (+ 0.1 0.2) 0.3)

18:09 TEttinger: good ol' epsilon.

18:09 aptablips: arguably the simplest way for those exact numbers is

18:10 aptablips: You mean I should just compare with the absolute value of the difference?

18:10 TEttinger: ,(= (+ 1/10 2/10) 3/10)

18:10 clojurebot: true

18:10 aptablips: Well, those exact numbers are only an easy illustration. My app needs floating point. :)

18:10 TEttinger: yeah, sadly

18:11 the ratios are a pretty useful concept, though they need more numeric tower support

18:12 aptablips: Hmm, well, googling for "clojure epsilon" just turned this up: https://crossclj.info/doc/avenir/0.2.0/avenir.math.html#_approx%3D

18:12 TEttinger: I was just going to do

18:12 aptablips: (defn approx= "Approximate equality test within epsilon ( *default epsilon* 1e-6)" {:added "0.2.0"} ([x y] (approx= x y 1e-6)) ([x y epsilon] (< (abs (- x y)) epsilon)))\

18:13 TEttinger: ok you got it :)

18:13 aptablips: Well, the formatting got messed up. But it does exactly what one would expect.

18:13 Thanks! (I only just started Clojure a couple days ago.)

18:14 TEttinger: cool. there's a few neat things you might not have seen yet in regards to those floating point things

18:14 ,1M

18:14 clojurebot: 1M

18:14 TEttinger: ,0.0001M

18:14 clojurebot: 0.0001M

18:14 TEttinger: ,0.00000000000000000000000001M

18:14 clojurebot: 1E-26M

18:15 aptablips: BigDecimal, then? How is it on performance? I need this thing to run super-fast.

18:52 sdegutis: Hello!

18:52 How are you this evenign?

18:53 Hello justin_smith how are you?

18:53 tolstoy: Avoiding his phone, apparently. ;)

18:53 sdegutis: Good day TEttinger how is your status thus far?

18:53 TEttinger: is good.

18:53 sdegutis: tolstoy: Good evening kind sir, what is your state now?

18:54 TEttinger: I am glad to hear this.

18:54 tolstoy: Wrapping protocols around defrecords. Like any other day.

18:54 sdegutis: tolstoy: Adds up.

18:54 I have found that a few glasses of alcohol increases my ability to concentrate and thus my productivity.

18:55 However, it decreases my ability to hit the correct keys on the keyboard, which seems to neutralize at least some of the productivity benefit.

18:55 (Since I have to backspace quite often.)

18:55 Also, it increases my ability and will to DANCE!!!

18:55 I am sciencing alcohol.

18:56 Especially to Bon Iver, which is a homonym for the French phrase for "good winter", which I suppose is due to it sounding very much like winter when I listen to them.

18:57 :)

19:03 amalloy_: I'm not sure if you're aware of it, but your IRC nick often changes between amalloy_ and amalloy.

19:03 amalloy_: At least N times per hour, where N is roughly a unit.

19:05 Yeah, like that.

19:11 amalloy: have you also noticed that i am never signed out of irc?

20:06 cfleming: spieden: I've noticed that too, but I haven't had time to investigate.

20:06 All the other indexes update pretty much immediately, but that one lags for some reason.

21:20 sdegutis: amalloy: yes

21:31 amalloy: i will give you a hint, sdegutis: those two phenomena are closely linked

21:31 sdegutis: amalloy: it wasn't a mystery for me to solve, requiring hints

21:31 amalloy: it's a "feature" you may want to consider disabling

21:32 bbl renting The Usual Suspects

21:32 amalloy: i could. i think it's nice for people to know that i'm not actually here by looking at my nick

21:43 sdegutis: amalloy: that would be cool, if it were always accurate, but in my experience those things are often very inaccurate

22:03 TimMc: Some channels kick people for changing their nick as an afk indicator.

22:03 (which just raises the question: who doesn't ignore nick changes?!)

22:29 machinewar: if I do doseq over a sequence of maps with possibly nested maps, willl it visit every key?

22:30 http://www.chrisumbel.com/article/clojure_xml_parsing_xml-seq I'm reading this and can't understand how I can get to every nested key in the sequence as in first example it does!

22:46 TimMc: machinewar: It will only "visit" the maps themselves.

22:48 machinewar: Ah, I think I see your confusion -- you'd be iterating over a seq of all the XML nodes. I think you're confusing maps with keys with XML nodes maybe?

22:48 Not sure what your goal is.

22:54 justin_smith: machinewar: look at what xml-seq outputs for that example file

22:55 machinewar: https://gist.github.com/noisesmith/5e277b89e2c6cb7c00525378a74a721d

22:55 that should make it clear how doseq found the nested tags

22:55 output is from loading a copy of the data in that post

22:56 xml-seq is a tree walk

22:56 it returns each node, until it hits all the leaves

22:57 machinewar: justin_smith: ahhh wow

22:57 what a function!

22:58 i'm stilll getting the hang of this whole functional thing, and its insane how powerful some of these standard library functions are

22:58 justin_smith: also, they combine in really powerful ways, yeah

22:59 machinewar: thanks for pointing that out

22:59 TimMc: I should... not be trying to answer questions, and go to bed. :-P

22:59 machinewar: TimMc: thanks to you too

Logging service provided by n01se.net