#clojure log - Sep 06 2014

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

0:03 wei: is it a good idea to bind request map to *request* (lib-noir style), so it can be accessed from any function?

0:05 danneu: wei: i remember doing that when i was more of a beginner with compojure. can't remember why. these days id just pass the request through as an argument

0:07 though i do still bind *current-user*, but it's out of habit. i should prob just assoc it to the request

0:22 joobus: Woohoo! "You have achieved clojure enlightenment. Namaste."

0:22 I defeated the clojure koans!

0:34 alexbaranosky_: I have to say el-get is amazing. At work a few of us religiously try to get others using it.

0:37 technomancy: alexbaranosky_: I'd say it's less that el-get is amazing and more that everything else is just dismal

0:40 alexbaranosky_: technomancy: yes. i just need to be able to specify versions of packages... before el-get I couldn't easily tell people which actual package versions I was using

0:51 abaranosky: I'm here canvasing for upvotes on my Clojure patch :) http://dev.clojure.org/jira/browse/CLJ-1519

4:31 kryft: I'm trying to make a stand-alone jar, but `lein jar' seems to run forever (I'm assuming it doesn't take hours for 100 lines of code)

4:33 dimasangga: kryft: do you run any function in your namespaces top level?

4:33 TEttinger: kryft, yeah, what dimasangga said

4:34 kryft: dimasangga: No -- well, not as far as I know. I don't know what compojure's defroutes macro does.

4:34 TEttinger: as in a function being run inside a (def ...) or just like (some-db-call ...) not wrapped in a defn

4:35 dimasangga: or your jetty run-server?

4:35 kryft: But I even tried wrapping every single top-level definition inside a function, but still no luck.

4:35 TEttinger: those things will get run by lein as part of the compile process

4:35 could also be fetching deps if you have many large ones

4:36 I waited about 4 hours one time for RoboVM to download off maven central when it was having a bad day

4:37 kryft: Oh, I assumed it had fetched deps already for lein repl

4:37 dimasangga: kryft: try `lein deps` first, then `lein clean` before doing `lein jar`

4:40 kryft: Here's core.clj and project.clj, in case I'm missing something obvious: https://gist.github.com/kryft/9303dfdfa730cac346ea

4:42 dimasangga: Tried that; I got two lines with "Compiling abhimata_backend.core" and now it's been running for 3.5 minutes with full CPU usage

4:55 TEttinger: Is there any way to see what's causing lein to hang? For example, how did you know you were waiting for RoboVM?

4:56 TEttinger: that was actually using another tool (that also used maven central for some deps), but I think if it is fetching a dep it would say so

4:59 dimasangga: kryft: i put put :gen-class before :import on ns declaration like this

4:59 kryft: (ns(ns abhimata-backend.core

4:59 (:gen-class)

5:00 and it was compiled under 10 secs

5:00 justin_smith: kryft: you can use jstack to find out what a jvm is doing on each running thread

5:01 dimasangga: kryft: i will post my version of your project.clj and core.clj in gist shortly

5:02 kryft: dimasangga: Ok, thanks :)

5:03 dimasangga: kryft: https://gist.github.com/dimas-angga/280b06871831fa95850a

5:19 kryft: dimasangga: Thanks! If I copy those intoa new directory, I can make a jar, but in the original directory lein jar still hangs (with your project.clj and core.clj)

5:23 dimasangga: So apparently there's something wrong with something outside those two files

5:24 Strange

5:27 dimasangga: kryft: i don't get what you mean with new directory, did you make a new project or something?

5:28 kryft: dimasangga: Well I just copied project.clj to tmp_dir, copied core.clj to tmp_dir/src/abhimata_backend, and then ran 'lein jar' in tmp_dir

5:30 dimasangga: Hmm, actually it seems that 'lein jar' *does* work in the sense that the jar file gets created, but for some reason lein jar keeps running at 100% CPU anyway.

5:31 Oh well, at least the jar file gets created,

5:37 dimasangga: Anyway, thanks for your help; now I know that there's something wrong with the project directory, not the source files (since jar creation works if I copy the files into a new project)

5:54 dimasangga: kryft: You're welcome :)

7:49 dagda1_: how do I move 1 s-expression inside another using paredit in emacs?

7:57 hyPiRion: ~paredit

7:57 clojurebot: paredit is not for everyone, but what you need to understand ís how to become the kind of person that paredit ís for.

7:57 hyPiRion: dagda1_: http://www.emacswiki.org/emacs/PareditCheatsheet

8:11 dagda1_: can anybody explain why this https://gist.github.com/dagda1/94c2823d47645f26f7aa goes into an infinite loop when I thought I was returning a lazy-seq

8:12 or is it because I am running it in the repl?

8:13 no, I just think it is wrong :).

8:45 hyPiRion: dagda1_: reduce is eager

8:45 it will run until it hits the end of the list

8:45 dagda1_: hyPiRion: I thought lazy-seq would stop this

8:46 hyPiRion: lazy-seq will defer the evaluation of a reduce

8:46 but once reduce has been called, it will happily run until the sequence is empty

8:47 dagda1_: hyPiRion: what could I do instead?

8:48 hyPiRion: You could either do the loop itself recursively, where each cons call is wrapped in a lazy-seq

8:48 or, in this case, you could just do (reductions + (range))

8:48 ,(reductions + (range))

8:48 clojurebot: (0 1 3 6 10 ...)

8:49 hyPiRion: You can usually use existing functions to get the functionality you want with laziness, without using lazy-seq itself.

8:51 dagda1_: hyPiRion: i'm trying to recreate reductions just to increase my clojure knowledge

8:51 hyPiRion: aha

8:52 dagda1_: hyPiRion: I think I have an idea what tod o

