#clojure log - Mar 12 2015

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

0:00 justin_smith: sejje: it's odd that it uses the term "confusing" instead of the more standard "conflict", might be worth making a pr for

0:00 sejje: aren't you just the fountain of knowledge!

0:01 (inc justin_smith)

0:01 lazybot: ⇒ 207

0:02 justin_smith: sejje: I have never regretted the time I wasted learning to do things by hand with the Linux CLI while my peers were pointing and clicking :)

0:03 sejje: i'm about a decade into my linux foray, it's my daily. haven't run into that issue, though. and i'll admit my knowledge is still a bit superficial.

0:03 i've had to fix about 25 wifi card driver issues, though...

0:03 justin_smith: heh

0:04 sejje: justin_smith: hopefully one last question...what's this syntax? :exclusions [com.cognitect/transit-clj]] -> [org.clojure/data.json "0.2.5"]

0:05 amalloy: justin_smith: i think that's because it doesn't tell you aobut every conflict, only those that it thinks might surprise you

0:05 justin_smith: amalloy: oh, I guess that would be a nuance

0:05 yeah, it won't list the things you have proper :exclusions for

0:05 amalloy: eg, if you ask for a recent version, and some library asks for an older one, it assumes you are doing that an purpose and that it won't cause problems (though IMO that is not particularly true)

0:06 justin_smith: oh, it doesn't list conflicts when you ask for an explicit version at the top level? that's an odd choice, I would have expected an explicit exclusion

0:07 razum2um: is there any videos from http://euroclojure.com/2014/#programme-jump ?

0:07 justin_smith: sejje: it's saying [foo/bar :exclusions [com.cognitect/transit-clj]] pulls in a dep for [org.clojure/data.json "0.2.5"]

0:07 amalloy: i believe that's the case, but try it and see if i'm wrong, of course

0:07 justin_smith: sejje: replacing foo/bar with whatever was actually in your deps output of course

0:13 raspasov: hey guys - anyone with Cursive + ClojureScript experience, what's the state of the union on that ? :)

0:19 dnolen: raspasov: code navigation, completion, etc. works great. REPL bits need a lot work, but cfleming is on it as far as I know.

0:19 raspasov: dnolen: cool, are you using it from Cursive? can you eval from IntelliJ into the browser?

0:19 or better to just hit refresh? :)

0:20 dnolen: raspasov: no I'm sick of ClojureScript tooling, it's Clojure scripts fed to the ClojureScript compiler for me

0:21 raspasov: dnolen: ok cool! thanks :)

0:21 dnolen: however, the goals is to stabilize the fundamentals to the point that downstream tooling can be productive for the people that want it

0:37 sejje: justin_smith: that moment when the problem wasn't a dependency issue...sigh. all resolved, ring still won't start. ::throws desk::

0:37 nuwanda_: raspasov: you can eval from intellij into the browser

0:38 raspasov: nuwanda_: yea? nice - how do I hook it up?

0:38 do you Import the project into IntelliJ?

0:38 just started following https://github.com/omcljs/om/wiki/Basic-Tutorial

0:38 got Figwheel and the Hello World

0:38 haven't touched Cljs in months, trying to get up to speed :)

0:40 nuwanda_: raspasov: yeah, you can import lein projects into intellij

0:40 you can follow cursive's guides to starting repls etc

0:41 raspasov: ok got that, how do I hook up the repl? I do it all the time with JVM Clojure

0:41 but this doesn't seem to work that way

0:41 nuwanda_: they have instructions on the website on how to get their repl started inside the ide

0:41 you can start a browser repl inside that one

0:42 and then you normally use whatever is the default keybind for "eval form in repl"

0:51 sejje: http://pastebin.com/DXUqK7ny if anyone has any insight, i'd surely appreciate it!

0:53 justin_smith: sejje: looks like something that happened when you were loading watt

0:54 sejje: justin_smith: it's definitely related to watt, as removing the :require from home.clj leaves things running smoothly. fwiw i've used watt in a non-web (luminus) project with no issues.

0:55 some brief googling made me suspect a dependency issue, based on similar issues (but for other projects)---but alas, that doesn't seem to have helped.

0:55 doesn't help that i find clojure stack traces fairly incomprehensible

0:55 justin_smith: sejje: do you have a link to watt.core? clojure watt isn't a useful google search from here

0:55 watt.core is where the error is being reported

0:56 sejje: https://github.com/nicknovitski/watt/blob/217e3a28ecc01f77282faad265c5a42e47268765/src/watt/core.clj

0:57 btw, an aside: does the stacktrace report line 1 (in watt/core) because it's ignoring whitespace?

0:58 justin_smith: sejje java.lang.ClassNotFoundException: org.apache.http.conn.ssl.SSLContexts

0:58 puredanger: clj_http.conn_mgr imports org.apache.http.conn.ssl.SSLContexts

0:58 justin_smith: and that's the error, right

0:58 puredanger: which is from org.apache.httpcomponents/httpclient

0:58 justin_smith: sejje: manually add that dep (or change the version you get so you get that class defined)

0:59 puredanger: that seems to be in the deps list so not sure why that wouldn't get picked up

1:00 justin_smith: puredanger: he was messing with version conflicts though, it could be he settled on a version that did not provide that class?

1:01 puredanger: it's in the 4.2.1 that's in the deps tree

1:01 justin_smith: that's weird

1:01 sejje: so guys, adding this ([org.apache.httpcomponents/httpclient "4.3.5"] ) to project dependencies fixed the issue, but i don't understand why--i had to explicitly exclude that when importing watt (and several other libraries) to satisfy lein deps

1:02 puredanger: was just going to say it looked like you had excluded it

1:02 why?

1:02 clojurebot: why is the ram gone

1:02 puredanger: sometimes I hate clojurebot

1:02 sejje: but i only had to exclude it because lein thought it conflicted, right?

1:02 justin_smith: clojurebot: are you really that bad??

1:02 lazybot: justin_smith: What are you, crazy? Of course not!

1:02 clojurebot: Excuse me?

1:03 puredanger: it looks to me like leiningen itself is also excluding it so maybe that was causing something weird

