#clojure log - May 08 2015

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

1:40 edbond: question about core.memo: is it possible to combine several strategies? For example ttl + lru

1:45 dysfun: you mean core.cache?

1:45 core.memoize uses core.cache under the hood

1:45 edbond: yes, I use core.memoize. It is higher level lib over cache?

1:46 dysfun: you can provide a custom core.cache to core.memoize

1:47 edbond: ok. Another question: is it possible to run cached function in background and return last known result value?

1:47 I think this may result in many updates running at the same time. So need to coordinate updates somehow.

1:48 dysfun: i think you're outgrowing core.memoize and probably want direct cache control

1:49 but c.m has functions for manipulating the cache too, have a play

1:50 as for your coordination, well, sounds like the perfect job for an atom

1:51 edbond: yes, I basically need an atom with expiration for keys and update in background. Keep only one updater per key.

1:52 dysfun: that sounds like an atom with a core.cache

1:52 Niac: http://paste.ubuntu.com/11020908/

1:53 dysfun: Niac: is that fibonacci?

1:53 edbond: Niac, recur should be in same order as loop

1:53 Niac, take 2 will take first two, not last two

1:54 dysfun: incidentally, also a fantastic example of a good place to use core.cache :)

1:55 edbond: c.c should be avail to any function :)

1:55 (defn ^{:cache :ttl} ...)

1:55 Niac: So,can anybody show me the right code?

1:56 dysfun: edbond: disagree. tht would encourage a lot of laziness. if you really want it, you can write a macro

1:56 edbond: Niac, some examples here - http://rosettacode.org/wiki/Fibonacci_sequence#Clojure

1:59 dysfun: i reckon there's a fairly short version involving 'reduced' waiting to be written

1:59 reductions, even

2:01 amalloy: dysfun: i think the version with reductions is just the iterate solution with an ignored argument thrown in

2:02 dysfun: quite possibly. i've not been awake long enough to actually write code yet

2:03 and frankly i'm not sure much code is going to be written in the uk today, given we're all mourning our election results

