#clojure log - Apr 02 2013

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

0:00 n_b: fbernier: It's a threading macro. The documentation explains it better than I could

0:00 ,(doc ->>)

0:00 clojurebot: "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc."

0:01 n_b: Essentially it takes each form and recursively inserts it as the last argument into the next form

0:43 Raynes: jhn: Psh, technomancy resolved it. You just poked it. Braggart.

0:48 technomancy: eh?

0:48 the clojure-test-mode thing? I don't think I actually fixed anything.

0:49 jhn: Raynes: lolwut. Someone else PM'd me after seeing that and I just pointed him to technomancy's instructions on the repo.

0:50 Raynes: technomancy, jhn: I was trying (and apparently failing) to tease jhn about a tweet he made a few minutes ago.

0:53 technomancy: I see

1:20 john2x: can I use clojure libraries in clojurescript?

1:24 scottj: john2x: generally not unless they've had (often minor) tweaks applied to make them compatible, afaik

2:13 john2x: scottj: oh ok. does clojurescript have its own repo for libraries? I wanna check out the ecosystem.

2:14 or does it also use clojars.org?

2:23 scottj: john2x: idk, some are on clojars, here's my personal non-exhaustive list: http://jaderholm.com/paste/projects-cljs.html

2:57 john2x: scottj: thanks!

3:24 Raynes: My internet is so fast.

3:24 When I started writing Clojure it was on a dialup connection.

3:25 rcg: Raynes, that makes clojure actually sound much older than it is ;)

3:26 Raynes: Yeah, I was just in a very rural area and uneducated about mobile broadband.

3:28 rcg: aye, well nonetheless fast internet is a pleasure

3:30 wink: extra-lazy-seq

3:50 tomoj: no, of course it won't work to special case (bound-fn [*vars* *i* *need*] ...) !

3:50 :(

4:01 maybe we just need to rewrite clojurescript.test so that it doesn't use any dynamic vars..

5:06 supersym: clojure is such a nice vehicle as it gives me many little epiphanies ... all roads eventually would lead to a lisp anyway, if you care about your programming I guess :)

5:08 but the shift in thinkin it requires coming from imperative world to functional and then what it gives back... wooa ^^

5:08 anyway preaching to the choir

5:09 andyfingerhut: and as is often the case, much of the choir is sleeping :)

5:22 kalasjohnny2000: ...fanfares in the distance

8:08 supersym: andyfingerhut: yeah lots of USA people I bet :P

8:13 why is that anyway, or is it my impression, that many in the Clojure world are native Americans?

8:13 questions, questions, too many to answer but internet helps :)

8:14 hyPiRion: supersym: it's not your imagination

8:22 supersym: is there a general consensus on the matter? surely people must have spoken about this before

8:22 clojurebot: min people is 5

8:23 hyPiRion: well, it's true that the majority are American, but what is there to talk about, really?

8:25 supersym: lol

8:25 * hyPiRion shrugs.

8:25 supersym: oh nothing I just thought there would be an underlying linguistical nature to it...of course it could also be coincidence :D

8:25 never mind hehe

8:25 hyPiRion: Certainly I'd like to have more Norwegians using Clojure, but I'm not sure how to do that.

8:26 supersym: I'll be a good boy and go back top work

8:26 hyPiRion: Most certainly it's because Rich is living in the US himself

8:26 supersym: thats what I thought also

8:26 hyPiRion: Language is used by people he knows, and the people who know them uses it etc.

8:27 supersym: so it spreads

8:27 Python was made by a dutch guy

8:27 so they teach it at uni here because of that?

8:27 Perhaps...

8:27 hyPiRion: supersym: Well, they have it over here too. It seems like Python is very well established in Europe

8:28 then again, Python is an old language compared to Clojure

8:28 supersym: yeah

8:28 mpenet: there are quite a few clojure users in EU, it's mostly concentrated in the UK and around Germany it seems

8:28 supersym: and like you said, it has to spread too

8:28 mpenet: but not a lot of them are often on irc, this might give you the wrong impression

8:29 supersym: I'd say

8:30 hyPiRion: mpenet: Also, since I a messed up circadian rythm, I may end up speaking with more americans simply because Europeans aren't generally awake at that time :p

8:30 /s/I a/I have a/

8:30 supersym: ruby probably is more popular in Japan than here

8:30 mpenet: same here :p

8:39 ebaxt: hyPiRion: With regards to getting more Norwegians using Clojure. we need success stories and people talking

8:46 hyPiRion: ebaxt: at Java conferences, or other places? (e.g. JavaZone)

8:47 ebaxt: hyPiRion: JavaZone, NDC, meetups etc. But more importantly we need examples to point to in order for larger enterprises to not shoot down the idea of using it

8:48 hyPiRion: ebaxt: ah, okay

8:49 ebaxt: hyPiRion: Just look at Scala, there are plenty of companies using it in Oslo. Conferences like flatmap is also important

8:51 hyPiRion: ebaxt: Right, what I wonder about is whether the gap is too large (oh lord, parentheses, functional programming, immutability) to just jump from Java directly to Clojure

8:52 Scala is less frightening in that sense

8:52 Certainly, success stories is great, but I wonder if that's enough to pull the enterprise that way

8:54 ebaxt: hyPiRion: Sure, that's true, but the Scala community has done a good job of marketing specifically to the enterprise as well.

8:56 no7hing: concerning cheshire, why does this (parse-string "{\"jsonrpc\":\"2.0\",\"result\":\"{}\",\"id\":null}}" true) result in {:jsonrpc "2.0", :result "{}", :id nil} ?

8:56 aka the map stays a string?

8:56 jcrossley3: ebaxt: it's not just marketing. java devs *really* value strong type-safety.

8:57 mpenet: no7hing: it's not a string anymore, look at the keys

8:57 hyPiRion: jcrossley3: Well, I think that really depends on the developer. I don't think that many people think that hard about it

8:57 no7hing: @mpenet: i would expect :result to be {} and not "{}"

8:57 mpenet: oh, "result"

8:58 because it's passed as a string in it's json form

8:58 "{\"jsonrpc\":\"2.0\",\"result\":{},\"id\":null}}" would work

8:58 there is no quote on object litterals in json

8:58 no7hing: oh damn

8:58 sorry me

9:00 jcrossley3: hyPiRion: i'm constantly surprised by it, too.

9:01 hyPiRion: ebaxt: Oh, I forgot to reply. True, the Scala guys are really awesome at marketing their language. Clojure (the community, perhaps?) could be better at that.

9:01 ebaxt: jcrossley3: I think there are plenty of programmers working in large enterprises that would love using a more expressive language, not necessarilly strongly typed. I know of many companies using more and more Groovy for instance.

9:02 jcrossley3: ebaxt: i agree strongly, but it's been my experience that the ones who value the tooling that strong-typing affords them are way more vocal.

9:03 ebaxt: jcrossley3: That's my experience as well. Which is why I think it's important that we speak up as well ;)

9:03 mpenet: I doubt clojure will ever reach as much popularity as scala, its the syntax and mix oo/fp that makes it easier at the beginning and often more appealing to java devs

9:04 imho

9:04 lucian: jcrossley3: if java devs really valued type safety, they wouldn't be using java :)

9:05 jcrossley3: lucian: s/type safety/tooling/ :)

9:06 hyPiRion: lucian: Haskell to the rescue!

9:06 lucian: hyPiRion: sure, that's what they'd use if they really cared :)

9:06 scala isn't that far off, the syntax is just crazy

9:06 ebaxt: mpenet: I think there is a niche market for Clojure in the enterprise, but I agree that Scala has the "advantage" of OO that makes it less scary.

9:06 lucian: i think it's purely syntax

9:07 people hate python for similar reasons

9:10 hyPiRion: lucian: hm, is the enterprise hating python? I must be in this parallel universe then.

9:10 lucian: hyPiRion: i meant it as an initial reaction

9:10 hyPiRion: oh, okay

9:11 mpenet: same problem with erlang, it solves some problems beautifully, but it's scary to the newcomers

9:12 lucian: to be fair, erlang's syntax is just stupid

9:12 hyPiRion: lucian: well, that's subjective, isn't it? :)

9:12 lucian: hyPiRion: not at all

9:13 it has different terminators for the same thing in different contexts!

9:13 good luck swapping two lines

9:13 Pupnik: lisp flavoured erlang to the rescue!

9:13 lucian: elixir is particularly nice

9:14 hyPiRion: mpenet: Erlang has a very steep learning curve if you want to build an OTP-compliant app from the beginning

9:14 * hyPiRion can confirm this.

9:17 hyPiRion: I think Rich had it right when he came up with the simple/easy difference. People really value something which is easy at first sight, and aren't usually able to see (or value) the productivity of something on a longer time scale.

9:18 mpenet: about clojure, I just encountered this issue: having to handover a clojurescript app to a js/frontend developer. I could read "omg" in his eyes when he opened the source the first time. and to be honnest this is a real issue with clojurescript at least.

9:18 borkdude: is there a way to do (binding [*foo* bar] (some expr) (some other expr)) in the REPL, so I can do (some expr) and see what it returns, step by step, so not in all one binding expression?

9:18 mpenet: on the backend it's another story

9:19 lucian: mpenet: the other problem is the silly dependency on the jvm :(

9:19 mpenet: lucian: you mean for clojurescript?

9:19 lucian: yes

9:19 well, for clojure too

9:19 but it's a bit more forgivable there

9:20 mpenet: lucian: well without it, no google closure

9:20 lucian: don't care much about that

9:20 mpenet: lucian: you should, unless you want to serve mb of js files

9:20 lucian: at least not early in development

9:20 having to wait for the stupid jvm to spin up every single time i want to do something with lein is infuriating

9:20 that's why i always give up on trying to use clojure(script)

9:21 mpenet: lucian: lein cljsbuild solves that pretty much

9:21 lucian: language is nice, but the runtime is fucking useless

9:21 mpenet: lucian: or repl dev

9:21 lucian: mpenet: not really

9:21 mpenet: lucian: I find it fast enough in most case

9:21 lucian: it takes more than 2sec to start up, always

9:21 python takes a few ms

9:22 mpenet: lucian: you just start it up once, "lein cljsbuild auto"

9:22 lucian: right, and it takes about 10sec to start up once

9:22 and several seconds to notice it has to compile things

9:22 hyPiRion: lucian: You may want to watch out for https://github.com/halgari/clojure-metal

9:22 mpenet: lucian: yeah but once a day, it's fine, eclipse probably takes longer to launch :p

9:22 lucian: hyPiRion: i'd be happy with self-hosted clojurescript

9:22 Pupnik: lucian, use clojure-clr instead?

9:22 lucian: mpenet: that's another thing i don't use because of latency

9:23 mpenet: lucian: I dont use eclipse either, but this was an example, 10secs in a day is nothing

9:23 lucian: Pupnik: is that still alive? i thought it had bitrotted

9:23 mpenet: it is if the alternative is 0sec

9:23 hyPiRion: lucian: well, when we get it up to production value, I'll certainly start to port Lein over

9:23 lucian: hyPiRion: that would make me very, very happy :)

9:24 as for a clojure vm, i think a RPython one would have a better chance of actually making it

9:24 Pupnik: lucian, https://github.com/clojure/clojure-clr/commits/master plenty of stuff going on

9:25 hyPiRion: lucian: right, a restricted clojure vm?

9:25 or, a subset of clojure?

9:25 lucian: hyPiRion: one built on RPython? no, it'd be a full vm, with a jit for free

9:25 if someone were to build such a thing