1:03 sejje: puredanger: it had the issue before i excluded it--i did that because i thought it was a dependency conflict (lein deps :tree recommended it0

1:04 justin_smith: you know, if there were a unicode for waldo, we could put one in every stack trace

1:04 puredanger: just fyi (not that this would necessarily help you), but in clojure 1.7.0-alpha5 (can't remember which alpha it was changed exactly), imported classes are not loaded.

1:05 sejje: given these stack traces, it'd actually be a task to find him

1:06 hiredman: sejje: have you looked at `lein deps :tree` ?

1:06 sejje: hiredman: yessir, thanks. we actually got it sorted, just talking about the aftermath at this point.

1:07 hiredman: i had satisfied all of the :tree recommendations for conflicts

1:07 hiredman: likely you have two deps pulling in different versions of httpclient, so lein just picks one, and the one it picks doesn't work

1:08 so you have to explicitly tell it which transitive dep to pull in, either by excluding one, or declaring a non-transitive dependency on one

1:08 sejje: yeah apparently the remaining one wasn't recent enough, or was broken in some way. setting it explicitly in deps fixed it.

1:19 domokato: is it sufficient to store a cache (map) as an atom, even though there is a gap in time between a cache miss and adding to the cache?

1:21 justin_smith: domokato: atoms don't lock, if that's your concern

1:21 they retry if there is a conflict

1:22 domokato: the worst that would happen is an item would be added to the cache twice but one of them would be lost, which should be fine

1:22 right?

1:22 justin_smith: domokato: depending on how you write the function that you pass to swap!, it can refuse to associate data if it is already present

1:23 but do be aware that swap! will retry, so don't put side effects in the function

1:24 domokato: i'm just using assoc

1:24 passing assoc to swap!*

1:24 justin_smith: OK, that will just overwrite - I'm more trying to point out that writing a function with the preserving / overriding behavior you like is an option

1:25 hiredman: assoc in a delay

1:26 (swap! cache (fn [m] (if (contains? m k) m (assoc m k (delay get value))))) (force (get cache key))

1:26 @cache

1:34 domokato: hiredman: hm, how does that help?

1:36 the problem is I don't want to perform a swap! if the cache already contains the value, so I can't put the cache lookup in the function passed to swap! Unless...there's no harm in doing a swap! with no changes?

1:38 hm, actually the retrying thing might be a problem in the case where I'm trying to create a new Texture; I don't want to leave extra of those laying around

1:39 I guess I'll have to use locking then?

1:39 justin_smith: domokato: that's what the delay helps with

1:40 domokato: oooo, i get it

1:40 neat, thanks!

1:45 i don't get the (delay get value) part, though. The get is basically a noop, right?

1:46 justin_smith: yeah, I think he meant (delay (produce result))

1:46 or whatever

5:01 doritostains: there's a dependency in my project for tools.nrepl 0.2.6 but I don't know where it's coming from. I have 0.2.7 in my dependencies list but it's not taking. lein deps :tree doesn't show me any information about a conflict

5:01 how do I track down where 0.2.6 is being pulled in from or force 0.2.7?

5:05 TEttinger: is it a dev-dependency?

5:05 not sure if deps :tree shows those

5:07 doritostains: yeah it has a :scope of "test"

5:07 [org.clojure/tools.nrepl "0.2.6" :scope "test" :exclusions [[org.clojure/clojure]]]

5:12 cfleming: doritostains: That's injected by Leiningen. I'm not sure why it wouldn't take your explicit dependency though.

5:14 doritostains: cfleming: yeah I did lein upgrade and it says I'm at the lastest version. I'm confused, I'll try also adding the dependency to the dev profile

5:16 hyPiRion: doritostains: https://github.com/technomancy/leiningen/issues/1840

5:17 doritostains: hyPiRion: excelent, thanks!

5:18 was going to try that but forgot the exclusion, greatly appreciate it

5:19 hyPiRion: np :)

5:22 doritostains: working perfectly now, it's goign to be a good night!

5:52 egli: hyPiRion: your solution for upgrading the dependency of tools.nrepl only works for dev builds, doesn't it?

5:52 what if I want to include a repl in my production build?

5:54 hyPiRion: egli: I think it should work fine if you just copypaste that into :dependencies instead

5:54 but if not then there's probably an issue up on lein's tracker

5:54 egli: hyPiRion: ah, cool thanks

6:44 mpenet: is there a not awfull way to get to the methodTable keys in a defmulti ?

6:44 appart from (-> x bean :methodTable keys)

6:49 mpenet`: nevermind

7:42 noncom: i have some general style question

7:43 when you write things like (map ... coll) or (filter ... coll), then - how do you usually do it - do you first write (map coll) and then put the cursor in the middle and write the fn or do you first write the fn and then the coll? (and init in case of reduce, if needed)

7:43 i find myself always writing like (reduce init coll) and then returning to (reduce | init coll) and writing the actual fn...

7:43 seems kinda strange to me...

7:44 agarman: it's not unusual

7:44 nsjph: i usuall wrap it... (map .. coll) then figure out what to do in-between

7:45 noncom: why then don't we have (map coll ...) instead of (map ... coll) ? is it because the map is a verb and we map the fn over coll, and not coll over fn ?

7:45 nsjph: that's a great question, but i'm not knowledgeable to answer it

7:46 oh

7:46 well

7:46 usually with the notation method, you have the arguments last

7:46 (+ 1 1) for instance

7:46 clojurebot: 2

7:46 nsjph: so (map .. coll) has the arguments last as well

7:47 so with map, but the function and collection are arguments

7:48 given that you might re-use that in the future, with varying arguments, i would tend to agree that you leave coll as the final argument

7:48 if the (map f ...) usuall remains unchangeed

7:52 stuartsierra: *Sequence* functions (map, filter, reduce) take the sequence last. Almost everything else, including non-sequence collection functions, takes the "primary" argument first.

7:54 nsjph: for newcomers, it might feel a bit weird, but the consistency helps when you use other sequence funcs

7:56 gfredericks: I've always thought that a lot of things take a function as the first arg because it's occasionally useful with partial

7:57 (def compact (partial remove nil?)) ;; e.g.

7:57 agarman: yeah, no use of partial application over a collection

8:07 ticking: any idea what could cause wrong line numbers for IllegalArgumentExceptions?

8:08 TimMc: agarman: I've sometimes mapped a map or set over something.

8:08 but that's rare, yes

8:08 agarman: yes

8:16 rarer something is, uglier it can be e.g., #(map % set)

8:56 eli-se: do dynamic vars work well with core.async? e.g. doing channel operators in a binding block in a go block

8:57 ro_st: probably depends on whether you're using threaded or parked

8:57 double ! or single !

8:57 double ! probably won't work

8:57 mpenet`: eli-se: I dont think so, no guarantee that your parked op will be taken over by the same thread later on

9:53 Atarian: If I split up a program into seperate files that share the same namespace, do I have to :require libraries in both namespace declarations or just the first?

9:57 stuartsierra: Atarian: just the first, the other files should start with (in-ns 'the-namespace)

9:59 Atarian: Thanks stuartsierra

10:00 I was just putting the seesaw stuff in another file is all

10:01 stuartsierra: Some development tools/IDEs may have a harder time figuring out where things are when one namespace is split across multiple files, but Clojure itself doesn't care.

10:02 Atarian: I'm using emacs

10:03 I do find I have to C-c functions in the other file

10:29 eric_normand: clojurescript is feeling more mature

10:35 sveri: it is possible to have one namespace spanning several files?

10:36 arrdem: With load, yes

10:36 sveri: arrdem: ah ok

10:36 arrdem: clojure.pprint does this for instance IIRC.

10:38 sdegutis: Is there any news on ClojureScript being hosted on node without the JVM?

10:39 zerokarmaleft: sdegutis: I doubt that's a goal of the project

10:39 sdegutis: I thought it was coming 2015.

10:40 zerokarmaleft: perhaps I'm misunderstanding what you mean by "hosted on node"

10:40 sdegutis: The compiler.

10:41 noncom|2: is there a jvm-independant compiler?

10:41 zerokarmaleft: the compiler itself is written in clojure, I can't imagine it being rewritten in JS

10:41 charlespwd: is there a more elegant way of getting multiple keys out of a record than (map (into {} my-rec) [:x :y])

10:42 zerokarmaleft: that's a lot of effort for arguably little value

10:42 sdegutis: zerokarmaleft: but if the compiler is written in Clojure that's fully compatible with ClojureScript, it should be possible to run it via node

10:42 arrdem: charlespwd: (map my-rec keyseq) should work.

10:42 mpenet`: there's shin https://github.com/fasterthanlime/shin

10:42 charlespwd: it doesn't

10:42 sdegutis: charlespwd: select-keys

10:42 charlespwd: User.Ball cannot be cast to clojure.fn

10:42 sdegutis: (doc select-keys)

10:42 charlespwd: will try that

10:42 mpenet`: but it trades the jvm bits with ruby/v8

10:43 clojurebot: "([map keyseq]); Returns a map containing only those entries in map whose key is in keys"

10:43 charlespwd: thanks, select-keys is exactly what I was looking for

10:44 tbaldridge: IMO at this point the hardest part of "porting" CLJS off the JVM would be advanced compilation. I don't think anyone feels like writing a JS tree shaker...

10:44 noncom|2: is there a one-liner to make the following regexp match return "176006" string?

10:44 ,(re-find #"(rc_)(\d)([\.]*)(\d)([\.]*)(\d+)(_\w+?_\w+)" "rc_1.76006_android_int")

10:44 clojurebot: ["rc_1.76006_android_int" "rc_" "1" "." "7" ...]

10:44 zerokarmaleft: sdegutis: I suppose that's true...I haven't been following the ML closely recently, so maybe I'm missing something

10:44 tbaldridge: (I know I don't)

10:45 arrdem: ##(re-find #"(rc_)((\d)([\.]*)(\d)([\.]*)(\d+))(_\w+?_\w+)" "rc_1.76006_android_int")

10:45 lazybot: ⇒ ["rc_1.76006_android_int" "rc_" "1.76006" "1" "." "7" "" "6006" "_android_int"]

10:46 arrdem: noncom|2: ^

10:48 noncom: sorry if i missed a reply, i got dropped out

10:49 arrdem: noncom: try #"(rc_)((\d)([\.]*)(\d)([\.]*)(\d+))(_\w+?_\w+)"

10:49 sdegutis: tbaldridge: don't what?

10:49 oh

10:50 tbaldridge: nvm

10:50 noncom: arrdem: it returns "1.76006".. it is with the dot.. oh.. well, maybe there is no way..

10:50 i will just take items from the []

10:50 since i am sure of their positions

10:51 sdegutis: Does clojure.typed have anything like ADTs, maybe using pre-defined keywords?

10:51 i.e., it verifies that a value can either be :foo or :bar, nothing else, not even another keyword.

10:53 mpenet`: ,(.replaceAll "rc_1.76006_android_int" "[^0-9]" "") ?

10:53 clojurebot: "176006"

10:53 mpenet`: hairy but...

10:53 noncom: wow

10:53 arrdem: lol

10:53 noncom: that does it i think

10:53 mpenet`: I am sorry

10:53 noncom: u see, i am so lame about regexps, even the one you saw above, was made by my friend..

10:54 arrdem: (inc mpenet) ;; for knowing your sins

10:54 lazybot: ⇒ 5

10:54 mpenet`: I suck so much in RE that I have to resort to that, my bad

10:54 noncom: :D

10:57 arrdem: is there some reason you need to strip the '.'s? I'm just looking at your regex and thinking about possible collisions between legitimate strings if '.'s are stripped.

10:58 noncom: ummm yes, i have to receive an int from the string..

10:58 arrdem: Ex. (= (f "1.23") (f "12.3"))

10:59 noncom: yes, just like that..

11:00 sdegutis: Is core.typed ready for production use?

11:02 mpenet`: sdegutis: some are using it with success, ex circle-ci

11:02 sdegutis: anyway, it's compile time checks, so you're not risking much

11:19 noncom: i have a [] with strings of 3 types, mixed. like 1) a string, containing #, 2) a string containing "sugar" and 3) a string, containing "best". what is the most idiomatic way to get the 3 []s of strings, in respect to the grouping criteria?

11:19 i could surely use 3 (filter ...) things, but that looks clumsy..

11:20 gfredericks: noncom: does group-by work for you?

11:20 justin_smith: (inc gfredericks)

11:20 lazybot: ⇒ 121

11:20 justin_smith: he even said the magic "group" word

11:20 gfredericks: ,(* 11 11)

11:21 clojurebot: 121

11:22 noncom: oh, right :)

11:22 thank you very much

12:08 bhurlow: hi guys, datomic question here:

12:08 what's the SQL LIMIT equivalent for datomic queries. Do I necessarily have to use take/drop?

12:09 what if I am taking from a really big collection? i.e how lazy is datomic?

12:11 noncom: do i imitate "curl -F" thing in clj-http with (client/get ... {:form-params ...}) ?

12:11 justin_smith: bhurlow: probaly a better question for #datomic, but the results will be pulled from the local cache whenever possible, and results you don't access should populate the cache when first received regardless of usage

12:15 tbaldridge: bhurlow: however, Datomic's query engine is set based, so if you try joining super large datasets you might thrash the cache if you don't have enough RAM

12:16 bhurlow: but Datomic also offers several APIs for talking directly to the indexes, so sometimes it's faster to start with a lazy search over a index, and then query off of the first result. But all that really depends on what you are trying to do

12:17 eli-se: mpenet`: I see.

12:17 I like to use dynamic vars for DI and I'm trying to find a solution for this other than passing things around or clobbering everything with reader monad.

12:18 gfredericks: eli-se: have you looked at component?

12:18 justin_smith: eli-se: the thing is that if the base implementation is passing things around, then you can do dynamic vars, or magic global atoms, or whatever else on top of that

12:18 the others are not as flexible

12:18 eli-se: gfredericks: the technique/library by stuartsierra?

12:18 Watched a video about it but never used it.

12:19 justin_smith: eli-se: yeah, most attempts to deal with this stuff will be clumsy and / or buggy attempts to do half of what component does

12:19 eli-se: I see.

12:20 bhurlow: thanks tbaldridge! I'm gonna move this over to #datomic but many thanks

12:21 mpenet`: eli-se: actually i prefer fn argument, easier to test, more predictable and actually faster in most cases

12:24 justin_smith: mpenet`: well, it may be more powerful, more general, faster to execute, more predictable, and very easy to test, but it also means you have to add an argument to a function. Think of the poor typing fingers.

12:25 eli-se: I have trouble with that in a current project and it's very urging to just create hard dependencies on DB connections and such since it's very cumbersome to add something.

12:25 Although I think that problem has more to do with the fact that SRP is violated all over the place.

12:25 justin_smith: eli-se: component is designed to alleviate that encumberance

12:26 eli-se: E.g. if we want to add a widget to a page then we tend to acquire the data in the request handler of the page. I've been thinking about a different architecture lately which is less like the URL-corresponds-to-function design.

12:26 mpenet`: yeah component is good, just a bit complicated to retrofit depending on the app size/way it's coded.

12:27 eli-se: But rather doing the UI client-side and fetching all data through separate requests.

12:27 That'd be much easier to program, though not feasable to add to the current system. I'll apply it in a new thing I'm working on.

12:28 justin_smith: eli-se: sounds like you are in the uncanny valley between OO and FP

12:29 eli-se: Mwah not really, I prefer procedural/FP over OOP. We use very little OO techniques.

12:29 justin_smith: SRP is OO. encapsulation is OO

12:30 clojer: Editing Clojure in Emacs Live! it seems sometimes my updates are not recognised when I C-c c a form following an edit. Any ideas?

12:31 justin_smith: clojer: what sort of thing are you updating?

12:31 eli-se: justin_smith: SRP is only OO if you are in the narrow minded world where responsibilities apply only to classes

12:32 SRP applies to anything be it a module or a function or a program.

12:32 clojer: justin_smith: File within a project. I change the (defmethod and it seems to cling to the old error.

12:32 kitallis: I was hoping extracting out defroutes* and putting explicit middlewares would only apply it to a section of the routes and not to the entire defapi that they are composed in – but that is not the case – anyone have experience with that in compojure-api?

12:32 justin_smith: clojer: defmethod is defonce

12:32 clojer: to actually change it, you have to assign it to nil first

12:32 or undef it

12:33 clojer: justin_smith: I'm not assigning to it. Just editing a mistake.

12:33 justin_smith: eli-se: functions don't have responsibilities, responsibilities imply encapsulation and state, functions have return values that are fully controled by their inputs.

12:33 eli-se: Basically, I want to have more request handlers that do fewer things. It'd lead to a much nicer design.

12:33 justin_smith: clojer: like I said, defmethod is defonce

12:33 clojer: justin_smith: Same error after correcting and I'm pretty sure it's fixed.

12:33 justin_smith: you *have* to assign it to nil, or no change will happen

12:33 eli-se: justin_smith: I disagre.

12:34 justin_smith: clojer: do you understand what defonce is?

12:34 clojer: if defmethod has been evaluated before, it won't be evaluated again

12:34 clojer: justin_smith: How do I "assign it to nil"?

12:34 justin_smith: clojer: so you need to explicitly assign it to nil or it cannot update

12:34 clojurebot: Cool story bro.

12:34 Deraen: kitallis: You can use context to limit middleware to only certain routes

12:34 justin_smith: clojer: (def method-name nil)

12:35 kitallis: Deraen, aha

12:35 clojer: justin_smith: Is this an Emacs thing or a Clojure thing?

12:35 justin_smith: clojer: clojure thing

12:35 Bronsa: justin_smith: isn't just defmulti defoncey?

12:35 justin_smith: Bronsa: oh, shit, you're right :)

12:36 clojer: justin_smith: I'll have to brush up on (defonce :(

12:36 justin_smith: clojer: listen to Bronsa - defmulti is defonce, defmethod is not

12:36 clojer: justin_smith: Something I need to learn. Doesn't make blind bit of sense right now.

12:37 justin_smith: clojer: I was just using "defonce" as a shorthand. A way of saying the form is not re-evaluated if the definition has been created already.

12:38 eli-se: can you show me a pure function that has a "responsibility" ?

12:38 Deraen: kitallis: Here is a gist as it seems readme is missing this: https://gist.github.com/Deraen/0d37fdcbf98f3d9056e6

12:38 clojer: justin_smith: Will take your word for it but the reason I'm peeved is that I read up on defmulti/defmethod in several sources and don't recall a mention of this. Clojure has some weirdness at times.

12:38 kitallis: Deraen, yup, got it, thx a ton

12:40 kaplan: kitallis, o/

12:40 {blake}: I just checked out Rich Hickey's "ants" thing from a couple years back. (defstruct!)

12:41 justin_smith: arrdem: someone should add a mention that defmulti is defonce to this page http://conj.io/store/v0/org.clojure/clojure/1.7.0-alpha4/clj/clojure.core/defmulti/

12:41 maybe I need to check out that repo finally...

12:41 tbaldridge: does anyone know why it contains defonce?

12:41 {blake}: On my machine, about every 8 seconds it stops cold for half-a-second.

12:42 justin_smith: tbaldridge: so that all your defined multis don't break when you reload the file containing the method

12:42 tbaldridge: I guess to not have it accidentally blow away all defmethods when a ns is reloaded

12:42 arrdem: justin_smith: noted

12:42 justin_smith: tbaldridge: otherwise reloading the file with the method impl, would always require reloading every file that defines a multi

12:42 tbaldridge: seems like someone could defonce part but not the other

12:42 justin_smith: hmm

12:42 {blake}: I'd say garbage collection but I can't see why it would need to GC that often. Is it maybe related to all the threads?

12:42 tbaldridge: on re-evaluation, reset the dispatch function and all caches, but leave the method list alone

12:43 {blake}: Also, it takes 1.6GB of RAM. lol

12:43 justin_smith: tbaldridge: might be a worthwhile contribution

12:43 arrdem: fuck it, I'm doing it, expect a PR shortly

12:44 arrdem: justin_smith: lol you'll want to pr the clojure-grimoire/datastore

12:45 *repo

12:46 justin_smith: arrdem: is that different from https://github.com/clojure-grimoire/grimoire

12:46 it is, and I found it, don't mind me

12:47 arrdem: <3

12:48 justin_smith: woah, this is the first fork? inconceivable

12:48 arrdem: I need to get a real editing workflow built.... people didn't seem to go for the original PR based workflow.

12:48 justin_smith: yep. andyf and I are entirely to blame for all the notes at present.

12:50 justin_smith: arrdem: cool - so it looks like functions are grouped by the earliest covered clojure version that implemented them?

12:50 arrdem: justin_smith: bingo

12:50 justin_smith: just throw that comment in 1.4.0. I think that's where it is at present.

12:50 justin_smith: arrdem: just making sure editing defmulti under 1.4 would show up where expected :)

12:50 yup

12:50 * justin_smith feels smrt.

12:51 arrdem: https://github.com/clojure-grimoire/lib-grimoire/blob/master/src/grimoire/api.clj#L95-L102

12:51 justin_smith: ok, what about the wacky file names for the examples?

12:51 arrdem: those filenames are literally meaningless.

12:51 just has to be a file in that dir to show up.

12:51 justin_smith: so I can just generate something and it suffices that it be unique?

12:52 arrdem: correct.

12:52 many examples are in files named andy<n>.clj

12:52 others have numeric names that are legacy from how clojuredocs indexes and names examples.

12:53 justin_smith: cool, making a "defmulti is stubborn" example now

12:55 arrdem: justin_smith: as long as you're monkeying around in there https://github.com/clojure-grimoire/grimoire/issues/176

12:55 <3

12:55 justin_smith: arrdem: OK, if you're gonna twist my arm about it, sure, why not

12:55 SirRobin: in cljs ~*file* returns a tmp file /tmp/form-init...clj

12:56 arrdem: (inc justin_smith)

12:56 lazybot: ⇒ 208

12:56 SirRobin: is there an easy way around this?

12:58 hiredman: SirRobin: you are likely looking at the wrong *file* if cljs has one at all

12:59 due to generally horriblness, clojure's *file* tends to be bound to that at runtime when using lein (at compile time it is actually bound to file being compiled)

12:59 I dunno if the clojurescript compiler has its own *file*

12:59 Bronsa: there should be a cljs.analyzer/*cljs-file* or something like that IIRC

13:00 {blake}: Are there any hooks for knowing when GC is being called?

13:00 hiredman: (clojurescript macros being written in clojure when expanded are running at "runtime" for clojure which is why you see that value for *file*)

13:00 tbaldridge: {blake}: https://blog.codecentric.de/en/2014/01/useful-jvm-flags-part-8-gc-logging/

13:03 justin_smith: arrdem: another thing missing is the demonstration of defmulti with more than one arg

13:03 SirRobin: Bronsa: awesome, cljs.analyzer/*cljs-file* did the trick

13:03 thanks

13:03 arrdem: justin_smith: I'll open a ticket.

13:04 justin_smith: arrdem: I'll do an example of that while I'm at tit

13:04 *it

13:04 arrdem: thanks

13:06 {blake}: (inc tbaldridge)

13:06 lazybot: ⇒ 19

13:06 {blake}: tbaldridge: Groovy.

13:19 noncom: how do i avoid the "pending takes exceed 1024" in core.async when trying to take from a channel inside a (go (<! ..)) block inside a method of a proxied Java class that executes on a like 100 FPS basis

13:19 ?

13:20 all in all, what is the general advice on avoiding this pending takes thing? using alts?

13:22 agarman: you need to have something take

13:22 or something put

13:23 either side you can cause the error if there's too many pending ops

13:33 tbaldridge: noncom: that's a problem you get when you aren't properly handling backpressure

13:34 perhaps you're spinning up > 1024 go blocks?

13:35 noncom: a gist might help

13:43 justin_smith: arrdem: big cleanup and extension sent your way

13:44 https://github.com/clojure-grimoire/datastore/pull/2/files

13:45 noncom: tbaldridge: https://www.refheap.com/98371

13:45 justin_smith: includes showing the super cool feature that a defmulti can be varargs while the defmethods are not

13:46 noncom: the printer and dispatcher are simple java threads which just perform the method on each run

13:46 justin_smith: perhaps s/cool/weird/

13:47 tbaldridge: noncom: so two things. (go (<!)) and (go (>!)) are just slower versions of take! and put!

13:48 but that's your problem, you either need to use >!! and <!! or need a way to not continue executing until the callback passed to a take! or put! is called.

13:48 Or just use a dropping/sliding channel

13:49 otherwise, this code would eventually run out of heap space, that's what core.async is complaining about with the 1024 thing

13:50 noncom: umm... but <!! will block until it receives a message, effectively preventing the reader thread from doing other things?

13:52 hmm, messaging with core.async seems a little bit more complex than with googles event bus :)

13:52 i wished for just a similar simplicity...

13:53 raspasov: noncom: how is google's event bus different in that regard? (I have never used it)

13:54 noncom: raspasov: it is totally clear of any synching problems afaihui (as far as i have used it)

13:55 raspasov: also, it is built on totally different concepts.. more javaish ones

13:55 raspasov: noncom: well but does that mean that it is also all just callback-based?

13:55 noncom: idk how it works internally... it just does not have a similar pressureback problem..

13:56 arrdem: justin_smith: great thanks. redeploying now.

13:56 tbaldridge: well most likely the google event bus is using unbounded queues, something core.async refuses to let you do

13:56 justin_smith: arrdem: cool beans, glad I could help

13:57 noncom: well, google event bus just calls particular methods, passing them the events. the dispatching and synching mechanism somehow handles that and makes it feel, like messages just get instantly delivered where they should be

13:57 and the methods are just called with these events passed to them

13:57 justin_smith: arrdem: next is to make an example using the :heirarchy key I guess (I've never needed that before...)

13:57 noncom: here, in core.async, i have to control the receiving site on my own

13:58 raspasov: nancom: in core.async you can prevent blocking a thread if you use something like (go (let [msg (<! a-chan)] (println msg))), almost like a callback but much nicer

13:59 arrdem: ah buggery I have datafile changes that expect the development version of Grimoire love

13:59 *live

13:59 raspasov: noncom: *

14:00 tbaldridge: noncom: so you do have some options here. the reader side could be using a loop inside a single go,

14:00 arrdem: justin_smith: yeah sorry your changes aren't gonna show up in the live site until I do the next release. Which should be next week.

14:00 noncom: raspasov: well, yes, but the problem is that if the reading thread is 100 faster than the writing thread, then the reading thread will generate an excessive amount of "takes"

14:00 tbaldridge: noncom: but on the writer side, you could do something a tad ugly and use an agent that calls >!!, but yeah, that's a bit ugly

14:01 But I'll now quote Rich: "having unbounded queues is just saying 'I know there's a problem, but I don't want to deal with it right now'"

14:01 raspasov: noncom: no, it won't; in a (go-loop) it will "park" effectively blocking, but not really blocking a real java thread

14:02 justin_smith: arrdem: no biggie

14:02 noncom: yes, probably i have to somehow make all this work, just get the right design of it..

14:02 raspasov: (go (loop []

14:02 (println (<! a-chan))

14:02 (recur)))

14:03 (>!! a-chan 1)

14:03 noncom: (def a-chan (chan 1)) first

14:04 noncom: maybe you can make some comment on my scenario: i have thread A which listens to mouse and posts all the messages it generates (can be like 100 msgs/sec). the messages get posted to a bus (a core.async channel), and later, some other threads, running on slightly different speeds have to take these events and process them

14:04 raspasov: noncom: is this ClojureScript or Clojure?

14:04 noncom: clojure

14:05 raspasov: noncom: ok, so

14:05 noncom: raspasov: i start to see what you mean, i can embed the thing in a go-loop and put all the functionality in there..?

14:05 raspasov: first of all, do you can about **all** events or only latest, since it's mouse events?

14:05 do you care*

14:06 I have seen browser scenarios where you care about only latest, but not all

14:06 noncom: i think all events... if i am to use just the latest ones, i do not even have to use any messaging, an atom would suffice..

14:06 raspasov: since you can discard old if newer ones are more important - depends on the use case; let me know because that might influence the design sligthly

14:06 ehhh not really

14:07 I would use atom if I care for all

14:07 and a core.async sliding-buffer

14:07 if I care only for latest

14:07 but here's the thing

14:07 you're saying the consumer might not be fast enough

14:07 noncom: yes..

14:08 raspasov: so how could you possibly care for all events? like, you need a policy there

14:08 you can be like "producer is at a random, potentially infinite speed"

14:08 and my consumer is limited, but I still care for all

14:08 do you see what I mean ? : )

14:08 can't*

14:08 noncom: partly :)

14:09 raspasov: another question: I assume this runs on one machine?

14:09 no distributed processing, right?

14:10 noncom: yes

14:10 one machine

14:10 one jvm :)

14:11 raspasov: ok cool

14:11 so if the events are only mouse clicks... right?

14:12 noncom: well, not actually.. they are also mouse moves

14:12 and mouse clicks

14:12 they can also be touches (up to 10)

14:12 or even more than 10 touches...

14:12 raspasov: ok - what is the amount of processing that happens per each event?

14:12 is this for Android/mobile?

14:13 noncom: this should work on desktop and also android, but also on TUIO-enabled devices like multitouch tables...

14:13 (the tuio ones are desktops as for the processing unit)

14:14 so three can be many events. the events themselves do not get much processing

14:14 however, different places in code may react on them differently

14:14 basically, this is a gui..

14:15 raspasov: ok yea I get it, is there any IO associated with an event or it's all local to the device, i.e. is there any writing to disk, calling the internet etc?

14:15 or it's all just GUI changes?

14:15 eli-se: with Component is it typical to have multiple systems?

14:15 like, subsystems

14:17 noncom: raspasov: in general, no io is associated with it directly

14:17 (aside from 3d and opengl stuff as for output)

14:17 raspasov: noncom: ok let me make a quick gist

14:21 noncom: https://gist.github.com/raspasov/d006968103b6854a4565

14:24 noncom: looking at it..

14:27 raspasov: wow, well, that looks rather useful! i have to try to apply this in my situation..

14:28 raspasov: noncom: ok cool :) I hope it helps; one thing is though, the (go) loop runs on a different thread pool... I am not quite sure if Android restricts updating the UI from the main thread only? you need to look into that

14:28 noncom: raspasov: well, i have a fully opengl gui, so android should not get in the way :)

14:29 raspasov: noncom: ok good :)

14:29 noncom: thank you! you have been very helpful!

14:29 raspasov: you're welcome, any time

14:29 noncom: (inc raspasov)

14:29 lazybot: ⇒ 1

14:29 gfredericks: eli-se: no, I usually have one system at a time on a jvm; what you're thinking of as subsystems is probably just a component that depends on other components

14:29 eli-se: ok

14:31 raspasov: noncom: have you gotten Clojure to run on Android? I have never tried that

14:32 noncom: raspasov: yes, clojure runs just fine on android. there is a special initiative http://clojure-android.info/ that has a little tuned clojure.jar to work flawlessly on android

14:32 it is somewhat slower, but i managed to get a repl inside my app

14:33 also, there is a repl in google play

14:33 raspasov: nice, that's good to know :)

14:33 noncom: (but not very functional, since it is very bare :))

14:39 lemonodor: raspasov: there are a few example android apps around. i wrote this one to control a drone: https://github.com/wiseman/shrimpdroid

14:40 raspasov: lemonodor: that's neat

14:46 justin_smith: arrdem: tbaldridge: in making an example for the optional :hierarchy key to defmulti, I discovered that it throws an error if you provide a hierarchy directly, and tells you it needs a derefable type. Which makes me realize, if you specified the dispatch function as a var, you wouldn't need to worry about defmulti being defonce, because you could just reassign the var

14:47 amalloy: justin_smith: you would still need to worry

14:47 because it would save the old dispatch values

14:47 justin_smith: ahh, caching

14:47 ick

14:47 amalloy: well, not "caching" really

14:47 it's caching in the same sense that when you (def x 1), clojure saves 1 as the value for x

14:48 it has to do that in order for the def to be functional

14:48 justin_smith: OK. So you don't mean save the dispatch values as in saving the results of dispatch function for a given input?

14:49 amalloy: no

14:49 it doesn't do that

14:50 i mean the defmethods are still there, being mapped to by (f x), even though your dispatch function is now g

14:50 justin_smith: ahh, now I see what you mean

14:51 gfredericks: anybody know if there's anything wrong with a single throwable object getting thrown in multiple situations?

14:51 amalloy: gfredericks: a number of libraries do this already

14:52 i think it's not a big deal

14:52 justin_smith: also, it was interesting to use make-hierarchy and the three arg version of derive. It's the immutable version of derive, so you need to chain it, but that also means you can "fork" two hierarchies locally off the same base hierarchy.

14:53 gfredericks: amalloy: cool thanks

14:55 atyz: Random question: What log management tools do you all use?

14:56 Preferably hosted solutions

14:57 agarman: log to Kafka where I am no

14:58 logged to Cassandra at the Weather Channel

14:59 justin_smith: amalloy: we may have been miscommunicating, what I was talking about works

14:59 agarman: used LogStash & Flume

14:59 justin_smith: amalloy: https://www.refheap.com/98378

14:59 atyz: agarman: I'm more interested in hosted solutions. Currently looking at moving away from our splunk

15:00 How did you find logstash and flume?

15:00 amalloy: justin_smith: yes, but that's something to worry about. what if you had defmethods for "a" and for ["a"] already?

15:01 then the behavior of (rebindable ["a"]) just changed, as a result of you changing the dispatch function. obviously this *could* be what you want, but it's unchecked mutability

15:01 it's not something that's obviously wrong to do, but it's something you have to be very careful with

15:01 justin_smith: amalloy: yes, fair point, it trades one problem for another. But needing to change your defmethod if the defmulti dispatch changes is predictable, defmulti doing nothing with no error message is tricky and catches many of us.

15:01 *has caught

15:01 I won't make the mistake again :)

15:02 agarman: atyz: either lib was fine. flume had issues with some of the load we put through it ... sinks overflowed

15:05 atyz: fluentd is another good lib

15:05 and app

15:05 atyz: agarman: thank oyu

15:09 amalloy: i don't know which mistake you mean, justin_smith, but i'm pretty sure i will make the mistake of forgetting how redefining a defmulti works again

15:09 gfredericks: handling partial failure with component is tricky

15:09 amalloy: gfredericks: (System/exit 300)

15:09 gfredericks: like what if I want the rest of the system to keep running, and for the failed thing to keep trying to revive itself

15:12 eli-se: Hmm.

15:13 this is neat: http://ideone.com/Udb6OL

15:14 I don't like (let […] (do stuff) (let […] (do more stuff))) as it tends to get unreadable quickly.

15:15 justin_smith: eli-se: one trick is to put _ (do stuff) inside the let block

15:15 _ conventionally meaning that you won't be using the return value

15:15 eli-se: yeah right

15:16 amalloy: eli-se: this isn't going to work if you call it from another macro definition, eg (defmacro foo [x] `(im (let [y# 1]) (+ ~x y#)))

15:16 eli-se: though that'd still put the last thing out of the […].

15:16 justin_smith: eli-se: right, this is just for avoiding nested let blocks

15:17 another trick is to make some bindings into (delay ...) forms that are later dereffed, then you can still do short circuiting within one let block

15:17 but that is also often a sign that it should be more than one function

15:19 ane: what's a good way of avoiding nesting when-lets?

15:20 gfredericks: ane: some-> is sometimes (ha!) applicable

15:20 amalloy: cross to the other side of the street when you see one coming

15:20 justin_smith: ane: the two tricks I use are and or when inside the form generating the value, or using (delay ...) and then dereffing the value later only if the proper conditions are met

15:21 (let [cond (some calc) a (when cond ...) b (when (and cond a) ...) ...] ...)

15:21 but that's less than ideal

15:21 better than nested when-let though

15:21 actually b could just use (when a ...)

15:23 ane: that looks... a bit confusing

15:25 i want to bind two variables though, which is why i had them nested initially. should i "tuple" them somehow? make the ultimate cond return (x y) and then bind using that?

15:25 i mean, (list x y)

15:25 justin_smith: ane: that really doesn't work so well with when-let

15:25 ,(when-let [[x y] (list nil nil)] :OK)

15:26 clojurebot: :OK

15:26 justin_smith: probably not what you expect

15:26 ane: oh, poop

15:26 a cond-let would be great!

15:26 justin_smith: there is probably something like that in flatland/useful

15:27 or and-let

15:27 or soemthing like that

15:27 ane: hrm, actually, these two when-lets aren't dependent of each other

15:27 so i could just let [a (...) b (...)] and then when (and a b) (...)

15:28 justin_smith: you could avoid unneeded work with the form I suggested (let [a (...) b (when a ...)] (when b ...))

15:28 because you don't even need b if a is falsey

15:30 ane: oh yeah, that's amazing!

15:30 justin_smith: haha, you called it confusing the first time

15:30 ane: heh

15:30 i just couldn't parse it for all the ellipses

15:31 justin_smith: ane: the thing in flatland/useful I was thinking of was let-later https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L224

15:32 (let-later [a (...) ^:delay b (...)] (when (and a b) ...))

15:34 amalloy: justin_smith: egamble/let-else has something more focused on conditionals inside of let clauses. i don't really care for it myself, but if nested when-lets bother you you will probably like it

15:35 and i think he borrowed my :delay notation

15:35 raspasov: random: I just turned on :global-vars {*warn-on-reflection* true *unchecked-math* :warn-on-boxed} ... omg :)

15:35 only on 1.7 for :warn-on-boxed...

15:36 justin_smith: raspasov: yeah, that's an awesome feature

15:36 (inc puredanger)

15:36 lazybot: ⇒ 36

15:36 raspasov: just turn that on, run lein repl, and get scared :)

15:36 puredanger: wat!

15:36 justin_smith: ?

15:36 raspasov: puredanger: yea that's awesome

15:36 puredanger: sorry, woke me up

15:37 justin_smith: it's OK, you can sleep again, it's just that your work is appreciated

15:37 raspasov: there's so many reflections/boxed math things in so many popular libs

15:37 puredanger: which actually is totally fine, mostly doesn't matter at all

15:37 justin_smith: raspasov: and finding them all is the first step in squashing them all

15:37 puredanger: except for when it does

15:37 raspasov: yea :)

15:37 great feature, definitely!

15:38 (inc puredanger)

15:38 lazybot: ⇒ 37

15:38 puredanger: it's not perfect - won't catch return boxing and a few other cases. hard to fix that one without introducing a lot of false negatives though

15:39 http://dev.clojure.org/jira/browse/CLJ-1585

15:39 if anyone wants to make that patch suck less, that'd be cool

15:41 if I could go back in time and use :warn-on-boxed while redoing all the alioth programs, that would free up a lot of my past self's time

15:41 raspasov: puredanger: haha, one day!

15:41 justin_smith: puredanger: where the issues are "unfixable", is that as in the jvm can't unbox it, or Clojure can't with the current implementation?

15:42 pyr: hi clojure. I need to reify an interface that expects a void return, is there any way to do it without resorting to a java shim ?

15:42 puredanger: justin_smith: I don't remember now, mostly just that it caught a lot of cases where the boxing was a totally reasonable thing and gave more ignorable results than usable

15:43 pyr: you can type hint ^void

15:43 amalloy: pyr: just reify it? there's nothing special to do

15:43 you don't have to hint it at all

15:43 puredanger: amalloy: annoyingly, compiler will still prepare the return value though

15:43 and *box* it if it's a primitive oy

15:43 justin_smith: amalloy: ahh, is this a thing where javac would enforce a certain signature but the vm actually doesn't care?

15:43 amalloy: and then throw it away? that's pretty funny

15:44 puredanger: amalloy: yes, bit me in some perf stuff

15:44 pyr: amalloy: yup, that doesn't work :-)

15:44 amalloy: justin_smith: no, the compiler knows what the return type is without you telling it

15:44 justin_smith: oh, that actually makes sense

15:44 amalloy: pyr: then it's nothing to do with the return type, you're doing something else wrong

15:45 that is, you've asked "how do i do X", and the answer is "just do X"; but really X isn't working because you're doing Y instead and we need to know what Y is to fix it

15:45 justin_smith: ~xy

15:45 clojurebot: xy is http://mywiki.wooledge.org/XyProblem

15:49 puredanger: pyr: you can't type-hint ^void, I'm dumb - you can use that in definterface, but not when implementing it

15:49 amalloy: probably in gen-class too

15:49 arohner__: ERROR clojure.tools.nrepl.server - Unhandled REPL handler exception processing message {:op stacktrace, :session 7e32246a-44ba-4abf-b140-1aec3a202e6e, :print-level 50, :id 23}, running tools.nrepl 0.2.7. Anyone here interested?

15:50 puredanger: probably, never use it :)

15:53 pyr: puredanger: the interface i'm reifying comes from java and defines void as the return

15:53 puredanger: yeah, that shouldn't matter

15:53 pyr: my reification just does (reify Interface (method [this arg] ...))

15:54 the compiler tells me: Mismatched return type: onEvent, expected: void, had: java.lang.Object

15:54 puredanger: Clojure compiler? or javac?

15:55 pyr: clojure

15:56 amalloy: pyr: does this interface have multiple methods with the same name and argument count?

15:58 if it doesn't, then remove all typehints you've put in the reify method signature and this will fix itself

15:58 puredanger: pyr: can you post a larger paste of the results or something?

15:59 amalloy: if it does, then add more typehints

15:59 puredanger: an example with JDK interface Closeable:

15:59 (def c (reify java.io.Closeable (close [_] (println "hi"))))

16:02 pyr: this is the interface: https://github.com/shyiko/mysql-binlog-connector-java/find/master#L730-L733

16:02 it is a subclass

16:02 creese: For s3-wagon-private, where do I put pom.xml and settings.xml?

16:03 amalloy: pyr: you linked to a directory, not an interface

16:05 pyr: sorry, be back in 5

16:05 puredanger: creese: settings.xml is in ~/.m2

16:06 pom.xml is in your project

16:07 creese: puredanger: where in the project? root?

16:07 puredanger: yes, like project.clj

16:16 pyr: so that's the one https://github.com/shyiko/mysql-binlog-connector-java/blob/master/src/main/java/com/github/shyiko/mysql/binlog/BinaryLogClient.java#L730-L733

16:16 really straightforward

16:17 justin_smith: pyr: so you are implementing BinaryLogCLient$EventListener ?

16:17 pyr: justin_smith: yes

16:18 got my error, i was giving a hint in the reify method

16:18 in the interface implementation i should say

16:18 sorry for the noise

16:22 amalloy: well, it's not "noise" if hearing it helps other people avoid your problem

16:23 pyr: to confirm, the solution was what i said earlier, right? "remove all typehints you've put in the reify method signature and this will fix itself"

16:24 pyr: amalloy: i managed to miss that line (got held up on the phone)

16:24 amalloy: but indeed, it is the right approach

16:32 eli-se: I wish I were a good programmer.

16:33 jjmojojjmojo: eli-se: do more clojure, it'll just happen :)

16:35 mdrogalis: eli-se: No one is born being good at this stuff. :)

16:36 justin_smith: mdrogalis: speak for yourself, I was refactoring my legos at age 2 /s

16:36 eli-se: I like to think I was born whilst programming.

16:47 justin_smith: eli-se: puts "push, push" in a whole different context

16:47 eli-se: She was committed to it, though.

16:47 arrdem: puredanger: to your knowledge, has anyone done translations/internationalization of clojure's docs?

16:47 eli-se: Not to mention the guy saying that was a total git.

16:48 puredanger: arrdem: no

16:48 arrdem: okie doke.

16:49 (inc justin_smith)

16:49 lazybot: ⇒ 209

16:50 arrdem: justin_smith: you can put "Fixes clojure-grimoire/grimoire#<issue-num>" in a merge message and it'll auto-close the related issue(s).

16:50 justin_smith: arrdem: cool, I'll try to remember that

16:51 also, locally bound first class heirarchies are interesting...

16:51 *hierarchies

16:58 creese: when I add repositories, leiningen tries to fetch deps from there too. How can I prevent this?

16:58 justin_smith: you want to add repositories but not use them?

16:59 creese: I want add one to deploy jars to

16:59 amalloy: creese: you can put them in deploy-repositories

16:59 creese: ah, ok

17:14 when I deploy, leiningen complains about missing maven metadata, but it seems to work okay? What is expected?

17:15 hiredman: (why is lein, a build tool, involved in deploying at all?)

17:15 gfredericks: lein does what maven does

17:16 hiredman: oh deploying to a maven repo, of course

17:17 I was thinking deployment to servers running stuff

17:43 Risiko: Hello guys!! I need to ``use`` a configuration variable sharing it between files... I did try some trick but I did obtain only compilation error...

17:44 How do you set config variables for a cli application?

17:45 justin_smith: Risiko: the best option is probably to pass the config from your -main to the functions it calls

17:47 Frozenlock: Risiko: https://github.com/clojure/tools.cli

17:48 Risiko: Frozenlock: mmmh, 500 Internal server error

17:48 Frozenlock: What? Try to refresh...

17:49 Risiko: Ah, ok, github is down!!

17:49 justin_smith: works here

17:49 $ping github.com

17:49 lazybot: justin_smith: FAILURE!

17:49 Risiko: $ping www.github.com

17:50 lazybot: Risiko: FAILURE!

17:52 Risiko: @justin_smith Your is a functional solution but I'm actually passing it too many arguments... Other solutions like require_one in php?

17:52 creese: Once I have a jar, how do I install deps? Up to now, I've been using an uberjar.

17:53 justin_smith: creese: if you want to use it from other projects, lein install

17:53 creese: if you want to share it generally, you can look at lein deploy

17:53 (lein deploy is for putting it on eg. clojars)

17:53 creese: I'm doing "lein deploy" to private S3

17:54 justin_smith: oh, OK then

17:54 creese: but it doesn't put the deps there

17:54 justin_smith: no, it doesn't need to

17:54 if another project loads your project, its responsibility is to also load its deps

17:54 and your project has a pom.xml describing those deps

17:55 (lein generates one)

17:55 that's why you don't have to specify all the deps of the libs you use, and they don't have to package them either

17:57 hiredman: use an uberjar

17:57 creese: lein deploy doesn't build one

17:57 hiredman: lein deploy is for deploying librarys that other things can depend on

17:58 libraries generally don't bundle all their deps, they just bundle depdency information

17:58 turbofail: perhaps they're asking about some sort of transitive deploy mechanism

17:58 creese: I haven't found a plugin that can deploy uberjars

17:59 hiredman: don't deploy uberjars

17:59 (to maven repos)

17:59 creese: for deploy means "send to s3"

17:59 hiredman: no

17:59 lein deploy can write to s3, but it is treating s3 as a maven repo

18:00 use s3cmd or whatever to have your ci server upload the built uberjar to some place on s3

18:01 lein deploy is strictly deployment in the maven sense of the word, which is all about deploying libraries to respositories, not deploying applications with all their dependencies to be run

18:01 creese: I see

18:02 hiredman: you can certainly stick an uberjar (or any random file) in to a maven repository, repos are basically just http servers

18:02 justin_smith: creese: maybe you are looking for something like "lein beanstalk deploy" offered by the lein beanstalk plugin? that builds and deploys an uberwar, and restarts the app server to use that uberwar

18:02 hiredman: lein isn't built around doing that though

18:02 creese: justin_smith: no, we use bare aws. I'm using supervisor

18:03 justin_smith: creese: OK

18:03 creese: We have multiple environments and we want to build once

18:05 vas: Hi. Eventually my website is going to have javascript for interactivity and animations, and I want to load new data from Datomic on certain changes, what's the preferred way to invoke clojure methods from javascript? or is this where clojurescript comes in?

18:06 justin_smith: vas: typically my sites will use an AJAX call from the js to hit a backend service that provides a json response

18:06 hiredman: at work we have archiva set up acting as a private caching maven repo, so internal libraries for reuse get deployed there, and application code (servers and what have you) is built as some kind of artifact on our ci servers (typically a tarball) and uploaded to some well known location on s3. the app is "deployed" when chef downloads the tarball and sets it up

18:06 justin_smith: vas: for pushing from the server side instead of pulling from the client, you could look into using websockets, or you could have the client poll

18:07 vas: justin_smith: okay, that makes at lot of sense. Thanks :D -- the actions are all client-triggered, but now that you mention it, it could be really cool to have it load via websockets.

18:07 justin_smith: vas: websockets are more complex to set up though, not really worth it unless you need server side push with quick response on the client side

18:08 or heavy two way communication I guess

18:08 hiredman: you can get a similar setup just replacing archiva with using s3 as your private maven repo, but having a caching maven repo is really nice

18:09 creese: caching maven repo? what's the advatage over something simple like s3?

18:10 hiredman: it is sort of like a caching http proxy, instead of directly fetching dependencies from other maven repos, you fetch from your archive setup, and archive is setup to fetch from some other repos if it doesn't already have a dep

18:10 so archiva keeps a copy of all your depdencies

18:10 if whatever maven repo goes away, or deletes an artifact, or whatever, no worries

18:10 creese: cool

18:11 yeah, we'll need something like that eventually

18:11 hiredman: it can also speed up your builds (by very little) because you tell lein to only grab artifacts from archiva instead of searching N different repos for artifacts

18:11 vas: justin_smith: okay, it doesn't have to be incredibly real-time, so perhaps polling will be good (in which case ajax is more-or-less the same "solution"?)

18:12 sdegutis: Are there times when a variadic function could only be implemented with apply but not with reduce?

18:12 justin_smith: yeah - the idea is that you have a timeout, and after that timeout you make an xhr from the js, get json back, do something interesting with that json

18:12 sdegutis: I'm difficult time finding when I _need* apply.

18:13 justin_smith: sdegutis: get is varargs, you can apply on it, reducing on it would make little sense

18:13 sdegutis: just a random example, not the specific case where you would likely be using apply

18:13 amalloy_: you need apply when you want to call a function, but instead of having N arguments individually you have a collection of N items

18:13 sdegutis: justin_smith: ah

18:14 In every use of apply at work, we could use reduce insead.

18:14 justin_smith: sdegutis: there are many varags functions that reduce on their args (+, *, assoc), but you can't generalize that to all varargs functions

18:14 vas: (comment "just reading ambient chat here i learn so much ")

18:14 turbofail: also it's not like apply can only be used with vararg functions

18:14 sdegutis: Maybe some libs we use internally use apply and can't replace it with reduce I guess.

18:15 justin_smith: turbofail: sure, but that's where the apply/reduce distinction comes up

18:15 sdegutis: justin_smith: ah like format

18:15 justin_smith: indeed

18:15 gfredericks: any of the update functions

18:15 sdegutis: vas: so tru

18:15 gfredericks: good point

18:16 I hoped to prove to myself the uselessness of apply, but nope.

18:33 {blake}: OK, so running Rich's "ants" thing and it does turn out to be GC that makes it so slow. It's fine up till it hits 1.6GB (lol) on my system.

18:33 So I'm trying it with -XmX3GB to see what that does.

18:34 amalloy: {blake}: try running it with -Xmx50m too

18:34 {blake}: (I'm guessing it'll be fine till it gets to 3GB, though why it would EVER get to 3GB, I don't know.)

18:34 amalloy: i'd bet there's too much memory, not too little

18:34 {blake}: amalloy: There's such a thing as "too much memory"?

18:34 amalloy: sure

18:35 {blake}: do you clean up your house/apartment every week or whatever, or do you let it pile up for five years because you have room to hold all the junk?

18:36 {blake}: amalloy: OK, fair point. This is every 8 seconds but...turns out all specifying 3GB did was...hide the GC messages?

18:36 amalloy: frequent small GCs can be a lot more efficient than occasional enormous collections

18:36 turbofail: well in theory the overall throughput should be similar for both cases

18:36 {blake}: (I probably screwed up those switches.)

18:36 amalloy: turbofail: yes, but nobody notices overall throughput most of the time. they notice long pauses

18:37 hiredman: it could also be no one has run ants.clj in 3 years and bit rot

18:38 amalloy: it's sad to see good bits go bad

18:38 {blake}: hiredman: I think there must be something like that afoot.

18:38 amalloy: {blake}: seriously though try it with 50mb

18:38 {blake}: amalloy: Wait, you don't think my machine's in danger, do you?

18:39 amalloy: lazybot runs with iirc 60mb, which is more than enough

18:40 {blake}: I'm going to try that, but I want to know why I was getting the slowdown W/O the GC error messages first. 'cause if I just screwed up both switches I learned nothing, except that I'm Java-ignorant.

18:40 amalloy: {blake}: remember that it's not -Xmx3gb, but -Xmx3g (i dunno if the excess b does anything, but don't do it)

18:42 {blake}: amalloy: OK.

18:42 Now I've specified 3G and the GC errors are back, well below 3GB.

18:43 (But I haven't hit the slowdown yet.)

18:43 ntaylor: are they in fact gc errors?

18:43 (e.g. are you seeing anything like "concurrent mode failure")

18:44 {blake}: They're "Allocation Failure" messages, which I believe occur when GC is called because...you know, it failed to allocate. =P

18:44 ntaylor: oh, no

18:44 what an allocation failure is is a) badly named ;) b) says that there wasn't enough room in the young-gen to satisfy an allocation, so it forces a generational promotion