8:53 hyPiRion: dagda1_: reductions use the technique I mentined earlier - it loops recursively (without recur)

8:53 dagda1_: hyPiRion: got it, thanks

8:53 hyPiRion: without recur?

8:54 hyPiRion: dagda1_: (defn reductions [...] ... (reductions ...)) instead of (defn reductions [...] ... (recur ...))

8:54 dagda1_: hyPiRion: and that is not tail recursive

8:55 hyPiRion: yeah, true

8:58 dagda1_: hyPiRion: I thnk it should work with recur

8:59 hyPiRion: dagda1_: it could work if you want it to be eager. But then you won't be able to use reductions on infinite lists

9:00 gfredericks: hey hey alpha2 has clojure.core/update

9:00 hooo ray

9:07 cfleming: gfredericks: Yeah, I was waiting for that one - nice

9:07 gfredericks: ,update

9:07 clojurebot: #<core$update clojure.core$update@1eee7b7>

9:09 samflores: gfredericks, what's the diff from update-in?

9:09 gfredericks: samflores: just for one level

9:09 samflores: (update-in {:k 1} [:k] inc)

9:09 nkozo: I want to create a service using core async, it receives request from a channel and must return a response. My first approach is to send the response to a reply-channel included in the request, so my make-request fn will allocate a reply-chan each time is called. Is this a good idiom? Or is the (chan) allocation call to costly to do each time?

9:09 gfredericks: ,(-> {:foo 12 :bar 14} (assoc :baz 8) (update :bar * 3))

9:09 clojurebot: {:baz 8, :bar 42, :foo 12}

9:09 samflores: isn't that bad :p

9:10 gfredericks: samflores: I get tired of it after the 57th time

9:10 samflores: why don't we get rid of assoc as well?

9:16 samflores: I don't get it

9:16 ,(-> {:foo 12 :bar 14} (assoc :baz 8) (update-in [:bar] * 3))

9:16 clojurebot: {:baz 8, :bar 42, :foo 12}

9:20 gfredericks: samflores: I assume you're arguing that we don't need update because you can do the same thing with update-in

9:21 in which case we also don't need assoc since we can do the same thing with assoc-in

9:23 samflores: I'm not arguing. just trying to really understand the value of having update and update-in

9:26 assoc can't receive a fn, so I can't *easily* update the value based on it's current value. I believe that's the diff of assoc and update-in that justify having both

9:26 gfredericks: yes I mean we don't need assoc because assoc-in can work

9:26 ,(-> {:foo 12 :bar 14} (assoc-in [:baz] 8) (update-in [:bar] * 3))

9:26 clojurebot: {:baz 8, :bar 42, :foo 12}

9:27 gfredericks: update is to update-in as assoc is to assoc-in

9:27 samflores: oh. now I got your point :D

9:27 gfredericks: also I use it all the time so I was tired of requiring it

11:10 nkozo: when you use <!! inside a core.async go block, it will park correctly as by using <!?

11:31 bacon1989: Hi, I was wondering, how would one typically design a system involving several instances of mutable objects?

11:32 justin_smith: bacon1989: what invariants need to be preserved as they mutate?

11:32 bacon1989: in this situation, would I use a deftype, over a defrecord, to store mutable state?

11:33 justin_smith: the Viewer is showing maps, so I started out with defrecord [maps], but the maps change, along with what maps might be showing

11:33 justin_smith: why do those maps need to change - can't you just view a different map?

11:34 bacon1989: but if i'm changing hte map that the viewer is showing, that would still require mutable state in the viewer, right?

11:35 justin_smith: not neccessarily any exposed mutable state - of course registers in a CPU mutate, what we can change is where mutation exists in our high level execution model

11:35 the general best practice in Clojure is to replace mutation with function arguments (such that the function mutates nothing, but does something different with different arguments provided)

11:36 bacon1989: justin_smith: I sort of see what you're getting at

11:36 justin_smith: should be view even be accessing the data model? why can't it just receive a request or command and make a new display based on that?

11:37 bacon1989: justin_smith: hmm... good point, I could just mutate the previous viewer, and display it

11:37 justin_smith: the mess we are avoiding here is the synchronization of layers - the brittle things that happen when changes could be coming from one end of the system or the other - the typical OO solution to this is to make one abstraction (the controller) that mutates the model, and reports the current state of the model to the viewer

11:39 when we have immutability, the data end can provide immutible data to the view end, and the view end can send requests to the data end (for the next version of the data) - none of these objects need to mutate

11:39 of course you can also use mutation if you really want to, but we like to avoid it in Clojure

11:40 if you want mutation, yeah, you can use deftype with mutable fields, then you probably want to create an imperative control layer to coordinate changes (the c in mvc)

11:40 and you will need to think about your invariants (as I first mentioned)

11:41 one nice thing about immutibility is that the set of invariants we actually need to think about / implement is much smaller (typically "this value cannot change" suffices on that count)

11:42 invariants can be things like "the sum total of values in all accounts must remain consistent as transactions are processed" or "the fields in the UI must all reflect details of one target object, and reflect its most recent modification at all times"

11:46 bacon1989: justin_smith: thank for that, i'm going to have to re-think how I implement this

11:47 justin_smith: np

11:49 Janiczek: Anybody using Figwheel here? I don't know how to re-render with an old state atom.

11:50 Maybe I can fake it with serializing into cookies or local storage, but maybe Figwheel has something under its sleeve?

11:51 justin_smith: bacon1989: that reminds me, on a more pragmatic note, you can try using an atom to hold coordinated state, where instead of mutating the datastructure, you use pure functions that are atomically applied to the state. The advantage here is no reader will be blocked, or see a partial update.

