#clojure log - May 30 2013

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

0:01 n_b: dnolen: So basically you'd accummulate changes and then request a frame to do all the updates in?

0:01 dnolen: n_b: yes

0:02 n_b: but requestAnimationFrame can be called at any time, multiple times

0:02 doesn't really matter

0:02 which is what you want

0:03 I don't mean the callback, I mean you can requestAnimationFrame again and again and simply will queue it up once when it's most convenient to actually execute the callback

0:04 cgag: has anyone had any experience using any javascript promise libraries with clojuescript and node?

0:04 tomjack: well the callback will be called again and again in that case, yes?

0:04 dnolen: tomjack: no

0:05 tomjack: my test suggests otherwise

0:05 (function() { var cb = function(){console.log('cb');}; requestAnimationFrame(cb); requestAnimationFrame(cb); })()

0:05 logs 'cb' twice

0:06 dnolen: https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame

0:06 tomjack: which doesn't really prove anything

0:06 your example I mean

0:06 since the cb and the work is trivial

0:07 tomjack: hmm, not sure if I'm missing something or if we're miscommunicating. I meant just that if you call requestAnimationFrame multiple times with the same callback, the callback will be queued (and eventually called) multiple times

0:08 so if the callback is like "draw everything to a canvas" you want to be sure to only call it once per frame

0:09 call requestAnimationFrame once per frame I mean

0:09 dnolen: tomjack: oh ok, yes you are right, that's why they return the requestID - I thought it worked more like Cocoa's setNeedsDisplay

0:09 tomjack: if it's something like "flush a queue of pending dom updates" maybe you don't care

0:19 how does virtual dom in cljs even work?

0:19 is it that you have a mutable queue of pending updates?

0:20 surely you're not gonna just deref and walk an atom every frame and somehow try to match it up with the dom?

0:28 recursor94: Does anybody know what became of clojure.contrib.server-socket? I understand that clojure.contrib is not maintained anymore, but I can not find any information about that specific namespace.

0:28 hiredman: https://github.com/technomancy/server-socket

0:29 bbloom: tomjack: if you're willing to assume that you're the only one changing the DOM (which is true-enough for applications) then you can "diff" two snapshots of the atom

0:30 tomjack: right, I remembered you talking about "owning everything" before

0:30 bbloom: tomjack: since it's a tree structure & clojure data has fast equality, that's a trivially and cheap process for incremental changes … and not significantly more complex for significant changes, like moved sub trees, since you can cache complex immutable values while traversing/modifying/whatever

0:30 tomjack: makes sense

0:31 bbloom: of course browser extensions or even just a dev with the inspector can invalidate those assumptions

0:31 but during normal operation, that's not really a problem for most use cases

0:32 recursor94: hiredman: Is there a version in clojars?

0:33 hiredman: I think so, not sure though

0:33 recursor94: Alright, thanks.

0:33 hiredman: https://clojars.org/server-socket

0:33 recursor94: sweet!

0:43 * technomancy glances away awkwardly

0:46 recursor94: :D

0:59 bbloom: dnolen: do you know much about the propegators stuff that was in the sussman "we don't really know how to compute" talk?

1:00 dnolen: bbloom: I've read and implemented bits of the art of propagator

1:00 bbloom: a lot of the material he covered is from that.

1:01 bbloom: dnolen: yeah, was planning to read that

1:07 dnolen: bbloom: it's interesting though I found the paper lacking in terms of references

1:07 bbloom: the list of interesting propagator work is massive

1:07 I'm glad their popularizing it here - but the paper doesn't cite much Prolog CLP, Mozart, Gecode, etc. if I recall

2:08 benkay: on the topic of composing functions to run on a datomic transactor:

2:08 I have two functions installed on the transactor already, update-balance and update-position, that as one might expect, update a balance and a "position" in place.

2:09 I want to write a new function that executes both of those functions on the transactor atomically, that is to say either they both fail or they both succeed.

2:10 now: do I compose a function out of the two functions that I have already? or, from a *new* function in the datomic scheme, should I call both database functions?

2:10 i feel like I just answered my own question.

2:35 mthvedt: benkay: rubber ducking

2:36 benkay: all that i succeeded in doing was exposing further depths of ignorance :(

2:36 mthvedt: benkay: if you're not exposing one's own ignorance, you're not living an inquisitive life

2:37 benkay: amen

2:37 it was an ironic sad face

2:39 ddellacosta: I'm constantly doing this thing where I process one value of one key of each map in a collection of maps, and I always find myself jumping through hoops. There must be a nice shorthand for this common procedure in Clojure…what is it?

2:41 hmm, maybe there is something in reducers

2:42 benkay: is it the same key every time?

3:53 quizme: is swanodette here ?

3:55 i was just wondering about the feasibility of writing a clojurescript compiler in node.js

3:55 sans jvm

3:59 nightfly: quizme: Please do it :)

3:59 And go for extra points and make it self-hosting as well

4:01 quizme: nightfly what do u mean by self-hosting ?

4:01 nightfly: Once you've got your javascript clojurescript compiler working you write another clojurescript compiler in clojurescript

4:02 quizme: oh

4:02 give me a few minutes to let that sink in

4:04 ok

4:04 i think i get that

4:04 that would be awesome.

4:05 but yeah

4:05 that's for bonus points

4:05 cuz really i just wanna use it without the jvm

4:05 call me an end-user if u have to

4:05 borkdude: hmm, http://www.4clojure.com/ isn't working?

4:06 quizme: nightfly so you agree that it would be awesome to have a clojurescript compiler for node.js sans jvm dependency ?

4:08 nightfly: yes, that would be awesome

4:29 tomjack: quizme: why?

4:35 mondraymond: good morning from Brussels

4:35 I'm just hopping on to get a little advice on filter

4:35 I have a function which returns something like this (() () () ({:id 1}) () ())

4:36 and I just want the map with the id

4:36 try as I might I cannot work out how to filter off the empty seqs

4:36 any suggestions before I fire off the google group?