18:45 so you can reduce those by either resizing your heap so that you get more space for the young generation, or let the JVM's "ergonomic" collection do it for you

18:46 but, young GCs are expected to be frequent anyway (especially in more functional-style languages like Scala and likely Clojure too, where more short-lived objects are allocated than in Java)

18:47 {blake}: ntaylor: Interesting.

18:48 I think amalloy has it: With the 50M option it uses a lot less memory and Full GCs being done right-and-left, you don't get the every-eight-second-beat thing.

18:49 ntaylor: yeah

18:49 amalloy: {blake}: today you learned: there's such a thing as too much memory

18:49 {blake}: And it uses a crapton less memory. So far just (just...lol) 120M versus 1.6GB previously.

18:49 amalloy: {blake}: i expect you could run ants with -Xmx20m, really. perhaps less

18:50 {blake}: amalloy: I did!

18:50 amalloy: most of the overhead will be the jvm

18:50 ntaylor: which collector are you running, btw?

18:50 {blake}: It's pouring out those GC messages like berserk.

18:50 ntaylor: (if this is a standard clojure benchmark apologies)

18:50 amalloy: {blake}: i'm curious what makes you say it uses 120M. there are a lot of incorrect ways to measure that

18:50 {blake}: ntaylor: The one that I got without knowing what I was doing.