12:15 awwaiid: I'm trying to understand the sourcecode relationship between clojure and clojurescript. They appear to be completely independent git repos. Is there any automatic correlation between them, or are all changes hand-moved?

12:16 justin_smith: awwaiid: some libs are written such that they can be used from clj or cljs, but the languages (java / javascript) are different enough that they share little of the same core clojure implementation

12:17 awwaiid: as they like to say on ##java, java is to javascript as ham is to hamster

12:19 awwaiid: I noticed that CinC was split and moved into independent repos -- tools.analyzer, tools.analyzer.jvm, tools.emitter.jvm. I see there is tools.analyzer.js . Do these get sucked into the build process for the main clojure/clojurescript builds?

12:19 I will continue to read about this, just looking to see if there is a high-level overview that I'm missing

12:21 justin_smith: awwaiid: Bronsa puredanger and arrdem would be good people to ask about this stuff

12:21 they work on or around those tools

12:22 awwaiid: I just noticed that there is a Cojure/West video about tools.analyzer for me to watch, might give a good intro

12:22 thanks

12:24 Bronsa: awwaiid: ATM none of the tools.* libraries (except for tools.reader) is being used for the official builds, they are separate entities

12:36 awwaiid: Bronsa: is it a goal?

12:40 Bronsa: awwaiid: I'd like to see cljs switch to tools.analyzer.js as its analyzer at some point, but there's still work that needs to be done before I can start bothering dnolen_ about it

12:40 awwaiid: ok cool

12:40 Bronsa: awwaiid: on the clojure side, that's less likely to happen

12:40 awwaiid: too complex, or momentum, or what?

12:41 Bronsa: awwaiid: a variety of reasons: bootstrapping issues, performance, stability just to name a few

12:41 awwaiid: ah

12:42 seems like it would be awesome to have the same code-foundation. I was looking at the abandoned python and ruby backends and thinking that, at least

12:45 justin_smith: awwaiid: if Clojure was more ambitious about abstracting away from the runtime, it would be possible. But one of the main advantages of clojure is how closely it reveals the runtime (ie. how trivial interop is, the relatively low cost of its abstractions as compared to just using the underlying impl language)

12:49 Bronsa: awwaiid: btw if you're looking at tim's clojure/west talk, I have to warn you that since then things have changed a bit and some of what he shows might not be true anymore

12:50 awwaiid: I'm mainly learning about the big picture rather than the details at this point

12:50 Bronsa: awwaiid: ok, if you have any question feel free to ask me about it

12:54 awwaiid: Bronsa: thanks

13:06 whilo: are there any attempts at a core.matrix cuda/opencl implementation yet?

13:06 i am using theano for cuda on python atm. and it would be nice to get something similar in idiomatic clojure

14:08 justin_smith: whilo: OS level interop on the jvm is kind of a pain, I don't know of any Clojure projects that attempt jni off the top of my head. There are java cuda libs you could use via clojure.

14:09 dbasch: justin_smith: there’s this https://github.com/Chouser/clojure-jna

14:09 justin_smith: dbasch: cool, I didn't know about that

14:10 dbasch: I hope I never have to use something like that though :P

14:17 sorbo_: anyone have experience using Enlive? https://github.com/cgrand/enlive

14:17 I'm trying to get src attributes for images

14:17 but it escapes the URLs

14:18 e.g. http:\/\/

14:18 I'm not sure how to prevent this

14:20 justin_smith: sorbo_: can you share a small paste on refheap that demonstrates what you are talking about?

14:21 sorbo_: justin_smith: sure, one second

14:28 justin_smith: https://www.refheap.com/89913

14:28 I haven’t run this paste, so there could be unbalanced parens or something like that

14:29 I’ve got the scraping working fine, I just can’t figure out how to properly un-escape the escaped link

14:30 yeah, there were unbalanced parens. fixed

14:34 dbasch: sorbo_: it works fine for me. What version of enlive are you using?

14:35 sorbo_: 1.1.5

14:35 justin_smith: sorbo_: cannot reproduce https://www.refheap.com/89915

14:36 sorbo_: dbasch: which version are you using?

14:36 dbasch: sorbo_: 1.1.5

14:36 sorbo_: justin_smith: hm. it’s possible the escaping is happening after enlive is doing its job

14:36 I’ll tinker with it

14:36 thanks for having a look

14:36 justin_smith: it looks like the kind of escaping a templating lib would do

14:59 PigDude: huh, what do you do when you need a record/type to refer to itself?

14:59 ah nevermind

14:59 separate extend-type/defrecord|type

15:12 jpena: can someone help me understand the error i'm getting here? http://dpaste.com/2SJCTT5

15:13 i'm just trying to write a simple standard deviation function

15:13 justin_smith: jpena: (i - avg-numbers)

15:14 should probably be (- i avg-numbers)

15:14 jpena: ah, damnit, im such a noob

15:14 justin_smith: "java.lang.Long cannot be cast to clojure.lang.IFn" gives a pretty good idea of what you are looking for

15:14 ,(1 + 1)

15:14 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

15:15 jpena: yeah, i was having trouble understanding that, but it makes sense now that you mention it

15:15 thanks justin_smith

15:16 justin_smith: np

15:16 for a little more detail, most everything in clojure is based on protocols / interfaces rather than concrete classes / types

15:17 IFn is for things objects you can call (functions, maps, keywords, etc.)

15:20 ToBeReplaced: is there a string plus in CLJS? I want to do a literal "a + b" where a and b are strings without calling str

15:20 justin_smith: you can use a StringBuffer

15:20 if you want to mutationally add chars to a string

15:20 but on an implementation level, a+b just creates a new string just like str does, in java

15:21 sorry, s/StringBuffer/StringBuilder