4:38 dedeibel: (def a '(() () () ({:id 1}) () ()))

4:38 (first (flatten a)

4:38 ?

4:39 mondraymond: boom - that works!

4:39 way hey! thanks very much ... completely forgot about flatten

4:41 Raynes: &(filter (comp map? first) '(() () () ({:id 1}) () ()))

4:41 lazybot: ⇒ (({:id 1}))

4:41 Raynes: &(first (some (comp map? first) '(() () () ({:id 1}) () ()))

4:41 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

4:41 Raynes: &(first (some (comp map? first) '(() () () ({:id 1}) () ())))

4:41 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean

4:41 Raynes: Ah.

4:42 &(ffirst (filter (comp map? first) '(() () () ({:id 1}) () ())))

4:42 lazybot: ⇒ {:id 1}

4:52 quizme: tomjack: why what ?

5:13 gtrak: good morning 5am #clojure

5:14 hyPiRion: 11 am here, but good morning

5:24 bordatoue: hi, I am trying to get log4j working but every time when I execute a method that uses log4j i get the message can not find log4j appender, it seems that project is not picking up the log4j.xml file I have added to resource-paths, is there any other location I need to specify the location of log4j.xml

5:26 rhymor: I'm not a log4j expert but if it cannot find the appender I'd guess it did find the log4j.xml but the class of the configured appender is not on the class path.

5:28 bordatoue: rhymor: i can see log4j.xm in the classpath using lein classpath cmd

5:30 rhymor: I think i need to place log4j.xml in src or resource directory based on | public TCPExchClient(int HB_sec,int conn_delay_sec,int exchPort,String exchHost){

5:31 rhymor: in log4j.xml there's a line like <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> can you instantiate that class on the repl?

5:31 gtrak: rhymor: yep

5:32 lemme find an example

5:32 bordatoue: rhymor: yes I can

5:32 gtrak: rhymor: https://gist.github.com/gtrak/5676736

5:32 bordatoue: let me change the location of log4j.xml file

5:36 mondraymond: Hey Raynes - yes that works thanks. It seems to me though that flatten seems so much simpler ... does it miss something that your filter catches?

5:36 gtrak: ~flatten

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

5:38 bordatoue: rhymor: got i working it; log4j file should be in the projects src directory , thanks

5:38 gtrak: bordatoue: test-resources is probably a better place

5:39 mondraymond: ok - yes indeed mapcat works for what I need

5:39 bordatoue: gtrak: is test-reources created by default using lein app

5:40 rhymor: If there is one thing I would like more developers to know it's that "semantics matters". People are often looking for a technical solution where they should be looking for a semantical solution.

5:40 aka. don't think what the program does, think what it means.

5:40 gtrak: bordatoue: if it is, it won't be saved in your git repo if it's empty

5:41 rhymor: tell those devs to use lisp :-), it makes it easier to give things names

5:43 rhymor: gtrak, I'm stuck in a project where we actually have a touring complete configuration language in XML. :(

5:44 gtrak: xml? you're one step away!

5:44 <tag1><tag2>WAT</tag2></tag1> -> (tag1 (tag2 "WAT"))

5:44 hyPiRion: oh dear

5:45 gtrak: I guess attributes and thing are a bit tougher

5:45 rhymor: yes, it's basically lisp with an ugly syntax.

5:45 hyPiRion: https://github.com/technomancy/lein-xml

5:45 rhymor: :D

5:46 gtrak: become more productive with this language by writing a code-generator, when people notice you running circles around them, maybe they'll do something about it...

5:49 rhymor: gtrak, that could actually work. I'll try it.

5:50 gtrak: lol, awesome

5:55 ddellacosta: How to find a hash-map with a particular key in a vector of hash-maps, and then return the value associated with that key? This seems too verbose and inelegant: (:summary-text (first (filter :summary-text (second search-results)))))

5:56 gtrak: some does it for you

5:56 (some :summary-text (second search-results))

5:56 bordatoue: is there any easy way to determine which version of java is used by lein

5:56 hyPiRion: bordatoue: lein version should print it out

5:57 gtrak: some is an underappreciated core funciton

5:57 function*

5:57 ~some

5:57 clojurebot: I don't understand.

5:57 augustl: some ftw :)

5:57 gtrak: see?

5:57 bordatoue: thanks hyPiRion , is there any way to specify a perticular version of java

5:57 ddellacosta: gtrak: thanks! This is not the first time I've forgotten some...

5:58 augustl: it has some nice use cases, and I use it some times, unless it's bothersome for some reason

5:58 ddellacosta: the problem is I'm always thinking about things the wrong way, so some seems orthogonal to the solution

5:58 here I was thinking too hard about processing a vector

5:59 hyPiRion: bordatoue: yeah. Do you want to change it system-wide or just for leiningen only?

5:59 gtrak: I generally enjoy overloading the notion of a pred with actually doing something useful, compojure works this way

5:59 ddellacosta: that's perfect, I just chopped that down to a much shorter version. Very happy.

6:00 gtrak: yeah, it seems to be a common meta-idiom, if I can say that, in Clojure

6:00 bordatoue: hyPiRion: just for a specific project

6:00 ddellacosta: and as I get better with the language I've started to be able to "smell" when that kind of solution exists…but I'm not familiar enough with it yet to know the right solution all the time. So thanks. ;-)

6:00 gtrak: yea, I'm always on the lookout for neat combinations of functions

6:01 like (juxt filter complement)

6:01 hyPiRion: gtrak: (juxt filter remove) I suppose?

6:01 gtrak: yea, that's what I meant

6:02 there must be sort of a implicit second-order standard lib of things like that

6:02 ddellacosta: yeah, juxt is another one that seems like it has some really awesome applications, but which I haven't been able to naturally integrate into my coding yet

6:03 hyPiRion: bordatoue: Humm. You can set the LEIN_JAVA_CMD environment variable to specify what java version leiningen should run, or JAVA_CMD if you want the app and tests to run on the same java version. Don't think you can do it per project yet, unfortunately

6:04 but if you're on Mac/Linux, `JAVA_CMD='path/to/the/java' lein run` should do the trick

6:04 bordatoue: hyPiRion, thanks very much

6:05 hyPiRion: no problemo

6:52 rhickey: how do I keep lein repl from spewing #_=> at me when I do C-M-x in inferior lisp mode?

7:02 llasram: I don't think that's a very well-tested combination... The `lein repl` nrepl server + nrepl.el works perfectly fine though

7:03 rhickey: llasram: thanks, not interested in adding more stuff until first stuff is working

7:13 llasram: Is there a reason for wanting in particular to run the `lein repl` task as the backing process vs just launching the clojure.main repl via Leiningen?

7:44 rhickey: llasram: you mean java -server -cp `lein classpath` clojure.main, or something else?

7:46 Bronsa: rhickey maybe lein run -m clojure.main ?

7:48 rhickey: Bronsa: that's better, thanks

7:57 Jetien: how do you retrieve values of a map from a list of keys idiomatically? ie a function f that evaluates like this: (f {:a 1 :b 2 :c 3} [:a :a :b :x]) -> (1 1 2)

7:58 rhymor: you can use the hashmap as function in map

7:59 Jetien: but if f=map then the example above evaluates to (1 1 2 nil)

8:00 rhymor: so you map, then filter or the other way round

8:02 Jetien: yep. i was just wondering if there's a simpler way.. thx!

8:02 rhymor: Jetien, what is the purpose of that function? I.e. why do you have a vector of keys, some of which might not be in the hash map?

8:02 Anderkent: ,(keep {:a 1 :b 2 :c 3} [:a :a :b :x])

8:02 clojurebot: (1 1 2)

8:02 Anderkent: Jetien: ^

8:02 Jetien: thanks

8:02 rhymor, i think these situations are not that seldom

8:03 rhymor: Oh, I learned something new :) good day today.

8:10 hyPiRion: Hmmmm

8:11 Keep in mind that nil values will not be returned

8:11 ,(keep {:a nil :b 3} [:a :b :c :a :b])

8:11 clojurebot: (3 3)

8:12 hyPiRion: ,(map val (keep (partial find {:a nil :b 3}) [:a :b :c :a :b])) ; solves it

8:12 clojurebot: (nil 3 nil 3)

8:15 Morgawr: can somebody explain in a very layman way what does "binding" do? in the doc it says it's like a let but executes a body and then re-establishes the previous binding? I don't fully understand it

8:16 manutter: slightly OT, but I notice luminus offers dailycred as a pre-configured 3rd party auth/auth service -- does anyone know of any similar services besides like Google/Facebook/etc?

8:17 I set up a luminus app with dailycred, and it works, but their error reporting leaves a little to be desired.

8:17 hyPiRion: Morgawr: it's like setting the variable, but only for the calls within the binding. It's reset afterwards.

8:18 Morgawr: so it's like a scope binding?

8:18 hyPiRion: dynamic scope binding, yes. Consider this:

8:18 console.log("new animation");

8:18 whoops

8:18 ,*print-length*

8:18 clojurebot: 5

8:19 hyPiRion: ,(let [f (fn [] (println *print-length*))] (f) (binding [*print-length* 9000] (f)) (f))

8:19 clojurebot: 5\n9000\n5\n

8:19 Morgawr: ah, I see

8:19 Foxboron: Morgawr: example. the varibale *out* tells clojure what stdout is. Say you bind it too a network socket. (binding [*out* (:in socket)] (println "hai"))

8:19 Morgawr: that's great, thanks for the explanation

8:20 Foxboron: s/:in/:out

8:20 Morgawr: ^ cool, thanks for a real world application too

8:20 hyPiRion: yeah, a common pattern is for example this

8:20 Foxboron: Morgawr: you could bind it to a file writer also.

8:21 hyPiRion: ,(let [s (new java.io.StringWriter)] (binding [*out* s] (println "hello world") (println "nice weather") (str s)))

8:21 clojurebot: "hello world\nnice weather\n"

8:21 hyPiRion: ^ that is exactly how with-out-str works

8:22 Morgawr: neat

8:22 Foxboron: Morgawr: i think that is one of the neatest things i have seen in Clojure so far ^^

8:22 Morgawr: how does it work with closures though?

8:23 if I return a function that uses the bound argument and then call it outside the binding

8:23 I guess it keeps the temp binding, yes?

8:24 hyPiRion: no

8:24 that's why it works in the first place

8:24 (let [f (binding [*print-length* 100] (fn [] *print-length*))] (f))

8:24 ,(let [f (binding [*print-length* 100] (fn [] *print-length*))] (f))

8:24 clojurebot: 5

8:25 Morgawr: ah

8:25 that's weird, good to know

8:25 and yeah, I guess that is why it works in the first place haha

8:25 I didn't give it much thought after all

8:26 hyPiRion: Consider a (def ^:dynamic *foo* ...) definition as a global (binding [*foo* ...] the-whole-app-here)

8:26 You can set up the binding within a function, of course

8:27 ,(let [f (fn [] (binding [*print-length* 100] *print-length*))] (f))

8:27 clojurebot: 100

8:27 Morgawr: yeah, that's a solution

8:27 thanks for the help

8:27 hyPiRion: np

8:34 kitti: join

8:35 :Q

8:35 q

8:35 quit

8:35 exit

8:37 hyPiRion: heh, prepend with /

8:58 edbond: can someone provide example usage of seque?

8:59 hyPiRion: edbond: if you start up a repl with `lein repl` and do `(cdoc seque)`, then there is an example there

9:00 edbond: hyPiRion, thanks, didn't know about cdoc

9:01 hyPiRion: it's a nice tool for examples, although its quality on functions vary

9:59 Pupnik: is the rhickey in here actually rich hickey?

10:01 hyPiRion: yeah

10:02 Pupnik: funny to see him asking questions

10:02 although I suppose he isn't an expert on all the various things that have grown around clojure

10:03 atyz: hi guys, I've been stuck on a small korma issue for a while. It keeps throwing a <NullPointerException java.lang.NullPointerException>. I've spent a lot of time trying to track down the source of the problem but I am ultimately unable to. I would be very grateful if someone would point me in the right direction. It's driving me crazy. http://pastebin.com/isTht8h9

10:04 hyPiRion: It's not weird. He's not working on the tooling and plumbing around Clojure, but rather on the language.

10:04 supersym: Pupnik: every API/implementation takes time to read-up, get in the intention/head of the maker

10:05 you may get a bit quicker/develop an eye... but that part always stays :)

10:07 I spoke to our king on two occasions...same feeling

10:07 we seem to attribute super-natural powers/knowledge to our idols

10:09 Pupnik: true, true

10:10 he does give great talks though

10:27 manutter: atyz: I think the problem is the [:as req] in your route, try just req instead.

10:28 (not that I'm at all knowledgeable about compojure routes, but try anyway)

10:29 supersym: Pupnik: indeed, I watched a video on infoq the day before yesterday, enlighting n refreshing: like the language imho

10:30 justin_smith: compojure routes use regular destructuring - if the destructuring doesn't work in a function parameter list it won't work in a compojure route

10:37 atyz: manutter: i have, unfortunately it makes no difference

10:38 manutter: If you change your "/" route so it just returns a hello-world string, does that work? I'm guessing it won't, and your problem is in your compojure route params.

10:39 Morgawr: what's the best way to create a vector out of all the elements that match the same key from multiple hashmaps?

10:39 justin_smith: Morgawr: (mapv :key hashmaps)

10:39 Morgawr: great, thanks

10:42 atyz: manutter: it does, it breaks when its' trying to do the insert

10:43 justin_smith: Morgawr: that is if you explicitly want a vector, otherwise map is good because it is lazy

10:44 Morgawr: justin_smith: oh yeah, right, thanks

10:44 justin_smith: well, sometimes map is bad because it is lazy, but yeah, anyway that is the big difference in behavior I have seen

10:46 now I am realizing I should start using mapv in many places where I am using (doall (map ...))

10:47 hyPiRion: justin_smith: do you need the result?

10:47 if not, doseq is probably a better choice

10:47 (for the hashmap case, it obviously is, but in general)

10:48 justin_smith: hyPiRion: I am using doall because I need the result, and it needs to be calculated inside the context of a db connection that should be short lived

10:48 hyPiRion: ah

10:48 justin_smith: so laziness either makes the db connection stay open (bad) or makes things get calculated where the db connection is not bound (breaks things)

10:49 manutter: atyz: ok, I'm barking up the wrong tree then, sorry.

10:49 atyz: manutter: no worries, thanks very much for helping

10:49 justin_smith: but you know, mapping across a bunch of results from a db, how often would you need to do that, right :P

11:34 abp: leathekd: Thanks!

11:37 leathekd: abp: No problem! Let me know if you have any troubles.

11:50 abp: leathekd: Works like a charm. Just tested my middleware.

11:54 leathekd: Nice. Glad to hear it.

11:58 yacin: if i have a string that represents a byte array ("[B@3ecc05a6") how can i convert it back to the byte array?

12:02 mpenet: yacin: unless its base64, hex or some other string representation you cant. What you show doesn't look like any of these, it's just the .toString of a byte array right?

12:07 yacin: yeah, i believe so

12:10 justin_smith: yeah, you may want to actually convert the byte array to a form that actually preserves the information as a string (like mpenet mentions base64 or a string encoding of the hex values or something)

12:10 mpenet: if you have a byte array and you want to turn it into a String you can just pass it as arg to String constructor

12:10 ,(String. (.getBytes "foo"))

12:10 clojurebot: "foo"

12:10 mpenet: but that's very naive, not sure in what context you are

12:11 ,(.getBytes "foo")

12:11 clojurebot: #<byte[] [B@10fa2ec>

12:16 S11001001: mpenet: uses current locale's character encoding, not great for running on more than one machine

12:16 mpenet: yeah I know

12:16 you can pass the locale as 2nd param

12:16 I think

12:16 S11001001: yacin might not

12:17 you can pass the character encoding as 2nd param

12:17 Anderkent: mpenet: yes, you can pass an encoding to .getBytes or String.

12:18 yacin: thanks y'all. this is some weird environment specific issue

12:20 Anderkent: yacin: but still, you probably want to use something like commons.codec Hex if it's arbitrary bytes

12:20 since not every byte array is a valid string

12:20 mpenet: yacin: where do you get this byte-array from ?

12:22 Anderkent: and unfortunately String. does not tell you the decoding failed

12:22 ,(String. (byte-array (vector (unchecked-byte 200) (unchecked-byte 201))) "ASCII")

12:22 clojurebot: "??"

12:23 llasram: Was the 4 bytes of an IPv4 address, generated by some internal code, and inadvertently .toString'd. Nothing more to see here, please move along :-)

12:24 mpenet: ~guards

12:24 clojurebot: SEIZE HIM!

12:24 Anderkent: llasram: no worries. String/byte handling in general is something people often do wrong, so talking about it may help someone :)

12:25 the take away is always be explicit about your encoding, and always use utf-8 :)

12:25 mpenet: yeah I was wondering about the context, most of the time libs that force you to do that stuff come with some helpers

12:27 yacin: haha thanks llasram

12:51 Morgawr: do I need to have a local maven repository of I want to use a personal .jar file in my lein project?

12:51 because I'm developing both my application and a standalone library (on which my app relies) at the same time

12:52 technomancy: Morgawr: you have a local maven repository

12:52 in ~/.m2/repository

12:52 Morgawr: oh

12:52 neat

12:52 so I just put my .jar in there or..?

12:53 technomancy: just `lein install`

12:53 will put it there

12:53 Morgawr: ah cool, so from my .jar project I do "lein install" and then from my app I just include it in the dependencies?

12:54 technomancy: you should probably read `lein tutorial`

12:54 but yeah

12:55 Morgawr: alright, thanks, sorry for asking a naive question

12:55 I appreciate the help

12:55 technomancy: no worries

12:56 actually I'm not sure the tutorial covers this; hm

12:58 gtrak: Morgawr: I think there's a maven shortcut for installing a jar http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

13:01 Anderkent: Morgawr: alternatively, if your library is also a lein project, you can make it a checkout, so that you can develop both at the same time

13:02 kinda like maven subprojects, except without the more insane bits

13:03 gtrak: hey, I like the reactor!

13:04 Anderkent: gtrak: 'we'll dynamically add these artifacts to your build for some tasks, but not others'. :)

13:05 gtrak: ah, I haven't hit that one

13:05 Anderkent: I was recently trying to get a reactor project to fetch all external dependencies (so that I could cache them between builds). Can't be done, had to revert to mvn install

13:06 gtrak: oh, really? I was pretty sure I've done that before

13:07 Anderkent: the reactor is much like maven in general - it works at the beginning, but then as you're trying to do something more complicated you hit a wall with no way around it

13:07 gtrak: unless you mean something different by a reactor project

13:07 Anderkent: gtrak: well, it works if you already have the subprojects installed, so the build does not fail due to missing dependencies

13:08 gtrak: might have been a bug in a specific version, I'm like 100% sure that works

13:08 Anderkent: say you have Parent -> {A, B, C}, B depends on A, C depends on B. Trying to do `mvn dependency:go-offline` under Parent will fail because B cannot resolve A anywhere

13:09 gtrak: what's the { } signify modules?

13:09 Anderkent: yeah, 3 modules under Parent

13:10 gtrak: hmm, I'll try it right now

13:13 ah, wait, is this specific to dependency:go-offline? that would make sense in the context of your initial comment

13:13 Anderkent: yeah

13:13 gtrak: install or compile's always worked for me, I've never tried that other task

13:13 Anderkent: yeah, install and compile will work

13:14 which is good enough most of the time

13:14 so I'm not saying reactor is completely broken - just broken enough to be really annoying :)

13:14 gtrak: gotcha, I can believe that :-)

13:17 nfisher: Hi all, rather new to clojure. I have a large log file I want to process. Are agents what I should be looking at to process the file as I'm reading?

13:20 technomancy: nfisher: pmap is probably fine for that

13:21 gtrak: Anderkent: yea, it's broken as you described. fun.

13:21 nfisher: technomancy; thanks!

13:21 technomancy: nfisher: I wrote a version using agents here, but someone pointed out pmap does a lot better: http://technomancy.us/130

13:22 if you want absolutely bonkers performance you can push the JVM to much better I/O perf like _ato does here: http://meshy.org/2009/12/13/widefinder-2-with-clojure.html

13:22 dobry-den: Newbie question: I've been struggling with coming up with a simple way to transform [:ul "A" "B" "C"] into [:ul [:li "A"] [:li "B"] [:li "C"]].

13:23 nfisher: I suspect the DB insertions will be the bottleneck... I'll profile it to see.

13:23 dobry-den: I can trivially map [:li %] across the ul children, but I can't figure out how to unroll the result back into [:ul ...]

13:23 gtrak: dobry-den: into [:ul]

13:24 which is equivalent to reduce conj

13:25 Anderkent: ,(let [[head & rest] [:ul "A" "B" "C"]] (into [head] (map #(vector :li %) rest)))

13:25 clojurebot: [:ul [:li "A"] [:li "B"] [:li "C"]]

13:26 gtrak: if it doesn't need to be a vector, can simply cons head onto the result of map

13:26 dobry-den: Thanks guys. I feel sheepish having to come here for that

13:27 Anderkent: np that's what we're here for (pretending to be productive while avoiding actual work)

13:27 nathanielk: korma seems to infuriate more than help. has that been the experience of others? do i just need to stick it out?

13:28 gtrak: nathanielk: meh, keep things simple?

13:28 Anderkent: nathanielk: I've found it pretty nice for simple stuff (querying/inserting into a single db)

13:28 still fall back to execute-raw from time to time though

13:28 gtrak: I thought this was interesting: https://github.com/cgrand/sqrel along with just the clojure.java.jdbc

13:29 nathanielk: well, for example: i can't figure out how to convince it to insert default values into a column

13:29 Anderkent: nathanielk: surely that's the db engine's job

13:29 nathanielk: hrm, perhaps, but i have a hard time believing that such a simple and obvious use case is broken at a lower level than korma

13:29 jjttjj: how do people test validation in lib-noir? I remember noir had noir.util.test/with-noir but there doesn't seem to be anything like that in lib-noir

13:30 Anderkent: nathanielk: what's the query look like if you tell korma to print the sql

13:30 (i.e. as-sql or dry-run)

13:30 nathanielk: Anderkent: good question, I should be examining that.

13:30 I'll go stare at it

13:31 it's generating hardcoded values for the id column

13:31 ie not telling the database "use a default"

13:31 Anderkent: hm, can you post your code?

13:33 nathanielk: it's really simple: (insert jump-table (values rows))

13:33 where rows is [{:foo_id 1, :bar_id 2},...]

13:34 the generated query attempts to put in the foo_id and bar_id correctly but generates a 1-indexed id for the jump table's row

13:34 i mean, it can't get much simpler, which is why i'm assuming that i'm doing something wrong

13:34 i just can't find any documentation to help me

13:36 dobry-den: are columns foo_id and bar_id not integer datatypes?

13:38 nathanielk: dobry-den: they are.

13:38 Anderkent: nathanielk: it's hard to say without seeing your code. It shouldn't be doing this, quick browsing through korma source doesn't find where that happens

13:40 nathanielk: Anderkent: well, thanks for thinking about it :) i'll start reading korma's source

13:42 Anderkent: are you completely sure your rows does not contain {:id} fields?

13:42 the simplest test case seems to work for me: https://www.refheap.com/15155

13:43 nathanielk: yeah, they don't

13:43 so I just ran the raw insert in psql without specifying an id and it did the bad thing.

13:43 korma is vindicated.

13:44 so i'll stare at my schema now :)

13:52 dobry-den: when does it make sense to embed functions with let/letfn vs specify them as private functions?

13:53 i like the idea of letfn, but i don't like losing the ability to sanity check it in the repl

13:53 ToBeReplaced: dobry-den: when they only make sense within the scope of the function

13:53 technomancy: dobry-den: if you have any hesitation, make it a top-level

13:54 ToBeReplaced: no one will ever complain about moving a letfn to a defn- though

13:54 * technomancy hates letfn for indentation reasons

13:54 ToBeReplaced: technomancy: what's the indentation problem? seems to work fine in emacs?

13:56 technomancy: sorry, not indentation, but rather breaking readability rules of clojure

13:56 hiredman: "rules"

13:56 technomancy: for nearly every other non-toplevel forms, any open paren followed by an identifier indicates a call

13:57 this is part of why clojure is more readable than other lisps that use parens for everything with no brackets

13:57 ToBeReplaced: good point; that's something that irks me about "case"

13:59 technomancy: I don't like case either, but I don't think it has this problem

14:00 ToBeReplaced: grouping multiple constants happens in a list literal, which is not a function call

14:00 technomancy: oh, interesting

14:00 I've never seen it used that way

14:00 but it sounds annoying

14:02 justin_smith: yeah, I definitely read it wrong the first time I saw it

14:02 especially when a vector literal would do the same thing in terms of show intent

14:02 unless you wanted the case to match a vector?

14:07 tomjack: &(case (list 1 2) [1 2] 3)

14:07 lazybot: ⇒ 3

14:07 dobry-den: The simplest way I can think of to turn "* abc" into "abc" is (join (drop 2 "* abc"))

14:07 gtrak: dobry-den: I think letfn makes mutual recursion more trivial, also, you don't have to indirect through a var, so it's a teensy bit faster

14:08 dobry-den: I didn't mean to hit enter

14:08 gtrak: that said, my coworkers look at me like I'm crazy when I use it for not-small things

14:08 hyPiRion: ,(subs "* abc" 2)

14:08 clojurebot: "abc"

14:08 hyPiRion: dobry-den: ^

14:08 jtoy_: clojure is da bomb!

14:09 dobry-den: hyPiRion: Thanks. Is there a way to browser Clojure functions by category like this: http://ruby-doc.org/core-2.0/Enumerable.html

14:10 hyPiRion: the cheatsheet is probably the closest one: http://clojure.org/cheatsheet

14:11 dobry-den: Cool. I found my next sideproject then

14:13 amalloy: technomancy: don't forget all the open parens in deftype, reify, defprotocol, and that family. and in catch/finally. and in specifying multiple arities for a defn. and in ns specifiers.

14:14 gtrak: clojure.test (is (thrown?

14:15 technomancy: amalloy: I did scope it to non-toplevel things

14:15 I think of catch and finally as macro calls FWIW

14:15 even though there's technically no var behind them

14:15 gtrak: thrown? isn't a real thing.. is a multimethod dispatch on a symbol

14:15 technomancy: gtrak: thrown? is horrible

14:16 it should be a macro, but it's not

14:16 amalloy: technomancy: reify is as non-top-level as letfn

14:16 technomancy: amalloy: yeah, reify is the one exception

14:16 aaelony: Does anyone know of a clj or cljs library that faciliates a pivot table interface? e.g. something like http://gumption.org/2004/pivot_table/test_page.html or http://www.iccube.com/products/contributions/gwt-pivot-table for the result of any database query?

14:16 technomancy: well, probably proxy too

14:16 clojurebot: proxy is not reify

14:16 amalloy: proxy is awful for other reasons

14:16 technomancy: yeah

14:16 amalloy: i won't use it as supporting evidence for my case

14:18 and of course function arities are also not top-level things

14:19 technomancy: amalloy: function arities don't have an open paren followed immediately by an identifier though

14:19 amalloy: oh, i missed the "followed by"

14:20 Foxboron: So, anyone know of any libs that could maybe use a hand? Planning on working on open-source projects this summer. (pretty much a newbie in Clojure)

14:23 gtrak: what are you interested in?

14:24 Foxboron: well, everything really.

14:24 Just wanna try enhance my knowledge in Clojure.

14:24 technomancy: Foxboron: clojars could use some help

14:24 also clojuredocs.org

14:25 Foxboron: hm, i'll try take a look. Thanks!

14:26 technomancy: Foxboron: I don't have a readily-accessible list of TODOs for clojars, but I can definitely try to put something together if you want to help out

14:26 Foxboron: technomancy: looking at clojars i think i will have a tought time trying to set myself into the code.

14:27 But a todo would be awsome.

14:27 technomancy: apart from the maven interop it's a pretty standard compojure app, if a bit dated

14:37 rbxbx: Foxboron: I know devn is looking for help on https://github.com/devn/getclojure || getclojure.org

14:38 trptcolin: Foxboron: a text-mode api for clojuredocs would be awesome

14:39 because i'd love to have that feature back to being included by default (w/ no extra dependencies) in REPLy / lein repl

14:40 Foxboron: hm, i don't got that much experience with clojure, but all of it are interesting projects

14:40 Ill do my best and see if i can contribute

14:45 konr: In http-kit, what's the correct way to handle redirects? It's not parsing the body of a 301 response, right?

14:54 nevermind, it's an issue with probably a patch :) https://github.com/http-kit/http-kit/issues/35

15:17 llasram: Blargh, why do github "deploy keys" provide full read/write access to the repository?

15:29 arrdem: is there a way to "live inject" dependencies to nrepl, or do I have to restart when I add new deps?

15:33 abp: arrdem: https://github.com/pallet/alembic

15:40 tomjack: what about making @ and #' and maybe ` put metadata on the forms read to record their having been used?

15:41 I suppose also '

15:41 but '1 and `2 are problematic..

15:41 amalloy: tomjack: not really, because '1 reads as (quote 1)

15:42 a form onto which you can put metadata if you like

15:42 tomjack: oh right

15:44 hmm looking at "not so homoiconic" again it looks like there are enough other problems that the metadata would only be useful for evil macro authors

15:45 i.e. we need sjacket anyway so no point..

15:49 cch1: Which protocol(s) must one support in order to allow destructuring as a map?

15:50 arrdem: abp: awesome, thanks!

15:51 amalloy: cch1: ILookup is all, i think

15:51 cch1: amalloy: thanks. Any idea of where I might find an example?

15:53 amalloy: $google clojure ilookup

15:53 lazybot: [Overloading keywords in Clojure - Stack Overflow] http://stackoverflow.com/questions/5583841/overloading-keywords-in-clojure

16:13 cch1: amalloy: thanks.

16:21 tomjack: I wonder why reduce-kv isn't the primitive

16:22 backwards-compatible reduction over map seqs would incur an extra map-entry allocation I guess

16:22 and you have an extra function maybe to drop the k for reduce

16:22 but are there important things which can be IReduce but not IKVReduce?

16:23 I'm just imagining stick a counter in all those places I guess..

16:59 Kowboy: <- just found out the hard way that 'empt' and 'empty?' functions both exist and do vastly different things. DOH!

16:59 *empty

17:00 in particular (when (empty {somthing here}) ...do something...) always does something

17:01 bbloom: Kowboy: heh, yup. whoops!

17:03 AWizzArd: Does Clojure support float literals? 13.0f vs (float 13.0)

17:05 Kowboy: I don't think it does. You get doubles by default

17:05 AWizzArd: yes

17:06 Kowboy: java.lang.NumberFormatException: Invalid number: 13.0f

17:06 AWizzArd: Yes, the “f” does not work. Was just an example, maybe there is some other syntax to denote floats.

17:07 dnolen: AWizzArd: not that I'm aware of.

17:07 Kowboy: are you integrating with a Java API that uses floats everywhere?

17:07 gzmask: clojurers, i got a list of mix symbols (:t1 :note1 :t2 :note2 ...) representing a song. (pairs of time and note to be play. I can only think of (doseq). what is the best fit for this kinda sets?

17:07 ohpauleez: Yeah, you can do hex and big int, thats all

17:08 rather, that's all I can think of

17:09 Kowboy: question about ^:dynamic vars vs using delay

17:09 ohpauleez: and by 8

17:09 ,010

17:09 clojurebot: 8

17:09 ohpauleez: ,0xa

17:09 clojurebot: 10

17:10 ohpauleez: ,1M

17:10 clojurebot: 1M

17:10 llasram: ,2r0101010

17:10 clojurebot: 42

17:10 ohpauleez: radix

17:10 Kowboy: I've been using delay refs so I can prevent them from loading until needed

17:10 patchwork: ,3r012012

17:10 clojurebot: 140

17:10 Kowboy: but I'd likt to change the value of the delay ref, for example in a test

17:10 is this possible?

17:12 ohpauleez: Why not just pass things in?

17:12 to the function

17:12 or pass along a context map?

17:12 llasram: Kowboy: For testing, you can mock with `with-redefs`

17:13 Kowboy: excellent, that is what I need

17:13 ohpauleez: yeah, with-redefs is the best bet if you truly want the behavior you're looking for

17:13 llasram: If you want changes for other than testing, then ohpauleez is probably right

17:13 Kowboy: I was using dynamic vars, but the initial root bindings would blow up in my unit tests

17:14 they were generally dependent on a config file

17:14 but in my tests, I wanted to pass in my own configuration

17:14 melipone: hello! I am trying to use pmap (instead of map) but it seems to be slower than map. Is that possible?

17:14 Kowboy: problem was, requiring the namespaces forced the root bindings to execute

17:14 GeorgeH: I'm considering learning closure to implement a format converter, am I crazy or wasting my time? The program will read a json file with design data, then render it to CNC toolpaths. This will be my first dive into functional languages, so I'd appreciate any warnings! Thanks :)

17:14 ohpauleez: melipone: Definitely

17:15 melipone: ohpauleez: why?

17:15 Kowboy: so I changed them to (def something (delay .....)))

17:15 ohpauleez: GeorgeH: Go for it! That sounds a great project for Clojure

17:15 Kowboy: I'd consider the refactor, given that scenario

17:16 melipone: How many item are in the sequence/collection you're mapping on?

17:16 Kowboy: I was trying to refactor to something that works both in my production scenario, and for testing/playing at the repl

17:16 GeorgeH: Awesome! Very reassuring, cheers

17:16 melipone: 3500 items

17:17 ohpauleez: Kowboy: I think passing in a context (a map of defs you currently have) might be the way to go

17:17 melipone: What's the function doing?

17:17 Kowboy: that would be a significant refactor

17:17 tomjack: bbloom: so I forget your recommendation about promises wrt core.async - if I resurrect a promise-like type, should it implement ReadPort/WritePort with different semantics than channels? right now I have Await and Deliver whose interfaces are exactly like ReadPort and WritePort

17:18 hard to tell what the acceptable scope of meanings for <! and >! are

17:18 AWizzArd: Kowboy: it’s for CUDA code that works with floats. Would just be handy to add something like an “f” to the end of a number to let Clojure know it’s a Float.

17:19 Kowboy: perhaps what I need to do is have my ^:dynamic vars default to nil, then bind them in my "main" method

17:19 melipone: well, it's 3500 functions executed several times. The functions are very simple like check for equality of strings.

17:19 AWizzArd: In principle there could be literals for chars, shorts, floats and ints ==> 1c 2s 3f 4i

17:19 Kowboy: and then use a test fixture to also bind them for testing

17:20 bbloom: tomjack: a promise is like a (delay (repeatedly value)) channel

17:20 melipone: ohpauleez: why would pmap be slower than map?

17:20 tomjack: oh, right, I didn't consider that such things could be called 'channels'

17:20 but the put! semantics are different I think?

17:21 Kowboy: simple functions run through pmap will be slower because of the overhead of threading

17:21 bbloom: tomjack: i'm not sure what the resource management implications are, but you can implement this w/o any custom types

17:21 Kowboy: only when the functions take significant time will you get a performance benefit

17:22 tomjack: core.async seems to use channels which emit the value and then close

17:22 bbloom: tomjack: give me a moment, let me experiment on this

17:22 tomjack: oh, I see, you mean make a process which takes from some channel and then goes into an endless put loop?

17:23 bbloom: tomjack: yeah, exactly

17:23 i dunno if it's actually useful, but that's essentially what a promise is in terms of channels

17:23 using (chan 1) so it blocks

17:24 the problem then is you need to somehow garbage collect that put loop…. dunno how that works

17:24 tomjack: I have another problem with that: if you accidentally use a normal channel where you thought you had a promise, all the nice guarantees of promises disappear, but the code will still run

17:25 ohpauleez: melipone: You might want to chunk your collection into number-of-cores+2 chunks

17:25 this will mean that each chunk is in its own thread when you run pmap

17:26 tomjack: just convinced myself to keep a separate interface for reads but the same one for writes, then my promise type can implement ReadPort as well by acting like a (repeat value) chan

17:27 melipone: ohpauleez: oh, I see, thanks for the hint. I'll try that. My code really needs to speed up.

17:27 tomjack: although :/

17:27 ohpauleez: Kowboy also filled in the reason - the overhead of allocating a new future, running it, and deref'ing it is outweighing the execution time of your function

17:27 melipone: You might also just try reducers, and see if being eager in the map helps (with fewer allocations)

17:28 again, depends on that function you're mapping

17:28 tomjack: bugs with (repeat value) chans are pretty dangerous (certainly to my emacs' health at least, and probably someday to a browser's..)

17:28 ohpauleez: AWizzArd: You could use reader literals

17:31 gzmask:

17:31 why (= [[1 1] [2 2] [3 3]] (map list [1 2 3] [1 2 3]))

17:31 melipone: ohpauleez: i heard about reducers

17:31 ohpauleez: what does "being eager in the map" mean?

17:31 tomjack: &(= [1 1] (list 1 1))

17:32 gzmask: but (map list [1 2 3] [1 2 3]) eval to ((1 1) (2 2) (3 3))

17:32 tomjack: sequential collections form an equality partition

17:33 bbloom: tomjack: refheap seems slow right now. anyway, here's an experiment: https://gist.github.com/brandonbloom/5681362

17:33 ehaliewicz: looks like it's down actually

17:33 gzmask: tomjack: ah, i see

17:33 ohpauleez: melipone: Maps are lazy by default, they return a LazySeq

17:34 technomancy: o_O

17:34 ohpauleez: map

17:34 the fn

17:34 haha

17:34 not Maps, the HashMap

17:35 melipone: ohpauleez: okay, thanks

17:35 technomancy: oh english... you definitely need a bugfix release

17:35 pjstadig: or perhaps the nomenclature of functional programming language

17:35 tomjack: I guess the resource problem is that the blocked put! action in the state machine will hold onto the promise channel?

17:35 technomancy: pjstadig: but I want a plural you and exclusive we too

17:36 pjstadig: technomancy: can't help you there

17:36 technomancy: at least you didn't say "yall"

17:36 pjstadig: hey now!

17:36 i reserve the right to say y'all

17:36 ztellman: bbloom: wouldn't a better approach be to just create a custom channel that only allows a single put!, and an arbitrary number of take! calls?

17:37 technomancy: pjstadig: what you do in the privacy of your home is your own business

17:37 pjstadig: technomancy: besides everyone knows that the plural of "y'all" is "all y'all"

17:37 tomjack: I'm worried that doing that will confuse CSP semantics

17:37 * technomancy 's head explodes

17:37 hiredman: itym "youse"

17:37 bbloom: ztellman: depends on how you define "better". if you define it as "performs better & doesn't leak memory" then yes ;-) but if you say "gets the job done w/o me having to implement a lock"…

17:37 ztellman: better still: don't use promises

17:38 pjstadig: hiredman: this is most definitely a yankeeism

17:38 tomjack: there's a mutex in core.async, so the impl is quite simple I think

17:38 bbloom: ztellman: promises are a expression-oriented idea, but channels are an procedure-oriented idea

17:39 tomjack: yes, this is why I don't want to use channels as promises :)

17:39 ztellman: bbloom: you'll need to expand on that a bit

17:39 tomjack: it's hard for me to imagine programming with result channels that emit the value once and then go nil

17:39 bbloom: 1 sec, brb

17:39 ohpauleez: Maybe he means in channels, order is implied?

17:39 bbloom: or ok i'm here now. the person that needed me just 1 seconded me :-P

17:40 what i mean is that promises are a reification of a lazy evaluation thunk

17:40 channels are a reification of a communication link

17:40 lazy evaluation is all about ignoring order and the demand driven nature of the world

17:41 channels have inherent sequencing

17:41 i'm saying that "pure and functional" isn't the be all end all of problem solving techniques

17:41 ztellman: well, not if you read from multiple channels at once

17:41 but I take your meaning

17:41 bbloom: it's OK to write some procedural call if what you are modeling is actually a proceedure

17:41 tomjack: bbloom: sure, but neither is CSP :)

17:41 bbloom: procedural code*

17:41 sure, CSP is about a bunch of little machines talking to each other

17:42 each machine is a procedural message pump. ideally, the logic in there is functionally pure

17:42 gzmask: ok... another question: how do i make this: [0 1 2 3 4 5] -> [[0 1] [2 3] [4 5]] ?

17:42 bbloom: push your procedural code to the fringes of your system: but don't try to eliminate it completely

17:42 jouiswalker: use partition

17:43 tomjack: bbloom: I completely agree

17:43 ztellman: bbloom: so how do these two models interact?

17:43 tomjack: you made me realize though that my imagined frustration with 'result channels' was just an imagined misuse of the

17:43 ToxicFrog: ,(partition 2 [0 1 2 3 4 5])

17:43 tomjack: them

17:43 clojurebot: ((0 1) (2 3) (4 5))

17:43 tomjack: I guess you do 'put argument in, take return value out'

17:43 gzmask: ToxicFrog: thanks

17:43 bbloom: ztellman: "evaluate this function" is a procedure

17:43 tomjack: and passing around a channel as a representation of an eventual return value is wrong

17:44 bbloom: tomjack: yeah, i'm not sure how i feel about the returns-a-channel behavior of core.async

17:44 single item channels just feels wrong to me

17:44 tomjack: ..so what should it return? :)

17:44 jouiswalker: is the repl the best way to do development with seesaw?

17:44 ztellman: there's been parallel work on async promises

17:45 weirdly, it seems completely disjoint from core.async

17:45 bbloom: tomjack: it should return a value, not a reified promise. that's what golang does

17:45 tomjack: it got replaced

17:45 patchwork: couldn't a single item channel be interpreted as a constant channel?

17:45 tomjack: cljque used to be in core.async

17:45 patchwork: A channel that never changes

17:45 tomjack: bbloom: but what about CLJS?

17:45 bbloom: tomjack: if you use macro magic to make that work & the single-item channels are an impl detail, that's probably fine

17:45 tomjack: i dunno, this shit is hard heh

17:45 tomjack: yeah :(

17:46 bbloom: tomjack: more macros & more SSA or CPS rewriting

17:46 tomjack: I'm writing new SSA for await/deliver now

17:46 shriphani: hi I have a clojure selector that looks like this but I am not sure the attr-has usage is correct. Can someone take a look: http://pastebin.ca/2385417

17:46 ohpauleez: ,(mapv vec (partition-all 2 [0 1 2 3 4 5]))

17:46 clojurebot: [[0 1] [2 3] [4 5]]

17:46 shriphani: enlive select *

17:46 ohpauleez: gzmask: ^

17:47 jouiswalker: ,(doc mapv)

17:47 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

17:47 ohpauleez: if you really want vectors for some reason

17:47 jouiswalker: huh

17:47 thats really nice

17:47 tomjack: unfortunately the current alt ioc will not cooperate with my efforts since it specifies async-chan-wrapper in its impl

17:47 jouiswalker: ,(mapv identity (partition-all 2 [0 1 2 3 4 5]))

17:47 clojurebot: [(0 1) (2 3) (4 5)]

17:49 bbloom: tomjack: ztellman: one of the things i don't like about the C# approach is that it creates ITask (aka listenable promises/futures) objects everywhere

17:49 tomjack: ztellman: but most of the time, you don't ever care about the promise object, just the contained value

17:50 promises are useful, but only a tiny portion of the time :-)

17:50 tomjack: yes, the @ is a wart caused by lack of static types :P

17:50 ztellman: bbloom: yes, but where the promise is generated and where it's consumed can be different places

17:51 allowing that to be decoupled can be useful

17:51 though certainly not always

17:51 ohpauleez: I agree with that

17:51 certainly not always, but nonetheless useful

17:51 justin_smith: what's the best way to provide a literal string to something that I would normally give a file handle to read from? (instead of creating a file just so it reads those contents)

17:51 jouiswalker: ,(symbol? '+)

17:51 clojurebot: true

17:51 bbloom: ztellman: like i said, if channel or promise objects are an impl detail, that's fine. i just don't think that object should always be exposed to the user on normal cases

17:52 tomjack: I think go returning a channel makes sense to me if all your processes return nil

17:52 bbloom: go doesn't have promises, but you can block on a channel and return a value & you get … a VALUE… not a channel, but still the runtime needs to yield

17:52 tomjack: and take chan in/out args or something

17:52 bbloom: internally, they are parking goroutines… internally core.async is returning a channel and scheduling a callback

17:52 tomjack: hmm, no, that still doesn't make sense to me

17:53 jouiswalker: does anyone here think they would benefit from a 4clojure clone for sicp?

17:53 ohpauleez: I haven't used it in a production system, so I have no idea the implications of the design decision

17:54 jouiswalker: http://sicpinclojure.com/

17:54 tomjack: my goal is to never have to use the promise impl methods except in the promise library impls

17:54 jouiswalker: i'm aware of it

17:54 ohpauleez: I'd just make the effort to fill that out

17:54 tomjack: you still have to worry about whether a fn returns a promise or not though

17:54 ohpauleez: and then make a scraper/generator to generate problems from the code

17:55 jouiswalker: but what theyre doing is rewriting a book

17:55 tomjack: oh and I think you still have to tell the ioc that you want to block on a promise with await or @ or whatever. but that's all I want to do to a promise, return it or @ it inside ioc

17:55 jouiswalker: i just mean a collection of test cases and such for the exercises

17:55 ohpauleez: jouiswalker: You read SICP and use the site to see the code in Clojure, then practice your skills more with generated 4clojure style problems

17:56 bbloom: tomjack: yeah, adding await to participate in ioc gets you most of the way there. it's essentially exactly what C# does… C# has this exact same IOC idea w/ reified promises instead of reified channels

17:56 tomjack: channels are more general, but that has it's pros and cons

17:56 ztellman: tomjack: either you go all the way and do dataflow IOC that treats promises and realized values interchangeably, or you need some convention for what's returned

17:57 I'm not sure there's a third option

17:57 tomjack: 'going all the way' I think is infeasibly with core.async's ioc-macros

17:57 bbloom: tomjack: but if you never read from a promise twice, you just <! on the channel and not care

17:57 jouiswalker: oh do they plan on implementing test cases?

17:58 tomjack: I guess the ! is right there on the tin. so treat it like you would a transient, non-shareable

17:58 bbloom: tomjack: which a simple (let [the-value (<! a-channel-like-promise)] ….) gets the job done

17:58 jouiswalker: i'll check with the developer of the project

17:58 ztellman: tomjack: I haven't read ioc-macros closely enough to tell, but it's certainly doable with the core.async <! mechanism

17:58 bbloom: tomjack: exactly. the advantages of promises is that that dereferencing them is idempotent.

17:58 jouiswalker: thanks for making me take a closer look

17:58 Licenser: hey guys :) quick question, by brother wants to learn some clojure, he is entirely unexperienced with programming and I wonder what resource would be the best to start with?

17:59 tomjack: ztellman: the problem I see is that every single sub-expression under ioc will get CPS'd

17:59 jouiswalker: http://java.ociweb.com/mark/clojure/article.html

17:59 ohpauleez: Licenser: Chas's book

17:59 tomjack: or.. SSA'd

17:59 technomancy: Licenser: I don't believe there are good resources for people who aren't already programmers.

18:00 tomjack: so like (go-promise (+ 1 2)) will have to have 4 take!s

18:00 unless you try to do inference about what's "trivial"

18:00 Licenser: technomancy awww

18:00 tomjack: which does not seem like fun to me without gradual types or something

18:01 ztellman: tomjack: agreed, back in the day when I took a run at the IOC macro, the idea was it would only be used at the top-level of a program

18:02 but even then, you need instrumentation to understand what intermediate state the dataflow's in

18:02 that's a lesser problem with the non-dataflow IOC (though still one that needs to be solved)

18:02 bbloom: tomjack: ztellman: i took the trivial vs serious approach w/ the CPS transform attempt i did

18:02 i had a macro called "spawn" which was essentially "go"

18:02 jouiswalker: Licenser: you might ask him to do the first two or three chapters of practical common lisp to get him used to the syntax

18:02 tomjack: yeah that was enlightening

18:03 the paper was unintelligible to me iirc

18:03 bbloom: it took me a while, yeah

18:03 technomancy: Licenser: htdp.org looks interesting for new programmers

18:03 bbloom: i think SSA was a better call, but i was hung up on going the CPS route for some reason

18:04 tomjack: my cljs tests so far of very simple go blocks have produced seemingly very large functions

18:04 bbloom: more over, i was dead set on supporting pluggable control structures, which is something i suggested to rich, but i think it was a better short term call to avoid that and go with a fixed set of primitives for v1

18:04 Licenser: guys you're awesome :)

18:04 tomjack: ioc-macros is obviously alpha and probably needs adjusting for cljs

18:04 bbloom: lastly, reified channels greatly simplifies the problem of "what do you do with return values?" when you have CPS, a continuation is NOT A FUNCTION. it isn't supposed to return & you need to pass the continuation to a function

18:04 gzmask: how do i construct as list by adding up part of another list like: [0 1 1 2 1 2 1] -> [0 1 2 4 5 7 8]?

18:04 tomjack: but we better be damn good at inferring triviality I think

18:05 ..or ^:trivial (+ 1 x) ?

18:05 bbloom: tomjack: well the brilliant part of SSA (as compared to CPS) is that you can do a single level of SSA

18:05 you rewrite ONE function into a state machine

18:05 rather than have to thread the CPS all the way through to the bottom

18:06 onthestairs: hmm, do i have a fundamental misunderstanding of core.logic? im trying to implement a simple solver which returns any functions from a list which are increasing

18:06 tomjack: ok, the function I am rewriting is (fn [in out] (let [x (<! in)] (>! out (+ x 42))))

18:06 onthestairs: https://gist.github.com/onthestairs/5681569

18:06 bbloom: i had attempted prior to studying golang, hadn't considered channels, and chose CPS over SSA. all of those mistakes are obvious to me now :-P

18:06 tomjack: well, no, channels won't be a good example

18:06 my worry applies in the 'go all the way' dataflow case

18:06 dnolen: onthestairs: gist

18:07 jouiswalker: has anyone here played with avout?

18:07 dnolen: onthestairs: oh sorry you pasted

18:07 onthestairs: dnolen: no worries, cheers

18:07 tomjack: oh, hmm, I see

18:07 I just tried an example and it seems to work out better than I thought

18:08 ohpauleez: ,(reductions + [0 1 1 2 1 2 1])

18:08 clojurebot: (0 1 2 4 5 ...)

18:08 technomancy: Licenser: racket's error messages are so much better than clojure it's ridiculous. there are actually several different levels of beginner mode you can put it in to get simplified vs detailed error messages.

18:08 ohpauleez: gzmask: ^

18:08 tomjack: vars are tricky

18:08 technomancy: huuuuge contrast vs clojure's "I dunno; here's some compiler guts you can look at I guess"

18:08 dnolen: onthestairs: hrm, yeah that doesn't make sense.

18:08 tomjack: (fn [x] (add x 42)) - should we await! on add?

18:08 gzmask: ohpauleez: I known reduce but reductions are cool! thx!

18:08 dnolen: onthestairs: why are you projecting g?

18:09 Licenser: technomancy hmmm hmmm

18:09 tomjack: other problem is how to let functions have trivial return values

18:09 dnolen: onthestairs: you should probably project f which will be bound to a fn

18:10 technomancy: Licenser: there are some stupid things too (no docstrings, no callable hash tables by default) but for beginners it's a drastically better place to start

18:10 Licenser: technomancy my brother says 'nahh I already fell in love with clojure' <-that's good feedback I guess ;)

18:10 I'll just have to help him out more ^^

18:10 onthestairs: dnolen: im not sure. i think i have a fundamental misunderstanding

18:10 technomancy: heh; well that works too; it just means he'll need more help from you rather than reading texts

18:10 hah, exactly

18:10 onthestairs: dnolen: is there a good reference page for project

18:11 Licenser: technomancy I think I'll have to get him a IRC client :P

18:11 tomjack: bbloom: your point has analogy to lazy seqs I think - they support exactly the same value-oriented functions as their forced values

18:11 technomancy: Licenser: if you can shoulder-surf from someone experienced who is patient then you can learn anything =)

18:11 Foxboron: ummm

18:11 tomjack: ..by bundling in a procedural notion?

18:11 Licenser: technomancy true!

18:11 Foxboron: I don't know Clojure that well. But i could help out mentoring another guy (Ref: technomancy Licenser)

18:12 mentored a few people in Python. Might as well be a good learning experience

18:12 dnolen: tomjack: heh core.match generates a lot of JS too. I imagine people will restrict go blocks to the bits of the program that are actually async no?

18:12 technomancy: it just doesn't scale well

18:12 tomjack: dnolen: yes, but not every subexpression of those bits will also be async

18:12 bbloom: tomjack: yeah, but that only works b/c seqs are protocols. if you wanted to do that w/o a seq you'd need to proxy/delegate all the same interface methods :-/

18:12 dnolen: onthestairs: tomjack yes but I can't imagine it will matter, if it's async it's likely IO bound

18:12 Licenser: Foxboron that's cool :) so I don't want to put that on anyone but me :) but I'll send him to the channel non the less, learning clojure is after all also about learnign the community ^^