18:50 ntaylor: haha.

18:51 amalloy: 120M doesn't particularly surprise me, but you could easily be getting the wrong number anyway

18:51 {blake}: amalloy: I'm just using the process manager to watch how much java.exe is consuming. Which, yeah. Caveats apply.

18:52 But I've seen those kinds of hits before, when the OS started allocating virtual memory and pretending it was RAM.

18:53 ntaylor: {blake}: if it helps, you can also set -Xms to the same thing as -Xmx and have the JVM preallocate its heap

18:53 rather than having it grow "as needed"

18:53 whether that removes a variable for you I donno

18:53 {blake}: ntaylor: Yeah, that's what I was going for when I set it to 3GB. (But forgot the minimum part.)

18:53 ntaylor: ah, cool

18:54 {blake}: But if I'm setting the heap to 50m, and the process manager reports 120M...well, I guess there's an...accounting issue.

18:54 ntaylor: oh, well, there's more to your java process than the heap

18:54 a lot of what the process manager tells you will be stuff that isn't your heap (like each thread's stacks, all the classes you've loaded, etc.

18:55 70mb overhead for all that stuff doesn't seem out of place to me

18:55 {blake}: Sure...although at 1.6GB...heh

18:55 ntaylor: :)

18:56 {blake}: ntaylor: But, yeah, that looks reasonable. I set it to 20MB and now the heap is down to 80+MB. So...