15:23 ToBeReplaced: justin_smith: anything lighter weight? i want the compiled javascript to read "a + b"... (js/+ a b) gives me _PLUS_(a, b), and i don't know if that's the same thing

15:24 i'm experimenting with CLJS for kicks, but I can't bring in the facilities because they are too large... i'm trying out using it for macros, but then i can't have "str" in my cljs source, i need to perform raw concatenation

15:25 justin_smith: oh I am sorry

15:25 I missed the CLJS part, my bad

15:25 ToBeReplaced: and unfortunately i only know a and b at runtime so i can't do it at compile time

15:31 justin_smith: ToBeReplaced: what about the concat method?

15:32 you could have a temporary accumulator string for sanity's sake

15:33 (.concat "hello" "world") should just compile to a String.concat call, right?

15:33 arrdem: should...

15:33 justin_smith: well, I don't have a handy cljs setup to test that atm, but it sounds like he does :P

15:34 amalloy: ToBeReplaced: you want to use cljs to emit javascript that doesn't depend on any of the cljs runtime?

15:36 ToBeReplaced: amalloy: yes

15:36 amalloy: i don't think you'll get far with that. almost everything needs the runtime; and if you just want to write "a + b", it's easier in javascript than in cljs

15:36 ToBeReplaced: experimenting ;), also interesting to hook in to closure compiler that way

15:37 yeah, all it's doing right now is calling macros that call native clj functions and expand to cljs forms

15:44 adamt: Hello dear fellow people and droids. I have a problem with some java-interop, which I hope you might be able to help me with. ;-)

15:47 justin_smith: ~ask

15:47 clojurebot: The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question.

15:47 arrdem: justin_smith: can I get a ~droids

15:47 adamt: (i am, just slow at typing :-( )

15:47 When trying to call a method, it seems like clojure can't find a method with a matching signature. I have a gist here https://gist.github.com/adamtulinius/76c11ec527a33a1bf698 with the exception thrown, and a link to the api of the java interface

15:48 justin_smith: arrdem: droids is ...

15:48 allenj12: so i need to go through a structure and each element i find falsey elem to a predicate, i need to to update a different vector and start going throught the prior structure all over again testing it again... what control structure/function do i want?

15:48 adamt: (please excuse my horrible clojure)

15:48 justin_smith: adamt: before looking, I am going to guess int or varargs

15:48 adamt: justin_smith: yes, varargs

15:48 signature is basically java.io.file and varargs on strings

15:49 justin_smith: adamt: (into-array ["all" "the" "strings"]) as the last arg

15:49 varargs is an illusion, it's really just an array as the last arg

15:49 Bronsa: adamt: or (into-array String []) if you have no params

15:50 justin_smith: Bronsa: excellent point, I missed that

15:50 (inc Bronsa)

15:50 lazybot: ⇒ 47

15:50 adamt: justin_smith + Bronsa: thanks, i'll try

15:55 (ing justin_smith)

15:55 (inc justin_smith)

15:55 lazybot: ⇒ 73

15:55 adamt: i fail horrible. Thanks both of joy, it worked great. Sorry for being slow at typing the silly question.

15:56 Wow, I just can't spell today, better be quiet now before I insult somebody by accident!

16:01 justin_smith: adamt: not a big deal, regarding the ~ask thing

16:01 no need to feel bad about it at all

16:02 the standards of what's "polite" on irc are different from other places, that's all

16:14 adamt: justin_smith: to be honest, I mostly wanted to break it up into two message, because I know about the limited length of a single message on IRC, but got interrupted because I realised I made a mistake in my gist. :P

16:21 amalloy: allenj12: i don't really understand the problem. it sounds special-case enough that just using loop might be appropriate

16:22 allenj12: amalloy: yea it seems the loop is best doing that now. thank you!

16:35 tadni: So, just finished giving my friend a very basic intro to programming in Clj. Lighttable is much easier to teach than Emacs.

16:36 dbasch: tadni: when it works :)

16:36 tadni: dbasch: I had no problems, but hey. :^P

16:37 I think that is more or less sticks with "traditional" key bindings helps too.

16:38 justin_smith: tadni: one of these days I am going to teach someone CLI, Linux, emacs, Clojure, database management, and git all at once - as they stab me to death and I gurgle my last words, those words will be "you are now a devop"

16:39 tadni: justin_smith: Well the person I was giving the intro to, had very very little technical backgroud. Even scared of a CLI in-general.

16:40 He picked up Lisp-like syntax pretty fast though, I was kinda shocked.

16:40 Any mistakes he made, I see was a failing for me to explain it simply.

16:40 justin_smith: it's easier if you haven't learned an algol syntax yet

16:41 tadni: I need to think of more simple examples though. We did a dice-roller and coin-flipper, and age-in-x programs. Rest was basic maths and hello world and the like.

16:42 justin_smith: tadni: extract some data from a simple json rest api using slurp and cheshire

16:42 tadni: justin_smith: Yeah, I guess. At that point I assume it's more unlearning syntax.

16:43 justin_smith: I was thinking because it would give opportunities to use the many marvelous sequence and datastructure transforming tools clojure has

16:43 extracting the data you want, putting it in the right place, that kind of oragami

16:43 * tadni is going to his local clj meetup this month to actually learn some notable libraries.

16:43 justin_smith: the cheshire part would just be one call - cheshire.core/read-string

16:44 the rest would be clojure.core sequence and map operations

16:44 tadni: justin_smith: Maybe a few lessons down the line, right now he's still at very basic starter notions of programming.

16:44 justin_smith: check out the cheat sheet and see how many functions you can try out http://grimoire.arrdem.com/

16:45 OK

16:45 so maybe do some of the math he already knows, translate it to clojure code