18:13 dnolen: and people will move out big expressions into fns as usual.

18:13 onthestairs: dnolen: oo nice, i have got it working. thanks

18:13 tomjack: maybe it would be OK

18:13 Licenser: plan is that we're going to do a little project together to learn some stuff, so it's more about learning the very basics so he's not staring blankly on the screen all the time ;)

18:13 tomjack: I mean I think current core.async go w/ channel output is probably OK

18:14 Foxboron: Licenser: teach him gist maybe?

18:14 Licenser: also, clojure-koans is a good place IMO

18:14 tomjack: to be clear I was discussing a different ioc macro which lets any subexpression return a single-assignment dataflow variable transparently

18:14 Licenser: Foxboron gist?

18:14 dnolen: tomjack: based on the Node.js crap I've had to right, I'm pretty sure it's OK

18:14 write

18:14 Foxboron: Licenser: https://gist.github.com/

18:15 Licenser: Foxboron oh hah! okay I wasn't thinking that simple ^^

18:15 tomjack: (which I have not really seriously considered in a long time)

18:15 (not that I have very good reasons not to)

18:15 Foxboron: Licenser: it is not git, but it helps him keep track of his files, changes etc.

18:15 ztellman: tomjack: if you confine the dataflow to a function, and force the function to return a realized value

