#clojure logs

2013-05-30

00:01n_bdnolen: So basically you'd accummulate changes and then request a frame to do all the updates in?
00:01dnolenn_b: yes
00:02dnolenn_b: but requestAnimationFrame can be called at any time, multiple times
00:02dnolendoesn't really matter
00:02dnolenwhich is what you want
00:03dnolenI 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
00:04cgaghas anyone had any experience using any javascript promise libraries with clojuescript and node?
00:04tomjackwell the callback will be called again and again in that case, yes?
00:04dnolentomjack: no
00:05tomjackmy test suggests otherwise
00:05tomjack(function() { var cb = function(){console.log('cb');}; requestAnimationFrame(cb); requestAnimationFrame(cb); })()
00:05tomjacklogs 'cb' twice
00:06dnolenhttps://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame
00:06dnolentomjack: which doesn't really prove anything
00:06dnolenyour example I mean
00:06dnolensince the cb and the work is trivial
00:07tomjackhmm, 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
00:08tomjackso if the callback is like "draw everything to a canvas" you want to be sure to only call it once per frame
00:09tomjackcall requestAnimationFrame once per frame I mean
00:09dnolentomjack: oh ok, yes you are right, that's why they return the requestID - I thought it worked more like Cocoa's setNeedsDisplay
00:09tomjackif it's something like "flush a queue of pending dom updates" maybe you don't care
00:19tomjackhow does virtual dom in cljs even work?
00:19tomjackis it that you have a mutable queue of pending updates?
00:20tomjacksurely you're not gonna just deref and walk an atom every frame and somehow try to match it up with the dom?
00:28recursor94Does 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.
00:28hiredmanhttps://github.com/technomancy/server-socket
00:29bbloomtomjack: 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
00:30tomjackright, I remembered you talking about "owning everything" before
00:30bbloomtomjack: 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
00:30tomjackmakes sense
00:31bbloomof course browser extensions or even just a dev with the inspector can invalidate those assumptions
00:31bbloombut during normal operation, that's not really a problem for most use cases
00:32recursor94hiredman: Is there a version in clojars?
00:33hiredmanI think so, not sure though
00:33recursor94Alright, thanks.
00:33hiredmanhttps://clojars.org/server-socket
00:33recursor94sweet!
00:46recursor94:D
00:59bbloomdnolen: do you know much about the propegators stuff that was in the sussman "we don't really know how to compute" talk?
01:00dnolenbbloom: I've read and implemented bits of the art of propagator
01:00dnolenbbloom: a lot of the material he covered is from that.
01:01bbloomdnolen: yeah, was planning to read that
01:07dnolenbbloom: it's interesting though I found the paper lacking in terms of references
01:07dnolenbbloom: the list of interesting propagator work is massive
01:07dnolenI'm glad their popularizing it here - but the paper doesn't cite much Prolog CLP, Mozart, Gecode, etc. if I recall
02:08benkayon the topic of composing functions to run on a datomic transactor:
02:08benkayI 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.
02:09benkayI 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.
02:10benkaynow: 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?
02:10benkayi feel like I just answered my own question.
02:35mthvedtbenkay: rubber ducking
02:36benkayall that i succeeded in doing was exposing further depths of ignorance :(
02:36mthvedtbenkay: if you're not exposing one's own ignorance, you're not living an inquisitive life
02:37benkayamen
02:37benkayit was an ironic sad face
02:39ddellacostaI'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?
02:41ddellacostahmm, maybe there is something in reducers
02:42benkayis it the same key every time?
03:53quizmeis swanodette here ?
03:55quizmei was just wondering about the feasibility of writing a clojurescript compiler in node.js
03:55quizmesans jvm
03:59nightflyquizme: Please do it :)
03:59nightflyAnd go for extra points and make it self-hosting as well
04:01quizmenightfly what do u mean by self-hosting ?
04:01nightflyOnce you've got your javascript clojurescript compiler working you write another clojurescript compiler in clojurescript
04:02quizmeoh
04:02quizmegive me a few minutes to let that sink in
04:04quizmeok
04:04quizmei think i get that
04:04quizmethat would be awesome.
04:05quizmebut yeah
04:05quizmethat's for bonus points
04:05quizmecuz really i just wanna use it without the jvm
04:05quizmecall me an end-user if u have to
04:05borkdudehmm, http://www.4clojure.com/ isn't working?
04:06quizmenightfly so you agree that it would be awesome to have a clojurescript compiler for node.js sans jvm dependency ?
04:08nightflyyes, that would be awesome
04:29tomjackquizme: why?
04:35mondraymondgood morning from Brussels
04:35mondraymondI'm just hopping on to get a little advice on filter
04:35mondraymondI have a function which returns something like this (() () () ({:id 1}) () ())
04:36mondraymondand I just want the map with the id
04:36mondraymondtry as I might I cannot work out how to filter off the empty seqs
04:36mondraymondany suggestions before I fire off the google group?
04:38dedeibel(def a '(() () () ({:id 1}) () ()))
04:38dedeibel(first (flatten a)
04:38dedeibel?
04:39mondraymondboom - that works!
04:39mondraymondway hey! thanks very much ... completely forgot about flatten
04:41Raynes&(filter (comp map? first) '(() () () ({:id 1}) () ()))
04:41lazybot⇒ (({:id 1}))
04:41Raynes&(first (some (comp map? first) '(() () () ({:id 1}) () ()))
04:41lazybotjava.lang.RuntimeException: EOF while reading, starting at line 1
04:41Raynes&(first (some (comp map? first) '(() () () ({:id 1}) () ())))
04:41lazybotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean
04:41RaynesAh.
04:42Raynes&(ffirst (filter (comp map? first) '(() () () ({:id 1}) () ())))
04:42lazybot⇒ {:id 1}
04:52quizmetomjack: why what ?
05:13gtrakgood morning 5am #clojure
05:14hyPiRion11 am here, but good morning
05:24bordatouehi, 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
05:26rhymorI'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.
05:28bordatouerhymor: i can see log4j.xm in the classpath using lein classpath cmd
05:30bordatouerhymor: 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){
05:31rhymorin log4j.xml there's a line like <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> can you instantiate that class on the repl?
05:31gtrakrhymor: yep
05:32gtraklemme find an example
05:32bordatouerhymor: yes I can
05:32gtrakrhymor: https://gist.github.com/gtrak/5676736
05:32bordatouelet me change the location of log4j.xml file
05:36mondraymondHey Raynes - yes that works thanks. It seems to me though that flatten seems so much simpler ... does it miss something that your filter catches?
05:36gtrak~flatten
05:36clojurebotflatten 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.
05:38bordatouerhymor: got i working it; log4j file should be in the projects src directory , thanks
05:38gtrakbordatoue: test-resources is probably a better place
05:39mondraymondok - yes indeed mapcat works for what I need
05:39bordatouegtrak: is test-reources created by default using lein app
05:40rhymorIf 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.
05:40rhymoraka. don't think what the program does, think what it means.
05:40gtrakbordatoue: if it is, it won't be saved in your git repo if it's empty
05:41gtrakrhymor: tell those devs to use lisp :-), it makes it easier to give things names
05:43rhymorgtrak, I'm stuck in a project where we actually have a touring complete configuration language in XML. :(
05:44gtrakxml? you're one step away!
05:44gtrak<tag1><tag2>WAT</tag2></tag1> -> (tag1 (tag2 "WAT"))
05:44hyPiRionoh dear
05:45gtrakI guess attributes and thing are a bit tougher
05:45rhymoryes, it's basically lisp with an ugly syntax.
05:45hyPiRionhttps://github.com/technomancy/lein-xml
05:45rhymor:D
05:46gtrakbecome 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...
05:49rhymorgtrak, that could actually work. I'll try it.
05:50gtraklol, awesome
05:55ddellacostaHow 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)))))
05:56gtraksome does it for you
05:56gtrak(some :summary-text (second search-results))
05:56bordatoueis there any easy way to determine which version of java is used by lein
05:56hyPiRionbordatoue: lein version should print it out
05:57gtraksome is an underappreciated core funciton
05:57gtrakfunction*
05:57gtrak~some
05:57clojurebotI don't understand.
05:57augustlsome ftw :)
05:57gtraksee?
05:57bordatouethanks hyPiRion , is there any way to specify a perticular version of java
05:57ddellacostagtrak: thanks! This is not the first time I've forgotten some...
05:58augustlit has some nice use cases, and I use it some times, unless it's bothersome for some reason
05:58ddellacostathe problem is I'm always thinking about things the wrong way, so some seems orthogonal to the solution
05:58ddellacostahere I was thinking too hard about processing a vector
05:59hyPiRionbordatoue: yeah. Do you want to change it system-wide or just for leiningen only?
05:59gtrakI generally enjoy overloading the notion of a pred with actually doing something useful, compojure works this way
05:59ddellacostathat's perfect, I just chopped that down to a much shorter version. Very happy.
06:00ddellacostagtrak: yeah, it seems to be a common meta-idiom, if I can say that, in Clojure
06:00bordatouehyPiRion: just for a specific project
06:00ddellacostaand 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. ;-)
06:00gtrakyea, I'm always on the lookout for neat combinations of functions
06:01gtraklike (juxt filter complement)
06:01hyPiRiongtrak: (juxt filter remove) I suppose?
06:01gtrakyea, that's what I meant
06:02gtrakthere must be sort of a implicit second-order standard lib of things like that
06:02ddellacostayeah, 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
06:03hyPiRionbordatoue: 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
06:04hyPiRionbut if you're on Mac/Linux, `JAVA_CMD='path/to/the/java' lein run` should do the trick
06:04bordatouehyPiRion, thanks very much
06:05hyPiRionno problemo
06:52@rhickeyhow do I keep lein repl from spewing #_=> at me when I do C-M-x in inferior lisp mode?
07:02llasramI don't think that's a very well-tested combination... The `lein repl` nrepl server + nrepl.el works perfectly fine though
07:03@rhickeyllasram: thanks, not interested in adding more stuff until first stuff is working
07:13llasramIs 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?
07:44@rhickeyllasram: you mean java -server -cp `lein classpath` clojure.main, or something else?
07:46Bronsarhickey maybe lein run -m clojure.main ?
07:48@rhickeyBronsa: that's better, thanks
07:57Jetienhow 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)
07:58rhymoryou can use the hashmap as function in map
07:59Jetienbut if f=map then the example above evaluates to (1 1 2 nil)
08:00rhymorso you map, then filter or the other way round
08:02Jetienyep. i was just wondering if there's a simpler way.. thx!
08:02rhymorJetien, 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?
08:02Anderkent,(keep {:a 1 :b 2 :c 3} [:a :a :b :x])
08:02clojurebot(1 1 2)
08:02AnderkentJetien: ^
08:02Jetienthanks
08:02Jetienrhymor, i think these situations are not that seldom
08:03rhymorOh, I learned something new :) good day today.
08:10hyPiRionHmmmm
08:11hyPiRionKeep in mind that nil values will not be returned
08:11hyPiRion,(keep {:a nil :b 3} [:a :b :c :a :b])
08:11clojurebot(3 3)
08:12hyPiRion,(map val (keep (partial find {:a nil :b 3}) [:a :b :c :a :b])) ; solves it
08:12clojurebot(nil 3 nil 3)
08:15Morgawrcan 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
08:16manutterslightly 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?
08:17manutterI set up a luminus app with dailycred, and it works, but their error reporting leaves a little to be desired.
08:17hyPiRionMorgawr: it's like setting the variable, but only for the calls within the binding. It's reset afterwards.
08:18Morgawrso it's like a scope binding?
08:18hyPiRiondynamic scope binding, yes. Consider this:
08:18hyPiRion console.log("new animation");
08:18hyPiRionwhoops
08:18hyPiRion,*print-length*
08:18clojurebot5
08:19hyPiRion,(let [f (fn [] (println *print-length*))] (f) (binding [*print-length* 9000] (f)) (f))
08:19clojurebot5\n9000\n5\n
08:19Morgawrah, I see
08:19FoxboronMorgawr: example. the varibale *out* tells clojure what stdout is. Say you bind it too a network socket. (binding [*out* (:in socket)] (println "hai"))
08:19Morgawrthat's great, thanks for the explanation
08:20Foxborons/:in/:out
08:20Morgawr^ cool, thanks for a real world application too
08:20hyPiRionyeah, a common pattern is for example this
08:20FoxboronMorgawr: you could bind it to a file writer also.
08:21hyPiRion,(let [s (new java.io.StringWriter)] (binding [*out* s] (println "hello world") (println "nice weather") (str s)))
08:21clojurebot"hello world\nnice weather\n"
08:21hyPiRion^ that is exactly how with-out-str works
08:22Morgawrneat
08:22FoxboronMorgawr: i think that is one of the neatest things i have seen in Clojure so far ^^
08:22Morgawrhow does it work with closures though?
08:23Morgawrif I return a function that uses the bound argument and then call it outside the binding
08:23MorgawrI guess it keeps the temp binding, yes?
08:24hyPiRionno
08:24hyPiRionthat's why it works in the first place
08:24hyPiRion(let [f (binding [*print-length* 100] (fn [] *print-length*))] (f))
08:24hyPiRion,(let [f (binding [*print-length* 100] (fn [] *print-length*))] (f))
08:24clojurebot5
08:25Morgawrah
08:25Morgawrthat's weird, good to know
08:25Morgawrand yeah, I guess that is why it works in the first place haha
08:25MorgawrI didn't give it much thought after all
08:26hyPiRionConsider a (def ^:dynamic *foo* ...) definition as a global (binding [*foo* ...] the-whole-app-here)
08:26hyPiRionYou can set up the binding within a function, of course
08:27hyPiRion,(let [f (fn [] (binding [*print-length* 100] *print-length*))] (f))
08:27clojurebot100
08:27Morgawryeah, that's a solution
08:27Morgawrthanks for the help
08:27hyPiRionnp
08:34kittijoin
08:35kitti:Q
08:35kittiq
08:35kittiquit
08:35kittiexit
08:37hyPiRionheh, prepend with /
08:58edbondcan someone provide example usage of seque?
08:59hyPiRionedbond: if you start up a repl with `lein repl` and do `(cdoc seque)`, then there is an example there
09:00edbondhyPiRion, thanks, didn't know about cdoc
09:01hyPiRionit's a nice tool for examples, although its quality on functions vary
09:59Pupnikis the rhickey in here actually rich hickey?
10:01hyPiRionyeah
10:02Pupnikfunny to see him asking questions
10:02Pupnikalthough I suppose he isn't an expert on all the various things that have grown around clojure
10:03atyzhi 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:04hyPiRionIt's not weird. He's not working on the tooling and plumbing around Clojure, but rather on the language.
10:04supersymPupnik: every API/implementation takes time to read-up, get in the intention/head of the maker
10:05supersymyou may get a bit quicker/develop an eye... but that part always stays :)
10:07supersymI spoke to our king on two occasions...same feeling
10:07supersymwe seem to attribute super-natural powers/knowledge to our idols
10:09Pupniktrue, true
10:10Pupnikhe does give great talks though
10:27manutteratyz: I think the problem is the [:as req] in your route, try just req instead.
10:28manutter(not that I'm at all knowledgeable about compojure routes, but try anyway)
10:29supersymPupnik: indeed, I watched a video on infoq the day before yesterday, enlighting n refreshing: like the language imho
10:30justin_smithcompojure routes use regular destructuring - if the destructuring doesn't work in a function parameter list it won't work in a compojure route
10:37atyzmanutter: i have, unfortunately it makes no difference
10:38manutterIf 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:39Morgawrwhat's the best way to create a vector out of all the elements that match the same key from multiple hashmaps?
10:39justin_smithMorgawr: (mapv :key hashmaps)
10:39Morgawrgreat, thanks
10:42atyzmanutter: it does, it breaks when its' trying to do the insert
10:43justin_smithMorgawr: that is if you explicitly want a vector, otherwise map is good because it is lazy
10:44Morgawrjustin_smith: oh yeah, right, thanks
10:44justin_smithwell, sometimes map is bad because it is lazy, but yeah, anyway that is the big difference in behavior I have seen
10:46justin_smithnow I am realizing I should start using mapv in many places where I am using (doall (map ...))
10:47hyPiRionjustin_smith: do you need the result?
10:47hyPiRionif not, doseq is probably a better choice
10:47hyPiRion(for the hashmap case, it obviously is, but in general)
10:48justin_smithhyPiRion: 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:48hyPiRionah
10:48justin_smithso laziness either makes the db connection stay open (bad) or makes things get calculated where the db connection is not bound (breaks things)
10:49manutteratyz: ok, I'm barking up the wrong tree then, sorry.
10:49atyzmanutter: no worries, thanks very much for helping
10:49justin_smithbut you know, mapping across a bunch of results from a db, how often would you need to do that, right :P
11:34abpleathekd: Thanks!
11:37leathekdabp: No problem! Let me know if you have any troubles.
11:50abpleathekd: Works like a charm. Just tested my middleware.
11:54leathekdNice. Glad to hear it.
11:58yacinif i have a string that represents a byte array ("[B@3ecc05a6") how can i convert it back to the byte array?
12:02mpenetyacin: 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:07yacinyeah, i believe so
12:10justin_smithyeah, 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:10mpenetif 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:10mpenet,(String. (.getBytes "foo"))
12:10clojurebot"foo"
12:10mpenetbut that's very naive, not sure in what context you are
12:11mpenet,(.getBytes "foo")
12:11clojurebot#<byte[] [B@10fa2ec>
12:16S11001001mpenet: uses current locale's character encoding, not great for running on more than one machine
12:16mpenetyeah I know
12:16mpenetyou can pass the locale as 2nd param
12:16mpenetI think
12:16S11001001yacin might not
12:17S11001001you can pass the character encoding as 2nd param
12:17Anderkentmpenet: yes, you can pass an encoding to .getBytes or String.
12:18yacinthanks y'all. this is some weird environment specific issue
12:20Anderkentyacin: but still, you probably want to use something like commons.codec Hex if it's arbitrary bytes
12:20Anderkentsince not every byte array is a valid string
12:20mpenetyacin: where do you get this byte-array from ?
12:22Anderkentand unfortunately String. does not tell you the decoding failed
12:22Anderkent,(String. (byte-array (vector (unchecked-byte 200) (unchecked-byte 201))) "ASCII")
12:22clojurebot"??"
12:23llasramWas 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:24mpenet~guards
12:24clojurebotSEIZE HIM!
12:24Anderkentllasram: no worries. String/byte handling in general is something people often do wrong, so talking about it may help someone :)
12:25Anderkentthe take away is always be explicit about your encoding, and always use utf-8 :)
12:25mpenetyeah I was wondering about the context, most of the time libs that force you to do that stuff come with some helpers
12:27yacinhaha thanks llasram
12:51Morgawrdo I need to have a local maven repository of I want to use a personal .jar file in my lein project?
12:51Morgawrbecause I'm developing both my application and a standalone library (on which my app relies) at the same time
12:52technomancyMorgawr: you have a local maven repository
12:52technomancyin ~/.m2/repository
12:52Morgawroh
12:52Morgawrneat
12:52Morgawrso I just put my .jar in there or..?
12:53technomancyjust `lein install`
12:53technomancywill put it there
12:53Morgawrah cool, so from my .jar project I do "lein install" and then from my app I just include it in the dependencies?
12:54technomancyyou should probably read `lein tutorial`
12:54technomancybut yeah
12:55Morgawralright, thanks, sorry for asking a naive question
12:55MorgawrI appreciate the help
12:55technomancyno worries
12:56technomancyactually I'm not sure the tutorial covers this; hm
12:58gtrakMorgawr: I think there's a maven shortcut for installing a jar http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
13:01AnderkentMorgawr: 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:02Anderkentkinda like maven subprojects, except without the more insane bits
13:03gtrakhey, I like the reactor!
13:04Anderkentgtrak: 'we'll dynamically add these artifacts to your build for some tasks, but not others'. :)
13:05gtrakah, I haven't hit that one
13:05AnderkentI 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:06gtrakoh, really? I was pretty sure I've done that before
13:07Anderkentthe 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:07gtrakunless you mean something different by a reactor project
13:07Anderkentgtrak: well, it works if you already have the subprojects installed, so the build does not fail due to missing dependencies
13:08gtrakmight have been a bug in a specific version, I'm like 100% sure that works
13:08Anderkentsay 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:09gtrakwhat's the { } signify modules?
13:09Anderkentyeah, 3 modules under Parent
13:10gtrakhmm, I'll try it right now
13:13gtrakah, wait, is this specific to dependency:go-offline? that would make sense in the context of your initial comment
13:13Anderkentyeah
13:13gtrakinstall or compile's always worked for me, I've never tried that other task
13:13Anderkentyeah, install and compile will work
13:14Anderkentwhich is good enough most of the time
13:14Anderkentso I'm not saying reactor is completely broken - just broken enough to be really annoying :)
13:14gtrakgotcha, I can believe that :-)
13:17nfisherHi 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:20technomancynfisher: pmap is probably fine for that
13:21gtrakAnderkent: yea, it's broken as you described. fun.
13:21nfishertechnomancy; thanks!
13:21technomancynfisher: I wrote a version using agents here, but someone pointed out pmap does a lot better: http://technomancy.us/130
13:22technomancyif 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:22dobry-denNewbie 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:23nfisherI suspect the DB insertions will be the bottleneck... I'll profile it to see.
13:23dobry-denI can trivially map [:li %] across the ul children, but I can't figure out how to unroll the result back into [:ul ...]
13:23gtrakdobry-den: into [:ul]
13:24gtrakwhich is equivalent to reduce conj
13:25Anderkent,(let [[head & rest] [:ul "A" "B" "C"]] (into [head] (map #(vector :li %) rest)))
13:25clojurebot[:ul [:li "A"] [:li "B"] [:li "C"]]
13:26gtrakif it doesn't need to be a vector, can simply cons head onto the result of map
13:26dobry-denThanks guys. I feel sheepish having to come here for that
13:27Anderkentnp that's what we're here for (pretending to be productive while avoiding actual work)
13:27nathanielkkorma seems to infuriate more than help. has that been the experience of others? do i just need to stick it out?
13:28gtraknathanielk: meh, keep things simple?
13:28Anderkentnathanielk: I've found it pretty nice for simple stuff (querying/inserting into a single db)
13:28Anderkentstill fall back to execute-raw from time to time though
13:28gtrakI thought this was interesting: https://github.com/cgrand/sqrel along with just the clojure.java.jdbc
13:29nathanielkwell, for example: i can't figure out how to convince it to insert default values into a column
13:29Anderkentnathanielk: surely that's the db engine's job
13:29nathanielkhrm, 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:29jjttjjhow 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:30Anderkentnathanielk: what's the query look like if you tell korma to print the sql
13:30Anderkent(i.e. as-sql or dry-run)
13:30nathanielkAnderkent: good question, I should be examining that.
13:30nathanielkI'll go stare at it
13:31nathanielkit's generating hardcoded values for the id column
13:31nathanielkie not telling the database "use a default"
13:31Anderkenthm, can you post your code?
13:33nathanielkit's really simple: (insert jump-table (values rows))
13:33nathanielkwhere rows is [{:foo_id 1, :bar_id 2},...]
13:34nathanielkthe 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:34nathanielki mean, it can't get much simpler, which is why i'm assuming that i'm doing something wrong
13:34nathanielki just can't find any documentation to help me
13:36dobry-denare columns foo_id and bar_id not integer datatypes?
13:38nathanielkdobry-den: they are.
13:38Anderkentnathanielk: 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:40nathanielkAnderkent: well, thanks for thinking about it :) i'll start reading korma's source
13:42Anderkentare you completely sure your rows does not contain {:id} fields?
13:42Anderkentthe simplest test case seems to work for me: https://www.refheap.com/15155
13:43nathanielkyeah, they don't
13:43nathanielkso I just ran the raw insert in psql without specifying an id and it did the bad thing.
13:43nathanielkkorma is vindicated.
13:44nathanielkso i'll stare at my schema now :)
13:52dobry-denwhen does it make sense to embed functions with let/letfn vs specify them as private functions?
13:53dobry-deni like the idea of letfn, but i don't like losing the ability to sanity check it in the repl
13:53ToBeReplaceddobry-den: when they only make sense within the scope of the function
13:53technomancydobry-den: if you have any hesitation, make it a top-level
13:54ToBeReplacedno one will ever complain about moving a letfn to a defn- though
13:54ToBeReplacedtechnomancy: what's the indentation problem? seems to work fine in emacs?
13:56technomancysorry, not indentation, but rather breaking readability rules of clojure
13:56hiredman"rules"
13:56technomancyfor nearly every other non-toplevel forms, any open paren followed by an identifier indicates a call
13:57technomancythis is part of why clojure is more readable than other lisps that use parens for everything with no brackets
13:57ToBeReplacedgood point; that's something that irks me about "case"
13:59technomancyI don't like case either, but I don't think it has this problem
14:00ToBeReplacedgrouping multiple constants happens in a list literal, which is not a function call
14:00technomancyoh, interesting
14:00technomancyI've never seen it used that way
14:00technomancybut it sounds annoying
14:02justin_smithyeah, I definitely read it wrong the first time I saw it
14:02justin_smithespecially when a vector literal would do the same thing in terms of show intent
14:02justin_smithunless you wanted the case to match a vector?
14:07tomjack&(case (list 1 2) [1 2] 3)
14:07lazybot⇒ 3
14:07dobry-denThe simplest way I can think of to turn "* abc" into "abc" is (join (drop 2 "* abc"))
14:07gtrakdobry-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:08dobry-denI didn't mean to hit enter
14:08gtrakthat said, my coworkers look at me like I'm crazy when I use it for not-small things
14:08hyPiRion,(subs "* abc" 2)
14:08clojurebot"abc"
14:08hyPiRiondobry-den: ^
14:08jtoy_clojure is da bomb!
14:09dobry-denhyPiRion: Thanks. Is there a way to browser Clojure functions by category like this: http://ruby-doc.org/core-2.0/Enumerable.html
14:10hyPiRionthe cheatsheet is probably the closest one: http://clojure.org/cheatsheet
14:11dobry-denCool. I found my next sideproject then
14:13amalloytechnomancy: 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:14gtrakclojure.test (is (thrown?
14:15technomancyamalloy: I did scope it to non-toplevel things
14:15technomancyI think of catch and finally as macro calls FWIW
14:15technomancyeven though there's technically no var behind them
14:15gtrakthrown? isn't a real thing.. is a multimethod dispatch on a symbol
14:15technomancygtrak: thrown? is horrible
14:16technomancyit should be a macro, but it's not
14:16amalloytechnomancy: reify is as non-top-level as letfn
14:16technomancyamalloy: yeah, reify is the one exception
14:16aaelonyDoes 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:16technomancywell, probably proxy too
14:16clojurebotproxy is not reify
14:16amalloyproxy is awful for other reasons
14:16technomancyyeah
14:16amalloyi won't use it as supporting evidence for my case
14:18amalloyand of course function arities are also not top-level things
14:19technomancyamalloy: function arities don't have an open paren followed immediately by an identifier though
14:19amalloyoh, i missed the "followed by"
14:20FoxboronSo, 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:23gtrakwhat are you interested in?
14:24Foxboronwell, everything really.
14:24FoxboronJust wanna try enhance my knowledge in Clojure.
14:24technomancyFoxboron: clojars could use some help
14:24technomancyalso clojuredocs.org
14:25Foxboronhm, i'll try take a look. Thanks!
14:26technomancyFoxboron: 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:26Foxborontechnomancy: looking at clojars i think i will have a tought time trying to set myself into the code.
14:27FoxboronBut a todo would be awsome.
14:27technomancyapart from the maven interop it's a pretty standard compojure app, if a bit dated
14:37rbxbxFoxboron: I know devn is looking for help on https://github.com/devn/getclojure || getclojure.org
14:38trptcolinFoxboron: a text-mode api for clojuredocs would be awesome
14:39trptcolinbecause i'd love to have that feature back to being included by default (w/ no extra dependencies) in REPLy / lein repl
14:40Foxboronhm, i don't got that much experience with clojure, but all of it are interesting projects
14:40FoxboronIll do my best and see if i can contribute
14:45konrIn http-kit, what's the correct way to handle redirects? It's not parsing the body of a 301 response, right?
14:54konrnevermind, it's an issue with probably a patch :) https://github.com/http-kit/http-kit/issues/35
15:17llasramBlargh, why do github "deploy keys" provide full read/write access to the repository?
15:29arrdemis there a way to "live inject" dependencies to nrepl, or do I have to restart when I add new deps?
15:33abparrdem: https://github.com/pallet/alembic
15:40tomjackwhat about making @ and #' and maybe ` put metadata on the forms read to record their having been used?
15:41tomjackI suppose also '
15:41tomjackbut '1 and `2 are problematic..
15:41amalloytomjack: not really, because '1 reads as (quote 1)
15:42amalloya form onto which you can put metadata if you like
15:42tomjackoh right
15:44tomjackhmm 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:45tomjacki.e. we need sjacket anyway so no point..
15:49cch1Which protocol(s) must one support in order to allow destructuring as a map?
15:50arrdemabp: awesome, thanks!
15:51amalloycch1: ILookup is all, i think
15:51cch1amalloy: thanks. Any idea of where I might find an example?
15:53amalloy$google clojure ilookup
15:53lazybot[Overloading keywords in Clojure - Stack Overflow] http://stackoverflow.com/questions/5583841/overloading-keywords-in-clojure
16:13cch1amalloy: thanks.
16:21tomjackI wonder why reduce-kv isn't the primitive
16:22tomjackbackwards-compatible reduction over map seqs would incur an extra map-entry allocation I guess
16:22tomjackand you have an extra function maybe to drop the k for reduce
16:22tomjackbut are there important things which can be IReduce but not IKVReduce?
16:23tomjackI'm just imagining stick a counter in all those places I guess..
16:59Kowboy<- just found out the hard way that 'empt' and 'empty?' functions both exist and do vastly different things. DOH!
16:59Kowboy*empty
17:00Kowboyin particular (when (empty {somthing here}) ...do something...) always does something
17:01bbloomKowboy: heh, yup. whoops!
17:03AWizzArdDoes Clojure support float literals? 13.0f vs (float 13.0)
17:05KowboyI don't think it does. You get doubles by default
17:05AWizzArdyes
17:06Kowboy java.lang.NumberFormatException: Invalid number: 13.0f
17:06AWizzArdYes, the “f” does not work. Was just an example, maybe there is some other syntax to denote floats.
17:07dnolenAWizzArd: not that I'm aware of.
17:07Kowboyare you integrating with a Java API that uses floats everywhere?
17:07gzmaskclojurers, 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:07ohpauleezYeah, you can do hex and big int, thats all
17:08ohpauleezrather, that's all I can think of
17:09Kowboyquestion about ^:dynamic vars vs using delay
17:09ohpauleezand by 8
17:09ohpauleez,010
17:09clojurebot8
17:09ohpauleez,0xa
17:09clojurebot10
17:10ohpauleez,1M
17:10clojurebot1M
17:10llasram,2r0101010
17:10clojurebot42
17:10ohpauleezradix
17:10KowboyI've been using delay refs so I can prevent them from loading until needed
17:10patchwork,3r012012
17:10clojurebot140
17:10Kowboybut I'd likt to change the value of the delay ref, for example in a test
17:10Kowboyis this possible?
17:12ohpauleezWhy not just pass things in?
17:12ohpauleezto the function
17:12ohpauleezor pass along a context map?
17:12llasramKowboy: For testing, you can mock with `with-redefs`
17:13Kowboyexcellent, that is what I need
17:13ohpauleezyeah, with-redefs is the best bet if you truly want the behavior you're looking for
17:13llasramIf you want changes for other than testing, then ohpauleez is probably right
17:13KowboyI was using dynamic vars, but the initial root bindings would blow up in my unit tests
17:14Kowboythey were generally dependent on a config file
17:14Kowboybut in my tests, I wanted to pass in my own configuration
17:14meliponehello! I am trying to use pmap (instead of map) but it seems to be slower than map. Is that possible?
17:14Kowboyproblem was, requiring the namespaces forced the root bindings to execute
17:14GeorgeHI'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:14ohpauleezmelipone: Definitely
17:15meliponeohpauleez: why?
17:15Kowboyso I changed them to (def something (delay .....)))
17:15ohpauleezGeorgeH: Go for it! That sounds a great project for Clojure
17:15ohpauleezKowboy: I'd consider the refactor, given that scenario
17:16ohpauleezmelipone: How many item are in the sequence/collection you're mapping on?
17:16KowboyI was trying to refactor to something that works both in my production scenario, and for testing/playing at the repl
17:16GeorgeHAwesome! Very reassuring, cheers
17:16melipone3500 items
17:17ohpauleezKowboy: I think passing in a context (a map of defs you currently have) might be the way to go
17:17ohpauleezmelipone: What's the function doing?
17:17Kowboythat would be a significant refactor
17:17tomjackbbloom: 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:18tomjackhard to tell what the acceptable scope of meanings for <! and >! are
17:18AWizzArdKowboy: 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:19Kowboyperhaps what I need to do is have my ^:dynamic vars default to nil, then bind them in my "main" method
17:19meliponewell, it's 3500 functions executed several times. The functions are very simple like check for equality of strings.
17:19AWizzArdIn principle there could be literals for chars, shorts, floats and ints ==> 1c 2s 3f 4i
17:19Kowboyand then use a test fixture to also bind them for testing
17:20bbloomtomjack: a promise is like a (delay (repeatedly value)) channel
17:20meliponeohpauleez: why would pmap be slower than map?
17:20tomjackoh, right, I didn't consider that such things could be called 'channels'
17:20tomjackbut the put! semantics are different I think?
17:21Kowboysimple functions run through pmap will be slower because of the overhead of threading
17:21bbloomtomjack: i'm not sure what the resource management implications are, but you can implement this w/o any custom types
17:21Kowboyonly when the functions take significant time will you get a performance benefit
17:22tomjackcore.async seems to use channels which emit the value and then close
17:22bbloomtomjack: give me a moment, let me experiment on this
17:22tomjackoh, I see, you mean make a process which takes from some channel and then goes into an endless put loop?
17:23bbloomtomjack: yeah, exactly
17:23bbloomi dunno if it's actually useful, but that's essentially what a promise is in terms of channels
17:23bbloomusing (chan 1) so it blocks
17:24bbloomthe problem then is you need to somehow garbage collect that put loop…. dunno how that works
17:24tomjackI 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:25ohpauleezmelipone: You might want to chunk your collection into number-of-cores+2 chunks
17:25ohpauleezthis will mean that each chunk is in its own thread when you run pmap
17:26tomjackjust 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:27meliponeohpauleez: oh, I see, thanks for the hint. I'll try that. My code really needs to speed up.
17:27tomjackalthough :/
17:27ohpauleezKowboy 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:27ohpauleezmelipone: You might also just try reducers, and see if being eager in the map helps (with fewer allocations)
17:28ohpauleezagain, depends on that function you're mapping
17:28tomjackbugs with (repeat value) chans are pretty dangerous (certainly to my emacs' health at least, and probably someday to a browser's..)
17:28ohpauleezAWizzArd: You could use reader literals
17:31gzmask
17:31gzmaskwhy (= [[1 1] [2 2] [3 3]] (map list [1 2 3] [1 2 3]))
17:31meliponeohpauleez: i heard about reducers
17:31meliponeohpauleez: what does "being eager in the map" mean?
17:31tomjack&(= [1 1] (list 1 1))
17:32gzmaskbut (map list [1 2 3] [1 2 3]) eval to ((1 1) (2 2) (3 3))
17:32tomjacksequential collections form an equality partition
17:33bbloomtomjack: refheap seems slow right now. anyway, here's an experiment: https://gist.github.com/brandonbloom/5681362
17:33ehaliewiczlooks like it's down actually
17:33gzmasktomjack: ah, i see
17:33ohpauleezmelipone: Maps are lazy by default, they return a LazySeq
17:34technomancyo_O
17:34ohpauleezmap
17:34ohpauleezthe fn
17:34ohpauleezhaha
17:34ohpauleeznot Maps, the HashMap
17:35meliponeohpauleez: okay, thanks
17:35technomancyoh english... you definitely need a bugfix release
17:35pjstadigor perhaps the nomenclature of functional programming language
17:35tomjackI guess the resource problem is that the blocked put! action in the state machine will hold onto the promise channel?
17:35technomancypjstadig: but I want a plural you and exclusive we too
17:36pjstadigtechnomancy: can't help you there
17:36technomancyat least you didn't say "yall"
17:36pjstadighey now!
17:36pjstadigi reserve the right to say y'all
17:36ztellmanbbloom: 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:37technomancypjstadig: what you do in the privacy of your home is your own business
17:37pjstadigtechnomancy: besides everyone knows that the plural of "y'all" is "all y'all"
17:37tomjackI'm worried that doing that will confuse CSP semantics
17:37hiredmanitym "youse"
17:37bbloomztellman: 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:37bbloomztellman: better still: don't use promises
17:38pjstadighiredman: this is most definitely a yankeeism
17:38tomjackthere's a mutex in core.async, so the impl is quite simple I think
17:38bbloomztellman: promises are a expression-oriented idea, but channels are an procedure-oriented idea
17:39tomjackyes, this is why I don't want to use channels as promises :)
17:39ztellmanbbloom: you'll need to expand on that a bit
17:39tomjackit's hard for me to imagine programming with result channels that emit the value once and then go nil
17:39bbloom1 sec, brb
17:39ohpauleezMaybe he means in channels, order is implied?
17:39bbloomor ok i'm here now. the person that needed me just 1 seconded me :-P
17:40bbloomwhat i mean is that promises are a reification of a lazy evaluation thunk
17:40bbloomchannels are a reification of a communication link
17:40bbloomlazy evaluation is all about ignoring order and the demand driven nature of the world
17:41bbloomchannels have inherent sequencing
17:41bbloomi'm saying that "pure and functional" isn't the be all end all of problem solving techniques
17:41ztellmanwell, not if you read from multiple channels at once
17:41ztellmanbut I take your meaning
17:41bbloomit's OK to write some procedural call if what you are modeling is actually a proceedure
17:41tomjackbbloom: sure, but neither is CSP :)
17:41bbloomprocedural code*
17:41bbloomsure, CSP is about a bunch of little machines talking to each other
17:42bbloomeach machine is a procedural message pump. ideally, the logic in there is functionally pure
17:42gzmaskok... another question: how do i make this: [0 1 2 3 4 5] -> [[0 1] [2 3] [4 5]] ?
17:42bbloompush your procedural code to the fringes of your system: but don't try to eliminate it completely
17:42jouiswalkeruse partition
17:43tomjackbbloom: I completely agree
17:43ztellmanbbloom: so how do these two models interact?
17:43tomjackyou made me realize though that my imagined frustration with 'result channels' was just an imagined misuse of the
17:43ToxicFrog,(partition 2 [0 1 2 3 4 5])
17:43tomjackthem
17:43clojurebot((0 1) (2 3) (4 5))
17:43tomjackI guess you do 'put argument in, take return value out'
17:43gzmaskToxicFrog: thanks
17:43bbloomztellman: "evaluate this function" is a procedure
17:43tomjackand passing around a channel as a representation of an eventual return value is wrong
17:44bbloomtomjack: yeah, i'm not sure how i feel about the returns-a-channel behavior of core.async
17:44bbloomsingle item channels just feels wrong to me
17:44tomjack..so what should it return? :)
17:44jouiswalkeris the repl the best way to do development with seesaw?
17:44ztellmanthere's been parallel work on async promises
17:45ztellmanweirdly, it seems completely disjoint from core.async
17:45bbloomtomjack: it should return a value, not a reified promise. that's what golang does
17:45tomjackit got replaced
17:45patchworkcouldn't a single item channel be interpreted as a constant channel?
17:45tomjackcljque used to be in core.async
17:45patchworkA channel that never changes
17:45tomjackbbloom: but what about CLJS?
17:45bbloomtomjack: if you use macro magic to make that work & the single-item channels are an impl detail, that's probably fine
17:45bbloomtomjack: i dunno, this shit is hard heh
17:45tomjackyeah :(
17:46bbloomtomjack: more macros & more SSA or CPS rewriting
17:46tomjackI'm writing new SSA for await/deliver now
17:46shriphanihi 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:46ohpauleez,(mapv vec (partition-all 2 [0 1 2 3 4 5]))
17:46clojurebot[[0 1] [2 3] [4 5]]
17:46shriphanienlive select *
17:46ohpauleezgzmask: ^
17:47jouiswalker,(doc mapv)
17:47clojurebot"([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:47ohpauleezif you really want vectors for some reason
17:47jouiswalkerhuh
17:47jouiswalkerthats really nice
17:47tomjackunfortunately the current alt ioc will not cooperate with my efforts since it specifies async-chan-wrapper in its impl
17:47jouiswalker,(mapv identity (partition-all 2 [0 1 2 3 4 5]))
17:47clojurebot[(0 1) (2 3) (4 5)]
17:49bbloomtomjack: 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:49bbloomtomjack: ztellman: but most of the time, you don't ever care about the promise object, just the contained value
17:50bbloompromises are useful, but only a tiny portion of the time :-)
17:50tomjackyes, the @ is a wart caused by lack of static types :P
17:50ztellmanbbloom: yes, but where the promise is generated and where it's consumed can be different places
17:51ztellmanallowing that to be decoupled can be useful
17:51ztellmanthough certainly not always
17:51ohpauleezI agree with that
17:51ohpauleezcertainly not always, but nonetheless useful
17:51justin_smithwhat'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:51jouiswalker,(symbol? '+)
17:51clojurebottrue
17:51bbloomztellman: 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:52tomjackI think go returning a channel makes sense to me if all your processes return nil
17:52bbloomgo 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:52tomjackand take chan in/out args or something
17:52bbloominternally, they are parking goroutines… internally core.async is returning a channel and scheduling a callback
17:52tomjackhmm, no, that still doesn't make sense to me
17:53jouiswalkerdoes anyone here think they would benefit from a 4clojure clone for sicp?
17:53ohpauleezI haven't used it in a production system, so I have no idea the implications of the design decision
17:54ohpauleezjouiswalker: http://sicpinclojure.com/
17:54tomjackmy goal is to never have to use the promise impl methods except in the promise library impls
17:54jouiswalkeri'm aware of it
17:54ohpauleezI'd just make the effort to fill that out
17:54tomjackyou still have to worry about whether a fn returns a promise or not though
17:54ohpauleezand then make a scraper/generator to generate problems from the code
17:55jouiswalkerbut what theyre doing is rewriting a book
17:55tomjackoh 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:55jouiswalkeri just mean a collection of test cases and such for the exercises
17:55ohpauleezjouiswalker: You read SICP and use the site to see the code in Clojure, then practice your skills more with generated 4clojure style problems
17:56bbloomtomjack: 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:56bbloomtomjack: channels are more general, but that has it's pros and cons
17:56ztellmantomjack: 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:57ztellmanI'm not sure there's a third option
17:57tomjack'going all the way' I think is infeasibly with core.async's ioc-macros
17:57bbloomtomjack: but if you never read from a promise twice, you just <! on the channel and not care
17:57jouiswalkeroh do they plan on implementing test cases?
17:58tomjackI guess the ! is right there on the tin. so treat it like you would a transient, non-shareable
17:58bbloomtomjack: which a simple (let [the-value (<! a-channel-like-promise)] ….) gets the job done
17:58jouiswalkeri'll check with the developer of the project
17:58ztellmantomjack: I haven't read ioc-macros closely enough to tell, but it's certainly doable with the core.async <! mechanism
17:58bbloomtomjack: exactly. the advantages of promises is that that dereferencing them is idempotent.
17:58jouiswalkerthanks for making me take a closer look
17:58Licenserhey 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:59tomjackztellman: the problem I see is that every single sub-expression under ioc will get CPS'd
17:59jouiswalkerhttp://java.ociweb.com/mark/clojure/article.html
17:59ohpauleezLicenser: Chas's book
17:59tomjackor.. SSA'd
17:59technomancyLicenser: I don't believe there are good resources for people who aren't already programmers.
18:00tomjackso like (go-promise (+ 1 2)) will have to have 4 take!s
18:00tomjackunless you try to do inference about what's "trivial"
18:00Licensertechnomancy awww
18:00tomjackwhich does not seem like fun to me without gradual types or something
18:01ztellmantomjack: 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:02ztellmanbut even then, you need instrumentation to understand what intermediate state the dataflow's in
18:02ztellmanthat's a lesser problem with the non-dataflow IOC (though still one that needs to be solved)
18:02bbloomtomjack: ztellman: i took the trivial vs serious approach w/ the CPS transform attempt i did
18:02bbloomi had a macro called "spawn" which was essentially "go"
18:02jouiswalkerLicenser: you might ask him to do the first two or three chapters of practical common lisp to get him used to the syntax
18:02tomjackyeah that was enlightening
18:03tomjackthe paper was unintelligible to me iirc
18:03bbloomit took me a while, yeah
18:03technomancyLicenser: htdp.org looks interesting for new programmers
18:03bbloomi think SSA was a better call, but i was hung up on going the CPS route for some reason
18:04tomjackmy cljs tests so far of very simple go blocks have produced seemingly very large functions
18:04bbloommore 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:04Licenserguys you're awesome :)
18:04tomjackioc-macros is obviously alpha and probably needs adjusting for cljs
18:04bbloomlastly, 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:04gzmaskhow 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:04tomjackbut we better be damn good at inferring triviality I think
18:05tomjack..or ^:trivial (+ 1 x) ?
18:05bbloomtomjack: well the brilliant part of SSA (as compared to CPS) is that you can do a single level of SSA
18:05bbloomyou rewrite ONE function into a state machine
18:05bbloomrather than have to thread the CPS all the way through to the bottom
18:06onthestairshmm, 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:06tomjackok, the function I am rewriting is (fn [in out] (let [x (<! in)] (>! out (+ x 42))))
18:06onthestairshttps://gist.github.com/onthestairs/5681569
18:06bbloomi 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:06tomjackwell, no, channels won't be a good example
18:06tomjackmy worry applies in the 'go all the way' dataflow case
18:06dnolenonthestairs: gist
18:07jouiswalkerhas anyone here played with avout?
18:07dnolenonthestairs: oh sorry you pasted
18:07onthestairsdnolen: no worries, cheers
18:07tomjackoh, hmm, I see
18:07tomjackI just tried an example and it seems to work out better than I thought
18:08ohpauleez,(reductions + [0 1 1 2 1 2 1])
18:08clojurebot(0 1 2 4 5 ...)
18:08technomancyLicenser: 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:08ohpauleezgzmask: ^
18:08tomjackvars are tricky
18:08technomancyhuuuuge contrast vs clojure's "I dunno; here's some compiler guts you can look at I guess"
18:08dnolenonthestairs: hrm, yeah that doesn't make sense.
18:08tomjack(fn [x] (add x 42)) - should we await! on add?
18:08gzmaskohpauleez: I known reduce but reductions are cool! thx!
18:08dnolenonthestairs: why are you projecting g?
18:09Licensertechnomancy hmmm hmmm
18:09tomjackother problem is how to let functions have trivial return values
18:09dnolenonthestairs: you should probably project f which will be bound to a fn
18:10technomancyLicenser: 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:10Licensertechnomancy my brother says 'nahh I already fell in love with clojure' <-that's good feedback I guess ;)
18:10LicenserI'll just have to help him out more ^^
18:10onthestairsdnolen: im not sure. i think i have a fundamental misunderstanding
18:10technomancyheh; well that works too; it just means he'll need more help from you rather than reading texts
18:10technomancyhah, exactly
18:10onthestairsdnolen: is there a good reference page for project
18:11Licensertechnomancy I think I'll have to get him a IRC client :P
18:11tomjackbbloom: your point has analogy to lazy seqs I think - they support exactly the same value-oriented functions as their forced values
18:11technomancyLicenser: if you can shoulder-surf from someone experienced who is patient then you can learn anything =)
18:11Foxboronummm
18:11tomjack..by bundling in a procedural notion?
18:11Licensertechnomancy true!
18:11FoxboronI don't know Clojure that well. But i could help out mentoring another guy (Ref: technomancy Licenser)
18:12Foxboronmentored a few people in Python. Might as well be a good learning experience
18:12dnolentomjack: 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:12technomancyit just doesn't scale well
18:12tomjackdnolen: yes, but not every subexpression of those bits will also be async
18:12bbloomtomjack: 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:12dnolenonthestairs: tomjack yes but I can't imagine it will matter, if it's async it's likely IO bound
18:12LicenserFoxboron 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:13dnolenand people will move out big expressions into fns as usual.
18:13onthestairsdnolen: oo nice, i have got it working. thanks
18:13tomjackmaybe it would be OK
18:13Licenserplan 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:13tomjackI mean I think current core.async go w/ channel output is probably OK
18:14FoxboronLicenser: teach him gist maybe?
18:14FoxboronLicenser: also, clojure-koans is a good place IMO
18:14tomjackto be clear I was discussing a different ioc macro which lets any subexpression return a single-assignment dataflow variable transparently
18:14LicenserFoxboron gist?
18:14dnolentomjack: based on the Node.js crap I've had to right, I'm pretty sure it's OK
18:14dnolenwrite
18:14FoxboronLicenser: https://gist.github.com/
18:15LicenserFoxboron oh hah! okay I wasn't thinking that simple ^^
18:15tomjack(which I have not really seriously considered in a long time)
18:15tomjack(not that I have very good reasons not to)
18:15FoxboronLicenser: it is not git, but it helps him keep track of his files, changes etc.
18:15ztellmantomjack: if you confine the dataflow to a function, and force the function to return a realized value
18:15LicenserFoxboron yea I know them just thought you mean something else :)
18:15technomancyspeaking of things that are horrible for newcomers... git =(
18:15bbloompersonally, i like implementing services as explicit state machines operating on sequences of messages… but i'm a crazy person :-)
18:15tomjackthese functions can't return realized values in cljs
18:15tomjackmaybe I misunderstand?
18:16dnolentomjack: they cannot
18:16ztellmanoh, I missed the cljs bit
18:16ztellmanyeah, that's a trick
18:17ztellmanis there a js-land full dataflow transformer, or do they all use some variant of 'await'?
18:17ztellmanI've only seen the latter
18:17Foxborontechnomancy: it is horrible for other people too. Used git every day for almost a year. I still fuck something.
18:17dnolenztellman: no, there are blocking reads in JS and there will be no tricks. All read/writes on channels must be in go block
18:17dnolenthere are no blocking reads
18:17dnolenI mean
18:17dnolener reads/writes
18:18tomjackthey have no macros so I would not be surprised if they haven't done it..
18:18jouiswalkerfoxboron: do you have something you prefer over git?
18:18Licensertechnomancy Foxboron got him sourcetree, it makes it mostly barable I think
18:18Foxboronjouiswalker: I actually like git. But i always manage to fuck something up.
18:18jouiswalkerfoxboron: hehe
18:19tomjackit's interesting how "transparent" can mean both "you can't see it" and "you can see it clearly"
18:20ztellmantomjack: http://en.wikipedia.org/wiki/Auto-antonym
18:20tomjack:D
18:20dnolenztellman: maybe await, but I didn't hear rhickey mention that
18:20ztellmandnolen: where was this discussed?
18:20LicenserAnd there we are :) may I introduce my brother SomeOtherGuy!
18:20jouiswalkertomjack: isn't it supposed to be an intermediate between tranlucent and opaque?
18:20dnolenztellman: rhickey's been popping into the channel talking about the core.async stuff now and then
18:20SomeOtherGuyHey guys! :)
18:20jouiswalkertranslucent*
18:21nopromptif anyone wants a good laugh i hand rolled a little migration lib for korma https://gist.github.com/noprompt/5681539
18:21technomancySomeOtherGuy: welcome
18:22nopromptfor the record, i have no idea what the hell i was doing or how those things should work.
18:22jouiswalkernoprompt: that is beautiful
18:23nopromptjouiswalker: you're being sarcastic, right? :)
18:23jouiswalkernoprompt: its better than what i manage :3
18:24noprompthonestly though, i'd love to know how to actually build something like this correctly.
18:24tomjacknoprompt: my gripe is that all the migrations are collected into a global atom
18:24noprompttomjack: yeah, i didn't know how else to do it.
18:25jouiswalkernoprompt: you might be able to use some partials with append-x and such
18:25SomeOtherGuySorry If I'm not very communicative. Try to understand things that seem to be above my intellect!
18:25noprompttomjack: so what would be the alternaive?
18:27tomjacka cheap fix would be to key the entries in the global somehow by user-specified keys
18:27tomjackand allow the user to somehow pick out the migrations to run with migrate!
18:27tomjackbut I don't like that either
18:27tomjacksimple thing seems to be to just have the user pass a collections of migrations to run?
18:27tomjack..but I haven't ever tried to write a migration library, so.. if it works for you, great :)
18:29nopromptso let me grab an example of the usage
18:30jouiswalkerare there any deprecated lein plugins that someone would like to see renovated?
18:32jouiswalkeri want to relieve boredom by making something useful :/
18:32tomjackjouiswalker: no, but I want to see a new one for generic run-task-on-file-change watches
18:32jouiswalkerwhats the current one and how would you like me to change it?
18:33tomjackthere isn't a current one really
18:33jouiswalker:x
18:33tomjackcljsbuild has an 'auto' which I don't like much
18:33tomjackthere are sketches of how to use the java 7 file watcher stuff in clojure
18:34tomjackI started a project for this 'lein-auto' but spent only about 15min so far on it..
18:34tomjackhmm
18:35tomjack
18:35jouiswalkeris your work on github?
18:35tomjackI realize now that could be a lot trickier than I thought
18:35jouiswalkeri just see a couple forks :p
18:35tomjackno, I have barely anything at all
18:35tomjack15min was mostly taken up by trying to grok the file watcher api
18:36tomjackthen I stopped and said "hey, cljsbuild is working"
18:36jouiswalkerlol
18:36jouiswalkeri'll try my hand at it
18:37tomjackI wonder if you can start up a project jvm, keep it running, and eval-in-project multiple times?
18:37ztellmantomjack: I think eval-in-project creates a new environment each time
18:37ztellmanyou'll need to eval something which runs a background process within the project
18:37tomjackwell I guess you can start up an nrepl thingy
18:37tomjack?
18:37justin_smithanwsering my own question above (def to-stream (fn [s] (io/input-stream (.getBytes s))))
18:38ztellmanthough there are other people who can speak more authoritatively about this than me
18:38tomjackyeah, makes sense
18:39noprompttomjack: i've updated the gist with a little example at the bottom
18:40nopromptjouiswalker: you should write a shell in clojure :) how's that for a fun project
18:40tomjacknoprompt: yeah, looks nice and pretty simple except for the globals :)
18:40jouiswalkernopromt: eww haha
18:44nopromptjouiswalker: well it could be fun.
18:44jouiswalkernoprompt: maybe a parser that converts s expressions to bash calls or something lol
18:45nopromptjouiswalker: 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:45jouiswalkernoprompt: garden?
18:45justin_smithjouiswalker: so basically a port of scsh
18:46nopromptjouiswalker: 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:46justin_smithscsh "regular expressions" are actually much more sane than the standard
18:46jouiswalkerjustin_smith: i knew there had to be one! thats cool.
18:47tomjack"it's a lisp" "oh, so there are a lot of parentheses..." <- happened :(
18:47justin_smithI 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:47nopromptjouiswalker: yeah, garden.
18:47tomjacknot jokingly, but trailing off and almost despairingly
18:48nopromptwell if you were gonna write a shell in clojure i would imagine it working kind of like the emacs shell
18:48jouiswalkerjustin_smith: it seems with paredit it wouldn't be painful
18:48jouiswalker^
18:48justin_smithyeah, my tty did not provide paredit
18:49jouiswalkerhehe, i tried installing scsh. at least for arch, it seems like its not compatible for 64 bit
18:50nopromptfish is a neato shell.
18:50nopromptit's got a lot of "geewiz" features.
18:50justin_smithscsh 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:50jouiswalkerspeaking of shells
18:51jouiswalkerwhenever i run lein repl in xterm backspaces start giving me weird behavior
18:51nopromptthat is weird
18:51clojurebotAlles klar
18:51justin_smithsounds like a bad termcap
18:52nopromptcan't remember the last time i used lein repl directly w/o emacs though
18:52jouiswalkertrue. an interesting effect though, since it plays well with ther terminals
18:53technomancyjouiswalker: have you seen this? https://groups.google.com/group/clojure-tools/browse_thread/thread/c08b628a9af8346d
18:53tomjackI wonder how core.async will deal with exceptions
18:53jouiswalkerfor example, "aoeu<backspace><backspace><backspace><backspace>" winds up as "aoeu^H^H^H^H"
18:53technomancyif you're looking for something to implement ... =)
18:54justin_smithI think nrepl uses a java readline library, that is notoriously less than perfect
18:58jouiswalkertechnomancy: now that is interesting
19:00dobry-denHere'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:02dobry-denIn other words, as soon as I `root = (ul | ol | p | code)+`, the lists only slurp up one list element each.
19:04jouiswalkertechnomancy: so he wants to be able to generate language-x from clojure-like code to target devtool-x?
19:05technomancyjouiswalker: he -> me =)
19:05technomancybut yeah
19:05jouiswalkertechnomancy: oh!
19:05noprompttechnomancy: did regex syntax highlighting ever get folded in to clojure-mode?
19:06technomancynoprompt: not that I'm aware of
19:06gzmasktime to go. thanks for help forks! :wq
19:07noprompttechnomancy: for some reason i thought i saw a PR for it.
19:09noprompttechnomancy: just out of curiousity, why not use the JVM to generate all the keyword code for clojure-mode?
19:09nopromptthat's how the vim-clojure-static does it https://github.com/guns/vim-clojure-static/blob/master/syntax/clojure.vim#L18
19:10technomancynoprompt: not sure; I didn't write it
19:10noprompttechnomancy: oh :)
19:10jouiswalkerman, i see tim pope's stuff everywhere
19:11supersymtechnomancy: looks cool, weren't protocols designed for this kind of interfacing though or wouldnt that work with vim/emacsen?
19:11technomancynoprompt: pjstadig has been merging some clojure-mode pull reqs too, so I could have missed it
19:11nopromptthat's because tpope care's
19:11technomancyone way to find out
19:11noprompt*cares
19:11technomancysupersym: clojure protocols?
19:11technomancysupersym: I don't think there's any connection
19:11supersymyea
19:12technomancythere's no polymorphism going on here
19:12supersymno thats what I thought
19:12jouiswalkeroh wow hes in here
19:12noprompttechnomancy: cool. yeah, regex highlighting would be seriously nice.
19:12technomancysupersym: the clojure-side code is quite trivial; the tricky part is defining a minimal language which can feasibly be implemented across client runtimes
19:13technomancywhere "language" is "vocabulary for describing operations, their arguments, and ways to display their return values"
19:13supersymI was actually thinking about something along these lines as well
19:13hiredmanbetter bencode it
19:17jouiswalkertechnomancy: in your example, does doc have already definitions in vimscript and elisp?
19:17supersymso 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:17jouiswalkeralready have*
19:18noprompthmm... guess i was wrong.
19:19tomjackI see promises are weirder than I thought from a core.async perspective
19:19tomjack-- when is the put!/deliver! callback called?
19:19tomjackit's not CSP so it doesn't make sense with put!. maybe deliver! has no callback..
19:19tomjack..of course it doesn't, I guess
19:20jouiswalkernoprompt: what do you need done in garden?
19:23jouiswalkertechnomancy: i dont see enough information in the example you gave to infer that a docstring needs to be displayed
19:29cbp``Do you still to dl curl/wget on windows for the latest lein version?
19:30cbp`to use the latest lein*
19:31decafcbp`: nope
19:31cbp`decaf: thank you
19:32cbp`Oh you can use upgrade now too :)
19:32tomjack(gofn [in-chan out-chan err-chan] (>! out-chan 42) (close! out-chan)) ?
19:33tomjack(gofn [{:keys [in out err]}] (>! out 42) (close! out))
19:37jouiswalkertechnomancy: what about sending asts of maps and defining some primitive operations in vimscript/elisp
19:39jouiswalkertechnomancy: actually, probably easier just to do a map with an ast nested inside
19:45technomancyjouiswalker: all emacs commands have docstrings attached to them
19:45technomancydunno about vim
19:46jouiswalkerhmm
19:46technomancysupersym: yeah
19:47jouiswalkerwell, if we catalogued vim commands that fulfilled the same as the emacs commands
19:47bbloomtechnomancy: vim has excellent documentation. :help whatever
19:48jouiswalkerit might be possible to just match from one source
19:48technomancyjouiswalker: no asts
19:48technomancythe point is to avoid writing elisp on a per-command basis
19:48bbloomtechnomancy: it uses external docs though. you don't put a doc string on a fn, you have docuementation with an annotation of keywords
19:48technomancyyou just describe the data type you intend to return, and the client already knows how to display it
19:49jouiswalkerwould you consider a docstring a datatype?
19:50technomancyno, strings would be the data type
19:50technomancyjouiswalker: 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:51jouiswalkersort of like... process of elimination through argument list and return type?
19:51technomancyI don't folow
19:52technomancyfollow
19:52cemerickI shall not be trolled :-P
19:52jouiswalkeri dont see anywhere in the example that specifies that a docstring has to be returned
19:53jouiswalkerbut i'd personally be surprised if vim required more information to display a docstring than emacs does
19:54jouiswalker
19:54jouiswalker{:op "doc"
19:54jouiswalker :doc "Display the docstring of a given var."
19:54jouiswalker :arglist [{:prompt "Var: " :type :var}]
19:54jouiswalker :client-handler [:message]}
19:54cemerickcan't.....resist...
19:54cemericktechnomancy: 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:54cemerick(or, op implementation, whatever)
19:54technomancycemerick: OK, works for me =)
19:55technomancyso upon re-reading this I don't think putting the return type on the op makes sense
19:55technomancyit should probably be included in the response itself
19:55jouiswalkerthats clearer
19:55technomancysince a given op could return different types based on whether it succeeds or fails, etc
19:55cemerickit's probably reasonable to put it on the op as well, so tools can indicate support ahead of invoking an op
19:56technomancymaybe
19:56cemerickno 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:57technomancyshould be optional
19:58technomancyRFC: http://p.hagelb.org/nrepl-discover.clj.html
19:58RaynesLadies and gentleman, do not leave your seats, refheap and 4clojure will be returning momentarily.
19:59technomancy^ the above assumes :value in the response is just a string unless :type is given
19:59technomancynot totally sold on :arglist ["var:var"] in particular
20:00technomancybasically it's saying use "var" as the prompt, and if you have any special completion UI for choosing an existing var, use that
20:00RaynesAnd we're good.
20:01nopromptw00t! yay! <3 <3 <3
20:01hiredmanwhy not just sexpressions?
20:01hiredman(var var)
20:02hiredman(or bencode it...)
20:02nopromptRaynes: i had to use a stinkin' gist today! :P
20:02Raynesnoprompt: Oh the agony.
20:02technomancyhiredman: yeah, ("var" var) would probably be better
20:02nopromptliterally tears running down my face.
20:02nopromptRaynes: did you enjoy the concert?
20:02Raynesnoprompt: Oh goodness yes.
20:02technomancyhiredman: emphasizing that the first is a literal string and the second is symbolic
20:03technomancyor maybe ("Var: " var)
20:03Raynesnoprompt: 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:03nopromptawesome. i can't remember the last time i went to a show. miss those things.
20:03technomancyI was trying to avoid alists because they seem like an elisp bias, but they do seem to be a good fit here =)
20:03nopromptRaynes: say wut? damn, that's awesome dude.
20:04technomancyactually... maybe we need three values? user-visible prompt string, type, and argument name to put in the nrepl msg?
20:04technomancyuser-visible string could be optional and default to the argument name
20:05jouiswalkerthat sounds like a good idea to me
20:05hiredmanobviously you need reader literals to semantically tag things without specifying their concrete type
20:05technomancy:arglist [[var var "Trace: "]]
20:06jouiswalkerare there types that var is limited to?
20:07technomancyjouiswalker: string, var, namespace, file, and position (file/line/col tuple) at least
20:07technomancyoh, and choose-one-of-a-predefined-set-of-options
20:08technomancythose are the main types I can think of for which the client can provide useful completion
20:09jouiswalkerwhy position instead of int and tuple?
20:10bbloomdnolen: sooo cljs' tagged literals are fundamentally broken
20:10bbloomuser=> '#inst "2000-01-01"
20:10bbloom#inst "2000-01-01T00:00:00.000-00:00"
20:10bbloomvs:
20:10bbloomClojureScript:cljs.user> '#inst "2000-01-01"
20:10bbloom(js/Date. 946684800000)
20:10technomancyjouiswalker: because the client can just provide the current position of the cursor without actually prompting the user
20:10dnolenbbloom: this is not the first time I've heard that
20:11technomancyif 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:12brehautdesigners. sheesh
20:13bbloomdnolen: yeah, turns out that stratefied environments are really difficult to formalize with respect to metaprogramming….
20:14dnolenbbloom: 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:14bbloomdnolen: note the quoting
20:14bbloomdnolen: the main benefit of reader literals from a metaprogramming standpoint is that they are evaluated prior to quoting
20:15bbloomdnolen: 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:15bbloomdnolen: tagged literals offer the same power: you can pass a date/time to a macro
20:15jouiswalkeroh hold on
20:15hiredmandnolen: that completely undermines literals
20:15jouiswalkeryou dont mean excluding tuple or int
20:15tomjackcurious what you're trying to do :)
20:16jouiswalkeryoure just saying you could leave position in there to simplify things
20:16hiredmandnolen: you are supposed to be able to read #inst "2000-01-01" and get a date without an eval step
20:17technomancyjouiswalker: right; arglist types would all be about convenience to the user
20:18jouiswalkergotcha
20:18dnolenbbloom: hiredman: right, though I never considered that anything but a bit of odd convenience of Clojure JVM implementation.
20:18dnolenbbloom: what do you need that behavior for in CLJS?
20:19hiredmandnolen: it is the whole shooting match regarding literals, expanding in to something requires eval is *not* a literal
20:20bbloomdnolen: 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:20hiredmanhaving reading literals turn in to forms takes the e out of edn
20:20dnolenhiredman: right
20:20bbloomdnolen: yeah totally agree w/ hiredman
20:21tomjackhiredman: (defn foo [] #inst "2012"). in cljs, foo does return a js date. did you already know this?
20:21dnolenbbloom: is this not something we can get around by treating reader literals specially in the presence of quoting?
20:21bbloomtomjack: (defmacro literal-type [x] (str (type x)))
20:21jtoyhow can I use lein to run a single command and quit out?
20:21hiredmantomjack: shh, I'm talking to people
20:21bbloomtomjack: try that in both clj and cljs, in clj you'll get a inst, on cljs, you'll get a list
20:22tomjackno..
20:22bbloomdnolen: in order to get this to work, we need a custom macro system
20:22bbloomdnolen: we can't use clojure's macro system
20:23bbloomdnolen: 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:23dnolenbbloom: I don't really understand, macro gets a java date via a literal, compiler emits a js/Date
20:23hiredmanbbloom: I don't see how that is correct?
20:23hiredmanbbloom: literals are a reader thing
20:23dnolenor a goog.date.Date
20:24hiredmanI guess the problem is if the macro emits a quoted form passed to a function
20:24dnolenbbloom: works well enough for Regex, why can't it work for date literals
20:25hiredmanso the compiler needs to walk quoted forms and effectively unquote forms that are the result of a reader literal
20:25bbloomthis 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:26brehautbbloom: the correct answer is you want neither :P
20:26tomjackcouldn't the cljs reader read with its own default handler that uses a TaggedLiteral?
20:26bbloomi 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:26tomjackI mean the clojure-for-cljs reader
20:27jouiswalkerlol. stu saying "i dont feel the absence of a debugger" ironically drew a lot of attention to debuggers for clojure
20:27dnolenbbloom: I still don't see the problem
20:28dnolenbbloom: looks like cljs.tagged_literals.clj is just doing the wrong thing
20:28dnolenshould always convert to Java types and not move around lists of symbols as it is now
20:28dnolenthen you can convert during emission
20:28tomjackthere is no way to register an unreader
20:29bbloomdnolen: that's certainly an improvement over what is there now
20:29tomjackif you do that you lose the 'e' completely?
20:29dnolenwe *already* emit Java types all the time and there's not much of an issue
20:29tomjackoh I guess there is a way, print-method :)
20:29dnolenI don't see how literals aer any different
20:29bbloomdnolen: no, you're right. i was just elaborating on the nature of the problem
20:30dnolenbbiab
20:30bbloomdnolen: 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:31hiredmanreaders
20:31bbloomhiredman: does that sound sane to you?
20:32hiredmanI dunno, thinking about it, how can literals work in a mixed environment like clojurescript?
20:33bbloomhiredman: 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:33hiredmanif 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:34bbloomthere are two readers: the clj and the cljs reader
20:34bbloomyou need to write two different functions for tagged literals in both
20:34bbloomthe first one, is used at compile time & the literals always return java types
20:34bbloombut you ALSO need to have an emit-constant method
20:34hiredmanso the clojurescript compiler pr-strs and read-strings?
20:34hiredmanerr, pr-strs and emits read-strings?
20:35bbloomno, the cljs compiler calls emit, which produces js code
20:35bbloomAFTER macro expansion
20:35hiredmanright, but the macros can pass through and result in arbitrary types in forms
20:35bbloomyeah, there is just an extra layer: the translation from clj -> cljs
20:36hiredman(which is why I guess the clojure compiler does this thing)
20:36bbloomor clj -> js, more specifically
20:37hiredmanlike, 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:37bbloomhiredman: no, it doesn't emit edn strings, it emits js code
20:37hiredmanit can't
20:38bbloomliterals (should) yield :op :constant AST nodes
20:38hiredmanFoo is an arbitrary object resulting from macroexpansion
20:38bbloomyeah, macro expansion occurs during the analysis phase, prior to code emission
20:38bbloomno strings involved yet
20:39hiredmanright, an instance Foo comes out of a macro, and now the compiler wants to emit js, what does it do?
20:40bbloomcurrently: calls emit-constant and throws a no matching method error :-)
20:40hiredmanhttps://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:41tomjackwow
20:42tomjackI was just wondering why a macro returning a date didn't blow up with "can't embed object in code"
20:42hiredmanI think I have a branch somewhere where I added an IConstant to clojure
20:43bbloominteresting.
20:45hiredmanyou can actually use IType I think, which if you extend it lets you sort of control how the type is embedded
20:45hiredmanIConstant I think just effected the type of the final field used as a "constant" table
20:45bbloomseems like *tagged-readers* needs a matching *type-emitters*
20:46hiredmana protocol like IType maybe
20:46bbloomyeah something like that
20:46hiredmanfeh
20:47hiredmanthe itype interface is empty now?
20:47bbloomi'm not familiar with this part of the clj compiler
20:47bblooma protocol or a multimethod would do the trick really
20:47hiredmanat 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:48bbloomemit-constant is currently a multimethod, but if you use a fn or multimethod, then you'd want that in a dynamic var
20:48hiredmanthe compiler would, for that type, emit a constructor call with the values of those fields
20:48hiredmanit looks like it still does, but it calls getBasis reflectively
20:49hiredmanhttps://github.com/hiredman/clojure/blob/reflection-method-caching/src/jvm/clojure/lang/Compiler.java#L4422-4444
20:50hiredmanoh, whoops, that is my branch, it may be old
20:51bbloomhaha
20:52hiredmannah, hasn't changed much on clojure master
20:52bbloomdnolen: i think we can just delete *cljs-data-readers* and replace it with *cljs-constant-emitters*
20:56dnolenbbloom: hmm I don't see a need to get rid of *cljs-data-readers*, bootstrapping is in our future
20:56dnolenbbloom: but yeah, *cljs-constant-emitters* that just explains how to convert Java types
20:57dnolenyou'll have to define your readers twice (compile-time / dynamic runtime reads), but this solves the issue you're talking about
20:58dnolenbbloom: 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:00bbloomdnolen: 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:01dnolenbbloom: sure, this may actually duplicate cemerick's tickets
21:01bbloomok, i'll search
21:02dnolenbbloom: actually unrelated, go ahead an open a ticket
21:03noprompti/
21:13akurilinQuick 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:14akurilinI 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:15bbloomakurilin: 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:15brehautakurilin: 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:17technomancyakurilin: are you using "method" to mean defmethod or just "a procedure attached to an object"?
21:17hiredman~#9
21:17clojurebot9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. -- Alan J. Perlis
21:17brehautakurilin: btw, clj-time is a slim wrapper around Joda Time, which is a java lib that uses methods everywhere (because it has to)
21:17akurilintechnomancy, procedure with implicit self/this as first parameter
21:18akurilinbrehaut, I get that, but doesn't it try to make the underlying operations more idiomatic with respect to Clojure?
21:18technomancyakurilin: ok, makes sense
21:18jouiswalkerdnolen: have you read doug hoyte's let over lambda?
21:18bbloomakurilin: 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:18hiredmanakurilin: 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:18dnolenakurilin: I don't think looking at a project that demands polymorphism is a good intro into Clojure
21:18dnolenjouiswalker: nope
21:18brehautakurilin: well, yes, but the fundamental immutable datamodel is in java, no clojure.
21:19akurilinbbloom, 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:19hiredmanmethods often also introduce polymorphism
21:19jouiswalkerdnolen: just curious ;p
21:19dnolenjouiswalker: yeah, it just sounded like CL drivel
21:19bbloomakurilin: when you are just learning clj, methods are NEVER the right way to go :-)
21:19dnolenjouiswalker: and I like macros a lot
21:20jouiswalkerdnolen: it sort of was. there was some interesting performance related stuff he did in it though
21:20bbloomakurilin: but the reason to really use methods is when you want fast single dispatch by type
21:20bbloomakurilin: that's basically the only reason
21:20jouiswalkerdnolen: it didnt take long for his words to go over my head though lol
21:21akurilinbbloom, is the idea to replace those with multimethods that can operate on a set of supported types?
21:22dnolenjouiswalker: 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:22brehaut~polymorphism
21:22clojurebotgenuine need for polymorphism just isn't very common
21:22hiredmanfeh
21:22hiredmantechnomancy: says you
21:22bbloomakurilin: multimethods are more flexible than methods, but are also more complicated than regular functions
21:22bbloomakurilin: the question you need to ask is whether or not you need open dispatch
21:23trptcolinjouiswalker: saw your note about an `lein repl` + backspace issue. is this lein 2.2.0?
21:23jouiswalkerdnolen: 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:23technomancyhiredman: on a regular basis
21:23bbloomakurilin: you can always do (cond (fn? x) y (number? z) w …)
21:23dnolenjouiswalker: both good books
21:23jouiswalkertrptcolin: yes
21:23akurilinbbloom, not familiar with the term, google isn't revealing anything either
21:23jouiswalkertrptcolin: but it was present before that as well
21:24brehauthiredman: its certainly not as necessary as its place in OO might suggest
21:24hiredmanbrehaut: sure, ala carte
21:24jouiswalkerdnolen: thanks for the book recommendation
21:24clojurebotbrehaut is ‽
21:24bbloomakurilin: in this case "open" means accessible for other people to extend
21:24brehautWTF clojurebot
21:25bbloomakurilin: an cond block sn't open to extension, you can't add more cases to it
21:25bbloomakurilin: but a multimethod lets you add more cases without changing the code
21:25bbloomakurilin: if you don't need open extension, start off with cond
21:25hiredmanit's not about prevalence, it is about disconnecting decisions about polymorphism from decisions about namespacing, etc
21:26dnolenakurilin: 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:26dnolenakurilin: 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:27trptcolinjouiswalker: sure. my xterm seems happy. so the two possibilities i see: ~/.inputrc setting overriding default keybindings or some keystroke is unmapped by jline
21:27decaf(do (def alphabet (char-array "abc")) (class alphabet)) returns "[C" without quotes. am I hitting a giant bug here?
21:27brehautdecaf: no; arrays are primatives
21:27hiredmanthat is the internal jvm type of an array of characters
21:28decafwe should get something more readable like char[]
21:28jouiswalkercat .inputrc : set editing-mode emacs, set keymap emacs
21:28jouiswalker
21:28technomancydecaf: it is pretty ridiculous
21:28hiredmanwe?
21:28technomancybut it's JVM ridiculousness, not clojure-specific ridiculousness
21:29jouiswalkertrptcolin: its sort of interesting, since using the repl within xterm works just fine
21:29akurilindnolen, 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:29akurilindnolen, 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:29decafhiredman: we, clojure programmers, especially newcomers. english is not my native language.
21:29jouiswalkertrptcolin: after i exit the repl using (exit), i'm able to do weird stuff like
21:29jouiswalkertrptcolin: aoeu^H^H^H^H
21:29jouiswalkerbash: $'aoeu\b\b\b\b': command not found
21:29jouiswalker
21:30trptcolinjouiswalker: oh, so this is after exiting the repl
21:30jouiswalkertrptcolin: yes
21:30bbloomakurilin: 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:30bbloomakurilin: and feel free to come back here and ask about a specific case, it's harder to understand these things in the abstract
21:31akurilindnolen, 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:31akurilinbbloom, for sure.
21:31dnolenakurilin: 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:31akurilinbbloom, appreciate it.
21:31dnolenakurilin: well, hopefully Clojure will convince you MVC is not really a great idea
21:31hiredmandecaf: 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:31jouiswalkertrptcolin: out of xterm, urxvt, terminology and terminator, xterm is the only one i have observed with this problem
21:32callenRaynes: home sweet home
21:32akurilindnolen, 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:32callentechnomancy: I survived LA
21:32decafI was just explaining what I meant by saying "we"
21:32dnolenakurilin: 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:34callenakurilin: 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:34jouiswalkertrptcolin: ahh, another interesting thing is that re-entering the repl fixes the problem, but that it returns again after you exit :/.
21:35callenakurilin: namely, less assuming of some kind of core (large) framework, more, "here's a bag of tools, do as thou wilt"
21:35callenakurilin: but I'm pretty fascist about keeping my libraries focused. *shrug*
21:35trptcolinjouiswalker: 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:36jouiswalkertrptcolin: i'll do that now. thanks!
21:37akurilincallen, 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:38akurilincallen, 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:40akurilinOn 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:42akurilinSo something like a GET on /repositories with "contributors > 5"
21:43akurilinWhat's neat about korma is that it should be pretty doable to map those to korma's DSL
21:43akurilin(watch me get sql injected on day 1)
21:49jouiswalkertrptcolin: it looks like stty -a revealed a lot about the problem
21:49jouiswalkertrptcolin: erase somehow gets set to something else outside the repl
21:55callenakurilin: activesupport always bothered me more than activerecord.
21:55callenakurilin: 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:56callentechnomancy: do you read the Culture novels?
21:57akurilincallen, awesome, thanks, always good to have more sources for inspiration. I do look at Luminus occasionally as well.
21:57akurilinGotta run folks, thanks for your responses
22:14callenRaynes: what happened to Refheap?
22:15callenoh, Linode.
22:15callenballs.
23:38tieTYTi was forbidden from writing clojure at work today
23:38ehaliewiczwhy is that?
23:39eggheadtoo much power
23:39bbloomehaliewicz: it might make him less fungable?
23:39bbloomfungible*
23:39callentieTYT: why?
23:40tieTYTi 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:40callenehaliewicz: interchangeability of resources (nb: PEOPLE) is highly prized in the gentry class.
23:40xeqiit would lead down to the downfall of the semicolon industry
23:40callentieTYT: to whit, wouldn't that mean firing his lazy ass so the many (company) can benefit from the higher productivity?
23:40xeqiand that is too big to fail
23:41tieTYTactually he's pretty good w/ lisp
23:41tieTYThe was thinking of everyone else at the company
23:41tieTYTwe already use drools though in some project. I think it's a pretty similar thing to bring into the company ecosystem
23:41bbloomright, like i said, fundability :-)
23:41ehaliewiczthe way he said it suggested to me that he was normally allowed, but temporarily banned
23:41ivanego-protective behavior, assuming everyone else is too dumb
23:41bbloomer fungibility
23:41bbloomi can't type
23:42tieTYTehaliewicz: no, permaband
23:42callenI really dislike drools.
23:42bbloomivan: i didn't say dumb
23:42ivanI never implied such ;)
23:42tieTYTcallen: I don't know much about it
23:42eggheadI 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:42tieTYTbut if you compare the two, both require you to think differently and program in a way that's different from java
23:42bbloomivan: somebody way smarter than me is less likely to be able to understand my dense expressive code than my boring mechanical code
23:42tieTYTegghead: at least you get to use it on the internal tools
23:43bbloomeven if the guy who takes my job is way smarter than me, he would rather i wrote some vanilla boring stuff
23:43ehaliewicztieTYT: write clojure code that generates java
23:43tieTYTehaliewicz: ha, yeah that'll fly
23:43ehaliewiczthey won't even know
23:43tieTYTnow the incident is on the radar, they'll get real pissed if I did that
23:44eggheadyou can very easily write stuff in java or groovy that a future maintainer wouldn't understand
23:44eggheadseems like they are just neophobes
23:44eggheadchange is scary!!!
23:44ehaliewicztieTYT: but you're supposed to get back at them
23:45ehaliewicz:D
23:48tieTYTegghead: 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:48tieTYTwhere do you draw the line? Am I not allowed to use CollectionUtils?
23:49tieTYTthe 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:49tieTYTyou people understand me :)
23:51callentieTYT: better to beg forgiveness next time?
23:51callenecallen: hello doppleganger.
23:52tieTYTcallen: That is how I approached it
23:52tieTYTi wrote the clojure first
23:53tieTYTnow i'm off to learn about clojure script
23:53taliossweet :) cheers
23:56tieTYTi must say it's really hard to find out how to get started with clojurescript
23:56tieTYTthe "getting started" guide's first paragraph tells you you shouldn't follow it
23:58bbloomtieTYT: lein cljs-build is the easiest way to get started
23:58tieTYTyeah I'm going to start checking that out
23:59callentieTYT: I hope you like pain :)
23:59tieTYTcan I use CCW with it? Do I need to use piggyback or something?
23:59tieTYTcallen: why?