16:45 (this will depend on their level of math education of course)

16:46 tadni: justin_smith: He's just at intermediate alg, so I'm think there's not a lot to work with.

16:47 * tadni remembers hi still needs to update his blog post and get cider working with his Emacs install.

16:47 tadni: Maybe by Tuesday.

16:50 justin_smith: ugh, cider - it wouldn't be so bad except setting it up is often one of the first things a new clojure user tries to do

16:50 lpaste: aa pasted “aa” at http://lpaste.net/110625

16:50 justin_smith: lpaste: you are in the wrong channel

16:51 tadni: justin_smith: Yeah, I wasn't able to get it working my first try. nrepl couldn't find my install of clj.

16:51 I'm assuming Fedora might install it somewhere weird.

16:51 justin_smith: nrepl?

16:51 clojurebot: nrepl is a network REPL implementation: http://github.com/clojure/tools.nrepl

16:51 justin_smith: I thought you were installing cider

16:52 tadni: justin_smith: Cider is based off nrepl, isn't it?

16:52 justin_smith: absolutely not

16:52 llasram: tadni: Also you don't really install Clojure. You install Leiningen

16:52 justin_smith: well, it replaces it

16:52 llasram: Er

16:52 tadni: Maybe it was just a regular repl -- but I couldn't connect to it.

16:52 llasram: CIDER replaces nrepl.el

16:52 justin_smith: OK, cider uses lein to open an nrepl instance when you jack in

16:52 llasram: nREPL is the Clojure network REPL protocol/implementation, which CIDER uses

16:52 dmitrygusev: what does "n" in nREPL stands for btw?

16:53 llasram: dmitrygusev: network(ed?)

16:53 tadni: Networked?

16:53 dmitrygusev: hm

16:54 ghadishayban: hiredman: is it more useful for reducible io wrappers to be one-shot or reusable?

16:55 * tadni probably needs to look into leiningen a lot more than he has.

16:55 * tadni is going afk for late lunch.

16:55 justin_smith: tadni: yeah, lein is the right way to use clojure at dev time

16:55 tadni: Peace for now, peeps. o/

17:10 LBRapid: Based on this small app, https://gist.github.com/LBRapid/1f04682e944182fd8ce7 how would I complete my remove-player function? I'm having trouble figuring it out

17:15 justin_smith: LBRapid: (swap! players dissoc player-name) maybe?

17:16 LBRapid: but change players to #{} instead of ()

17:16 that way you can only get one instance of each player, and you can do lookup / removal by value

17:16 LBRapid: justin_smith: Right, so really a map makes more sense in this case?

17:16 justin_smith: if you need any data attached to the player, change the #{} to {}

17:17 well, with what you have now a set #{} works, but yeah, you probably want a map if players have any associated data

17:18 LBRapid: Okay. I understand. Thanks! I'm still wrapping my head around things, working through some exercises in a concurrency book