18:15 Licenser: Foxboron yea I know them just thought you mean something else :)

18:15 technomancy: speaking of things that are horrible for newcomers... git =(

18:15 bbloom: personally, i like implementing services as explicit state machines operating on sequences of messages… but i'm a crazy person :-)

18:15 tomjack: these functions can't return realized values in cljs

18:15 maybe I misunderstand?

18:16 dnolen: tomjack: they cannot

18:16 ztellman: oh, I missed the cljs bit

18:16 yeah, that's a trick

18:17 is there a js-land full dataflow transformer, or do they all use some variant of 'await'?

18:17 I've only seen the latter

18:17 Foxboron: technomancy: it is horrible for other people too. Used git every day for almost a year. I still fuck something.

18:17 dnolen: ztellman: no, there are blocking reads in JS and there will be no tricks. All read/writes on channels must be in go block

18:17 there are no blocking reads

18:17 I mean

18:17 er reads/writes

18:18 tomjack: they have no macros so I would not be surprised if they haven't done it..

18:18 jouiswalker: foxboron: do you have something you prefer over git?

18:18 Licenser: technomancy Foxboron got him sourcetree, it makes it mostly barable I think

18:18 Foxboron: jouiswalker: I actually like git. But i always manage to fuck something up.

18:18 jouiswalker: foxboron: hehe

18:19 tomjack: it's interesting how "transparent" can mean both "you can't see it" and "you can see it clearly"

18:20 ztellman: tomjack: http://en.wikipedia.org/wiki/Auto-antonym

18:20 tomjack: :D

18:20 dnolen: ztellman: maybe await, but I didn't hear rhickey mention that

18:20 ztellman: dnolen: where was this discussed?

18:20 Licenser: And there we are :) may I introduce my brother SomeOtherGuy!