18:57 ntaylor: cool

18:57 {blake}: *shakes head* Too much memory. Next, it'll be "your computer is too fast."

18:57 ntaylor: yeah, it's just the cost of getting the benefits of the JVM :)

18:57 {blake}: (Though come to think of it, I've seen that.)

18:58 ntaylor: just hit the turbo button!!

18:58 (or make your heap larger :) )

18:58 {blake}: ntaylor: Hey, I'm old enough to remember having to turn the turbo button off...

18:59 vas: turbo button. let me "lock" this floppy with that physical switch

18:59 amalloy: {blake}: my first experience with "your computer is too fast" was with an old qbasic program, maybe 15 years ago

19:00 it calibrated its own speed (ie, amount of time it spent sleep()ing between frames) by counting from 0 to 100000 and seeing how many seconds that took, or something like that

19:00 {blake}: amalloy: A game? Something that checked the speed and found it couldn't slow down enough for your machine?

19:00 amalloy: on a faster machine, it did that in 0 seconds and divided by 0

19:00 {blake}: amalloy: Ha!

19:00 ntaylor: ouch.

19:00 turbofail: lol

19:01 amalloy: at least it was qbasic, though. easy enough to edit the source to count to 10000000 and adjust correspondingly

19:01 {blake}: amalloy: Turbo Pascal's CRT unit did a timing check. Somewhere around the time '486s came out, all the TP programs started breaking because the 32-bit counter went kerflooie.