17:18 justin_smith: ,(disj #{:a :b :c} :b)

17:18 clojurebot: #{:c :a}

17:18 dbasch: if you want it to be a list for some reason, you’d need something like (swap! players (fn [s x] (remove #(= x %) s)) player-name)

17:18 LBRapid: dbasch: Ah thanks. I was trying to use remove but was having trouble getting it right

17:19 justin_smith: LBRapid: dbasch: I'd welcome any argument as to why a list would make more sense than a set or map here

17:19 but I am not seeing any

17:19 dbasch: justin_smith: I don’t think it should be a list either

17:19 LBRapid: justin_smith: I don't think it does. That's just where the example was when I started the exercise, but makes sense to swap for a set to me

17:23 lodin: What's a proper use case for #=(...)?

17:25 justin_smith: lodin: I can find no documentation for #= http://clojure.org/reader

17:25 lodin: justin_smith. Neither did I. :-)

17:26 ,(read-string "#=(+ 1 2)")

17:26 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

17:26 lodin: :-(

17:26 justin_smith: ahh, right, I always forget about that

17:26 it's a terrible thing that should never have existed :P

17:27 lodin: justin_smith: Which makes me curious to why it exists in the first place. I'm assuming there was a use case for it.

17:27 justin_smith: people do seem to like being able to insert arbitrary executed code into data

17:41 dagda1_: can anyone explain why I get a stack overflow with this function when I use an infinite list https://gist.github.com/dagda1/6b4fc1e0ee6412b78c90.

17:43 amalloy: dagda1_: you're building up a result that looks like (lazy-seq (lazy-seq (lazy-seq ...)

17:43 ))

17:43 dagda1_: amalloy: ha, yes you are right

17:43 amalloy: when it comes time to find the first element of that, you have to go through a zillion levels of nesting

17:43 instead, you should use cons to build a lazy seq

17:43 like, what you've written here would be fine as a tail-recursive function

17:44 dagda1_: amalloy: so don't use letfn

17:45 amalloy: acutually I don't see how lazy-seq gets called multiple times if lazy-seq precedes letfn

17:45 amalloy: dagda1_: your conclusion doesn't follow at all from the evidence

17:45 dagda1_: amally: my conclusion?

17:45 amalloy: "don't use letfn"

17:45 dagda1_: amalloy: I don't think I understand

17:46 amalloy: dagda1_: your function returns successfully without causing a stackoverflow. the overflow comes only when attempting to seq it

17:46 $google stackoverflow dbyrne prime sieve

17:46 lazybot: [recursion - Recursive function causing a stack overflow - Stack ...] http://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow

17:48 dagda1_: but what if I want the function to work with infinite lists like (range) surely I need to use lazy-seq

17:48 justin_smith: dagda1_: right, use lazy seq with cons, as amalloy said

17:49 dagda1_: justin_smith: ok, so why is cons important

17:49 justin_smith: you need to do some work for each element, cons takes the element you are adding, plus the realizable lazy seq for getting the rest (which is where the recursion happens)

17:49 amalloy: dagda1_: never (or almost never?) use lazy-seq and an accumulator parameter for the same function. if you have a partial result to return, return it immediately with (cons x (keep-going ...)) instead of (keep-going (conj acc x))

17:50 justin_smith: that's a much clearer explanation

17:50 (inc amalloy

17:50 (inc amalloy)

17:50 lazybot: ⇒ 165

17:51 dagda1_: amalloy: great, thanks

17:58 tadni_: Back! :^)

17:59 dagda1_: so wrapping a function in a lazy-seq call does not make the seq lazy

17:59 justin_smith: it's lazy-seq is neccessary but not sufficient

18:02 amalloy: did you read the stackoverflow question i linked, dagda1_?

18:14 tadni_: justin_smith: Should I be using Lein 1 or 2?

18:14 justin_smith: definitely 2

18:15 but don't use 2.4.3 for repls where you have no project.clj - for projectless stuff you should downgrade to 2.4.2

18:15 hopefully 2.4.4 comes out soon

18:15 (and fix that issue)

18:17 tadni_: Hrm, keep getting "(Could not transfer artifact clojure-complete:clojure-complete:pom:0.2.3 from/to central (https://repo1.maven.org/maven2/): java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty)" when I try to run ./lein

18:17 Then it warns "This could be due to a typo in :dependencies or network issues. If you are behind a proxy, try setting the 'http_proxy' environment variable."

18:18 justin_smith: hrm - do you have any already-created lein project on disk?

18:18 if not, maybe clone a simple clojure project from github, and run "lein deps" from inside that

18:18 I think this is related to the other "no project" bugs

18:19 tadni_: justin_smith: This is a brand new install of the distro Arch/Parabola, I'm going to use for teaching/learning clj specifically.

18:19 justin_smith: OK

18:20 tadni_: https://github.com/flatland/useful clone this distro and try running "lein deps" inside the top level directory

18:20 tadni_: justin_smith: Lein's not even installed, I'm trying to run to build script from it.

18:20 justin_smith: right

18:20 it installs intsefl

18:20 *itself

18:20 ahh!

18:20 don't run the build script

18:20 run lein.sh (rename it to lein)

18:20 it is a dependency manager, it installs itself from that script

18:20 or runs if the deps are there

18:21 tadni_: justin_smith: What I installed is just "lein" and it told me to chmod it to a+x and ./lein.

18:21 justin_smith: so just put the lein script on your path and go

18:21 tadni_: What I downloaed*

18:21 justin_smith: ahh, OK

18:21 so yeah, put it in a directory in your $PATH

18:21 and then run "lein deps" from inside that flatland repo

18:21 johnwalker: tadni_: are you really on parabola ?

18:21 tadni_: johnwalker: Yes?

18:21 johnwalker: thats cool :)

18:22 justin_smith: tadni_: I was thrown off by you calling it a build script: it is a bootstrapping dependency manager, but the installation process does no building

18:22 tadni_: johnwalker: I was on the GNU Distro alpha for awhile on this box, but I didn't have the patience to package openjdk and related stuff, for Clj. :^P

18:23 justin_smith: tadni_: I find 2.4.3 issues that hit new users especially embarrasing - usually lein is one of the things about clojure I would be most proud of

18:28 tadni_: justin_smith: Well, "lein" script is now in /usr/local/bin ... which is in my path, but same error.

18:28 justin_smith: did you run it from inside a project directory?

18:29 tadni_: justin_smith: Ah, nope. Should I just search for projects on github?

18:29 justin_smith: I gave you a link for a good one above

18:29 https://github.com/flatland/useful

18:29 tadni_: justin_smith: Ah, sorry.

18:29 justin_smith: it's code worth reading to learn clojure also :)

18:29 contributions from many of our friends here on this channel

18:34 tadni_: justin_smith: Um... same error.

18:35 * tadni_ goes to his other box and sees if he has this issue on Fedora.

18:38 tadni: It's worked without fail on Fedora. Odd.

18:38 Well if I can't figure it out on Parabola, I guess I'll put Fedora on that box too.

18:39 justin_smith: that's weird

18:39 what it should be doing as it starts running is downloading a bunch of jar files into ~/.m2/repository

18:43 tadni: Welp, lein depends aborts on my Fedora box when I try to grab depends for useful. http://paste.lisp.org/display/143639

18:44 justin_smith: weird

18:45 technomancy: hyPiRion: either of you care to see what is going on here? I tried to make some common sense suggestions, but this looks weird

18:45 tadni: those guys actually work on lein

18:45 hyPiRion: tadni: how did you install lein?

18:46 prc: tadni there is a workaround posted here: https://bugzilla.redhat.com/show_bug.cgi?id=1063457 it worked for me

18:46 tadni: hyPiRion Via installation instructions on lein's site. Grab the raw github file, put it in ~/bin, chmod it and ./lein

18:50 justin_smith: prc: that issue mentions lein 1.x, the situation is the same for 2.x?

18:52 hyPiRion: tadni: could you try with the script at https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein ? Because I would be surprised if lein doesn't contain all its dependencies.

18:52 tadni: So I deleted ~/.lein and moved the lein chmod'd script to /usr/bin/lein and ran self-install and it worked.

18:52 lein depends pulled for useful.

18:53 hyPiRion: That's the script I was using.

18:53 justin_smith: awesome - so the bad previous state may have left corrupted contents in ~/.lein maybe? I doubt putting it in /usr/bin made a big difference

18:54 tadni: justin_smith: Yeah, that's the only thing I could reason.

18:54 hyPiRion: hrm, good it works now at least

18:56 tadni: So working on my primary box, my dedicated teaching/learning box I still need to do... but I'm just going to do a minimal install of Fedora in lew of Arch/Parabola, because I know that Fedora should work.

18:58 justin_smith: tadni: well you could at least try setting aside .lein (don't delete, things in it may help discover what broke if moving it aside fixes the problem)

19:00 tadni: justin_smith: True.

19:47 gfredericks: is there a canonical sequence of colors to use in a UI where you're trying to distinguish things by color?

19:48 justin_smith: gfredericks: I don't know about that, but I do know that there are guides to making color themes that are less ambiguous to people with r/g color blindness

19:48 http://dcp.ucla.edu/2011/04/tips-and-tools-for-creating-accessible-color-schemes/

19:49 gfredericks: colors are impossible

19:52 clj-learner2: why cant i (peek (range (rand-int 20)))?

19:52 gfredericks: ,(peek (range 5))

19:52 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack>

19:52 gfredericks: ,(doc peek)

19:52 clojurebot: "([coll]); For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil."

19:52 gfredericks: "list" is apparently the stricter definition here

19:54 clj-learner2: ok, so there's no way to peek a lazyseq

19:54 gfredericks: well first would do the same thing, no?

19:55 justin_smith: it's slightly odd that it is implemented for list but not lazy-seq though

19:55 gfredericks: are there any other major differences?

19:55 between lists and lazy seqs

19:56 I feel like there might be but can't think of any

19:56 justin_smith: besides the obvious one?

19:56 maybe it has to do with conj

19:56 gfredericks: right

19:56 conj does the same thing

19:56 ,(conj (range 3) 4)

19:56 clojurebot: (4 0 1 2)

19:56 justin_smith: you can't make a lazy seq with conj, I don't think

19:56 gfredericks: ,(conj '(0 1 2) 4)

19:56 clojurebot: (4 0 1 2)

19:56 justin_smith: ,(type (conj (range 3) 4))

19:56 clojurebot: clojure.lang.Cons

19:56 gfredericks: lazy seq feels less like a proper data structure in some ways

19:57 justin_smith: ,(type (rest (conj (range 3) 4)))

19:57 clojurebot: clojure.lang.ChunkedCons

19:57 gfredericks: ,(pop (conj (range 3) 4))

19:57 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IPersistentStack>

19:57 justin_smith: see, not a lazy seq any more

19:57 gfredericks: ,(first (conj (range) 4))

19:57 clojurebot: 4

19:58 justin_smith: oh - so the lazy seq is hiding in there somewhere obviously

19:58 nollidj: i've been out of the loop for clojure dev on emacs for a while. after updating packages, nrepl says it's version 20130919.757. has something supplanted it?

19:58 gfredericks: cider

19:58 justin_smith: nollidj: hypothetically, 0.7.0 is the stable cider version

19:59 nollidj: is that hypothetical because i should be running from HEAD?

19:59 amalloy: gfredericks: lists are counted, is the main difference

19:59 justin_smith: it's hypothetical because I don't know how much about cider is actually stable

20:00 nollidj: so is this a case of, nrepl is old and may not work, cider is new and may not work?

20:00 gfredericks: amalloy: ah hah I knew there was something

20:00 justin_smith: nollidj: I wouldn't run cider from head, it breaks pretty frequently

20:00 amalloy: i guess, more general than counted, is that they are concrete and finite

20:00 justin_smith: nollidj: nrepl is old, but it still works

20:00 gfredericks: amalloy: any good reason for p{op,eek} to fail on seqs?

20:00 justin_smith: nollidj: hell, even slime (even older) still works

20:00 amalloy: nothing brilliant that i'm aware of

20:00 nollidj: yeah, i used slime. nrepl-jack-in is nice, and i'm hoping that it will still work okay

20:01 amalloy: it means pop/peek can be fast, though, just going straight through IPersistentStack instead of having to seq

20:01 justin_smith: I still use nrepl

20:01 amalloy: (and you don't have to implement pop/peek for all sequences either)

20:01 justin_smith: ls

20:01 lazybot: bin boot dev etc home root

20:01 gfredericks: oh the "guaranteed to be fast" aspect is interesting

20:01 since it could be arbitrarily slow on a lazy seq of course

20:02 justin_smith: gfredericks: light bulb went off, I think that's it

20:02 gfredericks: clj-learner2: ^ in case you weren't following

20:02 nollidj: i guess i'll stick with nrepl until something stops working, then

20:02 thanks

20:03 justin_smith: in my experience nrepl works fine with 1.6, i haven't tried clojure 1.7 yet though

20:03 clj-learner2: gfredericks, thanks

20:07 gfredericks: construct a directed graph from vertices (range 2 n) where (a,b) is an edge if a divides b

20:08 for what n is the graph planar?

20:11 * gfredericks starts drawing

20:12 justin_smith: gfredericks: there is a path addition method, and a vertex addition method

20:12 you could probably iterate them in clj even

20:13 (said methods are for determining if a graph is planar - you could do a loop that keeps adding the edges and the appropriate vertexes until you are no longer planar)

20:13 maybe drawing is simpler :)

20:13 unless we want to do general "iterate until no longer planar" problems

20:14 gfredericks: justin_smith: "path addition" == "edge addition"?

20:15 justin_smith: it's from Hopcroft and Tarjan

20:15 http://en.wikipedia.org/wiki/Planarity_testing#Algorithms

20:15 http://dl.acm.org/citation.cfm?doid=321850.321852

20:16 "An ALGOL implementation of the algorithm succesfully tested graphs with as many as 900 vertices in less than 12 seconds." lol

20:20 gfredericks: I think I've got up to 16 by hand

20:20 oh 17 is free

20:24 so far: http://upload.gfredericks.com/tmp/divisors.png

20:25 justin_smith: you can reposition 9 to make 18 work, I suspect

20:30 gfredericks: yeah I got 18

20:30 20 looks possible but so much dragging would have to happen...

20:33 oh nauty comes with a planarity test; I should just use that

20:43 you can do up to 23; 24 breaks it

20:44 too many dang divisors

21:15 clojer: I have an Om/Weasel project open in Emacs Cider 0.7. The repl is connecting changes with the browser but nothing happens when I update the core.cljs file from which I launched cider-jack-in. I have `lein cljsbuild auto` running.

21:17 nollidj: what's the syntax now for instantiating a record? (MyRecord. fields)?

21:25 joobus: do many here use clojurescript for brower side code?

21:25 gfredericks: justin_smith: https://twitter.com/gfredericks_/status/508425098697912320

21:25 Bronsa: nollidj: (MyRecord. field1 field2 ..) or (->MyRecord field1 field2 ..) or (map->MyRecord {:field1 field1 :field2 field2 ..})

21:25 joobus: meant browser

21:26 clojer: joobus: I'm trying to work with Om, ie. clojurescript for React

21:26 nollidj: bronsa: oh, new syntax ->MyRecord. thanks.

21:26 well, not syntax. but whatever.

21:27 Bronsa: yeah it's just a regular function wrapping (new MyRecord ..)

21:29 joobus: clojer: I've written a static site generator in python that I'm now trying to port to clojure. One of the things it does is generate js from inline coffeescript. But clojurescript is different in that it requires the clojure core to compile. I was wondering if it would be worth it to try generating js from inline clojurescript in my content templates.

21:29 clojer: joobus: Sorry, but you're way ahead of me :)

21:30 joobus: clojer: not by much :)

21:30 clojer: joobus: Believe me :)

21:31 joobus: I'm struggling to get Emacs and the browser to work together so early days for my Clourescript adventures.

21:31 joobus: I have the repl half working but not recognition of file changes.

21:32 joobus: clojer: I'm a vimmer, so can't help you there :(

21:33 clojer: joobus: Tried evil-mode in Emacs? Best of both worlds.

21:34 joobus: clojer: that just sounds painful

21:34 clojer: joobus: My initial reaction but quite the opposite in practice.

21:35 catern: evil-mode++

21:57 joobus: does anyone here know how to select the meta name="description" in enlive?

21:57 something like [:meta (attr? :name)], but i don't know how to ask for name="description".

22:01 found it

22:17 sorbo_: justin_smith: thanks for your help earlier

22:17 you were right, it was a liberator thing

22:17 got it squared away

22:18 this might be more of a #ruby question, but anyone know if the rouge project is still alive? https://rubygems.org/gems/rouge-lang

22:23 clojer: sorbo_: I looked into this about 6 months ago and it seemed to be dead

22:24 sorbo_: clojer: :(

22:24 yeah, I get the same feeling

22:24 GH page is gone

22:24 clojer: sorbo_: Sad to see Python beat Ruby to it. Hy is thriving it seems.

22:25 sorbo_: clojer: yeah, for sure

22:25 I mean, I’m stoked for the Python folks

22:25 but my favorite Ruby bits are the ones it stole from Lisp

22:25 it’s a shame for a clojure + ruby project to not be reall taking off

22:25 s/reall/really/

22:25 clojer: sorbo_: I was rooting for that too.

22:26 sorbo_: Ruby seemed an ideal candidate given its Lips heritage

22:26 sorbo_: Maybe it's easier with Python's AST, however.

22:27 sorbo_: I dont thing Ruby has a compile to AST layer.

22:27 sorbo_: ... though Ryan Davis's s-expressions gems seem to be pointing in that direction.

22:28 sorbo_: clojer: interesting, I’ll take a look at that

22:30 clojer: sorbo_: Richard Verding did something similar with LFE (Lisp Flavoured Erlang), ie. manipulate Erlang's AST

22:33 oubiwann: clojer: Robert Virding ;-)

22:34 clojer: oubiwann: Thou art indeed correct ;-)

22:39 boblarrick: I feel like a complete idiot, I cannot figure out how to read a .wav file into a byte array, does anybody know of a simple example of reading a file into a byte array?

22:44 xeqi: boblarrick: https://github.com/clojure-cookbook/clojure-cookbook/blob/master/04_local-io/4-19_handle-binary-files.asciidoc

22:46 boblarrick: I read that, but it doesn't cover reading a file in, at least not one of a size greater than the 1024 buffer shown there

22:47 actually looks like http://crossclj.info/ns/overtone/latest/overtone.libs.binary-file-io.html works

22:51 joobus: Was just looking at the Hy docs. Hy (it seems to me) would still suffer from the mutability and side effects of python. Am I wrong?

22:51 boblarrick: or something close to it https://gist.github.com/deathbob/0a48901e00fd747cc098

22:51 joobus: Other than prefix notation and parens, I can't see what Hy offers.

22:51 * catern is interested in the answer to the question joobus asked

22:52 boblarrick: feels like an awful lot of work, is there no easier way?

22:53 john2x: hmm so calling `cider-eval-defun-at-point` in a `(ns ...)` form doesn't eval the `:require` forms in it?

22:54 I had to eval the :require form separately to be able to eval another form which uses the required namespace.. is this intended?

23:48 oubiwann: joobus, catern: yeah, Hy still has Python's mutable data

23:48 Paul is working on possible solutions for immutable data in Hy, though

23:49 he's a huge fan of Clojure and is deeply aware of the benefits of such

Logging service provided by n01se.net