18:20 jouiswalker: tomjack: isn't it supposed to be an intermediate between tranlucent and opaque?

18:20 dnolen: ztellman: rhickey's been popping into the channel talking about the core.async stuff now and then

18:20 SomeOtherGuy: Hey guys! :)

18:20 jouiswalker: translucent*

18:21 noprompt: if anyone wants a good laugh i hand rolled a little migration lib for korma https://gist.github.com/noprompt/5681539

18:21 technomancy: SomeOtherGuy: welcome

18:22 noprompt: for the record, i have no idea what the hell i was doing or how those things should work.

18:22 jouiswalker: noprompt: that is beautiful

18:23 noprompt: jouiswalker: you're being sarcastic, right? :)

18:23 jouiswalker: noprompt: its better than what i manage :3

18:24 noprompt: honestly though, i'd love to know how to actually build something like this correctly.

18:24 tomjack: noprompt: my gripe is that all the migrations are collected into a global atom

18:24 noprompt: tomjack: yeah, i didn't know how else to do it.

18:25 jouiswalker: noprompt: you might be able to use some partials with append-x and such

18:25 SomeOtherGuy: Sorry If I'm not very communicative. Try to understand things that seem to be above my intellect!

18:25 noprompt: tomjack: so what would be the alternaive?

18:27 tomjack: a cheap fix would be to key the entries in the global somehow by user-specified keys