19:01 ntaylor: an annoying variation on that one that I've found is when certain games don't know about your processor's CPU throttling capabilities so it checks the speed but doesn't compensate when speedstep kicks in

19:02 {blake}: ntaylor: I think FPS is the only way to go.

19:02 justin_smith: on the other hand, nethack's basic playability hasn't changed since 1985 and it's still awesome

19:03 {blake}: justin_smith: Right? The most exciting game news this year so far is "New Nethack coming!"

19:03 (Nethack hacking being the only reason I go near C these days.)

19:05 ntaylor: ncurses all the way, I guess!

19:05 amalloy: ncurses is the best physics engine around

19:06 {blake}: Is there a good Clojure ncurses interface? I went off of Losh's thing, which uses Lanterna.

19:08 amalloy: i think lanterna is it

19:08 ntaylor: yeah, I donno what ncurses' windows support is like but you'd probably need a layer for calling out to conio on that side of things

19:08 (is conio still a thing? Haven't touched windows development in years)

19:09 {blake}: ntaylor: I don't know but as of Windows 7 (and maybe Vista) you can't full screen a console.

19:09 ntaylor: oh wow

19:09 {blake}: I'm beginning to suspect large heap sizes in the Java switches don't actually do much.

19:10 * justin_smith hits Ctrl-Alt-F1 just to gloat.

19:10 sdegutis: Holding Fn key for F1?

19:10 justin_smith: Ctrl-Alt-F7 OK I'm back

19:10 {blake}: justin_smith: lol. I like to have 5 full-screen Nethack games running at once...

19:11 justin_smith: sdothum: on linux, control + alt + f<x> switches to virtual console <x>

19:11 err

19:12 anyway, that was for sdegutis, who probably has some amusing new name now but I suppress nick change spam

19:12 ntaylor: C-a n C-a n C-a n ... :)

19:13 justin_smith: ntaylor: sure, within one console - someone brought up windows console not being able to do full screen, and I was reveling in the fact that I could go into fully console mode

19:13 {blake}: I guess if you run emacs you can go into a full console Nethack without ever leaving your editor.

19:14 justin_smith: {blake}: emacs-el is funny, I have a partially-implemented clojure client for it

19:14 {blake}: it sends all game events as sexprs

19:15 ntaylor: sure :)

19:15 {blake}: emacs-el?

19:16 justin_smith: err, sorry, nethack-el

19:17 elisp frontend for nethack, I was re-implementing the client side

19:17 the server side presents game events to the client as sexprs

19:17 {blake}: justin_smith: Ha...how did I know, without even looking...that existed?

19:17 justin_smith: kind of how you would use json sent to the client from a webserver

19:18 amalloy: i liked the idea of emacs-el

19:18 ntaylor: hahahahaha

19:19 {blake}: What does it get you? I mean, it sounds AMAZING. But so does LSD.

19:19 gfredericks: is this similar to lein-lein?

19:19 justin_smith: {blake}: nethack-el? it means you can script the nethack game using elisp

19:19 emacs-el of course would be the self-hosting engine for emacs

19:20 {blake}: justin_smith: So...play scripts, presumably?

19:20 justin_smith: {blake}: macros for combined commands

19:20 {blake}: maybe an auto-play bot

19:21 {blake}: justin_smith: Right. Yeah, that's cool. I could write a program that played Nethack better than I did.

19:21 justin_smith: {blake}: things like pausing the game and warning you if certain dangerous events happen while the game is spammy and the message may have been missed

19:21 {blake}: justin_smith: Yeah, I hacked boots-of-safety in there once because I was tired of stepping in lava and off bridges.

19:21 justin_smith: eg. that time I died because I got too hungry. Really, that only happened once, it isn't a recurring issue or anything.

19:22 oh yeah, a "do you really want to do that" prompt for stepping into water/lava would be another good one

19:22 {blake}: sure, just like I never choked on the Astral plane eating a giant while satiated and with a 20 strength anyway.

19:22 justin_smith: hahaha

19:23 {blake}: justin_smith: Yeah, though in the Nethack mode, just building it in is too easy. It has to cost you a slot.

19:23 amalloy: justin_smith: i hate to interrupt the nethack reminiscence, but all this stuff is built into DCSS, with a lua scripting frontend if you need anything fancier

19:24 {blake}: amalloy: Yeah, I saw that. DCSS is pretty slick.

20:05 l1x: hey guys

20:07 https://gist.github.com/l1x/110ae53629b8579143ac

20:07 could somebody explain this please?

20:07 i can see a method in an instance

20:07 but i cant invoke it for some weird reason

20:07 justin_smith: l1x: what args does it take?

20:07 l1x: string

20:07 justin_smith: l1x: maybe it's vararg?

20:08 l1x: https://apache.googlesource.com/kafka/+/

20:08 https://apache.googlesource.com/kafka/+/

20:08 justin_smith: l1x: yup, it's vararg

20:08 l1x: i see

20:08 how can invoke that?

20:08 justin_smith: (. a subscript (into-array ["test-shovel-0"]))

20:09 s/subscript/subscribe, of course

20:09 l1x: i see

20:09 damn, i am stupid

20:09 thanks justin_smith !

20:09 https://www.irccloud.com/pastebin/EBjmY7zD

20:09 thanks!

20:10 justin_smith: np, glad it worked

20:10 gfredericks: justin_smith: do you think that deserves a helper in clojure.core?

20:10 justin_smith: gfredericks: that would be super nice

20:10 gfredericks: if nothing else it would at least call out the fact that those things need special handling

20:10 justin_smith: maybe (... a subscribe "test-shovel-0")

20:10 ... is a good way of saying vararg

20:10 gfredericks: not a bad idea

20:11 justin_smith: maybe it needs an indicator of where the var part starts though

20:11 gfredericks: (...subscribe a "test-shovel-0")

20:11 justin_smith: (...subscribe a ... "test-shovel-0")