9:26 Pupnik: that's nice. i guess mono's startup time is not as terrible

9:26 hyPiRion: lucian: Timothy already did some stuff on top of pypy

9:27 (halgari or tbaldrige, or what he goes by these days)

9:27 blrm: https://github.com/halgari/clojure-py

9:28 lucian: that is probably an easier path, since there already is a Python VM written in RPythonn (PyPy)

9:29 there are basically two things i'd like to use clojure for: 1) replacing javascript and 2) replacing java on android

9:29 the first will be easy when clojurescript is self-hosted

9:29 the second, i don't know. clojure bootstrap on android still takes many seconds

9:30 hyPiRion: lucian: Given you do no eval/resolve/etc, and perform some tree shaking, that shouldn't be impossible if one tweak AOT compilation.

9:31 But that's has a long way to go, sadly.

9:31 lucian: hyPiRion: the latest effort i've seen is http://nightweb.net/

9:31 but even on my nexus 4 it takes 5-10s to start up

9:31 at this point, xamarin or scala are still the only other options i consider reasonable for android dev

9:32 hyPiRion: heh

9:34 qz_: lucian: scala suffers from same startup time problems plus slow compilation :)

9:36 lucian: qz: the few android apps i've seen appear to start up fast enough

9:39 borkdude: ,(apply map vector nil)

9:39 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$map>

9:40 borkdude: is this sane behavior?

9:42 hyPiRion: borkdude: yes

9:43 ,(map vector) ;; is essentially what you do

9:43 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$map>

9:43 borkdude: (apply + [1 2 3]) == (+ 1 2 3), (apply + nil) == (+ … well, nothing to see here?) like that?

9:44 hyPiRion: right

9:45 ,[(apply map vector nil nil) (apply map vector [[]])]

9:45 clojurebot: [() ()]

9:48 borkdude: what is the reason again why you have to define clojure functions in a certain order? (not that I have problems with it, but before I get questions)

9:49 asteve: ,(/ 3 1)

9:50 clojurebot: 3

9:50 asteve: ,(/ 1 3)

9:50 clojurebot: 1/3

9:54 scottj: borkdude: I thought the reason was clojure compiler is single pass, but the actual reason might be more subtle.

9:57 noidi: borkdude, https://news.ycombinator.com/item?id=2467359

10:00 borkdude: noidi thanks

10:09 `fogus: scottj: Clojure's compiler is not single pass

10:10 * `fogus realizes too late that the HN link says as much

10:24 devn: good morning all

10:25 rbxbx_: devn g'morn

10:27 Guest98868: is there an idiomatic way to use a different kind of equality? my first thought was to rebind =, but it's not declared dynamic. but defining some protocol or other function wouldn't be used by say (some #{foo} [bar baz])

10:33 sundbp: anyone using expectations for testing around?

10:40 gfredericks: Guest64100: changing the meaning of clojure.core/= would be pretty nonstandard. Changing the meaning of the = symbol inside of some namespace or lexical scope is totally possible

10:41 danielglauser: gfredericks: I saw a presentation that showed you could do anything with macros

10:43 * nDuff notes the distinction between "could" and "should". :P

10:45 gfredericks: danielglauser: I think I specifically pointed out this sort of thing as an example of what you can't do with macros

10:45 borkdude: question: I guess (if … (swap! …)) is not good, since between the calculation of the conditional and the swap, some other swap might have happened. what is the common way to solve this?

10:46 (swap! (if … ….)) ?

10:46 danielglauser: gfredericks: I know, just razzing you :)

10:46 gfredericks: borkdude: wat?

10:47 borkdude: the conditional is based on the value of the atom?

10:47 borkdude: borkdude yeah

10:47 gfredericks yeah

10:47 gfredericks: borkdude: then you do that logic inside the swap function

10:47 borkdude: example:

10:47 gfredericks: (swap! a #(if (foo %) (bar %) (baz %)))

10:48 borkdude: gfredericks this is not good, I should have used swap! anyway: https://github.com/borkdude/tictactoe/blob/master/src/tictactoe/model.clj#L29

10:48 gfredericks this is how I've done it now https://gist.github.com/borkdude/5292814

10:49 gfredericks play! is near the bottom of the file now

10:52 gfredericks in this case it doesn't matter much, because the session is updated within one thread, but in general

10:52 gfredericks it would mean though, that a swap would always happen, either with a new value or the old value just gets stored back

10:53 gfredericks: I think that's fine

10:54 borkdude: gfredericks what, that a swap would always happen?

10:55 gfredericks: yeah

10:55 though if this is all single-threaded, maybe an atom isn't what you want to be using

10:56 borkdude: gfredericks I'm using noir.session

10:56 gfredericks and that is using an atom

10:56 gfredericks: oh right

10:56 nm then

10:56 borkdude: gfredericks what alternative would you have in mind? I used an atom before I made this a web app

10:57 gfredericks: hwelp if you have some "state" you could just write functions that transform it. I guess it's the state monad really.

10:57 er, burrito

10:58 borkdude: gfredericks the web app monad - I could do it, but I'd have to trust the user not to manipulate his data ;)

11:00 gfredericks I could also use ring sessions which are more functional, but I doubt if that would make this better

11:23 TimMc: borkdude: That's what cryptography is for.

11:24 gfredericks: well there's two "non-stateful" approaches to session middleware

11:24 one is to put all the data in the cookie which I imagine is what you're referring to

11:24 TimMc: Maybe you should thread the entire database state through all requests.

11:24 gfredericks: the other is to have server state, but handle it all in the middleware so that the actual ring handler doesn't need to do any side-effects -- it receives the current session as part of the request map and can change it in the response map

11:25 * TimMc mutters something about the eventually-consistent state monad as he is carted off to the psych ward

11:26 borkdude: gfredericks I think I have used the latter one. but how is the first not stateful?

11:26 gfredericks: haha

11:26 borkdude: not stateful from the server's perspective

11:26 borkdude: gfredericks I haven't used it now, but some other time

11:26 gfredericks right

11:27 gfredericks other way would not to use cookies but codify the state in some hidden field in the form

11:30 gfredericks I think Microsoft does this in ASP.NET or smth

11:36 TimMc: It's really irritating.

11:36 mpenet: borkdude: they call that PageState... heretics. You used to end up with 100s of KBs of pagestate per page on some apps.

11:36 TimMc: As a user, that is.

11:37 borkdude: mpenet In my memory they called it ViewState but they might have changed it

11:37 mpenet: right

11:37 TimMc: Death to timestamps.

11:38 (It really bugs me when a form submission becomes invalid just because I let the page sit open too long.)

11:38 Never mind, that can actually be an issue where ever the state is kept, if it expires.

11:38 geckos: What the last dot means at (java.util.Date.)

11:38 ?

11:39 borkdude: geckos creation

11:39 geckos calling the constructor

11:39 geckos: borkdude: thanks

11:39 nDuff: geckos: It's syntactic sugar for (new java.util.Date)

11:59 squidz: cemerick: i'm using youre shorleave remote libraries and currently have the problem of returning a javascript array from one of the remote functions. Do you know an easy way to do this? For example, my remote funciton returns a list of strings ("first "second) and when I call that remote clientside, I want to be able to get a javascript array ["first" "second"]

12:00 geckos: nDuff: I see... thanks again.. I'll stay with new aproach since I'm not an cloj guy, :-)

12:00 squidz: i mean ["first", "second"]

12:09 * ticking lol, I just read, "Open-Source is a philosophy not a checkbox" online and Immediately thought of Clojure.

12:10 ticking: clojures contribution policy is like a open halway, stuffed with barbwire, in thereory you can get to the end

12:13 joegallo: ticking: right, it'll tear the very meat from your bones, but you can get there in theory ;)

12:14 nDuff: Not so annoying for anyone who attends the conferences -- CAs sitting out ready to sign.

12:15 joegallo: the CA is just the moat, though, there's more stuff after that

12:21 technomancy: a miniboss

12:34 gfredericks: I wonder what the clochure contribution policy is like

12:34 technomancy: (constantly :rofl)

12:34 I was hoping to get some good joke pull requests for lein-xml

12:35 maybe someone all "XML is too strict; can we use SGML instead?"

12:35 joegallo: damn, that would have been a good one

12:35 i'm sorry, technomancy

12:36 technomancy: there's always next year

12:36 Foxboron: technomancy: i am still not sure if lein-xml was a april fools or not ._.

12:37 hyPiRion: lein-png: Whenever you need to ensure that project.clj is syntax highlighted the same on all machines.

12:37 project.png

12:38 gfredericks: need to make a change? photoshop has never been more user

12:38 friendly

12:38 technomancy: hyPiRion: lein-piet

12:38 hyPiRion: technomancy: hah, that would actually be fancy

12:39 It's rather simple too, so why not

12:39 well, easy*

12:40 technomancy: hyPiRion: well, you have twelve months now =)

12:40 hyPiRion: Foxboron: After the survey, we found out that many people use Java or Java+Clojure with Leiningen, and since it's usually common to use XML (maven uses it, etc) we figured out that it would make sense to use xml for lein

12:40 gfredericks: xmleiningen

12:41 hyPiRion: It's a plugin for now though, since it breaks compability.

12:41 jeremyheiler: I woudln't be surprised if someone successfully uses it as leverage to get Clojure into their shop. "See, we can even use the our existing pom.xml!"

12:41 Foxboron: hyPiRion: and the 1st of april date was not planned at all :P?

12:42 technomancy: jeremyheiler: I almost put a note saying explicitly that pom.xml syntax was not the goal, but I thought it might make it look too realistic.

12:44 jeremyheiler: technomancy: Haha.

12:47 tupi`: hello

12:54 i am making my fisrt steps using clojure to build small scripts using imagej/fiji anyone here is also doing digital image processing in imagej/fiji and clojure? is this a chat room i can ask Q related to this specific clojure useage?

12:55 nDuff: tupi`: We may not know the library, but we still may be able to answer questions about problems you're having.

12:55 hyPiRion: technomancy: Well, better start today then: https://github.com/hyPiRion/ariel

12:55 tupi`: nDuff: thanks

12:57 i have one Q to start width. please note that i am an experienced lisp/scheme programmer, but no java knowledge at all, so i suffer a lot :)

12:57 technomancy: hyPiRion: fun times

12:57 tupi`: also, fiji says they use clojure 1.3, this could be a problem i guess. here the Q:

12:57 hyPiRion: tupi`: You don't suffer, you're free from the chains man

12:59 tupi`: suppose i do (import ... '(ij Menus)) then (let [commands (keys (. Menus getCommands)) ..

12:59 it works, but this does not:

12:59 (let [commands (keys (.getCommands Menus)) ...

12:59

12:59 and i am particularly interrested in the lisp-ish way of writting code

12:59 dnolen: lynaghk: http://trifacta.github.com/vega/

13:00 nDuff: tupi`: Sounds to me like getCommands is a static method, no?

13:00 (Menus/getCommands)

13:00 ...if that is in fact the case.

13:00 tupi`: checcking

13:01 it says it's in static java.util.Hashtable

13:01 nDuff: Not its return value, the method itself.

13:01 tupi`: public static java.util.Hashtable getCommands()

13:01 nDuff: Exactly. So it's the syntax I gave earlier, (Menus/getCommands)

13:02 tupi`: http://clojure.org/java_interop#Java Interop-(Classname/staticMethod args*)

13:03 tupi`: ah: this clarifies, tx

13:05 lynaghk: dnolen: yeah, I saw that on the twitters this morning; Jeff and I talked about it briefly at VisWeek last fall---that kind of thing is in the air

13:05 dnolen: visualization + data all the thigns, I mean =)

13:21 tomoj: cemerick: saw your post about async testing for clojurescript.test -- given the lack of bound-fn in cljs, would we need to eliminate all dynamic vars, including the proposed *done*?

13:30 alternatively, people will need to manually carry those vars over any async boundary in the code under test? hoping I'm confused..

13:31 steves-erc: Is there a modulus relation in clojure.core.logic.fd or does anybody know how you would make one?

13:32 tupi`: i am very suprised and curious to read, for example, the setForeground java manual, where it says public synchronized void setForeground(Color c), where i'd expect 2 parameters. in my little test code i did try and replaced a (doto blabla (.setForeground (Color/red) by (.setForeground blabla (Color/red)) and it works [of course]. so how do i know the exact parameters i nedd to pass to write lisp-ish code?

13:33 [i realize it's a java quiz but...]

13:37 dnolen: steves-erc: there's isn't one

13:38 tupi`: i mean may i assume that the doto macro always expands its code inserting the instance-expr as the first arg of all expressions ?

13:38 technomancy: tupi`: no need to assume; try it with macroexpand-1

13:39 dnolen: steves-erc: http://www.swi-prolog.org/man/clpfd.html, supported by SWI so we should probably consider it.

13:39 technomancy: ,(macroexpand-1 (doto 'my.namespace (require) (in-ns) (prn)))

13:39 clojurebot: #<FileNotFoundException java.io.FileNotFoundException: Could not locate my/namespace__init.class or my/namespace.clj on classpath: >

13:39 tupi`: technomancy: of course! tx

13:39 technomancy: oops

13:39 ,(macroexpand-1 '(doto 'my.namespace (require) (in-ns) (prn)))

13:39 clojurebot: (clojure.core/let [G__74 (quote my.namespace)] (require G__74) (in-ns G__74) (prn G__74) ...)

13:40 saolsen_: dnolen: would it be some recursive thing with *?

13:43 S11001001: ,java.awt.Color/red

13:43 clojurebot: #<CompilerException java.lang.ExceptionInInitializerError, compiling:(NO_SOURCE_PATH:0:0)>

13:45 hyPiRion: ,(import java.awt.Color)

13:45 clojurebot: #<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.awt.Color>

13:46 dnolen: saolsen_: no it probably be preferable to provide an optimized version of some kind. opened a ticket - http://dev.clojure.org/jira/browse/LOGIC-128

13:48 saolsen_: dnolen: cool

13:52 cemerick: squidz: use clj->js

13:53 squidz: cemerick: okay thanks ill give it a try

13:55 cemerick: tomoj: I don't know. That whole topic is entirely theoretical to me at the moment, so heft that salt liberally.

14:08 technomancy: has anyone experimented with a transactional require?

14:10 gfredericks: technomancy: environment as a value?

14:10 wouldn't that require being able to unload code?

14:11 technomancy: gfredericks: not if the ns map was a ref, I think?

14:11 gfredericks: so we're at _least_ hoping there aren't top-level side effects

14:11 * gfredericks dares not mention defonce

14:12 technomancy: gfredericks: of course; you can easily break transactionality in any ref if you do something stupid

14:13 I don't think defonce would be hard though

14:13 oh yuck; it's all jabba code

14:13 gfredericks: (defmacro deftwice ...)

14:13 technomancy: lol

14:13 yeah, so mappings in Namespace.java is just an AtomicReference

14:14 if I knew Java maybe that could be a seajure hack

14:15 gfredericks: if you're not using your own fork of clojure you're not doing real work

14:15 technomancy: srsly

14:16 gfredericks: porting the java code to scala could have been a decent project for yesterday

14:16 or groovy?

14:16 nDuff: *shudder*

14:16 gfredericks: Scala, please. Groovy is awful.

14:17 cemerick: technomancy: not for long; the happy path is straightforward. The further you stray from that, the more it's like swiss cheese.

14:17 gfredericks: ok groovy it is.

14:17 nDuff: gfredericks: ...if you don't grok _how_ awful, take a look at the bytecode it generates.

14:17 gfredericks: nDuff: I've never even used it

14:17 nDuff: gfredericks: ...it's reflect-o-riffic; makes sloppily-written Clojure look like the pinnacle of efficiency.

14:18 technomancy: cemerick: sorry, I don't follow; you're talking about side-effects at the top-level?

14:18 gfredericks: I also was wondering what cemerick was talking about.

14:19 cemerick: I was responding to technomancy's original question as to whether anyone's experiemented

14:20 gfredericks: "straightforward" meaning "using clojure the normal way"?

14:21 cemerick: gfredericks: "if you're careful"?

14:21 straightforward to replace the atomic references with refs

14:22 of course, you have a serious bootstrapping problem, so you have to use clojure to load an alternatively-rooted clojure

14:22 gfredericks: cemerick: okay I think I totally misparsed the sentence

14:22 as "Going straight-forward is the only happy path."

14:23 do not go left or right.

14:23 cemerick: otherwise, you'll only ever end up right where you began, eventually

14:23 gfredericks: random walks in >2 dimensions don't return

14:24 cemerick: pay me no mind, I'm trying to pick up the pieces of my life after trying vim seriously this morning

14:25 * casion consoles cemerick

14:25 Glenjamin: does one of these bots have a "tell <someone> <message>" feature?

14:26 Raynes: Yes.

14:27 $mail amalloy Hi. Now you have to read your messages.

14:27 lazybot: Message saved.

14:27 amalloy: $timer 1 0 0 Raynes, you're a jerk

14:27 lazybot: Timer added.

14:28 gfredericks: amalloy: slingshot seems to like the &naming-convention with their &throw-context

14:28 Raynes: Glenjamin: So $mail person message and then that person gets a NOTICE every so often that they can run $mail to get their messages.

14:28 gfredericks: amalloy: is it gross for an anaphoric macro to check if &foo is used in the body and not bother to set it up otherwise?

14:28 `arrdem: hum... can anyone tell me why nrepl is vomiting on this deftype? https://www.refheap.com/paste/13215

14:29 Glenjamin: ah cool, was expecting something that'll just fire a message next time it sees activity from that person, but that'll work

14:29 amalloy: gfredericks: for sure that is bad

14:29 Glenjamin: $mail xeqi haven't found any other bugs, should be good to release

14:29 lazybot: Message saved.

14:29 amalloy: you can't tell if some other macro inside the body will expand to include &foo, for example

14:30 gfredericks: amalloy: and it's also bad to try to macroexpand-all the body before checking?

14:30 amalloy: if you want, you can bind &foo to a delay of the expensive work, and then symbol-macrolet it to forcing the delay

14:30 gfredericks: that's kind of deferring the tactic to symbol-macrolet

14:30 Glenjamin: definterface, haven't seen that before =/

14:31 amalloy: deferring the macroexpand-all?

14:31 it is, but symbol-macrolet will do a much better job of it than you will

14:31 `arrdem: yeah it's relatively new to me as well and I've been having bad luck with it thus far

14:32 gfredericks: amalloy: you are a wise man of macros

14:34 amalloy: gfredericks: i hope to one day accumulate enough reputation as a macro wise man that someone will order me a tribal shaman mask on amazon

14:39 gfredericks: that is perhaps the most efficient way to make a tribal shaman mask show up at your door

14:44 Glenjamin: say i have a working application, that contains a protocol. And some third parties implement that protocol. And I want to add another method to it. Is there a good way to do this without breaking existing third party code?

14:51 jeremyheiler: Glenjamin: Protocols are unlike Java interfaces in that not all methods need to be implemented. So technically you're fine if you only call the new method from types that have it implemented. Are you worried about calling the new method on existing extentions of the protocol?

14:52 Glenjamin: yep

14:53 the specific case is a test runner reporter for speclj, i'm adding a new type of message

14:53 so i want to call it if it exists, but not if it doesnt

15:00 gfredericks: separate protocol maybe?

15:01 Glenjamin: yeah, thats where i'm leaning

15:01 can i extend the old one in some way?

15:02 gfredericks: nope

15:08 jeremyheiler: Glenjamin: I suppose you could use clojure.reflect on it.

15:12 amalloy: jeremyheiler: no. that is more problems than solutions (for this problem; nothing wrong with clojure.reflect in general)

15:15 jeremyheiler: amalloy: I suppose.

15:18 Glenjamin: I'll just add an extra protocol for the new method specifically i think

15:18 jeremyheiler: Glenjamin: You could create a new protocol just for the new method. I guess the solution you use depends on if you want that your code to be that fine grained, or if you eventually expect all clients to adjust. (I am assuming just changing the version number your thing is not idea.)

15:18 Heh, cool.

15:19 no ideal*

15:19 ugh. "not ideal"

15:19 Glenjamin: i'm not actually sure how many third party reporters are there so it might be as easy to just break them

15:27 lazybot: Raynes, you're a jerk

15:28 Raynes: $kill

15:28 lazybot: KILL IT WITH FIRE!

15:28 gfredericks: (inc lazybot)

15:28 lazybot: ⇒ 17

15:28 Raynes: gfredericks: I just remembered that I blew you off yesterday,

15:28 gfredericks: Raynes: laser has made me want static types

15:28 Raynes: gfredericks: Are you still having those issues?

15:29 gfredericks: I think I'll be okay now. I'm just always getting confused about when I have a node or a collection of nodes or a zipper and what I'm supposed to do in each situation

15:29 e.g., I call parse-fragment and I get a zipper I think. When I call fragment on that it turns into something else that I can't call fragment on again.

15:29 so I have to call zip to turn it back into a zipper?

15:29 I need a hoogle so I can look up the type signatures

15:30 Raynes: fragment should be returning a collection of zippers which you should be able to pass to another fragment.

15:30 gfredericks: a collection of zippers, that's the fourth type :)

15:31 Raynes: Give me a link to your code again and I'll try to simplify and explain it.

15:35 gfredericks: Raynes: https://www.refheap.com/paste/13189

15:35 my most common error is 'Not a valid node' followed quickly by NPEs

15:38 amalloy: gfredericks: i don't think you want to parse-fragment there: a fragment is a collection of nodes, and therefore has multiple "content"s

15:38 gfredericks: how do I parse a single node?

15:38 amalloy: l/parse? it's what you did with page

15:39 gfredericks: no that's for whole documents

15:39 will add <html> and such

15:39 amalloy: ugh

15:39 well, i don't actually know how to use laser

15:41 gfredericks: I got it to work by I think passing the thing from parse-fragment through the fragment function; it got harder when I wanted to prepend something.

15:41 hyPiRion: Raynes: I think that was a lazybot timer

15:42 amalloy: he knows :P

15:42 gfredericks: I've gotten to the point where I can make any given thing work by twiddling the data types hard enough, but it doesn't help me avoid the next problem, because I still don't understand what the workflow ought to be (i.e., why I keep ending up with the wrong types)

15:42 hyPiRion: $timer 20:32:05 All hail our overlord rhickey.

15:42 lazybot: Timer added.

15:42 Raynes: gfredericks: Looking.

15:42 I just typed git repl

15:42 x)x

15:42 x_x*

15:43 hyPiRion: Heh, I tend to write /chmod * +o when I want to give people op

15:43 Raynes: lol

15:44 gfredericks: That code works fine for me broseph.

15:44 gfredericks: The current version is 1.1.1. Are you using that? Seriously dude, I break shit constantly. You've got to use the current version.

15:44 TimMc: :-(

15:45 gfredericks: Raynes: I am not I am using 1.0.0. I think I got that by looking at your tags on github.

15:45 Raynes: gfredericks: Seriously dude, I tag shit sporadically.

15:45 I'm just a bad guy in general.

15:45 TimMc: hyPiRion: One could set a series of $timers at 1 hour intervals for decreasing amounts of time such taht they'd all fire at once.

15:46 gfredericks: now I know

15:46 Raynes: $latest me.raynes/laser

15:46 lazybot: [me.raynes/laser "1.1.1"] -- https://clojars.org/me.raynes/laser

15:46 Raynes: gfredericks: ^ Always use that to find the current version of my libs.

15:46 * TimMc reconsiders using laser

15:46 Raynes: Seriously dude, I'm terrible at marketing.

15:46 hyPiRion: TimMc: that'd be like, "Imma charging my... lazybot"

15:46 Raynes: Don't listen to anything I say.

15:47 gfredericks: TimMc: I never grocked enlive any better. This might be inevitable for this kind of library.

15:47 hyPiRion: TimMc: oh hey

15:47 Raynes: gfredericks: The good news is that you have me whereas cgrand doesn't frequent this channel.

15:47 I also have a nice American sense of humor.

15:48 gfredericks: Raynes: I am a thankful person. Have you considered protocols and records for some of this stuff?

15:48 Raynes: For some of what?

15:48 amalloy: gfredericks: why?

15:48 Raynes: I haven't because wtf why.

15:48 amalloy: well, my reaction isn't as strong as Raynes's. he's allergic to protocols

15:48 hyPiRion: TimMc: If lazybot still listened to clojurebot, we could've made a "quine"-like thing which did exactly what you described

15:49 gfredericks: amalloy: Raynes: it might make it easier to implement transformations when people like me use the wrong sort of thing in the wrong place?

15:49 and easier for me to know what kind of thing I have

15:49 as it is I'm looking at a sequence or a map but it really might be one of at least four different things

15:49 Raynes: gfredericks: Well, you shouldn't have to care what any of these things are.

15:50 gfredericks: I see.

15:50 Raynes: And your biggest problem is that you're using an old version of laser.

15:50 All of this is supposed to Just Work.

15:50 gfredericks: I look forward to trying the newer one.

15:50 Raynes: I don't add protocols and records for documentation purposes. :P

15:51 gfredericks: thanks for the help

15:51 TimMc: Raynes: I don't like the Clojure community's half-assed approach to versioning.

15:51 dobladez: gurus: any idiomatic way or standard function to check if a map is fully contained in another one?

15:51 Raynes: TimMc: I usually tag. I wrote a lein task to do it for me.

15:52 TimMc: dobladez: No standard function. You want key and value equality? select-keys is a first step.

15:52 hyPiRion: TimMc: what do you mean?

15:52 TimMc: dobladez: (= small (select-keys big (keys small))) *almost* does it...

15:53 dobladez: TimMc: both keys and values. Thanks

15:53 TimMc: Throw in an `and` and something from clojure.set and you're on your way.

15:53 dobladez: yep, propably "recur" on that and I'll be close

15:53 TimMc: recur? why?

15:53 Glenjamin: is there an updated cheatsheet for 1.5?

15:53 Raynes: TimMc: Maybe I was drunk when I released that. *shrug*

15:53 I feel bad now.

15:54 How do you tag old commits?

15:54 * Raynes man pages

15:54 hyPiRion: (every? (partial find superset) (keys subset)) should work, I think

15:54 dobladez: TimMc: well... I need to check the whole structure, not just the top-level keys / values

15:54 hyPiRion: oh, urhg, then if you want more than key equality

15:55 Raynes: TimMc: There we go, all tagged up.

15:55 TimMc: Raynes: Oh, not the tagging -- this is about semver.

15:55 Although tagging is really important too.

15:55 Raynes: Yeah, you're not going to get me to stick to semver strictly.

15:57 hyPiRion: TimMc: So how would you usually do that kind of stuff?

15:57 Are you not happy with 0.1.0-RC10-alpha1?

15:57 mklappstuhl: Hey

15:58 does it make sense to write a "short running" cli application in clojure? (thinking of JVM boot time mainly)

15:59 Raynes: mklappstuhl: It depends on how often you need to run it and how fast you need it to run.

15:59 A Clojure CLI app can usually run in 2-3 seconds.

15:59 Glenjamin: the bigger issue with clojure versioning seems to be that every lib i see depends on old versions of everything

15:59 Raynes: I imagine that could be lessened a bit further with some fancy JVM options.

16:00 And if you use drip, it could be mitigated even more I expect.

16:00 hyPiRion: mklappstuhl: if you mean "less than 2 second short" then you shouldn't

16:00 Raynes: But it really depends on your specific usecase.

16:00 hyPiRion: Ssssh, I have command line apps that run in 2 seconds but only ever have to be ran like once every two weeks and I'm very happy to have written in Clojure.

16:00 :p

16:00 mklappstuhl: Raynes: hyPiRion: It'd be some simple script fetching some data from the internet

16:01 Raynes: https://github.com/Raynes/updoc

16:01 mklappstuhl: ^ Example command-line app that I wrote.

16:01 If you're interested.

16:01 TimMc: hyPiRion: Not sure what you're asking. I don't care what people do pre-v1, as long as they eventually release a v1. Once they do that, breaking changes really don't belong in anything but 1st-segment version bumps.

16:01 borkdude: hmz, how can 10 operations that take 1 second each be 10 seconds single threaded, but take 1 second on 4 cores? https://www.refheap.com/paste/13217

16:01 mklappstuhl: I also had the idea that some other runtime like JS could be used...

16:02 Raynes: You could do it in clojurescript with node.js. You could also toss yourself out a 10 story window.

16:02 hyPiRion: TimMc: Alright, that's what I though. x.y.z where x is breaking changes, y is enhancements/additions and z is bugfixes

16:02 gfredericks: borkdude: those aren't exactly CPU-bound functions

16:02 mklappstuhl: Raynes: clojurescript no good?

16:03 borkdude: gfredericks oh right

16:03 gfredericks: borkdude: the real question is why pmap gets it all the way to 1 second rather than 2 or 3

16:03 hyPiRion: borkdude: because they don't run. When a thread starts sleeping, another takes over

16:04 nDuff: Glenjamin: Unless those specifications include version ranges, though, lein should be able to substitute in the newer/current versions without issue.

16:04 borkdude: hyPiRion right

16:04 nDuff: Glenjamin: ...ie. usually, version specifications are minimum with no maximum.

16:04 technomancy: Raynes: I noticed laser has no images in its readme; can you add https://lanternhollow.files.wordpress.com/2011/05/laser_gun_pew_pew_pew.jpg ?

16:04 borkdude: I would try reducers, but when I want to install Java 1.7 I get some messages that Chrome won't keep working… anyone had this?

16:04 Raynes: technomancy: I absolutely can.

16:04 gfredericks: borkdude: how long does it take for 100?

16:05 Raynes: technomancy: You could send me a pull request and get in the contributor graph.

16:05 It's like winning.

16:05 hyPiRion: but yeah, pmap is weird, and spawns n+2 threads, where n is the amount of threads. And some other weird stuff

16:05 technomancy: tempted

16:05 TimMc: Raynes: That would be a pretty impressive window.

16:05 Glenjamin: nDuff: it mostly seems to work when newer libs are pulled in, but any non-back-compat changes would leave things totally broken

16:05 borkdude: gfredericks about 4 seconss

16:05 nDuff: Glenjamin: Sure. This isn't #ruby; backwards-incompatible changes to documented semantics are rare.

16:05 gfredericks: huh.

16:06 nDuff: Glenjamin: ...thus, the thing that's an issue is code relying on on _undocumented_ semantics.

16:06 borkdude: gfredericks 1000 takes a lot longer though, 32 seconds

16:06 TimMc: Which is pretty common.

16:06 Glenjamin: so basically we trust people to build libs without breaking things, and don't worry about it

16:07 gfredericks: borkdude: yeah at some point it would scale linearly

16:07 borkdude: gfredericks maybe I have to come up with a better example than Thread/sleep

16:07 gfredericks: how about ((apply comp (repeat 1000000 identity)) 42)

16:08 nDuff: Glenjamin: Pretty much, yes.

16:09 Glenjamin: i gotta be careful not to mock too much in my tests then

16:10 amalloy: gfredericks: yesterday i rewrote a geni function in point-free style for april fools. i gotta say, it came out as badly as i hoped: https://www.refheap.com/paste/13185

16:11 borkdude: gfredericks hm, the pmap version of this take a looong time with only 10 elements

16:13 gfredericks hm https://www.refheap.com/paste/13218

16:16 igorw: does lein have a fancy way of describing semver-ish version constraints? lots of other deps managers have that, and it helps a lot to promote more sane versioning

16:17 Raynes: technomancy: https://github.com/Raynes/laser#laser

16:17 technomancy: igorw: I am suspicious as to whether it actually helps

16:17 my observations have been more that it actively hurts when semver isn't applied, but not the other way around

16:17 brehaut: ~version ranges

16:17 clojurebot: version ranges are nothing but trouble: http://nelsonmorris.net/2012/07/31/do-not-use-version-ranges-in-project-clj.html

16:17 technomancy: Raynes: capital

16:18 Raynes: I broke travis-ci by force pushing 4 times in a row because I screwed up the README.

16:18 And it won't let me restart the build.

16:18 technomancy: oof

16:18 Raynes: Where is antares when you need him.

16:18 Oh, it's restarting automatically.

16:18 Not bad, travis.

16:18 Glenjamin: heh, there really needs to be better github readme preview tooling

16:18 technomancy: sometimes I test github's markdown via gist, but I know you might not believe in that

16:19 Raynes: technomancy: Yeah, but this required that the file be in the git repo so it was a catch 22.

16:19 https://travis-ci.org/Raynes/laser Yey green.

16:19 technomancy: aha

16:20 Glenjamin: Raynes: technomancy https://github.com/ypocat/gfms

16:20 nDuff: do you think as the ecosystem grows, the fuzzy version matching lein does will become an issue?

16:20 technomancy: igorw: but lein inherits its version range support from aether, which unfortunately provides a fairly broken implementation

16:21 nDuff: Glenjamin: Given as lein inherits that behavior from a far larger ecosystem, I'm not so worried.

16:21 Glenjamin: versions in java suck too :(

16:21 or maybe thats just from my pov

16:22 technomancy: the problem is it's more difficult to isolate off entire subtrees of the dependency graph with java than clojure

16:25 hq1: noob question, out of curiosity: using the Clojure REPL can I inspect the running system/VM like in Erlang?

16:25 nDuff: hq1: You certainly can inspect the running instance.

16:25 hq1: "like in Erlang" requires more knowledge of Erlang than all of us have. :)

16:25 igorw: technomancy: obviously it's not a replacement for actually telling people to version properly. it amazes me that so many packages in npm is still 0.x, although it has improved a bit

16:26 hyPiRion: nDuff: well, with rebar you can open up a console of a running OTP program

16:26 Not sure if that explains anything to you though.

16:26 TimMc: &(get-in 5 [])

16:26 lazybot: ⇒ 5

16:26 technomancy: hq1: probably the main difference is in clojure you have to explicitly start a repl server; you won't get one out of the box

16:26 hq1: hyPiRion: you don't need rebar at all (to put it mildly it isn't the greatest software in the Erlang's ecosystem)

16:27 technomancy: but it's trivial to do

16:27 hq1: so there's nothing stopping me from testing some functions in a production system runtime?

16:28 nDuff: hq1: If you set up that production system to have run an nrepl server or swank, correct.

16:28 technomancy: hq1: definitely not. you can even do it on a web app without opening extra ports if you like: https://devcenter.heroku.com/articles/debugging-clojure

16:28 hq1: just got my first Clojure book, will stop asking noob questions soon ;)

16:28 thanks guys

16:31 nDuff: Erlang shell is part of the OTP, you can use remote shells which is a killer feature (connect to a remote node from a local REPL).

16:31 nDuff: hq1: ...whereas the Clojure equivalent is using nrepl to remote in, potentially with drawbridge to tunnel over HTTP.

16:32 technomancy: clojure programs don't have the same level of isolation between concurrent threads as erlang processes (which is good and bad) but can lead to some unexpected behaviour with reloads

16:32 OTOH you are able to get much better performance communicating between them

16:32 hq1: hehe I'm biased so I won't get into this discussion :P

16:33 technomancy: erlang is better for things that erlang is better for; we can leave it at that. =)

16:33 hq1: yes please ;)

16:34 jack_rabbit: So I'm working with network programming, specifically the read() method of a SocketInputStream, and think I'm probably going about this wrong. Are there nice wrappers for socket programming floating around somewhere?

16:34 hq1: still quite excited to finally learn a proper LISP running on JVM. hopefully it will let me to deploy stuff without even thinking of Java.

16:36 are there any resources you guys would recommend to learn about JVM itself?

16:37 joegallo: like, java generally, or the jvm specifically?

16:37 amalloy: jack_rabbit: aleph and lamina are one approach, or you might be able to make do with slurp, clojure.java.io/copy, and friends. but for actual non-trivial network problems, it's not unreasonable to be using sockets yourself

16:37 hq1: JVM specifically, I am so *not* interested in Java itself. am I a bad person?

16:38 * technomancy doesn't know java either

16:38 technomancy: s'ok

16:38 Glenjamin: i think that makes you sane.

16:38 ztellman: jack_rabbit: what are you trying to do, at a high level?

16:38 jack_rabbit: amalloy, I'm just not liking having to create byte buffers for my read calls.

16:38 ztellman, At this point it's just an exercise creating a ServerSocket and reading input from the client.

16:39 (who is connecting through telnet)

16:39 hq1: still, being able to use some of the Java "goodies" like let's say SOAP support (<- mind you, the quotes) would be a good thing ;)

16:39 hyPiRion: hq1: You're not a bad person.

16:39 Java isn't the worst language to work with, but well, I've seen better

16:40 brehaut: hyPiRion: swearjure for instance

16:40 amalloy: (inc brehaut)

16:40 lazybot: ⇒ 10

16:40 hyPiRion: brehaut: hahah, I was for once not thinking about that

16:40 ztellman: jack_rabbit: clojure.java.io will give you enough to avoid dealing with bytebuffers

16:41 but if you end up wanting to try aleph, I can give some pointers there too

16:41 hq1: OK, so is there a place I can learn about JVM not being forced to read about AbstractFactoryStrategySingletons?

16:41 combataircraft: question: what is the most convenient & idiomatic way of creating a new function by editing the parameters of an existing one like: (def get-user 'request "/users/{0}.json") ?

16:41 amalloy: jack_rabbit: if you're starting from nothing, i recommend giving ztellman's lamina and aleph a try. there's some early conceptual hurdles, but once you get the hang of it it's a pretty neat way to write networking code

16:41 technomancy: hq1: this article is pretty great: http://copperthoughts.com/p/clojure-io-p1/

16:42 hq1: technomancy: ty, bookmark'd

16:42 technomancy: I/O is the most common place Java stuff sticks out

16:42 jack_rabbit: amalloy, ztellman Thanks I'll try out all that stuff.

16:42 ztellman: amalloy: bite your tongue, everything I write is intuitive and immediately effortless to use

16:42 combataircraft: I need some kind of parameter templating for editing creating functions. any ideas ?

16:42 hyPiRion: hq1: there's not much you need to know about Java when you program in Clojure. I/O is one thing, and blocking queues are the other.

16:43 amalloy: combataircraft: what on earth does that question mean?

16:43 hyPiRion: Otherwise everything else should not have a need for Java.

16:43 nDuff: Eh. One certainly has to know how to read javadocs.

16:43 hq1: hyPiRion: but I'd like to be able to call some external, hairy Java libs. Is that a problem at any point?

16:43 nDuff: One has to know how java's variadic arguments work.

16:43 combataircraft: amalloy: what is the most convenient & idiomatic way of creating a new function by editing the parameters of an existing one like: (def get-user 'request "/users/{0}.json")

16:44 nDuff: One really ought to know the Java standard library, as there's a whole lot more of it than there is standard-library for Clojure.

16:44 technomancy: you need to know not to use java.util.Date

16:44 hq1: I can grok those I guess ;)

16:44 technomancy: hq1: there's no substitute for hanging out on IRC though

16:44 amalloy: i'll get back to you if i ever find something you've written that is immediately effortless, ztellman

16:44 hyPiRion: hq1: Well, if you would like to do that, then you should know some Java, yeah.

16:44 ztellman: amalloy: :)

16:45 gtrak: any hadoop-app devs here? I'm curious if anyone's built an automated testing/deployment thing with pallet?

16:45 rboyd: combataircraft: do you want partial?

16:45 hq1: hyPiRion: I'm thinking rather of technical restrictions of Clojure if any. Got some hardcore java hackers around so I could ask them to type some stuff for me ;-)

16:46 combataircraft: rboyd: yes partial, but with re-arranging parameters by templating

16:46 like this; (def get-user 'request "/users/{0}.json")

16:46 hq1: hyPiRion: but I'm hoping this to be fully transparent

16:47 combataircraft: assume we have a function called request and it takes URL as a parameter. I wanna create a new function that says "call request function by formatting this parameter"

16:47 hq1: hyPiRion: like, is there some Java stuff out there I *can't* call from Clojure?

16:48 amalloy: hq1: no, although there are some things that can be hard

16:48 nDuff: hq1: There's Java stuff you need to jump through hoops to call from Clojure -- ie. sometimes you need to use gen-class to build something with annotations.

16:48 hyPiRion: hq1: Java interop is very well designed and tightly integrated, and unless you need very high performance or need to do some really messy locking, I don't think you have to jump down to Java.

16:48 nDuff: hq1: ...but there's nothing you _can't_ call from Clojure, just things that are tricky.

16:48 hq1: ...well, there are things you can't call from Clojure without an AOT compilation phase.

16:48 rboyd: combataircraft: (def get-user #(request (str "/users/" % ".json"))) ?

16:48 hugod: gtrak: https://github.com/pallet/pallet-hadoop if you haven't already seen it

16:48 gtrak: hugod: yea, I'm on it right now :-)

16:49 * hq1 googles for AOT

16:49 hq1: ah

16:49 brehaut: (def get-user (comp request (partial format "/user/%s.json")))

16:49 nDuff: hq1: ...unless you're dealing with 3rd-party APIs that inspect objects you pass them for annotations &c., though, those are generally fairly rare.

16:50 hq1: nDuff: I might deal with those, but I guess it all could be done with some kind of native Java wrappers as well, right?

16:50 nDuff: hq1: Yup.

16:50 hq1: OK, fair enough, that's perfect

16:50 rboyd: brehaut: slick

16:50 nDuff: hq1: Only time I've had to jump through hoops that large is when I'm using Clojure to build a plugin for a large Java project.

16:51 combataircraft: rboyd: brehaut: awesome answers, thanks!

16:51 hq1: nDuff: I see, thanks for clearing things up a little

16:51 brehaut: combataircraft: caveat that if you are bashing strings together you might have the wrong abstraction

16:52 amalloy: hq1: you might find https://github.com/flatland/io/tree/develop/src/flatland/io interesting, as an example of building a minimal java wrapper around an awful java api, and presenting a nice clojure api instead

16:53 the java IO library is all these awful abstract classes that you have to extend and reimplement bits of; we wrote instead a concrete class that gets passed an instance of an interface and delegates to it; that interface is easy to implement from clojure

16:54 hq1: amalloy: splendid, thank you, will look into it

17:12 Glenjamin: is there a way to load-file relative to the current file?

17:12 something like __FILE__ in other languages

17:17 amalloy: Glenjamin: don't do it, man

17:18 Glenjamin: amalloy: it's to make this work when using a lein checkout: (load-file "src/speclj/version.clj")

17:18 inside project.clj

17:22 technomancy: Glenjamin: if you need access to the version at runtime you can load pom.properties from the jar

17:23 Glenjamin: it's not my lib, so swapping it around seems like overreaching

17:24 i guess in general having logic in project.clj isn't a great idea though :)

17:32 i wasn't intending to commit that, just wanted it to work with the checkout

17:32 although i got a weird error with interface not matching the protocol, and just used lein install

17:36 tieTYT: in a let, the way even params are symbols and odd params are evaluated to values is called a binding form?

17:36 let me resay that

17:36 in a let, the way odd params are symbols and even params are evaluated to values is called a binding form?

17:38 gfredericks: technomancy: does slamhound make some attempt to solve the "what vars does this code refer to?" problem?

17:39 technomancy: gfredericks: heh... well... "some attempt", yes

17:39 "does this compile? no? let's screw with the ns form. how bout now?"

17:39 gfredericks: oh nice

17:39 technomancy: brute force search

17:39 gfredericks: that's brilly

17:39 technomancy: http://technomancy.us/148

17:39 gfredericks: I assume brute force means you try every possible subset of the namespaces you might want to require with all possible prefixes and refer lists and etc

17:40 technomancy: more or less

17:47 tomoj: tieTYT: the terminology is confusing to me

17:47 I think 'binding form' means the odd forms

17:48 but 'binding' can mean a pair of odd and even?

17:48 (I'm guessing you're 1-indexing?)

17:49 amalloy: tomoj: tieTYT: i think it's just all poorly defined and ambiguous. "binding", "binding form", "bindings" all mean whatever you want them to mean in context

17:49 tomoj: yeah :(

17:50 gfredericks: <form>

17:50 tomoj: core is no help for names internally iirc

17:51 (let [bents (partition 2 bindings)] ...)

17:52 I guess that's an abbreviation for "binding entry"?

17:53 then confusingly loop call it's binding entries 'bfs', binding forms?

17:53 calls its..

17:55 gfredericks: I used the term lettings a lot in currj

17:55 that's a good reason for nobody else to use it

18:01 this whole using ^:private thing gets really noisy after a while :(

18:02 for a fleeting moment I thought about writing a macro to do it and then remembered defn- exists and why I'm not using it

18:14 amalloy: gfredericks: so don't write so many dang private functions

18:14 * gfredericks doesn't know how to clojure

18:15 amalloy: i'd suggest making your public functions be closures around your private functions, but people always laugh at me when i do that

18:15 and i don't need to introduce more pain to your life

18:15 gfredericks: (let [...privates...] ...def publics...)

18:16 amalloy: gfredericks: well, that makes it hard to def a private, then a public, then a private...

18:16 Foxboron: Someone should write a new book about closuers in clojure and call it "Clojure in Closure"

18:16 amalloy: but it is what i was recommending, yes

18:17 holo: Foxboron, you mean "Closure in Clojure"?

18:17 Foxboron: holo: No. "Clojure in Closure"

18:17 amalloy: you could try something sneaky like (letfn [(private1[]) (public1*[]) (private2[]) (public2*[])] (def public1 public1*) (def public2 public2*)), but yuck

18:20 Foxboron: holo: it is a pun if you didn't get it ;)

18:20 been reading Let over Lambda for the past days and just can't come over the fact it would be an awsome name.

18:21 hiredman: "private" is gross

18:21 it limits reuse

18:22 technomancy: you can't always design for forever-future-proof re-use

18:22 hiredman: then don't

18:23 isn't it great we have actually dependencies and you can specify a dependency and just keep using it even if upstream releases a new version with breaking changes

18:24 technomancy: so the idea of communicating an explicitly demarcated stable API is a waste of time?

18:24 hiredman: technomancy: sure, communicate it, but making it a pain to work with the other parts is just silly

18:25 how about if you want something to be public you do ^:public

18:25 technomancy: resolving vars is not really a pain

18:25 it's like two extra chars

18:25 if you're a big kid and you can deal with your own breakage surely you can add two extra chars

18:25 hiredman: technomancy: sure, but once you start going "oh, I'll put my private bits in a let and close over them"

18:25 technomancy: hiredman: oh, yeah that's nuts

18:25 hiredman: which, well, honestly has never stopped me

18:26 but it is super annoying

18:27 we have some code at work that reflectively grabs the countdownlatch closed over in the reify of a promise so we could deref with a timeout since clojure 1.2

18:27 of course now there are deref arities with a timeout

18:29 luckily the name of the closed over count down latch has never changed

18:31 ,(->> (class (let [x 1] (fn [] x))) .getDeclaredFields (map #(.getName %)))

18:31 clojurebot: ("x")

18:33 Lajjla: ,(let [i "I" worship "worship" his "his" shadow "shadow"] (str I \space worship \space his \space shadow \ space))

18:33 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported character: \ space>

18:33 Lajjla: ,(let [i "I" worship "worship" his "his" shadow "shadow"] (str I \space worship \space his \space shadow \space))

18:33 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: I in this context, compiling:(NO_SOURCE_PATH:0:0)>

18:33 Lajjla: Oops

18:34 ,(let [i "I" worship "worship" his "his" shadow "shadow"] (str i \space worship \space his \space shadow \space))

18:34 clojurebot: "I worship his shadow "

18:34 Lajjla: Perfect

18:43 sandbags: Can someone tell me what version I should specify for Clojure contrib? Based on the examples I've seen I thought I should use the same version as my clojure (i.e. 1.5.1, or 1.5.0, or 1.5) but that doesn't seem to be right.

18:43 I looked at the contrib pages but it's not apparent to me from there either

18:43 amalloy: clojurebot: where did contrib go?

18:43 clojurebot: well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

18:43 sandbags: (sorry, "version" meaning what should I put in my leiningen project.clj)

18:45 amalloy: okay i'm a little confused .. from this i deduce there is no longer a single contrib jar file?

18:46 Raynes: The whole contrib landscape has changed.

18:47 If you're reading the original Stuart Halloway book it's pretty extremely outdated now.

18:47 sandbags: something of an equivalent heritage it seems

18:47 brehaut: deintensifier intensifier noun

18:47 high five raynes

18:48 Raynes: o/

18:48 sandbags: okay i found what i needed, apparently it got moved into clojure anyway :)

18:48 thx

18:48 brehaut: \o

18:52 tieTYT: in a let, the way the first params are symbols and second params are evaluated to values is called a binding form?

18:52 amalloy: tieTYT: please read the scrollback from last time you asked thie question before asking it again

18:53 tieTYT: sorry, i didn't see that

18:53 Raynes: lol

18:54 tieTYT: seems like the answer is "nobody knows"

18:55 does anyone know if Rich Hickey is anti test or just anti-tdd?

18:55 technomancy: he says regression tests are valuable

18:56 tieTYT: i see

18:56 in my limited experience, they're easier to write in clojure than java

18:57 really hard to write regression tests when you didn't write your code for testability in mind in java

18:57 at least write it in a way that's "good"

18:57 ztellman: writing with testing in mind != tdd, though

18:58 Apage43: tdd == writing tests with eventually writing code in mind

18:58 tieTYT: right

18:59 Raynes: technomancy: http://static.quickmeme.com/media/social/qm.gif

18:59 dpathakj: tieTYT: you may be interested in http://www.codequarterly.com/2011/rich-hickey/ . search for 'test'.

19:00 tieTYT: thanks

19:00 i've read this already

19:01 Raynes: The good news about programming is that you don't have to do what Rich says.

19:01 If you want to TDD, you go do you some TDD.

19:01 tieTYT: but Rich says...

19:01 Raynes: Insert comment about being told to jump off a bridge.

19:03 amalloy: Raynes: http://xkcd.com/1170/

19:12 tomoj: wow, apparently you can set! even non-dynamic vars is cljs

19:14 Apage43: does cljs have dynamic vars?

19:14 amalloy: tomoj: of course. it's the assignment operator, just like in clj-jvm where you can use it to set! public members of objects

19:15 Apage43: does cljs have vars? (no)

19:15 Apage43: well there we go

19:17 tomoj: amalloy: but I would've expected the compiler to throw on setting a non-dynamic var

19:17 at least, directly

19:17 nDuff: tomoj: ...but on a variant of the languages that doesn't _have_ Vars...

19:17 amalloy: tomoj: what var?

19:17 tomoj: vs (set! (.-foo js/cljs.user) 42)

19:17 the compiler knows about vars

19:17 amalloy: does it?

19:18 tomoj: indeed

19:18 e.g. if you try to (binding [non-dynamic ..]) you get a warning at least

19:19 tieTYT: is var short for variable?

19:19 Apage43: what does binding do in cljs

19:19 tomoj: it just set!'s then set!'s back after

19:20 Apage43: ah

19:20 well that makes sense

19:20 actually

19:20 nDuff: tieTYT: In Clojure, a Var is a specific construct with specific semantics.

19:20 tieTYT: ...thus, it's not as general a term as a "variable".

19:20 tieTYT: ok

19:21 I'm reading this: http://clojure.org/vars

19:21 Clojure is a practical language that recognizes the occasional need to maintain a persistent reference to a changing value and provides 4 distinct mechanisms for doing so in a controlled manner - Vars ...

19:21 but vars can only do that if theyr'e defined with ^:dynamic right?

19:21 Raynes: No.

19:21 tieTYT: i guess the with-redefs is another way

19:21 hyPiRion: tieTYT: Ever tried (def foo 10) (def foo 20) ?

19:21 Raynes: You can change a var at any time.

19:22 Not a good example. I'm disappointed.

19:22 $google alter-var-root clojure

19:22 lazybot: [ClojureDocs - clojure.core/alter-var-root] http://clojuredocs.org/clojure_core/1.2.0/clojure.core/alter-var-root

19:22 Raynes: Ugh

19:22 tomoj: (set! + -)

19:22 seems nuts

19:22 Raynes: I wish I hadn't done that now.

19:22 hyPiRion: tomoj: Well, you can do that in Java too

19:22 tieTYT: Raynes: what hyPiRion said isn't a good example?

19:22 Raynes: I like alter-var-root.

19:22 tomoj: you can't do (set! + -) in clojure at least

19:23 hyPiRion: I tried to change Boolean/TRUE to false, and the whole JVM collapsed. Fun times.

19:23 possibilities: newbie alert! what's the best way to coerce clojurescript output to be a requirejs compat module?

19:23 nDuff: tieTYT: ...well -- it's fair if you're replacing something over a REPL. It's not something you'd ever want to have code to programatically.

19:24 Apage43: possibilities: how do you do it in javascript?

19:24 nDuff: possibilities: I'd look at how requirejs plays with the Google Closure ecosystem, to start

19:24 tieTYT: that alter-var-root is interesting

19:25 possibilities: ok, nuff said, nice way of saying "don't be dumb", thank you. (:

19:25 hyPiRion: you could do it through java calls too, with .bindRoot

19:26 Though well, it's obvious that this dangerous material.

19:26 nDuff: possibilities: ...well -- Google Closure has their own module / dependency system, and that's the one cljs plays well with; I honestly don't know how/whether requirejs integrates with it cleanly.

19:29 corecode: oh nice, there is clj->scm

19:29 maybe my dream of clj-on-microcontroller will work out?

19:29 Denommus: hi

19:30 how do I make leiningen detect my $HOME/Projects directory as the root of where I put my projects?

19:30 hyPiRion: corecode: https://github.com/halgari/clojure-metal

19:30 corecode: hyPiRion: ooooh

19:30 hyPiRion: i was looking at picobit http://www.iro.umontreal.ca/~feeley/papers/StAmourFeeleyIFL09.pdf

19:30 technomancy: Denommus: leiningen only really works on one project at a time

19:31 hyPiRion: corecode: oh dang, sweet

19:31 corecode: hyPiRion: the arm version compiles to 8KB VM code

19:31 possibilities: thanks peeps.

19:31 technomancy: Denommus: what is it exactly you're looking for?

19:31 corecode: hyPiRion: and i think if needed assembler/different coding could get it down to 4KB.

19:32 hyPiRion: corecode: ooh, I'll find you an interesting one, sec

19:33 Denommus: technomancy: I'm trying to work with clojure in Emacs, and I'm used to Common Lisp with quicklisp workflow

19:33 Raynes: technomancy: What are your thoughts on el-get?

19:34 technomancy: Raynes: it kinda bums me out

19:34 Raynes: Justin made me write a refheap.el recipe and send the guy a pull request because he won't use elpa directly. :p

19:34 corecode: ya el-get seemed like The Solution, but now melpa/elpa/marmalade are much better

19:34 technomancy: Raynes: I wish the effort that went into it had gone into making package.el better, because it's still lacking a lot of features.

19:34 Raynes: technomancy: The weird thing to me is that it isn't even entirely separate. You can use elpa as a method of fetching a package.

19:35 Makes my skull ache.

19:35 technomancy: Raynes: that said, it can do some things you can't currently do with package.el. but as a library author, you should probably pretend it doesn't exist and just upload to marmalade.

19:35 jack_rabbit: So... I have a future running an infinite loop with a thread monitoring it, but when I call (future-cancel the-future) on it, it doesn't seem to die, even though (future-cancelled? the-future) returns true.

19:35 Raynes: technomancy: I do typically do that, but Justin is, you know, my boss more or less. :P

19:36 technomancy: Raynes: well, if your hands are tied... =)

19:36 Raynes: technomancy: It required no modification of refheap.el. I just added a 5 line recipe thing that's like "Yo, here is a git repo. Go get it."

19:36 technomancy: my only objection with el-get is that it makes library authors slightly more likely to avoid doing proper packaging and the time spent writing it could have been better spent

19:37 hyPiRion: corecode: http://hypirion.com/pdf/igor.pdf <-

19:37 Sorry, my server spazzed out

19:37 technomancy: but I'm not the boss of anyone, and package.el has horrible political contribution barriers

19:37 nDuff: jack_rabbit: a cancel won't do anything that a thread interrupt method won't

19:38 jack_rabbit: see http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#cancel(boolean)

19:38 jack_rabbit: ...note that Java's thread interrupts are, err, somewhat voluntary.

19:39 jack_rabbit: see http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html for more details on that.

19:39 jack_rabbit: Yeah, it appears that way. I'll have a look. But before I do that, I need to write this handler so it doesn't do busy waiting.

19:39 Denommus: guys, how do you require your projects in nrepl inside of Emacs?

19:39 hyPiRion: jack_rabbit: oh hahaahah

19:40 jack_rabbit: Is there something that blocks until the value of an atom is changed? I've looked at agents and watches, but I don't really want more than one thread executing the handler at a time.

19:40 hyPiRion: you have the blocking read issue in Java

19:40 technomancy: Denommus: nrepl-jack-in is the most common way

19:40 hyPiRion: jack_rabbit: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4514257

19:40 Denommus: technomancy: I understand that, but this only opens the repl. I'm asking how to load my project

19:40 I mean, I have no idea how to run a project from inside emacs

19:41 technomancy: Denommus: usually C-c C-k

19:41 hyPiRion: Essentially it's a 12 year old unresolved bug report about the impossibility of killing threads on a blocking read

19:41 technomancy: you can also add :repl-options {:init-ns my.init.namespace} to have things loaded on startup

19:41 jack_rabbit: hyPiRion, I don't think that's it. This method I'm running doesn't call read anywhere.

19:41 technomancy: but I'm not sure whether that's checked in nrepl.el yet

19:41 hyPiRion: Denommus: C-c C-k and then C-k M-n (to switch namespace)

19:41 jack_rabbit: oh, lucky you

19:41 nDuff: jack_rabbit: If it's all CPU and not invoking anything that waits for I/O or sleeps, then there's likely nothing checking interrupt status.

19:41 jack_rabbit: Do see the last link I provided.

19:42 jack_rabbit: nDuff, I'm reading it now. Thanks.

19:42 Denommus: CompilerException java.lang.RuntimeException: Unable to resolve symbol: defproject in this context, compiling:(/home/yuri/Projetos/test-clojure/project.clj:1)

19:43 jack_rabbit: nDuff, So it appears I might just need to catch that exception, then.

19:43 nDuff: jack_rabbit: Not quite.

19:43 technomancy: Denommus: Leiningen isolates in-project code from code that runs in Leiningen itself

19:44 nDuff: jack_rabbit: The issue here is that you aren't calling anything that _throws_ that exception

19:44 jack_rabbit: so setting the interrupted flag on the thread isn't actually having any effect.

19:44 technomancy: Denommus: so C-c C-k will only work on stuff inside src/

19:44 you should never need to evaluate project.clj yourself

19:44 nDuff: jack_rabbit: ...you can poll it yourself, if need be.

19:44 jack_rabbit: hmm.

19:44 corecode: hyPiRion: boh, a lot to read

19:44 Denommus: technomancy: so, do I have to do C-c C-k for each of my files?

19:45 technomancy: Denommus: typically your project will have a single entry point which will require everything that's needed

19:45 corecode: hyPiRion: also i'd like to use existing microcontrollers :)

19:45 jack_rabbit: I need to implement some sort of blocking to wait for incoming data on an atom, so I think it'll be simple to get the thread to kill itself with particular messages.

19:46 nDuff: That... doesn't sound like an ideal use case for an atom.

19:46 mpenet: that sounds likes a promise

19:47 jack_rabbit: mpenet, I'll have a look at promises.

19:50 Okay. Here's what I'm doing. A few futures listen on sockets for incoming data, and then conj that data to a set in an atom which is distributed amongst the futures. Another future needs to handle this incoming data. That's where I'm stuck. Right now it works except for the busy-waiting and the one future not dying.

19:51 I think getting rid of busy-waiting will solve the thread-not-dying problem as well.

19:54 nDuff: The "atom distributed amongst the futures" part doesn't make sense to me.

19:54 Sounds more like a job for a queue.

19:54 jack_rabbit: Well it's basically a queue, yes.

19:54 nDuff: There are places where using java.util.concurrency primitives rather than native Clojure ones makes sense.

19:54 ...indeed, rhickey has explicitly endorsed the practice

19:54 jack_rabbit: The order in which they come isn't really that important.

19:56 There's a starter thread that creates the set in the atom, and then waits for connections. On connection, it spawns a future with that atom, and the future conj's data to the set whenever it gets any. There's another future out there that needs to pick up that data.

19:58 nDuff: Do these futures eventually deliver values?

19:58 mpenet: couldn't this be solved with an agent and throw away all the futures

19:59 * nDuff isn't even sure that this is appropriate for agents, as opposed to Java primitives.

19:59 mpenet: but anyway atoms+futures are probably not what you are looking for

20:02 jack_rabbit: nDuff, No.

20:02 Denommus: technomancy: ok, I tried to clone the compojure project from github, open core.clj and run C-c C-k

20:02 this is the result: FileNotFoundException Could not locate clout/core__init.class or clout/core.clj on classpath: clojure.lang.RT.load (RT.java:432)

20:04 technomancy: Denommus: you must have launched your nrepl session from the wrong project

20:05 Denommus: technomancy: ok, now I understand better

20:06 jack_rabbit: So I could do this with agents and watches instead it looks like.

20:10 Not even watches I guess. I thought multiple actions on an agent could run at the same time, but now I'm reading that's not the case.

20:19 thm_prover: dumb question: I have a string something that looks like "a < b, and c < d". Now, I need to encode this string in a XML-friendly manner. How do I do that?

20:19 What library shoudl I be using? I don't want to encode an entier list of map, I just want to encode a single string.

20:23 http://hpaste.org/85064

20:31 ivan: thm_prover: see data.xml/src/main/clojure/clojure/data/xml.clj and write an emit that doesn't (.writeStartDocument ...)

20:32 thm_prover: ivan: actually, I found that having that little header is acceptable

20:32 :-)

20:32 clojurebot: No entiendo

20:32 thm_prover: :- (+ 1 2)

20:32 : (+ 1 2)

20:32 ivan: ,(+ 1 2)

20:32 clojurebot: 3

20:32 thm_prover: :-)

20:32 how did I trigger the "No entiendo" ?

20:33 ivan: a glitch in the matrix, or perhaps a limit to spewing the same response

20:36 gfredericks: clojurebot occasionally assumes you're talking to him for no particular reason

20:38 technomancy: there's a reason

20:38 it's because it's occasionally hilarious

20:39 gfredericks: there's no denying that

20:40 amalloy: jack_rabbit: i know i recommended it already, but it really sounds like you're crying out for lamina

20:41 jack_rabbit: amalloy, Well if it can solve this stuff, maybe I'll give it a look.

20:41 amalloy: it is for doing exactly what you are trying to do

20:41 corecode: hyPiRion: that lisp machine is real cool

20:41 ztellman: jack_rabbit: can you explain the intent of all those futures and watches?

20:41 jack_rabbit: Thanks. I'll be checking it out right now, although I think I almost have it working with agents.

20:42 amalloy: ztellman: do you have a highlight for lamina?

20:42 ztellman: amalloy: ha, yes

20:43 jack_rabbit: ztellman, Its a simple "chat" server as an exercise. I call a function which loops continuously creating futures that listen to a client whenever one connects. The purpose of the futures was to have each client handled concurrently.

20:44 ztellman: jack_rabbit: https://github.com/ztellman/aleph#websockets

20:44 `arrdem: corecode: which machine?

20:45 ztellman: doing the same thing with TCP consists of changing about two lines

20:45 jack_rabbit: ztellman, I appreciate that actually, but you obviously had to handle this stuff when you were writing that lib. I'm more interested in learning how to properly do it than doing it easily with a lib, although if I ever wanted to actually implement something like this, I'd keep aleph in mind.

20:46 ztellman: jack_rabbit: fair enough, but the underlying implementation in no way resembles what you're doing with futures

20:46 jack_rabbit: ztellman, Maybe I'll have a look at your implementation then.

20:47 ztellman: okay, let me know if you have any questions :)

20:47 jack_rabbit: thanks!

20:49 ztellman, Do you think you could point me to a particular source file that might be of interest to me?

20:49 ztellman: jack_rabbit: there are a few

20:49 but for some context, I use netty, not java sockets

20:49 jack_rabbit: okay.

20:50 ztellman: which adds some capabilities, but does make the implementation a bit less minimal

20:50 so with that in mind:

20:50 https://github.com/ztellman/aleph/blob/perf/src/aleph/netty/server.clj

20:50 https://github.com/ztellman/aleph/blob/perf/src/aleph/tcp.clj

20:51 jack_rabbit: Thanks. I'll be reading those.

20:51 ztellman: I'm honestly not sure where to send you in lamina's source code, so try this first: https://github.com/ztellman/lamina/wiki/Channels-new

20:51 also https://github.com/ztellman/aleph/wiki/TCP

20:53 corecode: `arrdem: 01:39:27 < hyPiRion> corecode: http://hypirion.com/pdf/igor.pdf <-

20:53 `arrdem: cheers corecode

20:54 holy shit dude thanks for sharing this

20:55 hyPiRion: where'd you dig igor up? despite all my lispm googling I never found it.

20:56 oh. he wrote it. nvm.

21:12 corecode: he did?

21:12 yea, absolutely impressive project

21:13 maybe creating something clj-like for microcontrollers is not out of the question...

21:13 `arrdem: TBH that's going to be my next project

21:14 I'm working on a Pascal compiler for a class but the whole thing is over-architected with a view towards getting pointed at Clojure once the class is done.

21:16 we'll see if it ever materializes, but I think it would be very interesting to try and build a microkernel to run & JIT a Lisp bytecode then write a usable userland atop it in lisp.

21:17 'course that's only about a decade of man hours so I'll have it on github next week XP

21:20 corecode: ah

21:20 well, i'm talking about 32KB of flash and 4KB RAM

21:21 `arrdem: http://www.iro.umontreal.ca/~feeley/papers/StAmourFeeleyIFL09.pdf

21:21 gfredericks: Raynes: okay so let's say I have a vector of nodes

21:22 is that a normal thing to have even?

21:23 `arrdem: corecode: that's really cool too. One of the things I've been pondering is using something like that instead of C to do the hardware interop. Virtual memory, clock, disk and soforth.

21:23 gfredericks: is :content supposed to always be a sequence of nodes or can it be a single node as well?

21:24 hiredman: gfredericks: sequence

21:25 gfredericks: man I even manage to get nrepl into some kind of infinite exception-throwing loop

21:31 corecode: `arrdem: yes, that is my plan.

21:31 `arrdem: although for a more peripheral-heavy microcontroller

21:31 `arrdem: less disk, more ADC, etc.

21:32 usb peripheral. writing USB stacks in C is no fun.

21:36 gfredericks: Raynes: https://www.refheap.com/paste/13221 getting a cast exception with a single node

21:38 tieTYT2: i saw this as a parameter to a function, what is this called? [#^HeaderIterator headers]

21:38 the #^

21:38 gfredericks: metadata

21:39 there's just one parameter there

21:39 that's a typehint to say what the java type of the argument is

21:39 tieTYT2: ah

21:39 brehaut: its the old notation for metadata, just ^ now

21:39 tieTYT2: why do you need to do that?

21:39 gfredericks: so it compiles to better bytecode

21:39 tieTYT2: so it's for performance only?

21:39 gfredericks: I believe so

21:40 tieTYT2: ah

21:40 new topic

21:40 is there a way to get counterclockwise to give you compilation errors?

21:40 nDuff: tieTYT: If you're curious, see the *warn-on-reflection* flag

21:40 tieTYT2: i always have to load it in the repl to find errors

21:40 nDuff: nice

21:42 ok thanks guys

22:07 amalloy: gfredericks: there are unusual cases where typehints affect correctness rather than just performance

22:08 gfredericks: they'll at least cause class cast exceptions...are you thinking of something beyond that?

22:08 brehaut: amalloy: java method overide selection?

22:08 gfredericks: ,((fn [^String x] x) 12)

22:08 clojurebot: 12

22:08 amalloy: brehaut: that's one of the two i know, yes

22:08 brehaut: amalloy: whats the other one?

22:08 gfredericks: you guys know way more about computers than I do

22:09 mthvedt: ,(if (java.lang.Boolean. false) 1 0)

22:09 clojurebot: 1

22:09 brehaut: gfredericks: that is a sad indictment of my social life

22:09 mthvedt: whyyy

22:09 amalloy: brehaut: imagine an interface Fooable {void foo();} and a private class FooImpl implements Fooable {...}

22:09 brehaut: mthvedt: everything other than primative false and null are true in clojure

22:10 amalloy: if you get an instance of FooImpl and try to call .foo by reflection, it will complain that you don't have permission to access/use FooImpl

22:10 brehaut: huh interesting

22:10 amalloy: if you treat it as an instance of the public Fooable interface, that's allowed

22:10 brehaut: ah right, that makes sense

22:10 mthvedt: ,(if (boolean (java.lang.Boolean false)) 1 0)

22:10 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.IFn>

22:10 mthvedt: : ,(if (boolean (java.lang.Boolean. false)) 1 0)

22:11 amalloy: the clojure compiler could do a little more work and find that out for you, probably

22:11 mthvedt: ,(if (boolean (java.lang.Boolean false)) 1 0)

22:11 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.IFn>

22:11 amalloy: mthvedt: don't ever use (Boolean. anything)

22:11 mthvedt: man i'm bad at typing

22:11 ,(if (boolean (java.lang.Boolean. false)) 1 0)

22:11 clojurebot: 0

22:11 amalloy: bad in java, bad in clojure, bad everywhere

22:11 samedhi: Are we supposed to be using clojure.core.contracts or trammel?

22:11 brehaut: core.contracts

22:11 mthvedt: amalloy: i was using a library that returns Booleans

22:12 amalloy: write them a nasty letter

22:12 brehaut: ಠ_ಠ

22:12 amalloy: they are returning bad objects to you

22:12 mthvedt: because boolean objects print as false, i spent a long time trying to debug

22:12 gfredericks: so clojure boxes everything except booleans?

22:12 samedhi: ok, thanks.

22:12 mthvedt: unknowing i had a Boolean, not a boolean lurking in the code

22:12 gfredericks: ,(type true)

22:12 clojurebot: java.lang.Boolean

22:12 gfredericks: ??

22:12 lazybot: gfredericks: What are you, crazy? Of course not!

22:13 amalloy: gfredericks: huh? it boxes booleans, most of the time anyway

22:13 gfredericks: amalloy: but you were not just saying that boxed booleans are terrible?

22:13 amalloy: no

22:13 scottj: mthvedt: from docs of that constructor: "Note: It is rarely appropriate to use this constructor."

22:13 gfredericks: guys I'm really bad at computers

22:13 amalloy: constructing new booleans is terrible

22:13 scottj: mthvedt: opps, scroll was messed up on my window

22:13 amalloy: reusing boxed booleans like ##(Boolean/FALSE) is great

22:13 lazybot: ⇒ false

22:13 gfredericks: amalloy: wow, that really IS great!

22:13 brehaut: gfredericks: type requires an object to call get class on it, so of course it boxes to a Boolean

22:14 gfredericks: brehaut: yeah that part made sense; it was my perception of amalloy's point that didn't jive with anything else

22:15 the string version of the constructor doesn't have the warning o_O

22:16 ,(if (Boolean. "false") 1 0)

22:16 clojurebot: 1

22:16 `arrdem: amalloy: why would you ever use Boolean/FALSE given that we have false

22:16 amalloy: oh, i wouldn't, not by hand. but false *us* Boolean/FALSE

22:16 `arrdem: sure. qualified names and whatnot. just making sure.

22:17 gfredericks: ,(identical? false Boolean/FALSE)

22:17 clojurebot: true

22:18 gfredericks: ,(identical? (identical? true Boolean/TRUE) (Boolean/TRUE))

22:18 clojurebot: true

22:21 scottj: ,(identical? (Boolean/valueOf "false") false)

22:21 clojurebot: true

22:24 mthvedt: two things considered identical are logical opposites… makes sense

22:29 tieTYT2: can someone explain this let to me. I don't understand the or. It seems to be on the left hand side. What does it mean when you do that?

22:30 gfredericks: ,(or 1 2 3)?

22:30 clojurebot: 1

22:30 tieTYT2: oh nm, that first "param" is metadata, not a variable

22:30 rationalrevolt: when using println in a ring app and the jetty adapter - do i need to configure the logging explicitly to see the outputs?

22:30 tieTYT2: thanks

22:32 gfredericks: rationalrevolt: depends on how you're running it -- i.e., where STDOUT for the process is going

22:33 rationalrevolt: i'm running it within nrepl

22:33 .el

22:33 gfredericks: should just work I would think

22:33 assuming (println "foo") by itself works as well

22:34 ztellman: has anyone had issues with 'definterface' and 'hadoop jar' not playing well together?

22:34 Raynes: amalloy: So false *us* it?

22:34 ;)

22:34 ztellman: replacing it with a corresponding 'defprotocol' fixes the problem, for no reason that I can see

22:35 rationalrevolt: hmm, println by itself works, but the same doent print to the repl when it gets called from the handler on an incomming reques

22:35 amalloy: ztellman: what goes wrong? a bad jar is generated, no jar...?

22:35 rationalrevolt: ztellman: could you elaboarate?

22:35 amalloy: if you have a jar, i'd look through it to see if the generated interface looks right

22:36 ztellman: oh, right, I get something to the effect of "Type cannot be cast to IType"

22:36 which would typically lead me to believe that the interface is being double defined, but that doesn't appear to be the case

22:36 scottj: rationalrevolt: maybe buffer *nrepl-server*?

22:37 rationalrevolt: scottj: haha! yea, its there

22:37 thanks!

22:39 scottj: rationalrevolt: I don't recall the details and could be wrong, but maybe something like the *out* for the thread that hadnles your ring requests is different from the repl thread that has *out* going to nrepl.el, *I think*

22:40 gfredericks: scottj: that sounds super plausible

22:45 `arrdem: is there a way to get the arity of a function?

22:45 gfredericks: try calling it with all possible arities

22:45 I mean no I don't think so

22:45 `arrdem: that's unfortunate.

22:46 thanks.

22:46 brehaut: some functions in core have an :arglists meta property but thats not really universal

22:46 gfredericks: and that's a var

22:46 brehaut: and presumably you could do some shenanigans with reflection

22:46 yeah

22:47 `arrdem: I was just wondering.. rolling my own internal macro system for a compiler and I'm trying to add arity checking to my macros.

22:52 brehaut: (map #(-> % .getParameterTypes seq count) (.getDeclaredMethods (class map))) ; `arrdem

22:52 ,(map #(-> % .getParameterTypes seq count) (.getDeclaredMethods (class map)))

22:52 clojurebot: (3 2 4 5 0)

22:53 brehaut: you'd probably want to modify it so that it knows about .isVarArgs too

22:53 `arrdem: mm... thanks brehaut

22:53 (inc brehaut)

22:53 lazybot: ⇒ 11

22:54 brehaut: huh. maybe .isVarArgs is useless on clojure?

22:54 map's arity-5 method is the varargs, but it doesnt get listed as such

22:55 ,(map (juxt #(-> % .getParameterTypes seq count) #(.isVarArgs %)) (.getDeclaredMethods (class map)))

22:55 clojurebot: ([3 false] [2 false] [4 false] [5 false] [0 false])

22:55 `arrdem: ah juxt.. so much better than (map vec & seqs)

22:56 brehaut: `arrdem: fwiw http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Method.html

22:57 ,(map (juxt #(.getName %) #(-> % .getParameterTypes count) #(.isVarArgs %)) (.getDeclaredMethods (class map))) ; `arrdem you probably only want invoke and doInvoke rather than all methods in hindsight

22:57 clojurebot: (["invoke" 3 false] ["invoke" 2 false] ["invoke" 4 false] ["doInvoke" 5 false] ["getRequiredArity" 0 false])

22:58 brehaut: `arrdem: i suspect doInvoke is for varargs?

22:59 `arrdem: looking at https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IFn.java#L83-L86 it appears only the >20 arity version of invoke has javaspace varargs

22:59 amalloy: brehaut: doinvoke is probably an implementation detail

23:00 `arrdem: brehaut: *shrug* I'll just restructure this with a wrapper macro so I can get the arity at declaration.

23:00 brehaut: amalloy: everything about the reflection crap i experimented with above is probably an implementation detail

23:00 amalloy: oh, of course

23:00 but varargs are IFn/applyTo, not AFn/doInvoke or whatever

23:00 brehaut: oh ok

23:00 amalloy: i mean it's a *boring* implementation detail

23:01 otoh i'm not sure how useful what i said is; i think it's glossing over some important stuff because i don't know what's being asked here

23:02 brehaut: amalloy: `arrdem wants to find out arities of functions

23:02 amalloy: slit your throat to save time

23:02 it's not a thing you can find out

23:02 `arrdem: lol

23:02 brehaut: i handwaved a vague solution based on stupid reflection

23:03 hiredman: if you with-meta a function anywhere

23:03 if you use a multimethod

23:03 brehaut: ,(map (juxt #(.getName %) #(-> % .getParameterTypes count) #(.isVarArgs %)) (.getDeclaredMethods (class (partial + 1))))

23:03 hiredman: etc

23:03 clojurebot: (["doInvoke" 1 false] ["getRequiredArity" 0 false])

23:03 brehaut: heh

23:03 `arrdem: ... well that makes sense...

23:03 amalloy: seriously though, every IFn has dozens of arities defined, most of which are implemented as (throw (ArityException.))

23:03 brehaut: amalloy: right, but only some of those are declared on a particular instance

23:03 `arrdem: mmkay I'll just give up on arity checking then.

23:04 thanks amalloy, brehaut, hiredman

23:04 hiredman: ,(map (juxt #(.getName %) #(-> % .getParameterTypes count) #(.isVarArgs %)) (.getDeclaredMethods (class (fn [x] x)))))

23:04 clojurebot: (["invoke" 1 false])

23:04 hiredman: ,(map (juxt #(.getName %) #(-> % .getParameterTypes count) #(.isVarArgs %)) (.getDeclaredMethods (class (with-meta (fn [x] x) {})))))

23:04 clojurebot: (["meta" 0 false] ["withMeta" 1 false] ["doInvoke" 1 false] ["getRequiredArity" 0 false])

23:04 amalloy: oh, declared method? that might work, but hiredman is right

23:05 it can't possibly work all the time

23:05 brehaut: not to mention its worthless in teh face of a partial frinstance

23:08 `arrdem: ppft why do I need arity checking on functions anyway...

23:09 amalloy: (try (f a b c) (catch Exception "lol whatever man"))

23:09 hiredman: _

23:09 amalloy: oh yeah

23:09 `arrdem: oh please. this compiler is just going to ignore extra argument l3ik a bau5

23:10 hiredman: in the fine tradition of javascript

23:11 `arrdem: I mean as long as I get em off the stack...

23:13 hiredman: be sure to allow for multivalue returns

23:13 `arrdem: This edition is staticly typed Pascal, no such awesome here.

23:13 next edition will be clojure, then we'll talk

23:16 nonuby: i have simple compojure/ring/jetty web app that i run with "lein ring serverheadless", all okay, the ring/jetty lab emits "2013-04-03 10:12:04.166:INFO:oejs.Server:jetty-7.6.1.v20120215Started server on port 3000" however if I use clojure.logging info emits "INFO: testing", is there a simple way to tell my higher level libraries to use the log4j format used by the base

23:58 yacin: any recommendations for a good xmlrpc lib for clojure?

23:59 necessary-evil?

Logging service provided by n01se.net