18:27 and allow the user to somehow pick out the migrations to run with migrate!

18:27 but I don't like that either

18:27 simple thing seems to be to just have the user pass a collections of migrations to run?

18:27 ..but I haven't ever tried to write a migration library, so.. if it works for you, great :)

18:29 noprompt: so let me grab an example of the usage

18:30 jouiswalker: are there any deprecated lein plugins that someone would like to see renovated?

18:32 i want to relieve boredom by making something useful :/

18:32 tomjack: jouiswalker: no, but I want to see a new one for generic run-task-on-file-change watches

18:32 jouiswalker: whats the current one and how would you like me to change it?

18:33 tomjack: there isn't a current one really

18:33 jouiswalker: :x

18:33 tomjack: cljsbuild has an 'auto' which I don't like much

18:33 there are sketches of how to use the java 7 file watcher stuff in clojure

18:34 I started a project for this 'lein-auto' but spent only about 15min so far on it..

18:34 hmm


18:35 jouiswalker: is your work on github?

18:35 tomjack: I realize now that could be a lot trickier than I thought

18:35 jouiswalker: i just see a couple forks :p

18:35 tomjack: no, I have barely anything at all

18:35 15min was mostly taken up by trying to grok the file watcher api

18:36 then I stopped and said "hey, cljsbuild is working"

18:36 jouiswalker: lol

18:36 i'll try my hand at it

18:37 tomjack: I wonder if you can start up a project jvm, keep it running, and eval-in-project multiple times?

18:37 ztellman: tomjack: I think eval-in-project creates a new environment each time

18:37 you'll need to eval something which runs a background process within the project

18:37 tomjack: well I guess you can start up an nrepl thingy

18:37 ?

18:37 justin_smith: anwsering my own question above (def to-stream (fn [s] (io/input-stream (.getBytes s))))

18:38 ztellman: though there are other people who can speak more authoritatively about this than me

18:38 tomjack: yeah, makes sense

18:39 noprompt: tomjack: i've updated the gist with a little example at the bottom

18:40 jouiswalker: you should write a shell in clojure :) how's that for a fun project

18:40 tomjack: noprompt: yeah, looks nice and pretty simple except for the globals :)

18:40 jouiswalker: nopromt: eww haha

18:44 noprompt: jouiswalker: well it could be fun.

18:44 jouiswalker: noprompt: maybe a parser that converts s expressions to bash calls or something lol

18:45 noprompt: jouiswalker: also, if you know a thing or two about css you could help me improve my CSS lib which i haven't had much time for lately :*(

18:45 jouiswalker: noprompt: garden?

18:45 justin_smith: jouiswalker: so basically a port of scsh

18:46 noprompt: jouiswalker: i was working on a little project that would convert a vector of strings in to an efficient regular expression that would match any of the strings in the vector

18:46 justin_smith: scsh "regular expressions" are actually much more sane than the standard

18:46 jouiswalker: justin_smith: i knew there had to be one! thats cool.

18:47 tomjack: "it's a lisp" "oh, so there are a lot of parentheses..." <- happened :(

18:47 justin_smith: I used it for a while, ages ago. the extra parens are OK when you are coding and spending more time thinking than typing, in a shell they are a pain in the ass

18:47 noprompt: jouiswalker: yeah, garden.

18:47 tomjack: not jokingly, but trailing off and almost despairingly

18:48 noprompt: well if you were gonna write a shell in clojure i would imagine it working kind of like the emacs shell

18:48 jouiswalker: justin_smith: it seems with paredit it wouldn't be painful

18:48 ^

18:48 justin_smith: yeah, my tty did not provide paredit

18:49 jouiswalker: hehe, i tried installing scsh. at least for arch, it seems like its not compatible for 64 bit

18:50 noprompt: fish is a neato shell.

18:50 it's got a lot of "geewiz" features.

18:50 justin_smith: scsh is ancient, really it is a scheme library, so the best way would be to get an up to date scheme, and port scsh to it

18:50 jouiswalker: speaking of shells

18:51 whenever i run lein repl in xterm backspaces start giving me weird behavior

18:51 noprompt: that is weird

18:51 clojurebot: Alles klar

18:51 justin_smith: sounds like a bad termcap

18:52 noprompt: can't remember the last time i used lein repl directly w/o emacs though

18:52 jouiswalker: true. an interesting effect though, since it plays well with ther terminals

18:53 technomancy: jouiswalker: have you seen this? https://groups.google.com/group/clojure-tools/browse_thread/thread/c08b628a9af8346d

18:53 tomjack: I wonder how core.async will deal with exceptions

18:53 jouiswalker: for example, "aoeu<backspace><backspace><backspace><backspace>" winds up as "aoeu^H^H^H^H"

18:53 technomancy: if you're looking for something to implement ... =)

18:54 justin_smith: I think nrepl uses a java readline library, that is notoriously less than perfect

18:58 jouiswalker: technomancy: now that is interesting

19:00 dobry-den: Here's a few lines of a trivial parser: https://gist.github.com/anonymous/5681884 — How do you solve this fundamental ambiguity? `root = ul` will be greedy as I wish [:ul [:li "Item A"] [:li "Item B"]] — Yet `root = ul+` will make two [:ul] — one for each li.

19:02 In other words, as soon as I `root = (ul | ol | p | code)+`, the lists only slurp up one list element each.

19:04 jouiswalker: technomancy: so he wants to be able to generate language-x from clojure-like code to target devtool-x?

19:05 technomancy: jouiswalker: he -> me =)

19:05 but yeah

19:05 jouiswalker: technomancy: oh!

19:05 noprompt: technomancy: did regex syntax highlighting ever get folded in to clojure-mode?

19:06 technomancy: noprompt: not that I'm aware of

19:06 gzmask: time to go. thanks for help forks! :wq

19:07 noprompt: technomancy: for some reason i thought i saw a PR for it.

19:09 technomancy: just out of curiousity, why not use the JVM to generate all the keyword code for clojure-mode?

19:09 that's how the vim-clojure-static does it https://github.com/guns/vim-clojure-static/blob/master/syntax/clojure.vim#L18

19:10 technomancy: noprompt: not sure; I didn't write it

19:10 noprompt: technomancy: oh :)

19:10 jouiswalker: man, i see tim pope's stuff everywhere

19:11 supersym: technomancy: looks cool, weren't protocols designed for this kind of interfacing though or wouldnt that work with vim/emacsen?

19:11 technomancy: noprompt: pjstadig has been merging some clojure-mode pull reqs too, so I could have missed it

19:11 noprompt: that's because tpope care's

19:11 technomancy: one way to find out

19:11 noprompt: *cares

19:11 technomancy: supersym: clojure protocols?

19:11 supersym: I don't think there's any connection

19:11 supersym: yea

19:12 technomancy: there's no polymorphism going on here

19:12 supersym: no thats what I thought

19:12 jouiswalker: oh wow hes in here

19:12 noprompt: technomancy: cool. yeah, regex highlighting would be seriously nice.

19:12 technomancy: supersym: the clojure-side code is quite trivial; the tricky part is defining a minimal language which can feasibly be implemented across client runtimes

19:13 where "language" is "vocabulary for describing operations, their arguments, and ways to display their return values"

19:13 supersym: I was actually thinking about something along these lines as well

19:13 hiredman: better bencode it

19:17 jouiswalker: technomancy: in your example, does doc have already definitions in vimscript and elisp?

19:17 supersym: so if I get it right, this is a layer that exposes meta-data basically right? but self-describing in a generic fashion so people can hook to it, like a REST API almost? or did I get that wrong

19:17 jouiswalker: already have*

19:18 noprompt: hmm... guess i was wrong.

19:19 tomjack: I see promises are weirder than I thought from a core.async perspective

19:19 -- when is the put!/deliver! callback called?

19:19 it's not CSP so it doesn't make sense with put!. maybe deliver! has no callback..

19:19 ..of course it doesn't, I guess

19:20 jouiswalker: noprompt: what do you need done in garden?

19:23 technomancy: i dont see enough information in the example you gave to infer that a docstring needs to be displayed

19:29 cbp``: Do you still to dl curl/wget on windows for the latest lein version?

19:30 cbp`: to use the latest lein*

19:31 decaf: cbp`: nope