4:34 dfletcher: ,((fn [n] (letfn [(f [n a] (if (= n 2) a #(f (dec n) (conj a (+' (last a) (nth a (- (count a) 2)))))))] (trampoline f n [0 1]))) 10)

4:34 clojurebot: [0 1 1 2 3 ...]

4:34 dfletcher: :)

4:34 couple fun timewasters from a reddit post https://blog.svpino.com/2015/05/07/five-programming-problems-every-software-engineer-should-be-able-to-solve-in-less-than-1-hour

4:35 clearly written for procedural people hehe sum numbers using for and while heh.

4:36 (apply + [1, 22, 37, 55]) ; heh

4:43 Empperi_: dfletcher: damn I fail in those tests. "Write three functions that compute the sum of the numbers in a given list using a for-loop"

4:44 I don't have a for loop in Clojure :(

4:45 edbond: the tasks from pre-FP time

4:45 Empperi: "Write a function that combines two lists by alternatingly taking elements" - interleave and done

4:46 edbond: Empperi, pretend you don't have interleave

4:46 dfletcher: huh

4:46 TEttinger: ,(mapcat vec [1 2 3] [10 20 30])

4:46 clojurebot: #error{:cause "Wrong number of args (2) passed to: core/vec", :via [{:type clojure.lang.ArityException, :message "Wrong number of args (2) passed to: core/vec", :at [clojure.lang.AFn throwArity "AFn.java" 429]}], :trace [[clojure.lang.AFn throwArity "AFn.java" 429] [clojure.lang.AFn invoke "AFn.java" 36] [clojure.core$map$fn__4536 invoke "core.clj" 2627] [clojure.lang.LazySeq sval "LazySeq.java" 4...

4:46 dfletcher: ,(interleave [:a :b :c] [1 2 3])

4:46 clojurebot: (:a 1 :b 2 :c ...)

4:46 TEttinger: ,(mapcat vector [1 2 3] [10 20 30])

4:46 clojurebot: (1 10 2 20 3 ...)

4:46 dfletcher: ,(flatten (mapv list [:a, :b, :c] [1, 2, 3]))

4:46 clojurebot: (:a 1 :b 2 :c ...)

4:47 dfletcher: ^^ that was my solution

4:47 TEttinger: ~flatten

4:47 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

4:47 TEttinger: mainly because yours doesn't work if it's a nested list

4:47 dfletcher: heh yeah couldn't figure out how to get mapv to stick 2 items into the list heh

4:47 TEttinger: mapcat

4:47 dfletcher: aha

4:48 TEttinger: or concat after creating a list of pairs

4:50 dfletcher: ,(doc mapcat)

4:50 clojurebot: "([f] [f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection. Returns a transducer when no collections are provided"

4:58 egasimus: what's an up-to-date, per-project way for me to have `clojure.tools.namespace.repl.refresh`, `clojure.pprint.pprint`, etc utilities imported when I run `lein repl`?

5:00 is perhaps `:injections` what I'm looking for?

5:13 * jriga

5:28 * wasamasa

5:45 egasimus: tried :injections as well as https://github.com/zcaudate/vinyasa

5:45 but running (refresh) clobbers anything I've required

7:09 jonh: good mornin #clojure~

7:16 zot: is there by chance a way to convince cider to jump into java source?

7:29 * wWw-BukoLay-Com hi

7:32 wasamasa: urgh

7:32 * wasamasa got this spambot banned from #archlinux already

7:34 wasamasa: I've told #freenode now, let's see what happens

8:21 * wWw-BukoLay-Com hi

8:24 wasamasa: ...

8:25 * TEttinger angry face emoticon

8:25 wasamasa: who are the ops in this channel?

8:25 powrtoc_: zot: not that I know of yet... but I'd be interested too if you find out how :-)

8:29 justin_smith: wasamasa: amalloy_ and puredanger and technomancy (who never shows up here any more)

8:29 wasamasa: justin_smith: yeah, I figured I wouldn't get to see technomancy in here ever since his announcement of moving overseas

8:29 escherize: So, I was playing with bocko. What's a good way to make an event loop?

8:30 like, to do an animation

8:31 wasamasa: just loop and recur with a waiting period and callback function?

8:32 oddcully: give clojurebot op and add a vote feature? or are op bots against freenode rules?

8:32 mpenet: it dangerous, freenode or not

8:33 it's*

8:33 wasamasa: oddcully: votekicks?

8:33 oddcully: feels kind of wrong

8:34 oddcully: well, then /ignoreance is bliss

8:34 escherize: wasamasa: lgtm, thanks

8:34 wasamasa: escherize: that's how I've seen a scheme library do it

8:35 escherize: it lets you establish the canvas/game properties first (like, dimensions, color, timeout, etc.)

8:35 escherize: if i want to keep the repl functioning, should i use a future?

8:35 wasamasa: escherize: then you start the animation with a callback function that is called with the canvas as argument

8:35 justin_smith: you could even use core.async channel ops instead of callbacks

8:35 escherize: i get the f(state) => new-state

8:36 Ricardo-Arges: Anyone familiar with reagent?

8:36 justin_smith: Ricardo-Arges: I use it every day, what's up?

8:37 Ricardo-Arges: Hey justin_smith. I'm looking through its docs and to try and figure out if there's a way to return a mix of its hiccup-like mark up and raw HTML.

8:37 Say... have a [:ul ] inside of which I insert a list of raw <li>s

8:37 justin_smith: Ricardo-Arges: I haven't used raw html at all

8:38 escherize: I use reagent every day too.

8:39 justin_smith: escherize: cool, I am loving it so far

8:39 escherize: me too justin_smith. :)

8:39 I got to meet Mike Thompson last week

8:40 he's a funny thoughtful guy

8:40 Ricardo-Arges: How about that escherize? Something like a :raw or a way to just pass it the inner html. If I just return a string, it'll get wrapped in a span, and if I do [:li the-text] it gets quoted... so any inner HTML is displayed instead of rendered.

8:40 escherize: (he wrote re-frame)

8:40 what's a raw <li>, Ricardo-Arges

8:40 justin_smith: Ricardo-Arges: there are functions that return hiccup-ized data structures from html

8:41 Ricardo-Arges: I get a series of items from the backend. They may contain embedded HTML.

8:41 escherize: oh, so a string like "<li>a</li><li>b</li>"?

8:41 justin_smith: Ricardo-Arges: fix the backend?

8:41 escherize: haha

8:41 Ricardo-Arges: justin_smith: Heh, it's parsed data.

8:42 *scraped

8:42 justin_smith: Ricardo-Arges: there's a scraper in enlive that will turn it into hiccup format

8:42 err wait - maybe not the one in enlive

8:42 but I know this exists

8:42 escherize: http://stackoverflow.com/questions/11094837/is-there-a-parser-for-html-to-hiccup-structures

8:42 this^ ?

8:43 Ricardo-Arges: Oh, that'll help. I'll give it a shot, thanks!

8:44 escherize: but yes, justin_smith, have you checked out re-frame?

8:44 justin_smith: Ricardo-Arges: after a quick look, if all you need is the parsing, clj-tagsoup will be much simpler

8:44 escherize: no, not at all

8:44 escherize: I'd agree with justin_smith here.

8:44 justin_smith: escherize: we are using reagent and sente, with a custom two-way router in cljc for communication over websockets

8:45 escherize: re-frame helped me a lot re: how to structure

8:45 that's awesome!

8:45 I wrote a chatroom toy to mess with sente last weekend

8:45 super cool stuff.

8:45 re-frame doesn't talk to the server at all

8:45 Ricardo-Arges: justin_smith: Thanks, I am using enlive already since I use it for part of the scraping... it just hadn't occurred to me to use it to transform it into hiccup-like format. Tool myopia.

8:45 justin_smith: the cool part is that with a little bit of abstraction, I can use the same namespace for the frontend and backend websocket routing

8:46 Ricardo-Arges: ahh, OK.

8:46 escherize: is it opensource? :3

8:46 justin_smith: escherize: we plan to make it open source, it is kind of tangled in a proprietary app right now

8:46 just needs some refactoring basically

8:46 escherize: re-frame doesn't talk to the server. it's a cljs library that sits ontop of reagent and helps you maintain state.

8:46 justin_smith: ahh

8:47 escherize: there are 4 main parts

8:47 1 db: all the app's state kept in one place (like usual right)

8:47 2 subscription: kind of like a materialized view into the db

8:48 justin_smith: escherize: one pattern we have started on that I really want to get working before publishing the lib is -- if you tell the backend to send some data to {:foo {:bar {:bazes [...]}}} in the state map, and there is an error, it will put the error in {:errors {:foo {:bar {:bazes {:description ... :context ...}}}}

8:48 escherize: 3 view: the reagent stuff -- uses subscriptions to get data and uses 'dispatch' to edit the db

8:49 justin_smith: we need the support code that really handles those errors, and ties the error handling setup into the creation of the request

8:49 escherize: 4 handlers: kind of like stored procs on the DB, contain all the details about how to do what needs to be done

8:50 errors in channels (and websockets i assume) has been tricky for me.

8:50 justin_smith: escherize: interesting. We have another layer -- the "private and external apis we abstract over", which are enough for a fleshed out back end.

8:51 escherize: the idea is that the router has a top level try/catch, and if anything gets that far up without being caught, it gets sent to a path in the frontend state map that mirrors the original desired path(s)

8:51 every request to the router has two paths - the routing path, and the "place" it will update when it finishes the round trip

8:52 escherize: round trip = back to server?

8:52 justin_smith: round trip = back to client

8:52 escherize: I see

8:52 justin_smith: client says "call :foo/bar on the server, put the result in [:foo :bar :bazes]"

8:53 end result is either {:foo {:bar {:bazes [...]}}} in the state map

8:53 or, {:errors {:foo {:bar {:bazes {:descritpion ... :context ... :etc ...}}}}

8:54 escherize: I see. and that's handled by some top level function on the incoming channel on the client?

8:54 justin_smith: on the server

8:54 the server discovers the error, so it alters the path

8:55 which is just edn that round trips

8:55 escherize: right

8:55 justin_smith: so the client can establish two components - one watching the desired path, one watching the error path

8:56 and I think with a bit of mental pretzaling, I can establish the error handling in the same code that does the request

8:56 with the help of a generic error watcher component maybe

8:56 escherize: while it's cool, I'm not actually a fan of using cljc for stuff that's not super simple.

8:57 I found the sente example using cljx pretty rough

8:57 justin_smith: if nothing else, putting results under :errors if there were unhandled exceptions works. So I can make a component that creates a red flag on the page (literally?) if any errors are there, and let handlers remove them

8:57 escherize: this is what I do, but with request/response

8:57 justin_smith: escherize: the key is figuring out what part of the logic can be that abstracted, of course

8:58 escherize: I can see an argument for it: it's kind of a symmetric problem

8:58 justin_smith: I realized I had a lot of duplicated code in my client side and server side sente routers

8:58 that's why I pulled it into cljc

8:58 escherize: i.e. cljs -> clj usually looks like clj -> cljs

8:59 how are you finding sente

8:59 justin_smith: but it was only when I separated routing from everything else that they became so similar

8:59 escherize: I havn't used it but for a toy project

8:59 justin_smith: it's good, there were a few differences between client and server that I had to make some small shims for

8:59 escherize: yes, i think a router abstraction is really a good choice there

8:59 justin_smith: but other than that it has been great

9:00 escherize: and passing data back and forth = ++

9:00 justin_smith: I do wonder now what using raw websockets look like (and would need to do that before I really know how good sente is), but using it has been great

9:01 escherize: Yeah, a friend of mine is using pure websockets + channels with aleph

9:01 puredanger: wasamasa: did you have a question re ops?

9:02 escherize: is this still a hot topic: https://news.ycombinator.com/item?id=9511207

9:02 wasamasa: puredanger: yeah, there's still a spambot in here

9:02 puredanger: www<tab>

9:02 puredanger: thx

9:03 escherize: woah SwiftKey is made with clojure on android!

9:19 Ricardo-Arges: escherize / justin_smith : That _almost_ did the trick. Keywords are being stringified when being turned into Json, so I can't be 100% sure of when something was an honest-to-god string and when it was a keyword. For instance... [:p "Hello"] is turned into ["p" "Hello"].

9:19 I can probably get away with expecting the first element on any list to have been a keyword. Need to check.

9:20 tdammers: I'd go with the convention that only hash keys translate to keywords

9:21 so {"p": "Hello"} -> {:p "Hello"}, but ["p", "Hello"] -> ["p" "Hello"]

9:21 vOv

9:26 escherize: yeah, sadly json is inferior to edn

9:26 it's probably not a good idea, but you could do something like ["__key__h2" "hi"] => [:h2 "hi"] on the client

9:27 probably a bad idea though :)

9:28 tdammers: maps might not work because you can have an odd number of items in a hiccp-y vector [:div {:width "10px"} "hi"]

9:28 tdammers: ah hmm

9:28 escherize: but Ricardo-Arges: probably transit is a good fit there have you checked it out?

9:28 tdammers: then I guess the "forward" conversion is basically lossy, and you have no way to reliable reverse it

9:29 escherize: true that

9:29 tdammers: my stance is that when that is the case you shouldn't even try

9:29 escherize: it's a good stance

9:29 good solution, with higher friction: introduce transit

9:29 tdammers: maybe resorting to a different JSON encoding would be an option

9:29 escherize: bad solution with lower friction: roll your own unkeyworder

9:29 Ricardo-Arges: escherize: I was not aware of it, checking.

9:29 Thanks.

9:29 tdammers: hrmph

9:30 puredanger: transit is (effectively) an extensible, caching, cross-platform JSON encoding

9:31 escherize: are you in the states, puredanger?

9:31 puredanger: yes

9:31 escherize: it must be early or late there. I guess it's early and you're in NC.

9:31 how'd i do?

9:31 puredanger: I'm in St. Louis Missouri and it's earlier :)

9:31 but not that early

9:32 justin_smith: pdx, even earlier

9:32 work starts in 2.5 hours

9:32 escherize: damn guys, it's 1:32 AM in New Zealand.

9:32 puredanger: you might not remember me but I was the guy at the Cider unsession at Conj who looked over and was like 'damn ur alex miller'

9:32 puredanger: ha :)

9:33 I'm just this guy

9:33 escherize: ikr

9:33 i think thats what u told me haha

9:34 are there other clojrue librarys with this kind of annotation? http://ideolalia.com/aleph/literate.html#aleph.examples.http

9:34 justin_smith: escherize: that's the output of lein marg

9:34 margenalia plugin for leiningen

9:35 escherize: wow I'll look into it

9:36 justin_smith: escherize: there's a link on the bottom of that page

9:36 escherize: most useful meta artifact ive ever seen: https://fogus.github.io/marginalia/

9:36 justin_smith: haha

9:46 Ricardo-Arges: escherize / justin_smith : For what it's worth, turns out you can do [:li {:dangerouslySetInnerHTML {:__html "The text here"}}]

9:46 justin_smith: Ricardo-Arges: woah - I guess it's intentional that it's that ugly

9:47 Ricardo-Arges: justin_smith: And clearly named too.

9:48 escherize: Haha. how'd you find that out Ricardo-Arges?

9:50 Ricardo-Arges: escherize: Looking into the reagent code.

9:50 escherize: https://github.com/reagent-project/reagent/blob/19a384443f6353875cc4a0eef468e45f5411d2c5/demo/sitetools/core.cljs#L161-L162

9:50 escherize: thanks for the link

9:55 wasamasa: I must be overlooking something really obvious, but how do I turn a keyword into a string?

9:55 bacon1989: ,(name :test)

9:55 clojurebot: "test"

9:55 escherize: ,(name :namespace/test)

9:55 clojurebot: "test"

9:55 wasamasa: thanks

9:55 escherize: probably won't matter tho, wasamasa

9:55 wasamasa: so there's no generic to_string thing like from java

9:56 or rather, it's used for different purposes

9:56 bacon1989: well, there's (str)

9:56 but yeah, it does funky things

9:56 wasamasa: like, displaying a human-readable variant of something more complex than a built-in data structure

9:56 escherize: ,#(apply str (rest (pr-str % :keyword)))

9:56 clojurebot: #object[sandbox$eval74$fn__75 0x7349edac "sandbox$eval74$fn__75@7349edac"]

9:56 escherize: ,(apply str (rest (pr-str :keyword)))

9:56 clojurebot: "keyword"

9:57 justin_smith: ,(name :keyword)

9:57 clojurebot: "keyword"

9:57 justin_smith: oh, we covered that

9:57 escherize: ,(apply str (rest (pr-str :namespace/keyword)))

9:57 clojurebot: "namespace/keyword"

9:57 clojer: Records and protocols both have a self-referential first arg but I haven't seen any defrecord code which actually makes use of it. As such, might not "_" be a better convetion than "this" or "self"? How is the first arg customarily used, if at all?

9:57 justin_smith: ,(subs (str :namespace/keyword) 1)

9:57 clojurebot: "namespace/keyword"

9:58 escherize: i should use subs more

9:58 wasamasa: name is exactly what I need, thanks

9:58 escherize: ,(doc subs)

9:58 clojurebot: "([s start] [s start end]); Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive."

9:58 justin_smith: clojer: when I use stuart sierra's component lib, the arg gets called component and I use it extensively

9:59 escherize: (subs "this is cool! not!" 0 13)

9:59 clojer: justin_smith: Ah, good. Do you have anything on Github I could look at?

9:59 justin_smith: clojer: since records are maps, the component system adds your deps as extra keys on the this arg

9:59 TEttinger: nosesmith

10:00 justin_smith: clojer: https://github.com/stuartsierra/component#creating-components

10:01 TEttinger: yeah, that is me, but I think the official examples are better than anything I have in my public github in this case

10:01 TEttinger: heh, you're noisesmith though

10:01 nosesmith has a very dirty keyboard

10:01 justin_smith: hha

10:03 clojer: justin_smith: His first example begins with (defrecord Database [host port connection] .... I'm confused. I thought the first arg was like "this" in Java, ie. the object.

10:03 justin_smith: the vec given to defrecord is its defined fields

10:03 the first arg to its methods are this

10:04 clojer: justin_smith: Of course. I was looking in the wrong place.

10:11 powrtoc_: clojer: I pass the this parameter onto other functions too - not all the time sure -- but often enoug

10:11 h

10:12 justin_smith: a subset of the component usage: (some-method [this] (assoc this :frobbed true))

10:12 and then (other-method [this] (if (:frobbed this) ... ...))

10:30 kaiyin: https://gist.github.com/kindlychung/f16aaa240e7fc63f00ab#file-all-clj-L9 what is wrong with this macro?

10:31 Bronsa: kaiyin: it shoouldn't be a macro

10:31 '(repeat nil) is true

10:32 kaiyin: all = (partial every? identity), any = (partial some identity)

10:35 kaiyin: ,(and (repeat nil))

10:35 clojurebot: (nil nil nil nil nil ...)

10:36 kaiyin: why doesn't it return false?

10:36 Bronsa: why should it? a collection is not a falsey value

10:36 kaiyin: ,(apply and (repeat nil))

10:36 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" 6543]} {:type java.lang.RuntimeException, :message "Can't take value of a macro: #'clojure.core/and", :at [clo...

10:37 Bronsa: and is a macro, you can't apply it

10:37 use every?

10:37 kaiyin: alright.

10:37 Bronsa: ,(every? identity (repeat 5 nil))

10:37 clojurebot: false

10:37 kaiyin: i see.

10:37 Bronsa: kaiyin: this is not the issue in your example though

10:38 kaiyin: Bronsa: what's the issue then?

10:38 ~@ applied to a lazy sequence?

10:38 clojurebot: Huh?

10:38 Bronsa: kaiyin: deh, nevermind.

10:39 kaiyin: What's clojurebot doing? Last time I saw it speaking Dutch.

10:39 Bronsa: kaiyin: it looks like you're expecting your macro to work automatically on both varargs and collections

10:39 clojurebot: ??

10:39 lazybot: Bronsa: What are you, crazy? Of course not!

10:39 clojurebot: ? is !

10:40 TimMc: kaiyin: clojurebot has a factoid engine that unfortunately (?) autopopulates from the chat on a random basis.

10:40 Oh, but I guess what you're seeing is it thinking that random statements are addressed to it -- in this case, a factoid lookup.

10:41 kaiyin: ok

10:41 looks cool, :)

10:41 TimMc: clojurebot: gfredericks?

10:41 clojurebot: gfredericks is a sexp wizard who only types transpositions

10:42 kaiyin: clojurebot: Bronsa

10:42 clojurebot: Bronsa trusts me to recall all of clojure.core by heart

10:48 TimMc: clojurebot: TimMc?

10:48 clojurebot: TimMc is the other gfredericks

10:48 TimMc: \o/

10:49 Bronsa: lol

10:52 kaiyin: clojurebot: waar kom je van daan?

10:52 clojurebot: Gabh mo leithscéal?

11:00 zot: i have a stateful predicate function … filter docs say "pred must be free of side effects." what's the 'right way', instead of filter?

11:02 adereth: Does any other code affect the state? Are you relying on it being in a particular state at the end of the filtering?

11:02 andyf_: zot: I think I'd just use filter, as long as I understood that sometimes lazy sequences have more than the minimum necessary evaluated in order to produce their results. If that is bad for your side effects, be cautious of that.

11:03 gfredericks: TimMc: well botted

11:03 zot: this is testing code, and the results are immediately eval'd, so i figured it to be safe here. and yet, i wondered if i misunderstand.

11:05 mpenet: (doseq [... :when ...]) is probably cleaner

11:07 kaiyin: is there something like this builtin in clojure? (defn truthy? [expr] (if expr true false))

11:08 hyPiRion: kaiyin: boolean

11:08 kaiyin: cool

11:08 hyPiRion: ,[(boolean 2) (boolean nil)]

11:08 clojurebot: [true false]

11:08 gfredericks: ,(boolean boolean)

11:08 clojurebot: true

11:10 zot: mpenet: i was checking the do family, but i need the return value, not just the side effects; (for [… :when] …) seemed more natural

11:18 kaiyin: Bronsa: well, this seemes to be working: https://gist.github.com/kindlychung/8423af12c554e0abdf66

11:36 https://gist.github.com/kindlychung/e59a3a607fcf4ac5a71e Why isn't ~(count match-expression) evaluated to 2 here?

11:36 ,(let [x [1 2]] `(= 3 ~(count x)))

11:36 clojurebot: (clojure.core/= 3 2)

11:40 oddcully: ,(count [1 2])

11:40 clojurebot: 2

11:40 oddcully: because the vector holds two items

11:41 oh "why not"... sorry... all the macrofoo...

11:50 john_atx: I just installed leinigen on Ubuntu 15, but I can't create a new ring project

11:51 if I do "lein new ring test", I get Failed to resolve version for ring:lein-template:jar:RELEASE: Could not find metadata ring:lein-template/maven-metadata.xml in local (/home/john/.m2/repository)

11:51 Any ideas on that one?

11:59 ah, changed it to lein new compojure test

11:59 now its workign

12:00 oddcully: if you say "installed on ubuntu" you mean via wget and via apt-get?

12:01 chances are good, that you get some incredible old stuff via your distribution and you should in that case check the versions

12:14 justin_smith: johann: agreed with oddcully - leiningen is better at managing its own deps (including its own version) than ubuntu is at managing lein, better to install by downloading the lein script and put it in your path (disregard of course if this is how you installed it)

12:15 err, john_atx left, sorry

12:15 johann: justin_smith: you are forgiven lol

12:29 alandipert: does anyone recall an odd thread on clojure dev maybe a year ago wherin people publicly willed contributions to clojure? it was some kind of legal library absorption ritual

12:32 puredanger, perhaps you would recall? ^^

12:32 puredanger: yes

12:33 alandipert: puredanger, this is re: http://dev.clojure.org/jira/browse/DPRIMAP-8

12:34 there are 4 contributors, all have CA signed, all probably willing to help - thanks for advice!

12:34 puredanger: there is a statement we ask each contributor to make when they donate a whole library into contrib, like https://groups.google.com/d/msg/clojure-dev/3kT3Pijwjrk/4-BijVCTMwcJ

12:35 would be cool to see that stuff get added

12:35 alandipert: puredanger, great, thanks, i will cajole

12:36 puredanger: I am not sure what build hurdles exist for building/testing/releasing clj/cljs libs in contrib process

12:36 that's new ground

12:37 if only there were a build tool where I could create customized task pipelines

12:38 alandipert: hehe

12:39 andyf_: alandipert: data.priority-map has already gone through that legal process long ago, has it not?

12:39 It should not need to repeat that.

12:39 Oh, you mean the ClojureScript version?

12:39 alandipert: andyf_, it has, but the contributions in question were to an unofficial port

12:40 andyf_: If they can be made into patches for data.priority-map, and all authors have signed CAs on file, that would do it?

12:43 alandipert: andyf_, possibly, but it sounds like more work. i think it's probably easiest for daniel compton to be able to use the port as a reference as he pursues unifying the two

12:43 andyf_, as i'm not sure any one patch would necessarily end up in the final result

12:44 puredanger, i'm game for boot-age

12:45 puredanger, one thing that would be easy-ish is running 1.7 in a pod and disappearing .cljc as a build step

12:45 puredanger: well, it's something I've thought about a bit and I think it would be pretty great, but Rich would have to ok using it since it's non-contrib

12:47 I grow weary of the Maven but there are a few things in the current setup where we would need to patch some gaps. In particular releasing to Maven central with GPG-signing and artifact signatures

12:47 I'm certain that's achievable but would probably need a bit of effort

12:47 I'd really like to get async off of its bespoke build process too

12:48 alandipert: i am happy to help but one glaring difference would be, boot doesn't work well in windows, which i imagine would deter contributors to whatever library its used on

12:49 which is not to say windows champions won't emerge, they just haven't yet

12:49 (in force)

12:52 puredanger, anyway i gotta go but i'll get a thread going re: priority-map

12:52 puredanger: good to know, thx

13:08 * SexGirL hi

13:09 * SexGirL help me

13:09 * SexGirL I'm having a problem with the installation, see http://www.bukolay.com

13:10 * SexGirL I'm having a problem with the installation, see http://www.bukolay.com

13:10 Bronsa: puredanger: ^

13:10 * SexGirL I'm having a problem with the installation, see http://www.bukolay.com

14:27 wasamasa: lol

14:28 how clever

14:40 Steve_Miller: anyone know a selmer tag library someone already wrote and made available? for html forms.

15:12 wxl: anyone know of forum software built in clojure?

15:24 dnolen: ClojureScript 0.0-3255 released https://groups.google.com/d/msg/clojurescript/A--qv0JxfO8/FoCzLNQ-D4EJ

15:26 tatut: dnolen: awesome!

15:27 dfletcher: Man. Was playing with a fib impl for fun and wondered how others did it. Found http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci#Recursive_Version ... Dang. Been doing this thirty years. Aaaand Clojure teaches me I've been thinking about recursion backwards that whole time. <3

15:31 amalloy: dfletcher: well, data recursion as opposed to algorithmic recursion is rather fiddly, in clojure

15:31 it works great in haskell, but the simple version only works in clojure because you're leaning on the global-mutable fib-seq. it's not practical for actually using fibonacci numbers, because you can't GC the seq as you walk through it

15:32 dnolen: ah forgot to add that with this release, ClojureScript and all its Clojure dependencies are now available as AOTed artifacts

15:32 amalloy: try writing it as a function that returns a fib seq, dfletcher, as an exercise. you'll probably want to use ##(doc promise)

15:32 lazybot: ⇒ "([]); Returns a promise object that can be read with deref/@, and set, once only, with deliver. Calls to deref/@ prior to delivery will block, unless the variant of deref with timeout is used. All subsequent derefs will return the same delivered value without blocking. See also - realized?."

15:34 dfletcher: amalloy, huh well there is a "Properly Scoped Version" on that page that seems alright

15:35 anyway I just mean conceptually. there is a different way than just "top down, wide scope towards narrow", the opposite of that (corecursion) and it's really compelling in some situations.

15:35 amalloy: dfletcher: oh, it is. but it's a totally different technique: recursion through a function, instead of data with recursive pointers into itself

15:37 bacon1989: dnolen: what do you mean by them being Ahead-Of-Timed artifacts?

15:37 also, great work porting pprint, that's awesome!

15:38 dnolen: bacon1989: they won't be compiled on the fly, ClojureScript is no longer a small library, loading a REPL required compiling 12000 or 13000 lines of Clojure

15:38 bacon1989: I didn't port pprint thank Jonathan Boston & Shaun Lebron

15:39 bacon1989: dnolen: in the long run, does this mean we could have a clojure repl live directly in javascript?

15:39 or are you suggesting that only bits and pieces of the clojure.core are included in a javascript output?

15:39 sortof like advanced pruning?

15:42 dfletcher: oh right amalloy btw my original version did return a function but not quite like you described. is the following legit?

15:43 ,((defn fib [n] (letfn [(f [x a] (if (= x 2) a #(f (dec x) (conj a (apply +' (take-last 2 a))))))] (trampoline f n [0 1]))) 10)

15:43 clojurebot: [0 1 1 2 3 ...]

15:43 amalloy: uh, aren't you holding the entire fib seq in memory forever there?

15:44 like, (last (fib 1e8)) will run out of heap

15:44 dfletcher: no it builds and returns a vector

15:44 amalloy: right: it's not lazy

15:44 it's fine, although quite inefficient, as an eager recursive solution

15:45 dfletcher: it's the procedural poison in my brain that needs expunging :>

15:47 gfredericks: ~it's |the| procedural poisin in your brain that needs expunging

15:47 clojurebot: Ok.

15:53 TimMc: Oh no, a typo!

15:53 <commence 5 minutes of fighting with clojurebot>

15:55 lodin: Is there any way to add a Clojure lib to a lein project without going through some kind of centralized repo? Like having it in ./dependencies in the project directory.

15:55 TimMc: There is, but it will lead to sadness.

15:55 dnolen: bacon1989: if you're not familiar with Clojure AOTed artifacts I wouldn't worry about this too much :) no has nothing to do JavaScript at all

15:55 other than ClojureScript compiling to it

15:56 lodin: TimMc: How? (And why?)

15:56 TimMc: lodin: This page has some pointers: https://github.com/technomancy/leiningen/wiki/Repeatability

15:56 What's the use-case?

15:57 Proprietary stuff?

15:58 lodin: TimMc: That, plus maximum repeatability.

16:01 TimMc: lodin: What's the situation you're worried about? Repos going down?

16:05 lodin: TimMc: For instance, yes. Or just need for offline installation.

16:06 (Yes. Offline is still a thing.)

16:26 TimMc: lodin: I code offline plenty, but I just run lein deps beforehand. (Doesn't help with plugin-added dependencies but it covers most cases.)

16:29 lodin: Offline installation... do you mean deployment on a machine that will be offline?

16:32 kaiyin: I want to define a function f so that (f (inc 1)) returns '(inc 1), how can i do that?

16:35 lodin: TimMc: I don't have that problem currently, but before I've had such setups so part of the question is just for future reference. I know you can make a standalone jar, so that helps a lot, as long as you don't need to do any patching then and there.

16:38 kaiyin: ,(defmacro f3 [& body] (quote `(~@body)))

16:38 clojurebot: #'sandbox/f3

16:48 lodin|away: kaiyin: Or (defmacro f [form] (list 'quote form)).

16:53 cmcfarlen: I ran into this issue with fressian causing problems: (type (fressian/read (fressian/write [1 2 3 4]))) => java.util.Arrays$ArrayList (i.e. conj doesn't love this). Looking into this and similar has been reported as a bug, but is adding a custom 'list' reader the way to go for getting the same round-trip types?

16:56 jtmarmon: hey yall. i'm trying to wrap my head around the various choices for dependency injection as it seems the literature in the clojure community is pretty undecided on this. it seems like perhaps the simplest way to share, for example, a database connection object, is to put it in its own namespace and :require that in all files that need to perform database operations. is this correct/a common way of handling shared state? thanks!

16:57 geirby: (was going to disconnect but now I need to watch this)

16:57 justin_smith: jtmarmon: use stuartsierra's component library

16:58 and provide the database as a component

16:58 jtmarmon: yeah i've taken a look at component as well. it just seems like a bit of an extensive solution for say a hacked together web app. is there really no standard way for handling this without component?

16:59 justin_smith: jtmarmon: without component, just make it a global, and require the namespace

16:59 like you first suggested

16:59 gfredericks: and pray your app never has to get more complicated

16:59 jtmarmon: > "a global" what does this mean exactly? and lool gfredericks this is actually for an ETL tool so it'll get used once and never touched again :P

16:59 justin_smith: exactly. It's easy to start out with component. Taking a complex app and "componentizing" later can be a huge pain.

17:00 jtmarmon: top level defs, all defs in clojure are global mutable objects.

17:00 jtmarmon: got it. thank you :)

17:01 gfredericks: jtmarmon: somebody will figure out a way to twist it into a crucial core business product

17:02 jtmarmon: "disgusting mess of an ETL script in clojure...as a service"

17:02 bezos is coming for me :x

17:02 lodin: gfredericks: Can you elaborate on what "more complicated" means in relation to component? (I've never use component myself; seen the video though.)

17:04 gfredericks: lodin: more complicated things like needing several database connections, or just a large variety of inherently stateful resources that you need to keep track of

17:05 lodin: gfredericks: Isn't that exactly the problem component is supposed to solve? :-)

17:05 jtmarmon: lodin: gfredericks is saying that if I use globals I should hope that my app never gets more complicated, otherwise i _will_ need component

17:06 lodin: Oh. I connected the "and" to the wrong line. :-)

17:10 gfredericks: yep

17:16 justin_smith: yeah, I just componentized our main app, and the ability to define a function that safely stops all resources (if running), reloads all changed files, then restarts the services, without exiting the repl or worrying about straggling state, is awesome

17:25 gfredericks: straggling state is for wusses

17:28 justin_smith: clojure.tools.namespace.repl/refresh-all is what separates us from the apes

17:28 gfredericks: I haven't gotten into that yet

17:29 I assume it will solve all of my protocols+records reloading problems

17:29 justin_smith: it solves the ones that come from libs outside your project

17:30 gfredericks: with my own project - all records belonging to my own app that interact with state are introduced by the component system, so I can safely redefine them. and refresh-all doesn't reload eg. core.async and thus break their defrecords / defprotocols

17:33 now if I had eg. a big queue or something stored in an atom that wasn't reset by a component restart, I could see this problem still happening. But as long as my system is a defonce, in practice I think the problem is always preventable

17:33 akkad: anyone do db migrations that are backward compatable?

17:46 lodin: I think it's an interesting phenomenon that everyone loves the immutable data structures, but many are so fast to reach for the mutability of namespaces when the code grows beyond functions and into applications, which is where the need to be able to reason about the code is even more important. And not just for state, but for configuration or avoiding to pass an argument around, effectively trading simple for easy.

17:48 gfredericks: I think that happens because you're not using OOP and so there's not any other easy way to do it

17:48 globals are all you have

17:50 kaiyin: what are the prerequisites of reading this paper? http://moscova.inria.fr/~maranget/papers/ml05e-maranget.pdf

17:52 ambrosebs: kaiyin: I found it pretty self contained.

17:52 kaiyin: have you tried to jump in?

17:52 lodin: gfredericks: I sometimes got the feeling, a few years back anyway, that people were really sick of Java OOP so passing a configuration object as the first argument, effectively writing your functions like (defn f [this & args]) was shunned, even though it sometimes was the proper thing to do.

17:53 ambrosebs: kaiyin: you can browse core.match for an implementation

17:53 kaiyin: and turn on all the tracing stuff

17:53 kaiyin: ambrosebs: trying. what is the tracing stuff?

17:56 ambrosebs: kaiyin: I forget but IIRC there's a few flags to turn on in the core.match implementation to step through the algorithm

17:56 lodin: gfredericks: As I see it, the thing with component is that it "reintroduces" objects in Clojure (and helps you with ordering). :-)

17:56 ambrosebs: also some high level docs in the main clj file

17:58 kaiyin: ambrosebs: ok, i'll look it up.

18:21 ambrosebs: i don't quite understand the occurrences notation here: http://i59.tinypic.com/4qqzh0.jpg could you help me a bit?

18:23 lodin: justin_smith: What were the major pain points when you componentized your main app?

18:48 ambrosebs: kaiyin: looks like it's a way to dig into subterms in a pattern

18:48 (cons (cons 'a 'b) 'c)/1/2/ /\ should be 'b

18:49 erm imagine that's zero-indexed

18:50 wait no, maranget uses 1-indexing here

18:51 kaiyin: that help?

18:51 kaiyin: ambrosebs: very much, crystal clear now.

18:51 ambrosebs: great

18:52 kaiyin: does this apply only to cons list?

18:52 or can it be generalized to vectors and maps?

18:55 ambrosebs: kaiyin: all ML constructors are represented as c(1 ... k)

18:55 kaiyin: ok

18:56 ambrosebs: read the start of that section

18:56 talks more about c

18:57 kaiyin: i see.

18:57 thanks a lot.

19:27 justin_smith: lodin: it took a while to ensure that things which get called at runtime would all be able to get components passed in as needed

19:28 err, better way to put that was ensuring that everything could have components passed in at runtime

19:34 gdev: https://www.refheap.com/100759

19:35 using a map with a hashtag anonymous function is perplexing me

19:37 hiredman: ,'#({:a :b})

19:37 clojurebot: (fn* [] ({:a :b}))

19:37 hiredman: ,'(#({:first-name %1 :last-name %2} "foo" "bar") "baz" "bang")

19:37 clojurebot: ((fn* [p1__49# p2__50#] ({:first-name p1__49#, :last-name p2__50#} "foo" "bar")) "baz" "bang")

19:39 hiredman: if #(+ %1 %2) is a function that immediately applies the function + to the first and second argument, what does that make #({:a :b}) ?

19:40 if (let [f +] #(f)) is a function that invokes + with no args, then what is (let [f {:a :b}] #(f)) ?

19:42 gdev: my repl says it's a function

19:43 hiredman: yeah, but what does it do when you invoke it?

19:43 (this is not a trick a question)

19:43 gdev: arity exception

19:44 turbofail: ,(#(hash-map :first-name %1 :last-name %2) "Foo" "Barson")

19:44 clojurebot: {:last-name "Barson", :first-name "Foo"}

19:44 hiredman: if #(FOO) returns a function that immeidate invokes whatever foo is as a function, then what is going to happen when FOO is a map?

19:44 immediately

19:45 (it is going to invoke the map as a function)

19:45 lodin: justin_smith: How was it structured before component?

19:46 hiredman: (clojure maps are functions, taking 1 or 2 arguments, so of course when you invoke it with no arguments you get an arity exception)

19:46 gdev: Okay I see now

19:46 justin_smith: lodin: stateful objects in the top level defs, with init functions that bound / created their contents

19:48 lodin: on a per-case basis, either a promise, or an atom, or a regular def

19:51 lodin: justin_smith: I see.

19:51 justin_smith: lodin: a bonus with component is jsvc integration became much simpler

19:53 lodin: justin_smith: How's that?

19:54 justin_smith: lodin: jsvc exposes hooks from your app for start / stop / refresh, and this integrates nicely with the lifecycle protocol

19:54 lodin: justin_smith: Ah.

20:13 ben_vulpes: how would i go about using code from a leiningen plugin (eg https://github.com/montoux/lein-less) in my own clojure code?

20:14 naively requiring 'leiningen.less fails

20:14 justin_smith: ben_vulpes: have you tried requiring it as a normal dep?

20:14 plugins are available in the lein process, but not in yours. But you should be able to add it to your project.clj in the deps section

20:15 ben_vulpes: myeah, i have [lein-less "1.7.2"] in my :dependencies, but then calling (use 'leiningen.less) fails to find the right classes

20:16 justin_smith: ben_vulpes: because of plugin weirdness, you may need to require its deps https://github.com/montoux/lein-less/blob/master/project.clj#L13

20:16 probably leiningen-core should suffice?

20:16 ben_vulpes: shmooookay

20:17 wao :optional :true that's a scary thing to see

20:17 * ben_vulpes restarts his jvm

20:17 justin_smith: now that I think about it, that makes sense - as a plugin it should use the lein and clojure that pulled it in, and not specify its own

20:18 ben_vulpes: better..."could not locate leiningen/compile__init.class or leiningen.compile.clj on classpath"

20:18 * ben_vulpes tries again without optionality

20:47 ben_vulpes: how would one go about accessing a clojure project.clj at runtime?

20:48 [mad]: hi

20:50 xeqi: ben_vulpes: thats hard. Some steps would include leininegen-core and using l.c.project/read on the project.clj from the classpath. What are you trying to do with it?

20:54 ben_vulpes: https://github.com/taoeffect/slothcfg looks like it will help

20:54 ben_vulpes: i'm hooking less compilation into the reloaded workflow, want to specify less source and output dirs in the common place, and use those both in the reloaded workflow and in jarification

20:54 xeqi: ^^

20:56 xeqi: l-c.p/read looks to do the trick. thank you!

21:31 gfredericks: is there a builtin way to get the index of the lowest set bit in a Long?

21:32 I'm trying to write my own and am getting the feeling that I'd have to use java to get the best bytecode for it

21:33 (I was going to do a binary search, which I guess is 6 steps or something)

21:35 hiredman: how can you do that as a binary search?

21:35 gfredericks: (if (zero? (bit-and x 0xFFFFFFFF)) (it's in the upper bits) (it's in the lower bits))

21:36 hiredman: oh

21:36 anyway

21:36 http://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#numberOfLeadingZeros%28long%29

21:36 gfredericks: oh hey yeah

21:36 I was just scanning that page and swore that nothing applied

21:36 thanks

21:37 (inc hiredman)

21:37 lazybot: ⇒ 78

21:37 hiredman: and I sort of assume that method has an intrinsic in the jvm, but who knows

21:38 gfredericks: if it doesn't I doubt I can do better on my own anyhow

21:50 TEttinger: (inc hiredman)

21:50 lazybot: ⇒ 79

22:23 mysamdog: So I have my repl set to start in the namespace atm.core, and atm.core requires atm.db. I had a mistake in atm.db (I meant to have a vector, but I put curly brackets around it to make it a hashmap)

22:24 When I ran the repl with 'lein trampoline repl' I couldn't call any functions in clojure.core or anything that is part of my project

22:25 But if I did 'lein repl' it not only told me what was wrong with my code, but it also loaded clojure.core. What about trampoline causes this?

23:13 Niac: how to use createImage method in java.awt.Toolkit?

23:14 I try to use proxy ,but something is wrong

Logging service provided by n01se.net