20:11 gfredericks: yeah I'm not sure if they'red be ambiguity otherwise

20:11 there'd

20:11 theired

20:11 thair'd

20:11 justin_smith: I'm sure there are methods that would be ambiguous, somewhere

20:12 but yeah, that would be a nice reader macro to have

20:12 some variation on that

20:12 maybe (.subscribe a ... "test-shovel-0")

20:12 where the ... indicates where varargs start

20:12 gfredericks: but but

20:12 ... might be bound

20:12 justin_smith: ahh, yeah

20:13 we could use the … unicode then

20:13 gfredericks: ,(let [... (fn [& args] (reduce + (map (constantly 3) args)))] (... ... ... ...))

20:13 clojurebot: #error{:cause "Illegal field name \"...\" in class sandbox$eval25", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassFormatError: Illegal field name \"...\" in class sandbox$eval25, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6732]} {:type java.lang.ClassFormatError, :message "Illegal field name \"...\" in class sandbox$eval2...

20:13 gfredericks: justin_smith: that could also be bound

20:13 l1x: damn

20:13 gfredericks: oh heeeey

20:13 l1x: this library drives me crazy

20:13 gfredericks: maybe you can't

20:14 l1x: https://www.irccloud.com/pastebin/GUQD0gJy

20:14 justin_smith: gfredericks: starting with . is special in the calling position

20:14 l1x: it supposed to wait 100ms

20:14 justin_smith: ,(let [... 42] (list ...))

20:14 clojurebot: #error{:cause "Illegal field name \"...\" in class sandbox$eval51", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassFormatError: Illegal field name \"...\" in class sandbox$eval51, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6732]} {:type java.lang.ClassFormatError, :message "Illegal field name \"...\" in class sandbox$eval5...

20:14 justin_smith: oh, wait

20:14 never mind!

20:14 we can totally use ...

20:14 lvh: Is there something special about requiring a record?

20:15 gfredericks: yes

20:15 but don't do it

20:15 justin_smith: lvh: require the namespace that defines the record, then import the record type

20:15 gfredericks: lvh: use the constructor fns if you can

20:15 lvh: oh, because they're literally Java types.

20:15 gfredericks: I can't. I'm type-annotating.

20:15 justin_smith: That makes sense. Thanks :)

20:15 gfredericks: aw man

20:15 justin_smith: so yeah, you need the require / import 1-2 punch

20:16 lvh: gfredericks: Is the next point "don't type-annotate"?

20:16 gfredericks: lvh: well I wasn't sure exactly what you meant by that

20:16 so I was just going to let it go

20:16 but now that I've invested this much time typing about it the sunk-cost falacy says I have to press on

20:16 lvh: (ann some-name SomeRecord) <- that kind, where ann coes from clojure.core.typed :)

20:16 that takes java types, allegedly

20:17 gfredericks: okay so then

20:17 um

20:17 lvh: (I understand that that is not a very useful kind of type checking)

20:17 gfredericks: are you using protocols?

20:17 why are you using records?

20:17 lvh: gfredericks: Not my code. test.check has defrecord Generator in it

20:17 justin_smith: yeah, better to annotate with a protocol or even interface, then implement said protocol or interface with the record, for sure

20:17 gfredericks: oh snap it's core.typed + test.check

20:17 that's hardcore

20:18 lvh: gfredericks: no kidding

20:18 justin_smith: throw some core.match and core.async in there too, see how much the compiler can take

20:18 gfredericks: man why did we put a defrecord in there

20:19 lvh: justin_smith: it has core.logic and core.async, too!

20:19 well, not core.logic

20:19 but just wait until I find a reason

20:19 gfredericks: I think I had thought about doing a protocol with it

20:19 lvh: I guess it might not be too late to do it that way since generator is hella internal?

20:19 gfredericks: the record is sort of an impl detail but it wasn't designed with core.typed in mind

20:20 lvh: right

20:20 gfredericks: man core.typed I'll tell you what.

20:20 lvh: hey man, I'm not complaining; I'll just move some logic out to some fns

20:20 I just had a bug and thought "hey a type system could totally have told me about that one"

20:21 I mean, for it to be useful I don't want to say that something is of type Generator

20:21 gfredericks: but hey wait

20:21 lvh: I want to say it's a Generator of maps that look like *this*

20:21 gfredericks: are you type annotating your test code?

20:21 lvh: gfredericks: right now I'm not, no

20:22 gfredericks: then how did this even come up?

20:22 you're using test.check in your not-tests?

20:22 lvh: gfredericks: Yeah. It's program that tests an external system. Think ab, or something.

20:22 gfredericks: I wonder if you could make your own protocol and base your types off of that

20:22 lvh: gfredericks: I use test.check to generate some scenarios

20:23 gfredericks: that would even give you the paramaterization you need I think

20:23 I forget how to do that with core.typed

20:23 lvh: gfredericks: So I guess the next thing I do is learn what a rose tree is? I guess maybe I don't even really care about a rose tree because IIRC that's only about efficient shrinking, right?

20:23 gfredericks: you might even be able to do it w/o a protocol

20:24 lvh: it's just a lazy tree, and yeah only related to shrinking

20:24 lvh: gfredericks: well, if my signature is turns-a-random-number-into-a-thing, then...

20:24 gfredericks: I think rose might refer to it being N-ary

20:24 I was never sure where that terminology came from

20:24 lvh: I was doubting if I should capitalize it; I figured maybe the author

20:25 gfredericks: wikipedia, the SSOT about the universe, agrees with you

20:25 gfredericks: phew

20:27 lvh: so you're using just the generators then?

20:27 lvh: oh hey a maybe alternative to core.typed is to use prismatic/schema, and then maybe could even make use of schema->gen stuff

20:30 cjlarose: Hey does anyone know of any good references about hash array-mapped tries, such as those used in Clojure? I've got Phil Bagwell's papers up and the clojure implementation, but I thought maybe there's something more easily consumable around.

20:31 justin_smith: cjlarose: hyPiRion has a good series of blog posts on the persistent vector implementation

20:31 I don't know about anything good for hash array mapped tries though

20:31 cjlarose: Ooo that might be helpful.

20:42 cnb_: I need to deploy a webservice in immutant but there is no documentation on how to do it

20:43 tcrawley: cnb_: what do you mean by "webservice"?

20:44 cnb_: a javax.jws using anotations

20:45 tcrawley: what version of immutant are you using?

20:46 cnb_: 2.0.0.beta2, and I'm trying to deploy to wildfly

20:46 tcrawley: are you wanting to include the webservice as part of the immutant war file you are building? or do you want to deploy the webservice in a separate war?

20:47 cnb_: I'm using lein immutant war -o /srv/wildfly

20:49 tcrawley: where is the webservice? is it in your app's source tree? does it get compiled and included if you do `lein uberjar`?

20:55 cnb_: this is what I have http://pastebin.com/KJ901Ci3. I'm deploying using lein immutant war -o /wildfly

20:57 tcrawley: cnb_: hmm, I would think that would get scanned and properly loaded. Would you be willing to create a small app to reproduce the problem and file an issue at https://issues.jboss.org/browse/IMMUTANT?

20:58 I need to run now, but can take a closer look tomorrow

20:58 cnb_: thanks tcrawley

20:59 tcrawley: my pleasure!

21:01 gfredericks: (inc tcrawley)

21:01 lazybot: ⇒ 1

21:02 TEttinger: (inc \)

21:02 lazybot: ⇒ 1

21:04 justin_smith: ,(eval `(def ~(symbol "") 42)); hey gfredericks did you see this fun trick?

21:04 clojurebot: #'sandbox/

21:04 justin_smith: ,@(resolve (symbol "sandbox/"))

21:04 clojurebot: 42

21:04 gfredericks: I did not

21:04 ,sandbox/

21:04 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: sandbox/>

21:04 gfredericks: not so fun if you can't use it :/

21:05 TEttinger: ,

21:05 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

21:05 justin_smith: gfredericks: it exists, it's just not readable

21:05 gfredericks: sure

21:05 TEttinger: ,(eval `(def ~(symbol "[") 42))

21:05 clojurebot: #'sandbox/[

21:05 gfredericks: ,(create-ns (symbol "what about ythis?``"))

21:05 TEttinger: ,[

21:05 clojurebot: #object[clojure.lang.Namespace "what about ythis?``"]

21:05 #<RuntimeException java.lang.RuntimeException: EOF while reading>

21:05 gfredericks: oh hey

21:05 TEttinger: ,[[]]

21:05 clojurebot: [[]]

21:06 gfredericks: clojurebot's printing code there helps you distinguish between thrown/returned exceptions

21:06 justin_smith: oh, that is nice actually

21:06 TEttinger: ,(eval `(def ~(symbol "[]") 42))

21:06 clojurebot: #'sandbox/[]

21:06 TEttinger: ,[]

21:06 clojurebot: []

21:06 gfredericks: ,(ex-info "" {})

21:06 clojurebot: #error{:cause "", :via [{:type clojure.lang.ExceptionInfo, :message "", :at [clojure.core$ex_info invoke "core.clj" 4579]}], :trace [[clojure.core$ex_info invoke "core.clj" 4579] [sandbox$eval259 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] [clojure.lang.Compiler eval "Compiler.java" 6747] [clojure.core$eval invoke "core.clj" 3078] ...]}

21:06 Bronsa: ,(throw (ex-info "" {}))

21:06 clojurebot: #error{:cause "", :via [{:type clojure.lang.ExceptionInfo, :message "", :at [clojure.core$ex_info invoke "core.clj" 4579]}], :trace [[clojure.core$ex_info invoke "core.clj" 4579] [sandbox$eval283 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] [clojure.lang.Compiler eval "Compiler.java" 6747] [clojure.core$eval invoke "core.clj" 3078] ...]}

21:06 Bronsa: uh?

21:07 gfredericks: welp

21:07 nobody knows

21:07 Bronsa: ,(RuntimeException. "foo")

21:07 clojurebot: #error{:cause "foo", :via [{:type java.lang.RuntimeException, :message "foo", :at [sandbox$eval307 invoke "NO_SOURCE_FILE" -1]}], :trace [[sandbox$eval307 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] [clojure.lang.Compiler eval "Compiler.java" 6747] [clojure.core$eval invoke "core.clj" 3078] [clojure.core$eval285$fn__286$fn__296 invoke "NO_SOURCE_FILE" 0] ...]}

21:07 TEttinger: ,(eval `(def ~(symbol "1") 42))

21:07 clojurebot: #'sandbox/1

21:07 Bronsa: ,(throw (RuntimeException. "foo"))

21:07 TEttinger: ,1

21:07 clojurebot: #error{:cause "foo", :via [{:type java.lang.RuntimeException, :message "foo", :at [sandbox$eval355 invoke "NO_SOURCE_FILE" -1]}], :trace [[sandbox$eval355 invoke "NO_SOURCE_FILE" -1] [clojure.lang.Compiler eval "Compiler.java" 6784] [clojure.lang.Compiler eval "Compiler.java" 6747] [clojure.core$eval invoke "core.clj" 3078] [clojure.core$eval333$fn__334$fn__344 invoke "NO_SOURCE_FILE" 0] ...]}

21:07 1

21:07 Bronsa: wtf.

21:07 ,]

21:07 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

21:07 gfredericks: it's the read-time errors

21:08 ,(let)

21:08 clojurebot: #error{:cause "Wrong number of args (0) passed to: core/let", :via [{:type clojure.lang.ArityException, :message "Wrong number of args (0) passed to: core/let", :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6628]}], :trace [[clojure.lang.Compiler macroexpand1 "Compiler.java" 6628] [clojure.lang.Compiler macroexpand "Compiler.java" 6694] [clojure.lang.Compiler eval "Compiler.java" 6768] [...