19:31 cbp`: decaf: thank you

19:32 Oh you can use upgrade now too :)

19:32 tomjack: (gofn [in-chan out-chan err-chan] (>! out-chan 42) (close! out-chan)) ?

19:33 (gofn [{:keys [in out err]}] (>! out 42) (close! out))

19:37 jouiswalker: technomancy: what about sending asts of maps and defining some primitive operations in vimscript/elisp

19:39 technomancy: actually, probably easier just to do a map with an ast nested inside

19:45 technomancy: jouiswalker: all emacs commands have docstrings attached to them

19:45 dunno about vim

19:46 jouiswalker: hmm

19:46 technomancy: supersym: yeah

19:47 jouiswalker: well, if we catalogued vim commands that fulfilled the same as the emacs commands

19:47 bbloom: technomancy: vim has excellent documentation. :help whatever

19:48 jouiswalker: it might be possible to just match from one source

19:48 technomancy: jouiswalker: no asts

19:48 the point is to avoid writing elisp on a per-command basis

19:48 bbloom: technomancy: it uses external docs though. you don't put a doc string on a fn, you have docuementation with an annotation of keywords

19:48 technomancy: you just describe the data type you intend to return, and the client already knows how to display it

19:49 jouiswalker: would you consider a docstring a datatype?

19:50 technomancy: no, strings would be the data type

19:50 jouiswalker: cemerick is convinced that we can describe enough return types to completely remove the need for custom elisp. I don't think that's realistic, but I think we can cover common cases.

19:51 jouiswalker: sort of like... process of elimination through argument list and return type?

19:51 technomancy: I don't folow

19:52 follow

19:52 cemerick: I shall not be trolled :-P

19:52 jouiswalker: i dont see anywhere in the example that specifies that a docstring has to be returned

19:53 but i'd personally be surprised if vim required more information to display a docstring than emacs does


19:54 {:op "doc"

19:54 :doc "Display the docstring of a given var."

19:54 :arglist [{:prompt "Var: " :type :var}]

19:54 :client-handler [:message]}

19:54 cemerick: can't.....resist...

19:54 technomancy: the custom X (whether elisp, vimscript, java, python, or whatever else your tooling is written in) *will* be needed, it just shouldn't be the server's job to deliver it.

19:54 (or, op implementation, whatever)

19:54 technomancy: cemerick: OK, works for me =)

19:55 so upon re-reading this I don't think putting the return type on the op makes sense

19:55 it should probably be included in the response itself

19:55 jouiswalker: thats clearer

19:55 technomancy: since a given op could return different types based on whether it succeeds or fails, etc

19:55 cemerick: it's probably reasonable to put it on the op as well, so tools can indicate support ahead of invoking an op

19:56 technomancy: maybe

19:56 cemerick: no reason why an op's "return types" can't just be a vector of whatever other values you're going to ship with a response

19:57 technomancy: should be optional

19:58 RFC: http://p.hagelb.org/nrepl-discover.clj.html

19:58 Raynes: Ladies and gentleman, do not leave your seats, refheap and 4clojure will be returning momentarily.

19:59 technomancy: ^ the above assumes :value in the response is just a string unless :type is given

19:59 not totally sold on :arglist ["var:var"] in particular

20:00 basically it's saying use "var" as the prompt, and if you have any special completion UI for choosing an existing var, use that

20:00 Raynes: And we're good.

20:01 noprompt: w00t! yay! <3 <3 <3

20:01 hiredman: why not just sexpressions?

20:01 (var var)

20:02 (or bencode it...)

20:02 noprompt: Raynes: i had to use a stinkin' gist today! :P

20:02 Raynes: noprompt: Oh the agony.

20:02 technomancy: hiredman: yeah, ("var" var) would probably be better

20:02 noprompt: literally tears running down my face.

20:02 Raynes: did you enjoy the concert?

20:02 Raynes: noprompt: Oh goodness yes.

20:02 technomancy: hiredman: emphasizing that the first is a literal string and the second is symbolic

20:03 or maybe ("Var: " var)

20:03 Raynes: noprompt: I've also won a lottery and get to be part of the audience on June 4th at a secret/private Imagine Dragons concert for the season 6 finale of Live From The Artist's Den

20:03 noprompt: awesome. i can't remember the last time i went to a show. miss those things.

20:03 technomancy: I was trying to avoid alists because they seem like an elisp bias, but they do seem to be a good fit here =)

20:03 noprompt: Raynes: say wut? damn, that's awesome dude.

20:04 technomancy: actually... maybe we need three values? user-visible prompt string, type, and argument name to put in the nrepl msg?

20:04 user-visible string could be optional and default to the argument name

20:05 jouiswalker: that sounds like a good idea to me

20:05 hiredman: obviously you need reader literals to semantically tag things without specifying their concrete type

20:05 technomancy: :arglist [[var var "Trace: "]]

20:06 jouiswalker: are there types that var is limited to?

20:07 technomancy: jouiswalker: string, var, namespace, file, and position (file/line/col tuple) at least

20:07 oh, and choose-one-of-a-predefined-set-of-options

20:08 those are the main types I can think of for which the client can provide useful completion

20:09 jouiswalker: why position instead of int and tuple?

20:10 bbloom: dnolen: sooo cljs' tagged literals are fundamentally broken

20:10 user=> '#inst "2000-01-01"

20:10 #inst "2000-01-01T00:00:00.000-00:00"

20:10 vs:

20:10 ClojureScript:cljs.user> '#inst "2000-01-01"

20:10 (js/Date. 946684800000)

20:10 technomancy: jouiswalker: because the client can just provide the current position of the cursor without actually prompting the user

20:10 dnolen: bbloom: this is not the first time I've heard that

20:11 technomancy: if you are going to ask for an integer, you can ship it as a string; it's not going to save the user any typing for the client to know it's going to be used as an int

20:12 brehaut: designers. sheesh

20:13 bbloom: dnolen: yeah, turns out that stratefied environments are really difficult to formalize with respect to metaprogramming….

20:14 dnolen: bbloom: tho to be honest I don't really see the problem you're trying to demonstrate here since the literal just creates a java.util.Date

20:14 bbloom: dnolen: note the quoting

20:14 dnolen: the main benefit of reader literals from a metaprogramming standpoint is that they are evaluated prior to quoting

20:15 dnolen: clojure's extra syntax lets you sneak just a little bit extra info into macros -- something you can't do with just lists in scheme

20:15 dnolen: tagged literals offer the same power: you can pass a date/time to a macro

20:15 jouiswalker: oh hold on

20:15 hiredman: dnolen: that completely undermines literals

20:15 jouiswalker: you dont mean excluding tuple or int

20:15 tomjack: curious what you're trying to do :)

20:16 jouiswalker: youre just saying you could leave position in there to simplify things

20:16 hiredman: dnolen: you are supposed to be able to read #inst "2000-01-01" and get a date without an eval step

20:17 technomancy: jouiswalker: right; arglist types would all be about convenience to the user

20:18 jouiswalker: gotcha

20:18 dnolen: bbloom: hiredman: right, though I never considered that anything but a bit of odd convenience of Clojure JVM implementation.

20:18 bbloom: what do you need that behavior for in CLJS?

20:19 hiredman: dnolen: it is the whole shooting match regarding literals, expanding in to something requires eval is *not* a literal

20:20 bbloom: dnolen: i've got a pretty big macro that i want to work in cljs, but i have 2-ish custom types i need to pass to the macro. tagged literals are perfect on clj, but on cljs, i need to use metadata.. however i can't put metadata on numbers or keywords or anything, so i need to basically use a wrapper vector, it's awkward: ^MyType [theValue]

20:20 hiredman: having reading literals turn in to forms takes the e out of edn

20:20 dnolen: hiredman: right

20:20 bbloom: dnolen: yeah totally agree w/ hiredman

20:21 tomjack: hiredman: (defn foo [] #inst "2012"). in cljs, foo does return a js date. did you already know this?

20:21 dnolen: bbloom: is this not something we can get around by treating reader literals specially in the presence of quoting?

20:21 bbloom: tomjack: (defmacro literal-type [x] (str (type x)))

20:21 jtoy: how can I use lein to run a single command and quit out?

20:21 hiredman: tomjack: shh, I'm talking to people

20:21 bbloom: tomjack: try that in both clj and cljs, in clj you'll get a inst, on cljs, you'll get a list

20:22 tomjack: no..

20:22 bbloom: dnolen: in order to get this to work, we need a custom macro system

20:22 dnolen: we can't use clojure's macro system

20:23 dnolen: but even still, the result of a reader literal would need to be something that is serializable. ie you can't emit a java.util.Date

20:23 dnolen: bbloom: I don't really understand, macro gets a java date via a literal, compiler emits a js/Date

20:23 hiredman: bbloom: I don't see how that is correct?

20:23 bbloom: literals are a reader thing

20:23 dnolen: or a goog.date.Date

20:24 hiredman: I guess the problem is if the macro emits a quoted form passed to a function

20:24 dnolen: bbloom: works well enough for Regex, why can't it work for date literals

20:25 hiredman: so the compiler needs to walk quoted forms and effectively unquote forms that are the result of a reader literal

20:25 bbloom: this is yet another reason i think there needs to be a TaggedLiteral type…. read time is too early to decide if you want a java date or a js date

20:26 brehaut: bbloom: the correct answer is you want neither :P

20:26 tomjack: couldn't the cljs reader read with its own default handler that uses a TaggedLiteral?

20:26 bbloom: i could write a macro that takes a date as an argument to make a decision, or i could write a macro that takes a date and emits that date in the expansion

20:26 tomjack: I mean the clojure-for-cljs reader

20:27 jouiswalker: lol. stu saying "i dont feel the absence of a debugger" ironically drew a lot of attention to debuggers for clojure

20:27 dnolen: bbloom: I still don't see the problem

20:28 bbloom: looks like cljs.tagged_literals.clj is just doing the wrong thing

20:28 should always convert to Java types and not move around lists of symbols as it is now

20:28 then you can convert during emission

20:28 tomjack: there is no way to register an unreader

20:29 bbloom: dnolen: that's certainly an improvement over what is there now

20:29 tomjack: if you do that you lose the 'e' completely?

20:29 dnolen: we *already* emit Java types all the time and there's not much of an issue

20:29 tomjack: oh I guess there is a way, print-method :)

20:29 dnolen: I don't see how literals aer any different

20:29 bbloom: dnolen: no, you're right. i was just elaborating on the nature of the problem

20:30 dnolen: bbiab

20:30 bbloom: dnolen: i guess then the rule is that data readers always produce values in the compiler's environment, not the target environment. and therefore we also need pluggable emission for emit-constant

20:31 hiredman: readers

20:31 bbloom: hiredman: does that sound sane to you?

20:32 hiredman: I dunno, thinking about it, how can literals work in a mixed environment like clojurescript?

20:33 bbloom: hiredman: just 10 minutes ago, i'd have said that they can't work… but i think dnolen is right… they would work like this:

20:33 hiredman: if I define a clojurescript type and a clojurescript reader literal, what type does the clojrue reader create? what types do macros in clojure get?

20:34 bbloom: there are two readers: the clj and the cljs reader

20:34 you need to write two different functions for tagged literals in both

20:34 the first one, is used at compile time & the literals always return java types

20:34 but you ALSO need to have an emit-constant method

20:34 hiredman: so the clojurescript compiler pr-strs and read-strings?

20:34 err, pr-strs and emits read-strings?

20:35 bbloom: no, the cljs compiler calls emit, which produces js code

20:35 AFTER macro expansion

20:35 hiredman: right, but the macros can pass through and result in arbitrary types in forms

20:35 bbloom: yeah, there is just an extra layer: the translation from clj -> cljs

20:36 hiredman: (which is why I guess the clojure compiler does this thing)

20:36 bbloom: or clj -> js, more specifically

20:37 hiredman: like, if I have a java type Foo, how does the cljs compiler now how to conver that in to js? it doesn't it has to pr-str it and use read-string to reconstruct it on the js side

20:37 bbloom: hiredman: no, it doesn't emit edn strings, it emits js code

20:37 hiredman: it can't

20:38 bbloom: literals (should) yield :op :constant AST nodes

20:38 hiredman: Foo is an arbitrary object resulting from macroexpansion

20:38 bbloom: yeah, macro expansion occurs during the analysis phase, prior to code emission

20:38 no strings involved yet

20:39 hiredman: right, an instance Foo comes out of a macro, and now the compiler wants to emit js, what does it do?

20:40 bbloom: currently: calls emit-constant and throws a no matching method error :-)

20:40 hiredman: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4561-4586 the clojure compiler has to deal with the same thing

20:41 tomjack: wow

20:42 I was just wondering why a macro returning a date didn't blow up with "can't embed object in code"

20:42 hiredman: I think I have a branch somewhere where I added an IConstant to clojure

20:43 bbloom: interesting.

20:45 hiredman: you can actually use IType I think, which if you extend it lets you sort of control how the type is embedded

20:45 IConstant I think just effected the type of the final field used as a "constant" table

20:45 bbloom: seems like *tagged-readers* needs a matching *type-emitters*

20:46 hiredman: a protocol like IType maybe

20:46 bbloom: yeah something like that

20:46 hiredman: feh

20:47 the itype interface is empty now?

20:47 bbloom: i'm not familiar with this part of the clj compiler

20:47 a protocol or a multimethod would do the trick really

20:47 hiredman: at one point there was some interface (which I think was IType) that had a getBasis method that would return a vector of field names

20:48 bbloom: emit-constant is currently a multimethod, but if you use a fn or multimethod, then you'd want that in a dynamic var

20:48 hiredman: the compiler would, for that type, emit a constructor call with the values of those fields

20:48 it looks like it still does, but it calls getBasis reflectively

20:49 https://github.com/hiredman/clojure/blob/reflection-method-caching/src/jvm/clojure/lang/Compiler.java#L4422-4444

20:50 oh, whoops, that is my branch, it may be old

20:51 bbloom: haha

20:52 hiredman: nah, hasn't changed much on clojure master

20:52 bbloom: dnolen: i think we can just delete *cljs-data-readers* and replace it with *cljs-constant-emitters*

20:56 dnolen: bbloom: hmm I don't see a need to get rid of *cljs-data-readers*, bootstrapping is in our future

20:56 bbloom: but yeah, *cljs-constant-emitters* that just explains how to convert Java types

20:57 you'll have to define your readers twice (compile-time / dynamic runtime reads), but this solves the issue you're talking about

20:58 bbloom: I'm willing to take a patch for that, perhaps a clojure-dev mailing list post is order just to get a little more feedback

21:00 bbloom: dnolen: i'll send you a patch if it ever becomes a real problem for me. in the meantime, should i just make a ticket?

21:01 dnolen: bbloom: sure, this may actually duplicate cemerick's tickets

21:01 bbloom: ok, i'll search

21:02 dnolen: bbloom: actually unrelated, go ahead an open a ticket

21:03 noprompt: i/

21:13 akurilin: Quick question: I'm trying to grok the whole idea behind moving past OO. Specifically with regards to methods. Is the idea that instead of having methods be part of the types I define, operating on their state, I should rather extract that method into a function in a namespace somewhere, and pass the object to it?

21:14 I think it's interesting to see something like moment. js and clj-time do very similar operations on time types, yet the former is all about methods and the latter is the reverse.

21:15 bbloom: akurilin: OOP & methods still makes sense with mutable objects, hence why deftype defprotocol, all that jazz exists. but they are tools for a different set of problems than most business logic deals with. by default, you should be working with immutable data & free functions

21:15 brehaut: akurilin: your question is quite general. methods / objects bundle a bunch of different things together into a single mechanism. there are multiple different things to do the job of methods in clojure/FP

21:17 technomancy: akurilin: are you using "method" to mean defmethod or just "a procedure attached to an object"?

21:17 hiredman: ~#9

21:17 clojurebot: 9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. -- Alan J. Perlis

21:17 brehaut: akurilin: btw, clj-time is a slim wrapper around Joda Time, which is a java lib that uses methods everywhere (because it has to)

21:17 akurilin: technomancy, procedure with implicit self/this as first parameter

21:18 brehaut, I get that, but doesn't it try to make the underlying operations more idiomatic with respect to Clojure?

21:18 technomancy: akurilin: ok, makes sense

21:18 jouiswalker: dnolen: have you read doug hoyte's let over lambda?

21:18 bbloom: akurilin: have you ever asked yourself "what class does this method go on?" and then realized a sensible argument could be made for either? you shouldn't make an arbitrary factoring decision like that unless you're getting some benefit from doing so

21:18 hiredman: akurilin: see that is part of the problem, that is actually a very small part of what you get from most oo systems (and not all of them, I believe python doesn't have implicit selfs)

21:18 dnolen: akurilin: I don't think looking at a project that demands polymorphism is a good intro into Clojure

21:18 jouiswalker: nope

21:18 brehaut: akurilin: well, yes, but the fundamental immutable datamodel is in java, no clojure.

21:19 akurilin: bbloom, is there a good way to know when methods are indeed the right way to go, if you say in most cases they aren't?

21:19 hiredman: methods often also introduce polymorphism

21:19 jouiswalker: dnolen: just curious ;p

21:19 dnolen: jouiswalker: yeah, it just sounded like CL drivel

21:19 bbloom: akurilin: when you are just learning clj, methods are NEVER the right way to go :-)

21:19 dnolen: jouiswalker: and I like macros a lot

21:20 jouiswalker: dnolen: it sort of was. there was some interesting performance related stuff he did in it though

21:20 bbloom: akurilin: but the reason to really use methods is when you want fast single dispatch by type

21:20 akurilin: that's basically the only reason

21:20 jouiswalker: dnolen: it didnt take long for his words to go over my head though lol

21:21 akurilin: bbloom, is the idea to replace those with multimethods that can operate on a set of supported types?

21:22 dnolen: jouiswalker: I find Art of the Object Metaprotocol a more interesting exposition on the power of macros since it about combining well designed functions with well designed macros

21:22 brehaut: ~polymorphism

21:22 clojurebot: genuine need for polymorphism just isn't very common

21:22 hiredman: feh

21:22 technomancy: says you

21:22 bbloom: akurilin: multimethods are more flexible than methods, but are also more complicated than regular functions

21:22 akurilin: the question you need to ask is whether or not you need open dispatch

21:23 trptcolin: jouiswalker: saw your note about an `lein repl` + backspace issue. is this lein 2.2.0?

21:23 jouiswalker: dnolen: i'll take a look. i've been in this swapping in between on lisp and paradigms of artificial intelligence for about two years xD

21:23 technomancy: hiredman: on a regular basis

21:23 bbloom: akurilin: you can always do (cond (fn? x) y (number? z) w …)

21:23 dnolen: jouiswalker: both good books

21:23 jouiswalker: trptcolin: yes

21:23 akurilin: bbloom, not familiar with the term, google isn't revealing anything either

21:23 jouiswalker: trptcolin: but it was present before that as well

21:24 brehaut: hiredman: its certainly not as necessary as its place in OO might suggest

21:24 hiredman: brehaut: sure, ala carte

21:24 jouiswalker: dnolen: thanks for the book recommendation

21:24 clojurebot: brehaut is ‽

21:24 bbloom: akurilin: in this case "open" means accessible for other people to extend

21:24 brehaut: WTF clojurebot

21:25 bbloom: akurilin: an cond block sn't open to extension, you can't add more cases to it

21:25 akurilin: but a multimethod lets you add more cases without changing the code

21:25 akurilin: if you don't need open extension, start off with cond

21:25 hiredman: it's not about prevalence, it is about disconnecting decisions about polymorphism from decisions about namespacing, etc

21:26 dnolen: akurilin: jumping back a bit, the idea in Clojure is that polymorphism should come a la carte - not stuck inside of some object or a feature of some class, this emphasizes value oriented programming which the important thing.

21:26 akurilin: even in projects that make heavy use of protocols, you're still trying building things up to the point where you can get to simple value oriented programming.

21:27 trptcolin: jouiswalker: sure. my xterm seems happy. so the two possibilities i see: ~/.inputrc setting overriding default keybindings or some keystroke is unmapped by jline

21:27 decaf: (do (def alphabet (char-array "abc")) (class alphabet)) returns "[C" without quotes. am I hitting a giant bug here?

21:27 brehaut: decaf: no; arrays are primatives

21:27 hiredman: that is the internal jvm type of an array of characters

21:28 decaf: we should get something more readable like char[]

21:28 jouiswalker: cat .inputrc : set editing-mode emacs, set keymap emacs


21:28 technomancy: decaf: it is pretty ridiculous

21:28 hiredman: we?

21:28 technomancy: but it's JVM ridiculousness, not clojure-specific ridiculousness

21:29 jouiswalker: trptcolin: its sort of interesting, since using the repl within xterm works just fine

21:29 akurilin: dnolen, sounds great, thanks for clarifying. I've actually not run very much into need for polymorphism just yet because of how small my projects' scope generally is.

21:29 dnolen, I'd certainly love to know basic rule of thumbs I can follow until I've gotten enough experience that I can judge well on my own.

21:29 decaf: hiredman: we, clojure programmers, especially newcomers. english is not my native language.

21:29 jouiswalker: trptcolin: after i exit the repl using (exit), i'm able to do weird stuff like

21:29 trptcolin: aoeu^H^H^H^H

21:29 bash: $'aoeu\b\b\b\b': command not found


21:30 trptcolin: jouiswalker: oh, so this is after exiting the repl

21:30 jouiswalker: trptcolin: yes

21:30 bbloom: akurilin: that's what i was trying to provide. just work with pure functions & clj data structures until you have a problem you just don't know how to solve without them. then you can figure out which tool solves precisely the problem you have

21:30 akurilin: and feel free to come back here and ask about a specific case, it's harder to understand these things in the abstract

21:31 akurilin: dnolen, I think the closest I'm going to get to needing polymorphism soon is dealing with models in a MVC pattern. I might need a protocol possibly for something :)

21:31 bbloom, for sure.

21:31 dnolen: akurilin: I wouldn't mess with much protocols - stick with the standard API, reach for multimethods if you need some polymorphism. At some point you might find a use for protocols.

21:31 akurilin: bbloom, appreciate it.

21:31 dnolen: akurilin: well, hopefully Clojure will convince you MVC is not really a great idea

21:31 hiredman: decaf: I don't think optimizing for newcomers is a good use of time and energy, since it is almost entirely subjective and tends to degenerate in to just people expressing their opinion and saying it is good for newcomers

21:31 jouiswalker: trptcolin: out of xterm, urxvt, terminology and terminator, xterm is the only one i have observed with this problem

21:32 callen: Raynes: home sweet home

21:32 akurilin: dnolen, unfortunately most of my experience with writing web apis comes from the Rails world, so that's my point of reference. I'd certainly LOVE to shave off whatever extraneous layers I can.

21:32 callen: technomancy: I survived LA

21:32 decaf: I was just explaining what I meant by saying "we"

21:32 dnolen: akurilin: it's a bit of slog IME, but you'll eventually being very averse to the kinds of engineering decisions and libraries that continue to be popular.

21:34 callen: akurilin: counter-point, I find separation of concerns (often but not always manifesting as MVC) works fine and has improved with Clojure, but what changed is how I compose and "build up" my projects that stands in stark contrast with my older Rails and Django projects.

21:34 jouiswalker: trptcolin: ahh, another interesting thing is that re-entering the repl fixes the problem, but that it returns again after you exit :/.

21:35 callen: akurilin: namely, less assuming of some kind of core (large) framework, more, "here's a bag of tools, do as thou wilt"

21:35 akurilin: but I'm pretty fascist about keeping my libraries focused. *shrug*

21:35 trptcolin: jouiswalker: yeah, my xterm is still fine. i suspect there's an stty setting differing there that's causing issues. would appreciate a GH issue with details on OS, terminals, & results of `stty -a` before launching any repl (in the working state), and after exiting lein repl (in the broken state): https://github.com/trptcolin/reply/issues

21:36 jouiswalker: trptcolin: i'll do that now. thanks!

21:37 akurilin: callen, same here, I get pretty anxious when I don't know exactly what's in my app. Things like ActiveRecord can be pretty magical and hard to understand.

21:38 callen, basically at this point I'm doing the key parts of Rails by combining together little pieces of functionality from here and there, which seems to be what almost every other web application does out there, at least from what I've seen in repos

21:40 On the api note, does anybody know if there's any kind of accepted standard for passing sql-like query conditions to a rest api, or does everybody do something custom every time?

21:42 So something like a GET on /repositories with "contributors > 5"

21:43 What's neat about korma is that it should be pretty doable to map those to korma's DSL

21:43 (watch me get sql injected on day 1)

21:49 jouiswalker: trptcolin: it looks like stty -a revealed a lot about the problem

21:49 trptcolin: erase somehow gets set to something else outside the repl

21:55 callen: akurilin: activesupport always bothered me more than activerecord.

21:55 akurilin: I have an example clojure web app here: github.com/bitemyapp/neubite/ you can take some cues and ideas from there. It's based on Luminus.

21:56 technomancy: do you read the Culture novels?

21:57 akurilin: callen, awesome, thanks, always good to have more sources for inspiration. I do look at Luminus occasionally as well.

21:57 Gotta run folks, thanks for your responses

22:14 callen: Raynes: what happened to Refheap?

22:15 oh, Linode.

22:15 balls.

23:38 tieTYT: i was forbidden from writing clojure at work today

23:38 ehaliewicz: why is that?

23:39 egghead: too much power

23:39 bbloom: ehaliewicz: it might make him less fungable?

23:39 fungible*

23:39 callen: tieTYT: why?

23:40 tieTYT: i wrote some code in < half the lines it would take to write in java but I was told that my coworkers can't maintain it and, "the needs of the many outweigh the needs of the few"

23:40 callen: ehaliewicz: interchangeability of resources (nb: PEOPLE) is highly prized in the gentry class.

23:40 xeqi: it would lead down to the downfall of the semicolon industry

23:40 callen: tieTYT: to whit, wouldn't that mean firing his lazy ass so the many (company) can benefit from the higher productivity?

23:40 xeqi: and that is too big to fail

23:41 tieTYT: actually he's pretty good w/ lisp

23:41 he was thinking of everyone else at the company

23:41 we already use drools though in some project. I think it's a pretty similar thing to bring into the company ecosystem

23:41 bbloom: right, like i said, fundability :-)

23:41 ehaliewicz: the way he said it suggested to me that he was normally allowed, but temporarily banned

23:41 ivan: ego-protective behavior, assuming everyone else is too dumb

23:41 bbloom: er fungibility

23:41 i can't type

23:42 tieTYT: ehaliewicz: no, permaband

23:42 callen: I really dislike drools.

23:42 bbloom: ivan: i didn't say dumb

23:42 ivan: I never implied such ;)

23:42 tieTYT: callen: I don't know much about it

23:42 egghead: I work at a corporate company and we still silo all clojure to internal tools, I still don't get to use it on the larger projects for just that reason tieTYT

23:42 tieTYT: but if you compare the two, both require you to think differently and program in a way that's different from java

23:42 bbloom: ivan: somebody way smarter than me is less likely to be able to understand my dense expressive code than my boring mechanical code

23:42 tieTYT: egghead: at least you get to use it on the internal tools

23:43 bbloom: even if the guy who takes my job is way smarter than me, he would rather i wrote some vanilla boring stuff

23:43 ehaliewicz: tieTYT: write clojure code that generates java

23:43 tieTYT: ehaliewicz: ha, yeah that'll fly

23:43 ehaliewicz: they won't even know

23:43 tieTYT: now the incident is on the radar, they'll get real pissed if I did that

23:44 egghead: you can very easily write stuff in java or groovy that a future maintainer wouldn't understand

23:44 seems like they are just neophobes

23:44 change is scary!!!

23:44 ehaliewicz: tieTYT: but you're supposed to get back at them

23:45 :D

23:48 tieTYT: egghead: yeah I agree. I like comparing it to drools. I don't know drools at all, but if I had to maintain their drools code I'd be expected to learn it and wouldn't consider it ridiculous

23:48 where do you draw the line? Am I not allowed to use CollectionUtils?

23:49 the fucked up thing is I wrote teh code in clojure then rewrote it in java (half way). I had all the unit tests in place and it still took twice as long and i'm not even done

23:49 you people understand me :)

23:51 callen: tieTYT: better to beg forgiveness next time?

23:51 ecallen: hello doppleganger.

23:52 tieTYT: callen: That is how I approached it

23:52 i wrote the clojure first

23:53 now i'm off to learn about clojure script

23:53 talios: sweet :) cheers

23:56 tieTYT: i must say it's really hard to find out how to get started with clojurescript

23:56 the "getting started" guide's first paragraph tells you you shouldn't follow it

23:58 bbloom: tieTYT: lein cljs-build is the easiest way to get started

23:58 tieTYT: yeah I'm going to start checking that out

23:59 callen: tieTYT: I hope you like pain :)

23:59 tieTYT: can I use CCW with it? Do I need to use piggyback or something?

23:59 callen: why?

Logging service provided by n01se.net