21:08 gfredericks: yep

21:08 Bronsa: gfredericks: yeah

21:08 i can reproduce that in my repl

21:08 gfredericks: oh really?

21:08 Bronsa: yeah

21:08 gfredericks: wait huh

21:08 Bronsa: well

21:08 gfredericks: like with master code?

21:08 that can't be right

21:08 Bronsa: no, just kidding

21:08 gfredericks: phew

21:08 TEttinger: ,(eval `(def ~(symbol "forv") 42))

21:08 clojurebot: #'sandbox/forv

21:08 TEttinger: ,forv

21:08 clojurebot: 42

21:09 TEttinger: ,(eval `(def ~(symbol "#_") 42))

21:09 clojurebot: #'sandbox/#_

21:09 TEttinger: ,(+ 1 #_2 3)

21:09 clojurebot: 4

21:10 TEttinger: ,(+ 1 #_ 2 3)

21:10 clojurebot: 4

21:10 TEttinger: awwww

21:10 Bronsa: TEttinger there's no way that def'ing stuff changes the reader behaviour

21:10 TEttinger: yeah, I realize that now

21:50 weavejester: Does anyone happen to know of any debug middleware for Leiningen?

21:50 gfredericks: weavejester: depends on what you're trying to debug exactly probably; `lein pprint` helps for some things

21:50 justin_smith: weavejester: other than :eval-in pprint nope

21:51 weavejester: Hm, I haven't tried :eval-in pprint.

21:52 One of the problems with Leiningen's config is that it's sometimes extremely difficult to tell if anything's changing it.

21:53 As far as I can tell, whenever I add cljsbuild to my prep-tasks, something else runs it as well, before any of the other prep-tasks.

21:53 gfredericks: oh it has a debug option

21:53 I forget how to turn it on

21:53 may or may not help with that

21:54 weavejester: Hm, it looks like maybe a :debug true option in the project.clj file

21:54 But it doesn't appear to do anything.

21:56 dbell: stylistic question:

21:57 does anyone else define private fns with letfn and then define the public fn in the let block?

21:57 gfredericks: weavejester: not sure how familiar you are with the lein codebase, but a last-ditch option could be getting a user.clj on the classpath and hooking into things that way

21:58 dbell: traditionally hiredman will scoff at people for doing that

21:58 dbell: well i'm all ears for scoffing

21:59 weavejester: gfredericks: How would I get Leiningen to pull in a user.clj in Lein's classpath?

21:59 gfredericks: dbell: I believe the reasoning is that vars are a many splendored thing, vars lift us up where we belong, all we need is vars

21:59 dbell: ha

21:59 puredanger: they're like the force. they surround us and bind us together.

21:59 weavejester: dbell: It seems logical to use private functions to define private functions.

21:59 There are also benefits around namespace reloading

22:00 And there's less indentation

22:00 gfredericks: weavejester: oh also try the DEBUG env variable just in case that's different

22:00 weavejester: do you know if the java command accepts multiple -cp flags? if so you could add to the classpath with JVM_OPTS

22:01 huh LEIN_JVM_OPTS is a separate arg I wonder what the diff is

22:01 weavejester: gfredericks: Oh, the DEBUG env var pulls up some interesting results...

22:01 gfredericks: phew

22:01 weavejester: these vars are listed at the bottom of the sample.project.clj fyi

22:01 dbell: the thing i've liked is that it embeds the association in the code; with defn- you have to put it in comments or docs

22:02 but if there's performance penalties...WELL then

22:02 gfredericks: dbell: I think if anything there should be antipenalties

22:02 but probably not noticeably

22:03 dbell: is fn creation ever expensive?

22:03 gfredericks: uhm

22:03 dbell: i got on this tack because it felt dirty defining helper fns in the fns that use them

22:04 gfredericks: that's not too dirty

22:04 dbell: e.g. (defn do-complex-process [args] (let [helper-fn #(asdfasdlfjafs)] (use-helper-fn)))

22:04 gfredericks: it's certainly not expensive compared to having more defns

22:05 you have to be at a pretty low level before you worry about the cost of fns

22:05 amalloy: dbell: creating a function is one object allocation

22:06 if the function doesn't close over any locals, it's just a call to new MyFn(); if it does close over a local named x, it's a call to new MyFn(x)

22:06 weavejester: Hm, it looks like cljsbuild invokes prep-tasks, so it can't be in prep-tasks itself.

22:08 dbell: thanks all

22:08 weavejester: Oh, nope, it was this bug: https://github.com/lynaghk/cljx/issues/60

22:10 gfredericks: Thanks for the DEBUG tip

22:10 (inc gfredericks)

22:10 lazybot: ⇒ 122

22:10 gfredericks: weavejester: no probs

22:25 Seylerius: Anyone got a sec to talk about complex data structures in clojure? I'm thinking that a lisp may be more appropriate for the project I'm planning, but I don't know enough about clojure and other lisps to know what sort of data structure would be appropriate. I do know how I'd do it in an object-oriented way, but I'd like to know how it can be better expressed in a functional design.

22:28 gfredericks: ~anyone

22:28 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

22:29 Seylerius: Basically, it's a complex knowledge map, drawing heavily from graph theory, and where the relationships between the nodes are themselves defined by nodes. Premises would be groups of connected nodes, and have confidence values. One of the core features of the final system will be a prototyping ability, wherein a premise's confidence value can be linked to one or more prototypes. A prototype would define properties that a matching premise would have

22:29 , and if a matching premise were found, it would influence the confidence value of the original premise in a specified way.

22:29 clojurebot: #error{:cause "Can't take value of a macro: #'clojure.core/and", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "Can't take value of a macro: #'clojure.core/and", :at [clo...

22:30 Seylerius: Whoops. Did the place my client broke the line break clojurebot?

22:31 justin_smith: Seylerius: clojurebot is triggered by , at the beginning of the line

22:32 Seylerius: justin_smith: I figured as much. Hopefully the accidental non-command didn't crash it. Meanwhile, got any theories on such a thing, or a good paper to read on graph-theory-like data structures in functional programming and/or clojure?

22:32 justin_smith: Seylerius: are the relationships in the graph nodes because the relationships themselves can be connected to other nodes in the graph?

22:32 Seylerius: clojure doesn't

22:32 "crash" all that often

22:33 Seylerius: justin_smith: Good to hear. As far as the relationships, yes they are. Basically, I'm defining a comprehensive knowledge mapping, including the principles of the knowledge mapping, inside the knowledge mapping.

22:33 justin_smith: Seylerius: the standard representation for a relatively sparse graph would be an adjacency list

22:33 Seylerius: If this sounds like circular logic, that's because reflective coherency of a logic system looks a _lot_ like circular logic.

22:34 justin_smith: Seylerius: I studied cybernetics, so I think I have a gist of what you are getting at

22:34 Seylerius: Ah, good.

22:34 You're probably a good person to talk with, then.

22:36 Would you agree with my guess that Lisps and FP in general, and Clojure in particular, are a good idea for this type of task?

22:36 justin_smith: there are a few dedicated graph packages for clojure. But you can do a lot just starting with an adjacency list

22:36 Seylerius: Good.

22:36 justin_smith: yeah, clojure is pretty powerful for graph stuff, though for certain algorithms you may want to use something that is more mutation friendly

22:36 Seylerius: I've got a lot of graph theory to read up on.

22:37 justin_smith: it's a big (and fascinating) field

22:37 Seylerius: I may want to resist mutation, actually, since tracking variations of premises and their respective likelihoods separately is a _very_good_idea_.

22:38 Rather than changing premises, track all the different variations, their likelihoods, and the competition between them, y'know?

22:38 justin_smith: Seylerius: it mostly ends up being a pragmatic concern, but that really depends on the complexity of what you are doing and the size of the data set etc.

22:38 though there are ways to use mutable data in clojure, that's not what the language makes easy

22:38 TEttinger: Seylerius: a friend implemented dijkstra's algorithm for graph pathfinding in a pretty concise way in clojure, I've used it a lot

22:39 the version I use is array-based since my data is an array and it makes sense

22:39 xapak: ~.

22:39 clojurebot: No entiendo

22:40 Seylerius: The data set is going to end up being huge. And the processing likely very complex. But I really think the lack of mutation won't be a problem, since I'd actually prefer to consider a modification to a premise to be a new premise, rather than mutate (and thus possibly lose) the old one.

22:40 TEttinger: That's shiny. Got a link?

22:40 TEttinger: http://ideone.com/pwiTf2

22:40 justin_smith: Seylerius: this isn't just about the domain data, it's also about the intermediate data as you process things

22:40 TEttinger: that's a version with no dependencies that can run in ideone

22:41 the version I used in a game had a dependency on hiphip, an array handling library from Prismatic (who make some really good libraries for clojure)

22:43 Seylerius: justin_smith: Mind sharing a few examples?

22:43 TEttinger: thanks

22:43 TEttinger: intermediate data is a really good use case for transient collections in clojure

22:44 Seylerius: I kinda figured it would be.

22:44 TEttinger: which are mutable within a single fn, and must be made back into immutable persistent collections outside of it

22:45 Seylerius: Also, clojure will have the advantage of playing very nicely with the java-based I2P, which I intend to use as transport network underneath the DHT this thing will live in.

22:46 And yet clojure is thankfully still not java.

22:46 nsjph: until you get an exception ;P

22:46 TEttinger: heh

22:46 Seylerius: There is that.

22:46 vas: java is exceptional :D

22:46 TEttinger: nsjph, on the plus side, it takes much less code to actually cause that exception!

22:46 nsjph: yes

22:47 no more factories

22:47 TEttinger: public static void...

22:47 nsjph: ListFactory MapFactory VecFactory

22:48 TEttinger: C# has stuff like protected static internal IEnumerable<IKeyValuePair<K,V>> GetKeyValuePairs<K,V>(this IDictionary<K,V> the_horror)

22:50 which actually would let you write quite a bit less code... new Dictionary<string, int>{{"foo", 1}}.GetKeyValuePairs();

23:02 ,(let [na Double/NaN nana (* 0.0 Double/NaN) nanana (Double. Double/NaN) watman (Double. (* 0.0 Double/NaN))] (map #(= % %) [na nana nanana watman]))

23:02 clojurebot: (true true true true)

23:03 TEttinger: ,(let [na Double/NaN nana (* 0.0 Double/NaN) nanana (Double. Double/NaN) watman (Double. (* 0.0 Double/NaN))] [(= na na) (= nana nana) (= nanana nanana) (= watman watman)])

23:03 clojurebot: [false false true true]

23:05 TEttinger: &(let [na Double/NaN nana (* 0.0 Double/NaN) nanana (Double. Double/NaN) watman (Double. (* 0.0 Double/NaN))] (for [ogod [na nana nanana watman] wat [na nana nanana watman]] (= ogod wat)))

23:05 lazybot: ⇒ (false false false false false false false false false false true false false false false true)

23:17 namra: gotta love daniel higginbotham and his style of writing :D

23:37 justin_smith: namra: that's nonrecursive right?

23:38 namra: justin_smith: sry but i don't understand

23:38 what you mean

23:38 justin_smith: namra: I mean he hangs out here and has the nick nonrecursive

23:38 unless I am mistaken

23:38 namra: ah ok

23:39 i don't know if that's the case. haven't been here that long as you and are not so active as you. so you might be right ^^

23:39 justin_smith: namra: yeah, I checked twitter, that's his handle there, so that's the same guy here too

23:40 he's the one behind clojure for the brave and true

23:40 namra: :)

23:40 yea i know, read the blog series

23:40 and just saw the book version on no starch press

Logging service provided by n01se.net