2013-05-30
| 00:01 | n_b | dnolen: So basically you'd accummulate changes and then request a frame to do all the updates in? |
| 00:01 | dnolen | n_b: yes |
| 00:02 | dnolen | n_b: but requestAnimationFrame can be called at any time, multiple times |
| 00:02 | dnolen | doesn't really matter |
| 00:02 | dnolen | which is what you want |
| 00:03 | dnolen | I don't mean the callback, I mean you can requestAnimationFrame again and again and simply will queue it up once when it's most convenient to actually execute the callback |
| 00:04 | cgag | has anyone had any experience using any javascript promise libraries with clojuescript and node? |
| 00:04 | tomjack | well the callback will be called again and again in that case, yes? |
| 00:04 | dnolen | tomjack: no |
| 00:05 | tomjack | my test suggests otherwise |
| 00:05 | tomjack | (function() { var cb = function(){console.log('cb');}; requestAnimationFrame(cb); requestAnimationFrame(cb); })() |
| 00:05 | tomjack | logs 'cb' twice |
| 00:06 | dnolen | https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame |
| 00:06 | dnolen | tomjack: which doesn't really prove anything |
| 00:06 | dnolen | your example I mean |
| 00:06 | dnolen | since the cb and the work is trivial |
| 00:07 | tomjack | hmm, not sure if I'm missing something or if we're miscommunicating. I meant just that if you call requestAnimationFrame multiple times with the same callback, the callback will be queued (and eventually called) multiple times |
| 00:08 | tomjack | so if the callback is like "draw everything to a canvas" you want to be sure to only call it once per frame |
| 00:09 | tomjack | call requestAnimationFrame once per frame I mean |
| 00:09 | dnolen | tomjack: oh ok, yes you are right, that's why they return the requestID - I thought it worked more like Cocoa's setNeedsDisplay |
| 00:09 | tomjack | if it's something like "flush a queue of pending dom updates" maybe you don't care |
| 00:19 | tomjack | how does virtual dom in cljs even work? |
| 00:19 | tomjack | is it that you have a mutable queue of pending updates? |
| 00:20 | tomjack | surely you're not gonna just deref and walk an atom every frame and somehow try to match it up with the dom? |
| 00:28 | recursor94 | Does anybody know what became of clojure.contrib.server-socket? I understand that clojure.contrib is not maintained anymore, but I can not find any information about that specific namespace. |
| 00:28 | hiredman | https://github.com/technomancy/server-socket |
| 00:29 | bbloom | tomjack: if you're willing to assume that you're the only one changing the DOM (which is true-enough for applications) then you can "diff" two snapshots of the atom |
| 00:30 | tomjack | right, I remembered you talking about "owning everything" before |
| 00:30 | bbloom | tomjack: since it's a tree structure & clojure data has fast equality, that's a trivially and cheap process for incremental changes … and not significantly more complex for significant changes, like moved sub trees, since you can cache complex immutable values while traversing/modifying/whatever |
| 00:30 | tomjack | makes sense |
| 00:31 | bbloom | of course browser extensions or even just a dev with the inspector can invalidate those assumptions |
| 00:31 | bbloom | but during normal operation, that's not really a problem for most use cases |
| 00:32 | recursor94 | hiredman: Is there a version in clojars? |
| 00:33 | hiredman | I think so, not sure though |
| 00:33 | recursor94 | Alright, thanks. |
| 00:33 | hiredman | https://clojars.org/server-socket |
| 00:33 | recursor94 | sweet! |
| 00:46 | recursor94 | :D |
| 00:59 | bbloom | dnolen: do you know much about the propegators stuff that was in the sussman "we don't really know how to compute" talk? |
| 01:00 | dnolen | bbloom: I've read and implemented bits of the art of propagator |
| 01:00 | dnolen | bbloom: a lot of the material he covered is from that. |
| 01:01 | bbloom | dnolen: yeah, was planning to read that |
| 01:07 | dnolen | bbloom: it's interesting though I found the paper lacking in terms of references |
| 01:07 | dnolen | bbloom: the list of interesting propagator work is massive |
| 01:07 | dnolen | I'm glad their popularizing it here - but the paper doesn't cite much Prolog CLP, Mozart, Gecode, etc. if I recall |
| 02:08 | benkay | on the topic of composing functions to run on a datomic transactor: |
| 02:08 | benkay | I have two functions installed on the transactor already, update-balance and update-position, that as one might expect, update a balance and a "position" in place. |
| 02:09 | benkay | I want to write a new function that executes both of those functions on the transactor atomically, that is to say either they both fail or they both succeed. |
| 02:10 | benkay | now: do I compose a function out of the two functions that I have already? or, from a *new* function in the datomic scheme, should I call both database functions? |
| 02:10 | benkay | i feel like I just answered my own question. |
| 02:35 | mthvedt | benkay: rubber ducking |
| 02:36 | benkay | all that i succeeded in doing was exposing further depths of ignorance :( |
| 02:36 | mthvedt | benkay: if you're not exposing one's own ignorance, you're not living an inquisitive life |
| 02:37 | benkay | amen |
| 02:37 | benkay | it was an ironic sad face |
| 02:39 | ddellacosta | I'm constantly doing this thing where I process one value of one key of each map in a collection of maps, and I always find myself jumping through hoops. There must be a nice shorthand for this common procedure in Clojure…what is it? |
| 02:41 | ddellacosta | hmm, maybe there is something in reducers |
| 02:42 | benkay | is it the same key every time? |
| 03:53 | quizme | is swanodette here ? |
| 03:55 | quizme | i was just wondering about the feasibility of writing a clojurescript compiler in node.js |
| 03:55 | quizme | sans jvm |
| 03:59 | nightfly | quizme: Please do it :) |
| 03:59 | nightfly | And go for extra points and make it self-hosting as well |
| 04:01 | quizme | nightfly what do u mean by self-hosting ? |
| 04:01 | nightfly | Once you've got your javascript clojurescript compiler working you write another clojurescript compiler in clojurescript |
| 04:02 | quizme | oh |
| 04:02 | quizme | give me a few minutes to let that sink in |
| 04:04 | quizme | ok |
| 04:04 | quizme | i think i get that |
| 04:04 | quizme | that would be awesome. |
| 04:05 | quizme | but yeah |
| 04:05 | quizme | that's for bonus points |
| 04:05 | quizme | cuz really i just wanna use it without the jvm |
| 04:05 | quizme | call me an end-user if u have to |
| 04:05 | borkdude | hmm, http://www.4clojure.com/ isn't working? |
| 04:06 | quizme | nightfly so you agree that it would be awesome to have a clojurescript compiler for node.js sans jvm dependency ? |
| 04:08 | nightfly | yes, that would be awesome |
| 04:29 | tomjack | quizme: why? |
| 04:35 | mondraymond | good morning from Brussels |
| 04:35 | mondraymond | I'm just hopping on to get a little advice on filter |
| 04:35 | mondraymond | I have a function which returns something like this (() () () ({:id 1}) () ()) |
| 04:36 | mondraymond | and I just want the map with the id |
| 04:36 | mondraymond | try as I might I cannot work out how to filter off the empty seqs |
| 04:36 | mondraymond | any suggestions before I fire off the google group? |
| 04:38 | dedeibel | (def a '(() () () ({:id 1}) () ())) |
| 04:38 | dedeibel | (first (flatten a) |
| 04:38 | dedeibel | ? |
| 04:39 | mondraymond | boom - that works! |
| 04:39 | mondraymond | way hey! thanks very much ... completely forgot about flatten |
| 04:41 | Raynes | &(filter (comp map? first) '(() () () ({:id 1}) () ())) |
| 04:41 | lazybot | ⇒ (({:id 1})) |
| 04:41 | Raynes | &(first (some (comp map? first) '(() () () ({:id 1}) () ())) |
| 04:41 | lazybot | java.lang.RuntimeException: EOF while reading, starting at line 1 |
| 04:41 | Raynes | &(first (some (comp map? first) '(() () () ({:id 1}) () ()))) |
| 04:41 | lazybot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean |
| 04:41 | Raynes | Ah. |
| 04:42 | Raynes | &(ffirst (filter (comp map? first) '(() () () ({:id 1}) () ()))) |
| 04:42 | lazybot | ⇒ {:id 1} |
| 04:52 | quizme | tomjack: why what ? |
| 05:13 | gtrak | good morning 5am #clojure |
| 05:14 | hyPiRion | 11 am here, but good morning |
| 05:24 | bordatoue | hi, I am trying to get log4j working but every time when I execute a method that uses log4j i get the message can not find log4j appender, it seems that project is not picking up the log4j.xml file I have added to resource-paths, is there any other location I need to specify the location of log4j.xml |
| 05:26 | rhymor | I'm not a log4j expert but if it cannot find the appender I'd guess it did find the log4j.xml but the class of the configured appender is not on the class path. |
| 05:28 | bordatoue | rhymor: i can see log4j.xm in the classpath using lein classpath cmd |
| 05:30 | bordatoue | rhymor: I think i need to place log4j.xml in src or resource directory based on | public TCPExchClient(int HB_sec,int conn_delay_sec,int exchPort,String exchHost){ |
| 05:31 | rhymor | in log4j.xml there's a line like <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> can you instantiate that class on the repl? |
| 05:31 | gtrak | rhymor: yep |
| 05:32 | gtrak | lemme find an example |
| 05:32 | bordatoue | rhymor: yes I can |
| 05:32 | gtrak | rhymor: https://gist.github.com/gtrak/5676736 |
| 05:32 | bordatoue | let me change the location of log4j.xml file |
| 05:36 | mondraymond | Hey Raynes - yes that works thanks. It seems to me though that flatten seems so much simpler ... does it miss something that your filter catches? |
| 05:36 | gtrak | ~flatten |
| 05:36 | clojurebot | flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with. |
| 05:38 | bordatoue | rhymor: got i working it; log4j file should be in the projects src directory , thanks |
| 05:38 | gtrak | bordatoue: test-resources is probably a better place |
| 05:39 | mondraymond | ok - yes indeed mapcat works for what I need |
| 05:39 | bordatoue | gtrak: is test-reources created by default using lein app |
| 05:40 | rhymor | If there is one thing I would like more developers to know it's that "semantics matters". People are often looking for a technical solution where they should be looking for a semantical solution. |
| 05:40 | rhymor | aka. don't think what the program does, think what it means. |
| 05:40 | gtrak | bordatoue: if it is, it won't be saved in your git repo if it's empty |
| 05:41 | gtrak | rhymor: tell those devs to use lisp :-), it makes it easier to give things names |
| 05:43 | rhymor | gtrak, I'm stuck in a project where we actually have a touring complete configuration language in XML. :( |
| 05:44 | gtrak | xml? you're one step away! |
| 05:44 | gtrak | <tag1><tag2>WAT</tag2></tag1> -> (tag1 (tag2 "WAT")) |
| 05:44 | hyPiRion | oh dear |
| 05:45 | gtrak | I guess attributes and thing are a bit tougher |
| 05:45 | rhymor | yes, it's basically lisp with an ugly syntax. |
| 05:45 | hyPiRion | https://github.com/technomancy/lein-xml |
| 05:45 | rhymor | :D |
| 05:46 | gtrak | become more productive with this language by writing a code-generator, when people notice you running circles around them, maybe they'll do something about it... |
| 05:49 | rhymor | gtrak, that could actually work. I'll try it. |
| 05:50 | gtrak | lol, awesome |
| 05:55 | ddellacosta | How to find a hash-map with a particular key in a vector of hash-maps, and then return the value associated with that key? This seems too verbose and inelegant: (:summary-text (first (filter :summary-text (second search-results))))) |
| 05:56 | gtrak | some does it for you |
| 05:56 | gtrak | (some :summary-text (second search-results)) |
| 05:56 | bordatoue | is there any easy way to determine which version of java is used by lein |
| 05:56 | hyPiRion | bordatoue: lein version should print it out |
| 05:57 | gtrak | some is an underappreciated core funciton |
| 05:57 | gtrak | function* |
| 05:57 | gtrak | ~some |
| 05:57 | clojurebot | I don't understand. |
| 05:57 | augustl | some ftw :) |
| 05:57 | gtrak | see? |
| 05:57 | bordatoue | thanks hyPiRion , is there any way to specify a perticular version of java |
| 05:57 | ddellacosta | gtrak: thanks! This is not the first time I've forgotten some... |
| 05:58 | augustl | it has some nice use cases, and I use it some times, unless it's bothersome for some reason |
| 05:58 | ddellacosta | the problem is I'm always thinking about things the wrong way, so some seems orthogonal to the solution |
| 05:58 | ddellacosta | here I was thinking too hard about processing a vector |
| 05:59 | hyPiRion | bordatoue: yeah. Do you want to change it system-wide or just for leiningen only? |
| 05:59 | gtrak | I generally enjoy overloading the notion of a pred with actually doing something useful, compojure works this way |
| 05:59 | ddellacosta | that's perfect, I just chopped that down to a much shorter version. Very happy. |
| 06:00 | ddellacosta | gtrak: yeah, it seems to be a common meta-idiom, if I can say that, in Clojure |
| 06:00 | bordatoue | hyPiRion: just for a specific project |
| 06:00 | ddellacosta | and as I get better with the language I've started to be able to "smell" when that kind of solution exists…but I'm not familiar enough with it yet to know the right solution all the time. So thanks. ;-) |
| 06:00 | gtrak | yea, I'm always on the lookout for neat combinations of functions |
| 06:01 | gtrak | like (juxt filter complement) |
| 06:01 | hyPiRion | gtrak: (juxt filter remove) I suppose? |
| 06:01 | gtrak | yea, that's what I meant |
| 06:02 | gtrak | there must be sort of a implicit second-order standard lib of things like that |
| 06:02 | ddellacosta | yeah, juxt is another one that seems like it has some really awesome applications, but which I haven't been able to naturally integrate into my coding yet |
| 06:03 | hyPiRion | bordatoue: Humm. You can set the LEIN_JAVA_CMD environment variable to specify what java version leiningen should run, or JAVA_CMD if you want the app and tests to run on the same java version. Don't think you can do it per project yet, unfortunately |
| 06:04 | hyPiRion | but if you're on Mac/Linux, `JAVA_CMD='path/to/the/java' lein run` should do the trick |
| 06:04 | bordatoue | hyPiRion, thanks very much |
| 06:05 | hyPiRion | no problemo |
| 06:52 | @rhickey | how do I keep lein repl from spewing #_=> at me when I do C-M-x in inferior lisp mode? |
| 07:02 | llasram | I don't think that's a very well-tested combination... The `lein repl` nrepl server + nrepl.el works perfectly fine though |
| 07:03 | @rhickey | llasram: thanks, not interested in adding more stuff until first stuff is working |
| 07:13 | llasram | Is there a reason for wanting in particular to run the `lein repl` task as the backing process vs just launching the clojure.main repl via Leiningen? |
| 07:44 | @rhickey | llasram: you mean java -server -cp `lein classpath` clojure.main, or something else? |
| 07:46 | Bronsa | rhickey maybe lein run -m clojure.main ? |
| 07:48 | @rhickey | Bronsa: that's better, thanks |
| 07:57 | Jetien | how do you retrieve values of a map from a list of keys idiomatically? ie a function f that evaluates like this: (f {:a 1 :b 2 :c 3} [:a :a :b :x]) -> (1 1 2) |
| 07:58 | rhymor | you can use the hashmap as function in map |
| 07:59 | Jetien | but if f=map then the example above evaluates to (1 1 2 nil) |
| 08:00 | rhymor | so you map, then filter or the other way round |
| 08:02 | Jetien | yep. i was just wondering if there's a simpler way.. thx! |
| 08:02 | rhymor | Jetien, what is the purpose of that function? I.e. why do you have a vector of keys, some of which might not be in the hash map? |
| 08:02 | Anderkent | ,(keep {:a 1 :b 2 :c 3} [:a :a :b :x]) |
| 08:02 | clojurebot | (1 1 2) |
| 08:02 | Anderkent | Jetien: ^ |
| 08:02 | Jetien | thanks |
| 08:02 | Jetien | rhymor, i think these situations are not that seldom |
| 08:03 | rhymor | Oh, I learned something new :) good day today. |
| 08:10 | hyPiRion | Hmmmm |
| 08:11 | hyPiRion | Keep in mind that nil values will not be returned |
| 08:11 | hyPiRion | ,(keep {:a nil :b 3} [:a :b :c :a :b]) |
| 08:11 | clojurebot | (3 3) |
| 08:12 | hyPiRion | ,(map val (keep (partial find {:a nil :b 3}) [:a :b :c :a :b])) ; solves it |
| 08:12 | clojurebot | (nil 3 nil 3) |
| 08:15 | Morgawr | can somebody explain in a very layman way what does "binding" do? in the doc it says it's like a let but executes a body and then re-establishes the previous binding? I don't fully understand it |
| 08:16 | manutter | slightly OT, but I notice luminus offers dailycred as a pre-configured 3rd party auth/auth service -- does anyone know of any similar services besides like Google/Facebook/etc? |
| 08:17 | manutter | I set up a luminus app with dailycred, and it works, but their error reporting leaves a little to be desired. |
| 08:17 | hyPiRion | Morgawr: it's like setting the variable, but only for the calls within the binding. It's reset afterwards. |
| 08:18 | Morgawr | so it's like a scope binding? |
| 08:18 | hyPiRion | dynamic scope binding, yes. Consider this: |
| 08:18 | hyPiRion | console.log("new animation"); |
| 08:18 | hyPiRion | whoops |
| 08:18 | hyPiRion | ,*print-length* |
| 08:18 | clojurebot | 5 |
| 08:19 | hyPiRion | ,(let [f (fn [] (println *print-length*))] (f) (binding [*print-length* 9000] (f)) (f)) |
| 08:19 | clojurebot | 5\n9000\n5\n |
| 08:19 | Morgawr | ah, I see |
| 08:19 | Foxboron | Morgawr: example. the varibale *out* tells clojure what stdout is. Say you bind it too a network socket. (binding [*out* (:in socket)] (println "hai")) |
| 08:19 | Morgawr | that's great, thanks for the explanation |
| 08:20 | Foxboron | s/:in/:out |
| 08:20 | Morgawr | ^ cool, thanks for a real world application too |
| 08:20 | hyPiRion | yeah, a common pattern is for example this |
| 08:20 | Foxboron | Morgawr: you could bind it to a file writer also. |
| 08:21 | hyPiRion | ,(let [s (new java.io.StringWriter)] (binding [*out* s] (println "hello world") (println "nice weather") (str s))) |
| 08:21 | clojurebot | "hello world\nnice weather\n" |
| 08:21 | hyPiRion | ^ that is exactly how with-out-str works |
| 08:22 | Morgawr | neat |
| 08:22 | Foxboron | Morgawr: i think that is one of the neatest things i have seen in Clojure so far ^^ |
| 08:22 | Morgawr | how does it work with closures though? |
| 08:23 | Morgawr | if I return a function that uses the bound argument and then call it outside the binding |
| 08:23 | Morgawr | I guess it keeps the temp binding, yes? |
| 08:24 | hyPiRion | no |
| 08:24 | hyPiRion | that's why it works in the first place |
| 08:24 | hyPiRion | (let [f (binding [*print-length* 100] (fn [] *print-length*))] (f)) |
| 08:24 | hyPiRion | ,(let [f (binding [*print-length* 100] (fn [] *print-length*))] (f)) |
| 08:24 | clojurebot | 5 |
| 08:25 | Morgawr | ah |
| 08:25 | Morgawr | that's weird, good to know |
| 08:25 | Morgawr | and yeah, I guess that is why it works in the first place haha |
| 08:25 | Morgawr | I didn't give it much thought after all |
| 08:26 | hyPiRion | Consider a (def ^:dynamic *foo* ...) definition as a global (binding [*foo* ...] the-whole-app-here) |
| 08:26 | hyPiRion | You can set up the binding within a function, of course |
| 08:27 | hyPiRion | ,(let [f (fn [] (binding [*print-length* 100] *print-length*))] (f)) |
| 08:27 | clojurebot | 100 |
| 08:27 | Morgawr | yeah, that's a solution |
| 08:27 | Morgawr | thanks for the help |
| 08:27 | hyPiRion | np |
| 08:34 | kitti | join |
| 08:35 | kitti | :Q |
| 08:35 | kitti | q |
| 08:35 | kitti | quit |
| 08:35 | kitti | exit |
| 08:37 | hyPiRion | heh, prepend with / |
| 08:58 | edbond | can someone provide example usage of seque? |
| 08:59 | hyPiRion | edbond: if you start up a repl with `lein repl` and do `(cdoc seque)`, then there is an example there |
| 09:00 | edbond | hyPiRion, thanks, didn't know about cdoc |
| 09:01 | hyPiRion | it's a nice tool for examples, although its quality on functions vary |
| 09:59 | Pupnik | is the rhickey in here actually rich hickey? |
| 10:01 | hyPiRion | yeah |
| 10:02 | Pupnik | funny to see him asking questions |
| 10:02 | Pupnik | although I suppose he isn't an expert on all the various things that have grown around clojure |
| 10:03 | atyz | hi guys, I've been stuck on a small korma issue for a while. It keeps throwing a <NullPointerException java.lang.NullPointerException>. I've spent a lot of time trying to track down the source of the problem but I am ultimately unable to. I would be very grateful if someone would point me in the right direction. It's driving me crazy. http://pastebin.com/isTht8h9 |
| 10:04 | hyPiRion | It's not weird. He's not working on the tooling and plumbing around Clojure, but rather on the language. |
| 10:04 | supersym | Pupnik: every API/implementation takes time to read-up, get in the intention/head of the maker |
| 10:05 | supersym | you may get a bit quicker/develop an eye... but that part always stays :) |
| 10:07 | supersym | I spoke to our king on two occasions...same feeling |
| 10:07 | supersym | we seem to attribute super-natural powers/knowledge to our idols |
| 10:09 | Pupnik | true, true |
| 10:10 | Pupnik | he does give great talks though |
| 10:27 | manutter | atyz: I think the problem is the [:as req] in your route, try just req instead. |
| 10:28 | manutter | (not that I'm at all knowledgeable about compojure routes, but try anyway) |
| 10:29 | supersym | Pupnik: indeed, I watched a video on infoq the day before yesterday, enlighting n refreshing: like the language imho |
| 10:30 | justin_smith | compojure routes use regular destructuring - if the destructuring doesn't work in a function parameter list it won't work in a compojure route |
| 10:37 | atyz | manutter: i have, unfortunately it makes no difference |
| 10:38 | manutter | If you change your "/" route so it just returns a hello-world string, does that work? I'm guessing it won't, and your problem is in your compojure route params. |
| 10:39 | Morgawr | what's the best way to create a vector out of all the elements that match the same key from multiple hashmaps? |
| 10:39 | justin_smith | Morgawr: (mapv :key hashmaps) |
| 10:39 | Morgawr | great, thanks |
| 10:42 | atyz | manutter: it does, it breaks when its' trying to do the insert |
| 10:43 | justin_smith | Morgawr: that is if you explicitly want a vector, otherwise map is good because it is lazy |
| 10:44 | Morgawr | justin_smith: oh yeah, right, thanks |
| 10:44 | justin_smith | well, sometimes map is bad because it is lazy, but yeah, anyway that is the big difference in behavior I have seen |
| 10:46 | justin_smith | now I am realizing I should start using mapv in many places where I am using (doall (map ...)) |
| 10:47 | hyPiRion | justin_smith: do you need the result? |
| 10:47 | hyPiRion | if not, doseq is probably a better choice |
| 10:47 | hyPiRion | (for the hashmap case, it obviously is, but in general) |
| 10:48 | justin_smith | hyPiRion: I am using doall because I need the result, and it needs to be calculated inside the context of a db connection that should be short lived |
| 10:48 | hyPiRion | ah |
| 10:48 | justin_smith | so laziness either makes the db connection stay open (bad) or makes things get calculated where the db connection is not bound (breaks things) |
| 10:49 | manutter | atyz: ok, I'm barking up the wrong tree then, sorry. |
| 10:49 | atyz | manutter: no worries, thanks very much for helping |
| 10:49 | justin_smith | but you know, mapping across a bunch of results from a db, how often would you need to do that, right :P |
| 11:34 | abp | leathekd: Thanks! |
| 11:37 | leathekd | abp: No problem! Let me know if you have any troubles. |
| 11:50 | abp | leathekd: Works like a charm. Just tested my middleware. |
| 11:54 | leathekd | Nice. Glad to hear it. |
| 11:58 | yacin | if i have a string that represents a byte array ("[B@3ecc05a6") how can i convert it back to the byte array? |
| 12:02 | mpenet | yacin: unless its base64, hex or some other string representation you cant. What you show doesn't look like any of these, it's just the .toString of a byte array right? |
| 12:07 | yacin | yeah, i believe so |
| 12:10 | justin_smith | yeah, you may want to actually convert the byte array to a form that actually preserves the information as a string (like mpenet mentions base64 or a string encoding of the hex values or something) |
| 12:10 | mpenet | if you have a byte array and you want to turn it into a String you can just pass it as arg to String constructor |
| 12:10 | mpenet | ,(String. (.getBytes "foo")) |
| 12:10 | clojurebot | "foo" |
| 12:10 | mpenet | but that's very naive, not sure in what context you are |
| 12:11 | mpenet | ,(.getBytes "foo") |
| 12:11 | clojurebot | #<byte[] [B@10fa2ec> |
| 12:16 | S11001001 | mpenet: uses current locale's character encoding, not great for running on more than one machine |
| 12:16 | mpenet | yeah I know |
| 12:16 | mpenet | you can pass the locale as 2nd param |
| 12:16 | mpenet | I think |
| 12:16 | S11001001 | yacin might not |
| 12:17 | S11001001 | you can pass the character encoding as 2nd param |
| 12:17 | Anderkent | mpenet: yes, you can pass an encoding to .getBytes or String. |
| 12:18 | yacin | thanks y'all. this is some weird environment specific issue |
| 12:20 | Anderkent | yacin: but still, you probably want to use something like commons.codec Hex if it's arbitrary bytes |
| 12:20 | Anderkent | since not every byte array is a valid string |
| 12:20 | mpenet | yacin: where do you get this byte-array from ? |
| 12:22 | Anderkent | and unfortunately String. does not tell you the decoding failed |
| 12:22 | Anderkent | ,(String. (byte-array (vector (unchecked-byte 200) (unchecked-byte 201))) "ASCII") |
| 12:22 | clojurebot | "??" |
| 12:23 | llasram | Was the 4 bytes of an IPv4 address, generated by some internal code, and inadvertently .toString'd. Nothing more to see here, please move along :-) |
| 12:24 | mpenet | ~guards |
| 12:24 | clojurebot | SEIZE HIM! |
| 12:24 | Anderkent | llasram: no worries. String/byte handling in general is something people often do wrong, so talking about it may help someone :) |
| 12:25 | Anderkent | the take away is always be explicit about your encoding, and always use utf-8 :) |
| 12:25 | mpenet | yeah I was wondering about the context, most of the time libs that force you to do that stuff come with some helpers |
| 12:27 | yacin | haha thanks llasram |
| 12:51 | Morgawr | do I need to have a local maven repository of I want to use a personal .jar file in my lein project? |
| 12:51 | Morgawr | because I'm developing both my application and a standalone library (on which my app relies) at the same time |
| 12:52 | technomancy | Morgawr: you have a local maven repository |
| 12:52 | technomancy | in ~/.m2/repository |
| 12:52 | Morgawr | oh |
| 12:52 | Morgawr | neat |
| 12:52 | Morgawr | so I just put my .jar in there or..? |
| 12:53 | technomancy | just `lein install` |
| 12:53 | technomancy | will put it there |
| 12:53 | Morgawr | ah cool, so from my .jar project I do "lein install" and then from my app I just include it in the dependencies? |
| 12:54 | technomancy | you should probably read `lein tutorial` |
| 12:54 | technomancy | but yeah |
| 12:55 | Morgawr | alright, thanks, sorry for asking a naive question |
| 12:55 | Morgawr | I appreciate the help |
| 12:55 | technomancy | no worries |
| 12:56 | technomancy | actually I'm not sure the tutorial covers this; hm |
| 12:58 | gtrak | Morgawr: I think there's a maven shortcut for installing a jar http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html |
| 13:01 | Anderkent | Morgawr: alternatively, if your library is also a lein project, you can make it a checkout, so that you can develop both at the same time |
| 13:02 | Anderkent | kinda like maven subprojects, except without the more insane bits |
| 13:03 | gtrak | hey, I like the reactor! |
| 13:04 | Anderkent | gtrak: 'we'll dynamically add these artifacts to your build for some tasks, but not others'. :) |
| 13:05 | gtrak | ah, I haven't hit that one |
| 13:05 | Anderkent | I was recently trying to get a reactor project to fetch all external dependencies (so that I could cache them between builds). Can't be done, had to revert to mvn install |
| 13:06 | gtrak | oh, really? I was pretty sure I've done that before |
| 13:07 | Anderkent | the reactor is much like maven in general - it works at the beginning, but then as you're trying to do something more complicated you hit a wall with no way around it |
| 13:07 | gtrak | unless you mean something different by a reactor project |
| 13:07 | Anderkent | gtrak: well, it works if you already have the subprojects installed, so the build does not fail due to missing dependencies |
| 13:08 | gtrak | might have been a bug in a specific version, I'm like 100% sure that works |
| 13:08 | Anderkent | say you have Parent -> {A, B, C}, B depends on A, C depends on B. Trying to do `mvn dependency:go-offline` under Parent will fail because B cannot resolve A anywhere |
| 13:09 | gtrak | what's the { } signify modules? |
| 13:09 | Anderkent | yeah, 3 modules under Parent |
| 13:10 | gtrak | hmm, I'll try it right now |
| 13:13 | gtrak | ah, wait, is this specific to dependency:go-offline? that would make sense in the context of your initial comment |
| 13:13 | Anderkent | yeah |
| 13:13 | gtrak | install or compile's always worked for me, I've never tried that other task |
| 13:13 | Anderkent | yeah, install and compile will work |
| 13:14 | Anderkent | which is good enough most of the time |
| 13:14 | Anderkent | so I'm not saying reactor is completely broken - just broken enough to be really annoying :) |
| 13:14 | gtrak | gotcha, I can believe that :-) |
| 13:17 | nfisher | Hi all, rather new to clojure. I have a large log file I want to process. Are agents what I should be looking at to process the file as I'm reading? |
| 13:20 | technomancy | nfisher: pmap is probably fine for that |
| 13:21 | gtrak | Anderkent: yea, it's broken as you described. fun. |
| 13:21 | nfisher | technomancy; thanks! |
| 13:21 | technomancy | nfisher: I wrote a version using agents here, but someone pointed out pmap does a lot better: http://technomancy.us/130 |
| 13:22 | technomancy | if you want absolutely bonkers performance you can push the JVM to much better I/O perf like _ato does here: http://meshy.org/2009/12/13/widefinder-2-with-clojure.html |
| 13:22 | dobry-den | Newbie question: I've been struggling with coming up with a simple way to transform [:ul "A" "B" "C"] into [:ul [:li "A"] [:li "B"] [:li "C"]]. |
| 13:23 | nfisher | I suspect the DB insertions will be the bottleneck... I'll profile it to see. |
| 13:23 | dobry-den | I can trivially map [:li %] across the ul children, but I can't figure out how to unroll the result back into [:ul ...] |
| 13:23 | gtrak | dobry-den: into [:ul] |
| 13:24 | gtrak | which is equivalent to reduce conj |
| 13:25 | Anderkent | ,(let [[head & rest] [:ul "A" "B" "C"]] (into [head] (map #(vector :li %) rest))) |
| 13:25 | clojurebot | [:ul [:li "A"] [:li "B"] [:li "C"]] |
| 13:26 | gtrak | if it doesn't need to be a vector, can simply cons head onto the result of map |
| 13:26 | dobry-den | Thanks guys. I feel sheepish having to come here for that |
| 13:27 | Anderkent | np that's what we're here for (pretending to be productive while avoiding actual work) |
| 13:27 | nathanielk | korma seems to infuriate more than help. has that been the experience of others? do i just need to stick it out? |
| 13:28 | gtrak | nathanielk: meh, keep things simple? |
| 13:28 | Anderkent | nathanielk: I've found it pretty nice for simple stuff (querying/inserting into a single db) |
| 13:28 | Anderkent | still fall back to execute-raw from time to time though |
| 13:28 | gtrak | I thought this was interesting: https://github.com/cgrand/sqrel along with just the clojure.java.jdbc |
| 13:29 | nathanielk | well, for example: i can't figure out how to convince it to insert default values into a column |
| 13:29 | Anderkent | nathanielk: surely that's the db engine's job |
| 13:29 | nathanielk | hrm, perhaps, but i have a hard time believing that such a simple and obvious use case is broken at a lower level than korma |
| 13:29 | jjttjj | how do people test validation in lib-noir? I remember noir had noir.util.test/with-noir but there doesn't seem to be anything like that in lib-noir |
| 13:30 | Anderkent | nathanielk: what's the query look like if you tell korma to print the sql |
| 13:30 | Anderkent | (i.e. as-sql or dry-run) |
| 13:30 | nathanielk | Anderkent: good question, I should be examining that. |
| 13:30 | nathanielk | I'll go stare at it |
| 13:31 | nathanielk | it's generating hardcoded values for the id column |
| 13:31 | nathanielk | ie not telling the database "use a default" |
| 13:31 | Anderkent | hm, can you post your code? |
| 13:33 | nathanielk | it's really simple: (insert jump-table (values rows)) |
| 13:33 | nathanielk | where rows is [{:foo_id 1, :bar_id 2},...] |
| 13:34 | nathanielk | the generated query attempts to put in the foo_id and bar_id correctly but generates a 1-indexed id for the jump table's row |
| 13:34 | nathanielk | i mean, it can't get much simpler, which is why i'm assuming that i'm doing something wrong |
| 13:34 | nathanielk | i just can't find any documentation to help me |
| 13:36 | dobry-den | are columns foo_id and bar_id not integer datatypes? |
| 13:38 | nathanielk | dobry-den: they are. |
| 13:38 | Anderkent | nathanielk: it's hard to say without seeing your code. It shouldn't be doing this, quick browsing through korma source doesn't find where that happens |
| 13:40 | nathanielk | Anderkent: well, thanks for thinking about it :) i'll start reading korma's source |
| 13:42 | Anderkent | are you completely sure your rows does not contain {:id} fields? |
| 13:42 | Anderkent | the simplest test case seems to work for me: https://www.refheap.com/15155 |
| 13:43 | nathanielk | yeah, they don't |
| 13:43 | nathanielk | so I just ran the raw insert in psql without specifying an id and it did the bad thing. |
| 13:43 | nathanielk | korma is vindicated. |
| 13:44 | nathanielk | so i'll stare at my schema now :) |
| 13:52 | dobry-den | when does it make sense to embed functions with let/letfn vs specify them as private functions? |
| 13:53 | dobry-den | i like the idea of letfn, but i don't like losing the ability to sanity check it in the repl |
| 13:53 | ToBeReplaced | dobry-den: when they only make sense within the scope of the function |
| 13:53 | technomancy | dobry-den: if you have any hesitation, make it a top-level |
| 13:54 | ToBeReplaced | no one will ever complain about moving a letfn to a defn- though |
| 13:54 | ToBeReplaced | technomancy: what's the indentation problem? seems to work fine in emacs? |
| 13:56 | technomancy | sorry, not indentation, but rather breaking readability rules of clojure |
| 13:56 | hiredman | "rules" |
| 13:56 | technomancy | for nearly every other non-toplevel forms, any open paren followed by an identifier indicates a call |
| 13:57 | technomancy | this is part of why clojure is more readable than other lisps that use parens for everything with no brackets |
| 13:57 | ToBeReplaced | good point; that's something that irks me about "case" |
| 13:59 | technomancy | I don't like case either, but I don't think it has this problem |
| 14:00 | ToBeReplaced | grouping multiple constants happens in a list literal, which is not a function call |
| 14:00 | technomancy | oh, interesting |
| 14:00 | technomancy | I've never seen it used that way |
| 14:00 | technomancy | but it sounds annoying |
| 14:02 | justin_smith | yeah, I definitely read it wrong the first time I saw it |
| 14:02 | justin_smith | especially when a vector literal would do the same thing in terms of show intent |
| 14:02 | justin_smith | unless you wanted the case to match a vector? |
| 14:07 | tomjack | &(case (list 1 2) [1 2] 3) |
| 14:07 | lazybot | ⇒ 3 |
| 14:07 | dobry-den | The simplest way I can think of to turn "* abc" into "abc" is (join (drop 2 "* abc")) |
| 14:07 | gtrak | dobry-den: I think letfn makes mutual recursion more trivial, also, you don't have to indirect through a var, so it's a teensy bit faster |
| 14:08 | dobry-den | I didn't mean to hit enter |
| 14:08 | gtrak | that said, my coworkers look at me like I'm crazy when I use it for not-small things |
| 14:08 | hyPiRion | ,(subs "* abc" 2) |
| 14:08 | clojurebot | "abc" |
| 14:08 | hyPiRion | dobry-den: ^ |
| 14:08 | jtoy_ | clojure is da bomb! |
| 14:09 | dobry-den | hyPiRion: Thanks. Is there a way to browser Clojure functions by category like this: http://ruby-doc.org/core-2.0/Enumerable.html |
| 14:10 | hyPiRion | the cheatsheet is probably the closest one: http://clojure.org/cheatsheet |
| 14:11 | dobry-den | Cool. I found my next sideproject then |
| 14:13 | amalloy | technomancy: don't forget all the open parens in deftype, reify, defprotocol, and that family. and in catch/finally. and in specifying multiple arities for a defn. and in ns specifiers. |
| 14:14 | gtrak | clojure.test (is (thrown? |
| 14:15 | technomancy | amalloy: I did scope it to non-toplevel things |
| 14:15 | technomancy | I think of catch and finally as macro calls FWIW |
| 14:15 | technomancy | even though there's technically no var behind them |
| 14:15 | gtrak | thrown? isn't a real thing.. is a multimethod dispatch on a symbol |
| 14:15 | technomancy | gtrak: thrown? is horrible |
| 14:16 | technomancy | it should be a macro, but it's not |
| 14:16 | amalloy | technomancy: reify is as non-top-level as letfn |
| 14:16 | technomancy | amalloy: yeah, reify is the one exception |
| 14:16 | aaelony | Does anyone know of a clj or cljs library that faciliates a pivot table interface? e.g. something like http://gumption.org/2004/pivot_table/test_page.html or http://www.iccube.com/products/contributions/gwt-pivot-table for the result of any database query? |
| 14:16 | technomancy | well, probably proxy too |
| 14:16 | clojurebot | proxy is not reify |
| 14:16 | amalloy | proxy is awful for other reasons |
| 14:16 | technomancy | yeah |
| 14:16 | amalloy | i won't use it as supporting evidence for my case |
| 14:18 | amalloy | and of course function arities are also not top-level things |
| 14:19 | technomancy | amalloy: function arities don't have an open paren followed immediately by an identifier though |
| 14:19 | amalloy | oh, i missed the "followed by" |
| 14:20 | Foxboron | So, anyone know of any libs that could maybe use a hand? Planning on working on open-source projects this summer. (pretty much a newbie in Clojure) |
| 14:23 | gtrak | what are you interested in? |
| 14:24 | Foxboron | well, everything really. |
| 14:24 | Foxboron | Just wanna try enhance my knowledge in Clojure. |
| 14:24 | technomancy | Foxboron: clojars could use some help |
| 14:24 | technomancy | also clojuredocs.org |
| 14:25 | Foxboron | hm, i'll try take a look. Thanks! |
| 14:26 | technomancy | Foxboron: I don't have a readily-accessible list of TODOs for clojars, but I can definitely try to put something together if you want to help out |
| 14:26 | Foxboron | technomancy: looking at clojars i think i will have a tought time trying to set myself into the code. |
| 14:27 | Foxboron | But a todo would be awsome. |
| 14:27 | technomancy | apart from the maven interop it's a pretty standard compojure app, if a bit dated |
| 14:37 | rbxbx | Foxboron: I know devn is looking for help on https://github.com/devn/getclojure || getclojure.org |
| 14:38 | trptcolin | Foxboron: a text-mode api for clojuredocs would be awesome |
| 14:39 | trptcolin | because i'd love to have that feature back to being included by default (w/ no extra dependencies) in REPLy / lein repl |
| 14:40 | Foxboron | hm, i don't got that much experience with clojure, but all of it are interesting projects |
| 14:40 | Foxboron | Ill do my best and see if i can contribute |
| 14:45 | konr | In http-kit, what's the correct way to handle redirects? It's not parsing the body of a 301 response, right? |
| 14:54 | konr | nevermind, it's an issue with probably a patch :) https://github.com/http-kit/http-kit/issues/35 |
| 15:17 | llasram | Blargh, why do github "deploy keys" provide full read/write access to the repository? |
| 15:29 | arrdem | is there a way to "live inject" dependencies to nrepl, or do I have to restart when I add new deps? |
| 15:33 | abp | arrdem: https://github.com/pallet/alembic |
| 15:40 | tomjack | what about making @ and #' and maybe ` put metadata on the forms read to record their having been used? |
| 15:41 | tomjack | I suppose also ' |
| 15:41 | tomjack | but '1 and `2 are problematic.. |
| 15:41 | amalloy | tomjack: not really, because '1 reads as (quote 1) |
| 15:42 | amalloy | a form onto which you can put metadata if you like |
| 15:42 | tomjack | oh right |
| 15:44 | tomjack | hmm looking at "not so homoiconic" again it looks like there are enough other problems that the metadata would only be useful for evil macro authors |
| 15:45 | tomjack | i.e. we need sjacket anyway so no point.. |
| 15:49 | cch1 | Which protocol(s) must one support in order to allow destructuring as a map? |
| 15:50 | arrdem | abp: awesome, thanks! |
| 15:51 | amalloy | cch1: ILookup is all, i think |
| 15:51 | cch1 | amalloy: thanks. Any idea of where I might find an example? |
| 15:53 | amalloy | $google clojure ilookup |
| 15:53 | lazybot | [Overloading keywords in Clojure - Stack Overflow] http://stackoverflow.com/questions/5583841/overloading-keywords-in-clojure |
| 16:13 | cch1 | amalloy: thanks. |
| 16:21 | tomjack | I wonder why reduce-kv isn't the primitive |
| 16:22 | tomjack | backwards-compatible reduction over map seqs would incur an extra map-entry allocation I guess |
| 16:22 | tomjack | and you have an extra function maybe to drop the k for reduce |
| 16:22 | tomjack | but are there important things which can be IReduce but not IKVReduce? |
| 16:23 | tomjack | I'm just imagining stick a counter in all those places I guess.. |
| 16:59 | Kowboy | <- just found out the hard way that 'empt' and 'empty?' functions both exist and do vastly different things. DOH! |
| 16:59 | Kowboy | *empty |
| 17:00 | Kowboy | in particular (when (empty {somthing here}) ...do something...) always does something |
| 17:01 | bbloom | Kowboy: heh, yup. whoops! |
| 17:03 | AWizzArd | Does Clojure support float literals? 13.0f vs (float 13.0) |
| 17:05 | Kowboy | I don't think it does. You get doubles by default |
| 17:05 | AWizzArd | yes |
| 17:06 | Kowboy | java.lang.NumberFormatException: Invalid number: 13.0f |
| 17:06 | AWizzArd | Yes, the “f” does not work. Was just an example, maybe there is some other syntax to denote floats. |
| 17:07 | dnolen | AWizzArd: not that I'm aware of. |
| 17:07 | Kowboy | are you integrating with a Java API that uses floats everywhere? |
| 17:07 | gzmask | clojurers, i got a list of mix symbols (:t1 :note1 :t2 :note2 ...) representing a song. (pairs of time and note to be play. I can only think of (doseq). what is the best fit for this kinda sets? |
| 17:07 | ohpauleez | Yeah, you can do hex and big int, thats all |
| 17:08 | ohpauleez | rather, that's all I can think of |
| 17:09 | Kowboy | question about ^:dynamic vars vs using delay |
| 17:09 | ohpauleez | and by 8 |
| 17:09 | ohpauleez | ,010 |
| 17:09 | clojurebot | 8 |
| 17:09 | ohpauleez | ,0xa |
| 17:09 | clojurebot | 10 |
| 17:10 | ohpauleez | ,1M |
| 17:10 | clojurebot | 1M |
| 17:10 | llasram | ,2r0101010 |
| 17:10 | clojurebot | 42 |
| 17:10 | ohpauleez | radix |
| 17:10 | Kowboy | I've been using delay refs so I can prevent them from loading until needed |
| 17:10 | patchwork | ,3r012012 |
| 17:10 | clojurebot | 140 |
| 17:10 | Kowboy | but I'd likt to change the value of the delay ref, for example in a test |
| 17:10 | Kowboy | is this possible? |
| 17:12 | ohpauleez | Why not just pass things in? |
| 17:12 | ohpauleez | to the function |
| 17:12 | ohpauleez | or pass along a context map? |
| 17:12 | llasram | Kowboy: For testing, you can mock with `with-redefs` |
| 17:13 | Kowboy | excellent, that is what I need |
| 17:13 | ohpauleez | yeah, with-redefs is the best bet if you truly want the behavior you're looking for |
| 17:13 | llasram | If you want changes for other than testing, then ohpauleez is probably right |
| 17:13 | Kowboy | I was using dynamic vars, but the initial root bindings would blow up in my unit tests |
| 17:14 | Kowboy | they were generally dependent on a config file |
| 17:14 | Kowboy | but in my tests, I wanted to pass in my own configuration |
| 17:14 | melipone | hello! I am trying to use pmap (instead of map) but it seems to be slower than map. Is that possible? |
| 17:14 | Kowboy | problem was, requiring the namespaces forced the root bindings to execute |
| 17:14 | GeorgeH | I'm considering learning closure to implement a format converter, am I crazy or wasting my time? The program will read a json file with design data, then render it to CNC toolpaths. This will be my first dive into functional languages, so I'd appreciate any warnings! Thanks :) |
| 17:14 | ohpauleez | melipone: Definitely |
| 17:15 | melipone | ohpauleez: why? |
| 17:15 | Kowboy | so I changed them to (def something (delay .....))) |
| 17:15 | ohpauleez | GeorgeH: Go for it! That sounds a great project for Clojure |
| 17:15 | ohpauleez | Kowboy: I'd consider the refactor, given that scenario |
| 17:16 | ohpauleez | melipone: How many item are in the sequence/collection you're mapping on? |
| 17:16 | Kowboy | I was trying to refactor to something that works both in my production scenario, and for testing/playing at the repl |
| 17:16 | GeorgeH | Awesome! Very reassuring, cheers |
| 17:16 | melipone | 3500 items |
| 17:17 | ohpauleez | Kowboy: I think passing in a context (a map of defs you currently have) might be the way to go |
| 17:17 | ohpauleez | melipone: What's the function doing? |
| 17:17 | Kowboy | that would be a significant refactor |
| 17:17 | tomjack | bbloom: so I forget your recommendation about promises wrt core.async - if I resurrect a promise-like type, should it implement ReadPort/WritePort with different semantics than channels? right now I have Await and Deliver whose interfaces are exactly like ReadPort and WritePort |
| 17:18 | tomjack | hard to tell what the acceptable scope of meanings for <! and >! are |
| 17:18 | AWizzArd | Kowboy: it’s for CUDA code that works with floats. Would just be handy to add something like an “f” to the end of a number to let Clojure know it’s a Float. |
| 17:19 | Kowboy | perhaps what I need to do is have my ^:dynamic vars default to nil, then bind them in my "main" method |
| 17:19 | melipone | well, it's 3500 functions executed several times. The functions are very simple like check for equality of strings. |
| 17:19 | AWizzArd | In principle there could be literals for chars, shorts, floats and ints ==> 1c 2s 3f 4i |
| 17:19 | Kowboy | and then use a test fixture to also bind them for testing |
| 17:20 | bbloom | tomjack: a promise is like a (delay (repeatedly value)) channel |
| 17:20 | melipone | ohpauleez: why would pmap be slower than map? |
| 17:20 | tomjack | oh, right, I didn't consider that such things could be called 'channels' |
| 17:20 | tomjack | but the put! semantics are different I think? |
| 17:21 | Kowboy | simple functions run through pmap will be slower because of the overhead of threading |
| 17:21 | bbloom | tomjack: i'm not sure what the resource management implications are, but you can implement this w/o any custom types |
| 17:21 | Kowboy | only when the functions take significant time will you get a performance benefit |
| 17:22 | tomjack | core.async seems to use channels which emit the value and then close |
| 17:22 | bbloom | tomjack: give me a moment, let me experiment on this |
| 17:22 | tomjack | oh, I see, you mean make a process which takes from some channel and then goes into an endless put loop? |
| 17:23 | bbloom | tomjack: yeah, exactly |
| 17:23 | bbloom | i dunno if it's actually useful, but that's essentially what a promise is in terms of channels |
| 17:23 | bbloom | using (chan 1) so it blocks |
| 17:24 | bbloom | the problem then is you need to somehow garbage collect that put loop…. dunno how that works |
| 17:24 | tomjack | I have another problem with that: if you accidentally use a normal channel where you thought you had a promise, all the nice guarantees of promises disappear, but the code will still run |
| 17:25 | ohpauleez | melipone: You might want to chunk your collection into number-of-cores+2 chunks |
| 17:25 | ohpauleez | this will mean that each chunk is in its own thread when you run pmap |
| 17:26 | tomjack | just convinced myself to keep a separate interface for reads but the same one for writes, then my promise type can implement ReadPort as well by acting like a (repeat value) chan |
| 17:27 | melipone | ohpauleez: oh, I see, thanks for the hint. I'll try that. My code really needs to speed up. |
| 17:27 | tomjack | although :/ |
| 17:27 | ohpauleez | Kowboy also filled in the reason - the overhead of allocating a new future, running it, and deref'ing it is outweighing the execution time of your function |
| 17:27 | ohpauleez | melipone: You might also just try reducers, and see if being eager in the map helps (with fewer allocations) |
| 17:28 | ohpauleez | again, depends on that function you're mapping |
| 17:28 | tomjack | bugs with (repeat value) chans are pretty dangerous (certainly to my emacs' health at least, and probably someday to a browser's..) |
| 17:28 | ohpauleez | AWizzArd: You could use reader literals |
| 17:31 | gzmask | |
| 17:31 | gzmask | why (= [[1 1] [2 2] [3 3]] (map list [1 2 3] [1 2 3])) |
| 17:31 | melipone | ohpauleez: i heard about reducers |
| 17:31 | melipone | ohpauleez: what does "being eager in the map" mean? |
| 17:31 | tomjack | &(= [1 1] (list 1 1)) |
| 17:32 | gzmask | but (map list [1 2 3] [1 2 3]) eval to ((1 1) (2 2) (3 3)) |
| 17:32 | tomjack | sequential collections form an equality partition |
| 17:33 | bbloom | tomjack: refheap seems slow right now. anyway, here's an experiment: https://gist.github.com/brandonbloom/5681362 |
| 17:33 | ehaliewicz | looks like it's down actually |
| 17:33 | gzmask | tomjack: ah, i see |
| 17:33 | ohpauleez | melipone: Maps are lazy by default, they return a LazySeq |
| 17:34 | technomancy | o_O |
| 17:34 | ohpauleez | map |
| 17:34 | ohpauleez | the fn |
| 17:34 | ohpauleez | haha |
| 17:34 | ohpauleez | not Maps, the HashMap |
| 17:35 | melipone | ohpauleez: okay, thanks |
| 17:35 | technomancy | oh english... you definitely need a bugfix release |
| 17:35 | pjstadig | or perhaps the nomenclature of functional programming language |
| 17:35 | tomjack | I guess the resource problem is that the blocked put! action in the state machine will hold onto the promise channel? |
| 17:35 | technomancy | pjstadig: but I want a plural you and exclusive we too |
| 17:36 | pjstadig | technomancy: can't help you there |
| 17:36 | technomancy | at least you didn't say "yall" |
| 17:36 | pjstadig | hey now! |
| 17:36 | pjstadig | i reserve the right to say y'all |
| 17:36 | ztellman | bbloom: wouldn't a better approach be to just create a custom channel that only allows a single put!, and an arbitrary number of take! calls? |
| 17:37 | technomancy | pjstadig: what you do in the privacy of your home is your own business |
| 17:37 | pjstadig | technomancy: besides everyone knows that the plural of "y'all" is "all y'all" |
| 17:37 | tomjack | I'm worried that doing that will confuse CSP semantics |
| 17:37 | hiredman | itym "youse" |
| 17:37 | bbloom | ztellman: depends on how you define "better". if you define it as "performs better & doesn't leak memory" then yes ;-) but if you say "gets the job done w/o me having to implement a lock"… |
| 17:37 | bbloom | ztellman: better still: don't use promises |
| 17:38 | pjstadig | hiredman: this is most definitely a yankeeism |
| 17:38 | tomjack | there's a mutex in core.async, so the impl is quite simple I think |
| 17:38 | bbloom | ztellman: promises are a expression-oriented idea, but channels are an procedure-oriented idea |
| 17:39 | tomjack | yes, this is why I don't want to use channels as promises :) |
| 17:39 | ztellman | bbloom: you'll need to expand on that a bit |
| 17:39 | tomjack | it's hard for me to imagine programming with result channels that emit the value once and then go nil |
| 17:39 | bbloom | 1 sec, brb |
| 17:39 | ohpauleez | Maybe he means in channels, order is implied? |
| 17:39 | bbloom | or ok i'm here now. the person that needed me just 1 seconded me :-P |
| 17:40 | bbloom | what i mean is that promises are a reification of a lazy evaluation thunk |
| 17:40 | bbloom | channels are a reification of a communication link |
| 17:40 | bbloom | lazy evaluation is all about ignoring order and the demand driven nature of the world |
| 17:41 | bbloom | channels have inherent sequencing |
| 17:41 | bbloom | i'm saying that "pure and functional" isn't the be all end all of problem solving techniques |
| 17:41 | ztellman | well, not if you read from multiple channels at once |
| 17:41 | ztellman | but I take your meaning |
| 17:41 | bbloom | it's OK to write some procedural call if what you are modeling is actually a proceedure |
| 17:41 | tomjack | bbloom: sure, but neither is CSP :) |
| 17:41 | bbloom | procedural code* |
| 17:41 | bbloom | sure, CSP is about a bunch of little machines talking to each other |
| 17:42 | bbloom | each machine is a procedural message pump. ideally, the logic in there is functionally pure |
| 17:42 | gzmask | ok... another question: how do i make this: [0 1 2 3 4 5] -> [[0 1] [2 3] [4 5]] ? |
| 17:42 | bbloom | push your procedural code to the fringes of your system: but don't try to eliminate it completely |
| 17:42 | jouiswalker | use partition |
| 17:43 | tomjack | bbloom: I completely agree |
| 17:43 | ztellman | bbloom: so how do these two models interact? |
| 17:43 | tomjack | you made me realize though that my imagined frustration with 'result channels' was just an imagined misuse of the |
| 17:43 | ToxicFrog | ,(partition 2 [0 1 2 3 4 5]) |
| 17:43 | tomjack | them |
| 17:43 | clojurebot | ((0 1) (2 3) (4 5)) |
| 17:43 | tomjack | I guess you do 'put argument in, take return value out' |
| 17:43 | gzmask | ToxicFrog: thanks |
| 17:43 | bbloom | ztellman: "evaluate this function" is a procedure |
| 17:43 | tomjack | and passing around a channel as a representation of an eventual return value is wrong |
| 17:44 | bbloom | tomjack: yeah, i'm not sure how i feel about the returns-a-channel behavior of core.async |
| 17:44 | bbloom | single item channels just feels wrong to me |
| 17:44 | tomjack | ..so what should it return? :) |
| 17:44 | jouiswalker | is the repl the best way to do development with seesaw? |
| 17:44 | ztellman | there's been parallel work on async promises |
| 17:45 | ztellman | weirdly, it seems completely disjoint from core.async |
| 17:45 | bbloom | tomjack: it should return a value, not a reified promise. that's what golang does |
| 17:45 | tomjack | it got replaced |
| 17:45 | patchwork | couldn't a single item channel be interpreted as a constant channel? |
| 17:45 | tomjack | cljque used to be in core.async |
| 17:45 | patchwork | A channel that never changes |
| 17:45 | tomjack | bbloom: but what about CLJS? |
| 17:45 | bbloom | tomjack: if you use macro magic to make that work & the single-item channels are an impl detail, that's probably fine |
| 17:45 | bbloom | tomjack: i dunno, this shit is hard heh |
| 17:45 | tomjack | yeah :( |
| 17:46 | bbloom | tomjack: more macros & more SSA or CPS rewriting |
| 17:46 | tomjack | I'm writing new SSA for await/deliver now |
| 17:46 | shriphani | hi I have a clojure selector that looks like this but I am not sure the attr-has usage is correct. Can someone take a look: http://pastebin.ca/2385417 |
| 17:46 | ohpauleez | ,(mapv vec (partition-all 2 [0 1 2 3 4 5])) |
| 17:46 | clojurebot | [[0 1] [2 3] [4 5]] |
| 17:46 | shriphani | enlive select * |
| 17:46 | ohpauleez | gzmask: ^ |
| 17:47 | jouiswalker | ,(doc mapv) |
| 17:47 | clojurebot | "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments." |
| 17:47 | ohpauleez | if you really want vectors for some reason |
| 17:47 | jouiswalker | huh |
| 17:47 | jouiswalker | thats really nice |
| 17:47 | tomjack | unfortunately the current alt ioc will not cooperate with my efforts since it specifies async-chan-wrapper in its impl |
| 17:47 | jouiswalker | ,(mapv identity (partition-all 2 [0 1 2 3 4 5])) |
| 17:47 | clojurebot | [(0 1) (2 3) (4 5)] |
| 17:49 | bbloom | tomjack: ztellman: one of the things i don't like about the C# approach is that it creates ITask (aka listenable promises/futures) objects everywhere |
| 17:49 | bbloom | tomjack: ztellman: but most of the time, you don't ever care about the promise object, just the contained value |
| 17:50 | bbloom | promises are useful, but only a tiny portion of the time :-) |
| 17:50 | tomjack | yes, the @ is a wart caused by lack of static types :P |
| 17:50 | ztellman | bbloom: yes, but where the promise is generated and where it's consumed can be different places |
| 17:51 | ztellman | allowing that to be decoupled can be useful |
| 17:51 | ztellman | though certainly not always |
| 17:51 | ohpauleez | I agree with that |
| 17:51 | ohpauleez | certainly not always, but nonetheless useful |
| 17:51 | justin_smith | what's the best way to provide a literal string to something that I would normally give a file handle to read from? (instead of creating a file just so it reads those contents) |
| 17:51 | jouiswalker | ,(symbol? '+) |
| 17:51 | clojurebot | true |
| 17:51 | bbloom | ztellman: like i said, if channel or promise objects are an impl detail, that's fine. i just don't think that object should always be exposed to the user on normal cases |
| 17:52 | tomjack | I think go returning a channel makes sense to me if all your processes return nil |
| 17:52 | bbloom | go doesn't have promises, but you can block on a channel and return a value & you get … a VALUE… not a channel, but still the runtime needs to yield |
| 17:52 | tomjack | and take chan in/out args or something |
| 17:52 | bbloom | internally, they are parking goroutines… internally core.async is returning a channel and scheduling a callback |
| 17:52 | tomjack | hmm, no, that still doesn't make sense to me |
| 17:53 | jouiswalker | does anyone here think they would benefit from a 4clojure clone for sicp? |
| 17:53 | ohpauleez | I haven't used it in a production system, so I have no idea the implications of the design decision |
| 17:54 | ohpauleez | jouiswalker: http://sicpinclojure.com/ |
| 17:54 | tomjack | my goal is to never have to use the promise impl methods except in the promise library impls |
| 17:54 | jouiswalker | i'm aware of it |
| 17:54 | ohpauleez | I'd just make the effort to fill that out |
| 17:54 | tomjack | you still have to worry about whether a fn returns a promise or not though |
| 17:54 | ohpauleez | and then make a scraper/generator to generate problems from the code |
| 17:55 | jouiswalker | but what theyre doing is rewriting a book |
| 17:55 | tomjack | oh and I think you still have to tell the ioc that you want to block on a promise with await or @ or whatever. but that's all I want to do to a promise, return it or @ it inside ioc |
| 17:55 | jouiswalker | i just mean a collection of test cases and such for the exercises |
| 17:55 | ohpauleez | jouiswalker: You read SICP and use the site to see the code in Clojure, then practice your skills more with generated 4clojure style problems |
| 17:56 | bbloom | tomjack: yeah, adding await to participate in ioc gets you most of the way there. it's essentially exactly what C# does… C# has this exact same IOC idea w/ reified promises instead of reified channels |
| 17:56 | bbloom | tomjack: channels are more general, but that has it's pros and cons |
| 17:56 | ztellman | tomjack: either you go all the way and do dataflow IOC that treats promises and realized values interchangeably, or you need some convention for what's returned |
| 17:57 | ztellman | I'm not sure there's a third option |
| 17:57 | tomjack | 'going all the way' I think is infeasibly with core.async's ioc-macros |
| 17:57 | bbloom | tomjack: but if you never read from a promise twice, you just <! on the channel and not care |
| 17:57 | jouiswalker | oh do they plan on implementing test cases? |
| 17:58 | tomjack | I guess the ! is right there on the tin. so treat it like you would a transient, non-shareable |
| 17:58 | bbloom | tomjack: which a simple (let [the-value (<! a-channel-like-promise)] ….) gets the job done |
| 17:58 | jouiswalker | i'll check with the developer of the project |
| 17:58 | ztellman | tomjack: I haven't read ioc-macros closely enough to tell, but it's certainly doable with the core.async <! mechanism |
| 17:58 | bbloom | tomjack: exactly. the advantages of promises is that that dereferencing them is idempotent. |
| 17:58 | jouiswalker | thanks for making me take a closer look |
| 17:58 | Licenser | hey guys :) quick question, by brother wants to learn some clojure, he is entirely unexperienced with programming and I wonder what resource would be the best to start with? |
| 17:59 | tomjack | ztellman: the problem I see is that every single sub-expression under ioc will get CPS'd |
| 17:59 | jouiswalker | http://java.ociweb.com/mark/clojure/article.html |
| 17:59 | ohpauleez | Licenser: Chas's book |
| 17:59 | tomjack | or.. SSA'd |
| 17:59 | technomancy | Licenser: I don't believe there are good resources for people who aren't already programmers. |
| 18:00 | tomjack | so like (go-promise (+ 1 2)) will have to have 4 take!s |
| 18:00 | tomjack | unless you try to do inference about what's "trivial" |
| 18:00 | Licenser | technomancy awww |
| 18:00 | tomjack | which does not seem like fun to me without gradual types or something |
| 18:01 | ztellman | tomjack: agreed, back in the day when I took a run at the IOC macro, the idea was it would only be used at the top-level of a program |
| 18:02 | ztellman | but even then, you need instrumentation to understand what intermediate state the dataflow's in |
| 18:02 | ztellman | that's a lesser problem with the non-dataflow IOC (though still one that needs to be solved) |
| 18:02 | bbloom | tomjack: ztellman: i took the trivial vs serious approach w/ the CPS transform attempt i did |
| 18:02 | bbloom | i had a macro called "spawn" which was essentially "go" |
| 18:02 | jouiswalker | Licenser: you might ask him to do the first two or three chapters of practical common lisp to get him used to the syntax |
| 18:02 | tomjack | yeah that was enlightening |
| 18:03 | tomjack | the paper was unintelligible to me iirc |
| 18:03 | bbloom | it took me a while, yeah |
| 18:03 | technomancy | Licenser: htdp.org looks interesting for new programmers |
| 18:03 | bbloom | i think SSA was a better call, but i was hung up on going the CPS route for some reason |
| 18:04 | tomjack | my cljs tests so far of very simple go blocks have produced seemingly very large functions |
| 18:04 | bbloom | more over, i was dead set on supporting pluggable control structures, which is something i suggested to rich, but i think it was a better short term call to avoid that and go with a fixed set of primitives for v1 |
| 18:04 | Licenser | guys you're awesome :) |
| 18:04 | tomjack | ioc-macros is obviously alpha and probably needs adjusting for cljs |
| 18:04 | bbloom | lastly, reified channels greatly simplifies the problem of "what do you do with return values?" when you have CPS, a continuation is NOT A FUNCTION. it isn't supposed to return & you need to pass the continuation to a function |
| 18:04 | gzmask | how do i construct as list by adding up part of another list like: [0 1 1 2 1 2 1] -> [0 1 2 4 5 7 8]? |
| 18:04 | tomjack | but we better be damn good at inferring triviality I think |
| 18:05 | tomjack | ..or ^:trivial (+ 1 x) ? |
| 18:05 | bbloom | tomjack: well the brilliant part of SSA (as compared to CPS) is that you can do a single level of SSA |
| 18:05 | bbloom | you rewrite ONE function into a state machine |
| 18:05 | bbloom | rather than have to thread the CPS all the way through to the bottom |
| 18:06 | onthestairs | hmm, do i have a fundamental misunderstanding of core.logic? im trying to implement a simple solver which returns any functions from a list which are increasing |
| 18:06 | tomjack | ok, the function I am rewriting is (fn [in out] (let [x (<! in)] (>! out (+ x 42)))) |
| 18:06 | onthestairs | https://gist.github.com/onthestairs/5681569 |
| 18:06 | bbloom | i had attempted prior to studying golang, hadn't considered channels, and chose CPS over SSA. all of those mistakes are obvious to me now :-P |
| 18:06 | tomjack | well, no, channels won't be a good example |
| 18:06 | tomjack | my worry applies in the 'go all the way' dataflow case |
| 18:06 | dnolen | onthestairs: gist |
| 18:07 | jouiswalker | has anyone here played with avout? |
| 18:07 | dnolen | onthestairs: oh sorry you pasted |
| 18:07 | onthestairs | dnolen: no worries, cheers |
| 18:07 | tomjack | oh, hmm, I see |
| 18:07 | tomjack | I just tried an example and it seems to work out better than I thought |
| 18:08 | ohpauleez | ,(reductions + [0 1 1 2 1 2 1]) |
| 18:08 | clojurebot | (0 1 2 4 5 ...) |
| 18:08 | technomancy | Licenser: racket's error messages are so much better than clojure it's ridiculous. there are actually several different levels of beginner mode you can put it in to get simplified vs detailed error messages. |
| 18:08 | ohpauleez | gzmask: ^ |
| 18:08 | tomjack | vars are tricky |
| 18:08 | technomancy | huuuuge contrast vs clojure's "I dunno; here's some compiler guts you can look at I guess" |
| 18:08 | dnolen | onthestairs: hrm, yeah that doesn't make sense. |
| 18:08 | tomjack | (fn [x] (add x 42)) - should we await! on add? |
| 18:08 | gzmask | ohpauleez: I known reduce but reductions are cool! thx! |
| 18:08 | dnolen | onthestairs: why are you projecting g? |
| 18:09 | Licenser | technomancy hmmm hmmm |
| 18:09 | tomjack | other problem is how to let functions have trivial return values |
| 18:09 | dnolen | onthestairs: you should probably project f which will be bound to a fn |
| 18:10 | technomancy | Licenser: there are some stupid things too (no docstrings, no callable hash tables by default) but for beginners it's a drastically better place to start |
| 18:10 | Licenser | technomancy my brother says 'nahh I already fell in love with clojure' <-that's good feedback I guess ;) |
| 18:10 | Licenser | I'll just have to help him out more ^^ |
| 18:10 | onthestairs | dnolen: im not sure. i think i have a fundamental misunderstanding |
| 18:10 | technomancy | heh; well that works too; it just means he'll need more help from you rather than reading texts |
| 18:10 | technomancy | hah, exactly |
| 18:10 | onthestairs | dnolen: is there a good reference page for project |
| 18:11 | Licenser | technomancy I think I'll have to get him a IRC client :P |
| 18:11 | tomjack | bbloom: your point has analogy to lazy seqs I think - they support exactly the same value-oriented functions as their forced values |
| 18:11 | technomancy | Licenser: if you can shoulder-surf from someone experienced who is patient then you can learn anything =) |
| 18:11 | Foxboron | ummm |
| 18:11 | tomjack | ..by bundling in a procedural notion? |
| 18:11 | Licenser | technomancy true! |
| 18:11 | Foxboron | I don't know Clojure that well. But i could help out mentoring another guy (Ref: technomancy Licenser) |
| 18:12 | Foxboron | mentored a few people in Python. Might as well be a good learning experience |
| 18:12 | dnolen | tomjack: heh core.match generates a lot of JS too. I imagine people will restrict go blocks to the bits of the program that are actually async no? |
| 18:12 | technomancy | it just doesn't scale well |
| 18:12 | tomjack | dnolen: yes, but not every subexpression of those bits will also be async |
| 18:12 | bbloom | tomjack: yeah, but that only works b/c seqs are protocols. if you wanted to do that w/o a seq you'd need to proxy/delegate all the same interface methods :-/ |
| 18:12 | dnolen | onthestairs: tomjack yes but I can't imagine it will matter, if it's async it's likely IO bound |
| 18:12 | Licenser | Foxboron that's cool :) so I don't want to put that on anyone but me :) but I'll send him to the channel non the less, learning clojure is after all also about learnign the community ^^ |
| 18:13 | dnolen | and people will move out big expressions into fns as usual. |
| 18:13 | onthestairs | dnolen: oo nice, i have got it working. thanks |
| 18:13 | tomjack | maybe it would be OK |
| 18:13 | Licenser | plan is that we're going to do a little project together to learn some stuff, so it's more about learning the very basics so he's not staring blankly on the screen all the time ;) |
| 18:13 | tomjack | I mean I think current core.async go w/ channel output is probably OK |
| 18:14 | Foxboron | Licenser: teach him gist maybe? |
| 18:14 | Foxboron | Licenser: also, clojure-koans is a good place IMO |
| 18:14 | tomjack | to be clear I was discussing a different ioc macro which lets any subexpression return a single-assignment dataflow variable transparently |
| 18:14 | Licenser | Foxboron gist? |
| 18:14 | dnolen | tomjack: based on the Node.js crap I've had to right, I'm pretty sure it's OK |
| 18:14 | dnolen | write |
| 18:14 | Foxboron | Licenser: https://gist.github.com/ |
| 18:15 | Licenser | Foxboron oh hah! okay I wasn't thinking that simple ^^ |
| 18:15 | tomjack | (which I have not really seriously considered in a long time) |
| 18:15 | tomjack | (not that I have very good reasons not to) |
| 18:15 | Foxboron | Licenser: it is not git, but it helps him keep track of his files, changes etc. |
| 18:15 | ztellman | tomjack: if you confine the dataflow to a function, and force the function to return a realized value |
| 18:15 | Licenser | Foxboron yea I know them just thought you mean something else :) |
| 18:15 | technomancy | speaking of things that are horrible for newcomers... git =( |
| 18:15 | bbloom | personally, i like implementing services as explicit state machines operating on sequences of messages… but i'm a crazy person :-) |
| 18:15 | tomjack | these functions can't return realized values in cljs |
| 18:15 | tomjack | maybe I misunderstand? |
| 18:16 | dnolen | tomjack: they cannot |
| 18:16 | ztellman | oh, I missed the cljs bit |
| 18:16 | ztellman | yeah, that's a trick |
| 18:17 | ztellman | is there a js-land full dataflow transformer, or do they all use some variant of 'await'? |
| 18:17 | ztellman | I've only seen the latter |
| 18:17 | Foxboron | technomancy: it is horrible for other people too. Used git every day for almost a year. I still fuck something. |
| 18:17 | dnolen | ztellman: no, there are blocking reads in JS and there will be no tricks. All read/writes on channels must be in go block |
| 18:17 | dnolen | there are no blocking reads |
| 18:17 | dnolen | I mean |
| 18:17 | dnolen | er reads/writes |
| 18:18 | tomjack | they have no macros so I would not be surprised if they haven't done it.. |
| 18:18 | jouiswalker | foxboron: do you have something you prefer over git? |
| 18:18 | Licenser | technomancy Foxboron got him sourcetree, it makes it mostly barable I think |
| 18:18 | Foxboron | jouiswalker: I actually like git. But i always manage to fuck something up. |
| 18:18 | jouiswalker | foxboron: hehe |
| 18:19 | tomjack | it's interesting how "transparent" can mean both "you can't see it" and "you can see it clearly" |
| 18:20 | ztellman | tomjack: http://en.wikipedia.org/wiki/Auto-antonym |
| 18:20 | tomjack | :D |
| 18:20 | dnolen | ztellman: maybe await, but I didn't hear rhickey mention that |
| 18:20 | ztellman | dnolen: where was this discussed? |
| 18:20 | Licenser | And there we are :) may I introduce my brother SomeOtherGuy! |
| 18:20 | jouiswalker | tomjack: isn't it supposed to be an intermediate between tranlucent and opaque? |
| 18:20 | dnolen | ztellman: rhickey's been popping into the channel talking about the core.async stuff now and then |
| 18:20 | SomeOtherGuy | Hey guys! :) |
| 18:20 | jouiswalker | translucent* |
| 18:21 | noprompt | if anyone wants a good laugh i hand rolled a little migration lib for korma https://gist.github.com/noprompt/5681539 |
| 18:21 | technomancy | SomeOtherGuy: welcome |
| 18:22 | noprompt | for the record, i have no idea what the hell i was doing or how those things should work. |
| 18:22 | jouiswalker | noprompt: that is beautiful |
| 18:23 | noprompt | jouiswalker: you're being sarcastic, right? :) |
| 18:23 | jouiswalker | noprompt: its better than what i manage :3 |
| 18:24 | noprompt | honestly though, i'd love to know how to actually build something like this correctly. |
| 18:24 | tomjack | noprompt: my gripe is that all the migrations are collected into a global atom |
| 18:24 | noprompt | tomjack: yeah, i didn't know how else to do it. |
| 18:25 | jouiswalker | noprompt: you might be able to use some partials with append-x and such |
| 18:25 | SomeOtherGuy | Sorry If I'm not very communicative. Try to understand things that seem to be above my intellect! |
| 18:25 | noprompt | tomjack: so what would be the alternaive? |
| 18:27 | tomjack | a cheap fix would be to key the entries in the global somehow by user-specified keys |
| 18:27 | tomjack | and allow the user to somehow pick out the migrations to run with migrate! |
| 18:27 | tomjack | but I don't like that either |
| 18:27 | tomjack | simple thing seems to be to just have the user pass a collections of migrations to run? |
| 18:27 | tomjack | ..but I haven't ever tried to write a migration library, so.. if it works for you, great :) |
| 18:29 | noprompt | so let me grab an example of the usage |
| 18:30 | jouiswalker | are there any deprecated lein plugins that someone would like to see renovated? |
| 18:32 | jouiswalker | i want to relieve boredom by making something useful :/ |
| 18:32 | tomjack | jouiswalker: no, but I want to see a new one for generic run-task-on-file-change watches |
| 18:32 | jouiswalker | whats the current one and how would you like me to change it? |
| 18:33 | tomjack | there isn't a current one really |
| 18:33 | jouiswalker | :x |
| 18:33 | tomjack | cljsbuild has an 'auto' which I don't like much |
| 18:33 | tomjack | there are sketches of how to use the java 7 file watcher stuff in clojure |
| 18:34 | tomjack | I started a project for this 'lein-auto' but spent only about 15min so far on it.. |
| 18:34 | tomjack | hmm |
| 18:35 | tomjack | |
| 18:35 | jouiswalker | is your work on github? |
| 18:35 | tomjack | I realize now that could be a lot trickier than I thought |
| 18:35 | jouiswalker | i just see a couple forks :p |
| 18:35 | tomjack | no, I have barely anything at all |
| 18:35 | tomjack | 15min was mostly taken up by trying to grok the file watcher api |
| 18:36 | tomjack | then I stopped and said "hey, cljsbuild is working" |
| 18:36 | jouiswalker | lol |
| 18:36 | jouiswalker | i'll try my hand at it |
| 18:37 | tomjack | I wonder if you can start up a project jvm, keep it running, and eval-in-project multiple times? |
| 18:37 | ztellman | tomjack: I think eval-in-project creates a new environment each time |
| 18:37 | ztellman | you'll need to eval something which runs a background process within the project |
| 18:37 | tomjack | well I guess you can start up an nrepl thingy |
| 18:37 | tomjack | ? |
| 18:37 | justin_smith | anwsering my own question above (def to-stream (fn [s] (io/input-stream (.getBytes s)))) |
| 18:38 | ztellman | though there are other people who can speak more authoritatively about this than me |
| 18:38 | tomjack | yeah, makes sense |
| 18:39 | noprompt | tomjack: i've updated the gist with a little example at the bottom |
| 18:40 | noprompt | jouiswalker: you should write a shell in clojure :) how's that for a fun project |
| 18:40 | tomjack | noprompt: yeah, looks nice and pretty simple except for the globals :) |
| 18:40 | jouiswalker | nopromt: eww haha |
| 18:44 | noprompt | jouiswalker: well it could be fun. |
| 18:44 | jouiswalker | noprompt: maybe a parser that converts s expressions to bash calls or something lol |
| 18:45 | noprompt | jouiswalker: also, if you know a thing or two about css you could help me improve my CSS lib which i haven't had much time for lately :*( |
| 18:45 | jouiswalker | noprompt: garden? |
| 18:45 | justin_smith | jouiswalker: so basically a port of scsh |
| 18:46 | noprompt | jouiswalker: i was working on a little project that would convert a vector of strings in to an efficient regular expression that would match any of the strings in the vector |
| 18:46 | justin_smith | scsh "regular expressions" are actually much more sane than the standard |
| 18:46 | jouiswalker | justin_smith: i knew there had to be one! thats cool. |
| 18:47 | tomjack | "it's a lisp" "oh, so there are a lot of parentheses..." <- happened :( |
| 18:47 | justin_smith | I used it for a while, ages ago. the extra parens are OK when you are coding and spending more time thinking than typing, in a shell they are a pain in the ass |
| 18:47 | noprompt | jouiswalker: yeah, garden. |
| 18:47 | tomjack | not jokingly, but trailing off and almost despairingly |
| 18:48 | noprompt | well if you were gonna write a shell in clojure i would imagine it working kind of like the emacs shell |
| 18:48 | jouiswalker | justin_smith: it seems with paredit it wouldn't be painful |
| 18:48 | jouiswalker | ^ |
| 18:48 | justin_smith | yeah, my tty did not provide paredit |
| 18:49 | jouiswalker | hehe, i tried installing scsh. at least for arch, it seems like its not compatible for 64 bit |
| 18:50 | noprompt | fish is a neato shell. |
| 18:50 | noprompt | it's got a lot of "geewiz" features. |
| 18:50 | justin_smith | scsh is ancient, really it is a scheme library, so the best way would be to get an up to date scheme, and port scsh to it |
| 18:50 | jouiswalker | speaking of shells |
| 18:51 | jouiswalker | whenever i run lein repl in xterm backspaces start giving me weird behavior |
| 18:51 | noprompt | that is weird |
| 18:51 | clojurebot | Alles klar |
| 18:51 | justin_smith | sounds like a bad termcap |
| 18:52 | noprompt | can't remember the last time i used lein repl directly w/o emacs though |
| 18:52 | jouiswalker | true. an interesting effect though, since it plays well with ther terminals |
| 18:53 | technomancy | jouiswalker: have you seen this? https://groups.google.com/group/clojure-tools/browse_thread/thread/c08b628a9af8346d |
| 18:53 | tomjack | I wonder how core.async will deal with exceptions |
| 18:53 | jouiswalker | for example, "aoeu<backspace><backspace><backspace><backspace>" winds up as "aoeu^H^H^H^H" |
| 18:53 | technomancy | if you're looking for something to implement ... =) |
| 18:54 | justin_smith | I think nrepl uses a java readline library, that is notoriously less than perfect |
| 18:58 | jouiswalker | technomancy: now that is interesting |
| 19:00 | dobry-den | Here's a few lines of a trivial parser: https://gist.github.com/anonymous/5681884 — How do you solve this fundamental ambiguity? `root = ul` will be greedy as I wish [:ul [:li "Item A"] [:li "Item B"]] — Yet `root = ul+` will make two [:ul] — one for each li. |
| 19:02 | dobry-den | In other words, as soon as I `root = (ul | ol | p | code)+`, the lists only slurp up one list element each. |
| 19:04 | jouiswalker | technomancy: so he wants to be able to generate language-x from clojure-like code to target devtool-x? |
| 19:05 | technomancy | jouiswalker: he -> me =) |
| 19:05 | technomancy | but yeah |
| 19:05 | jouiswalker | technomancy: oh! |
| 19:05 | noprompt | technomancy: did regex syntax highlighting ever get folded in to clojure-mode? |
| 19:06 | technomancy | noprompt: not that I'm aware of |
| 19:06 | gzmask | time to go. thanks for help forks! :wq |
| 19:07 | noprompt | technomancy: for some reason i thought i saw a PR for it. |
| 19:09 | noprompt | technomancy: just out of curiousity, why not use the JVM to generate all the keyword code for clojure-mode? |
| 19:09 | noprompt | that's how the vim-clojure-static does it https://github.com/guns/vim-clojure-static/blob/master/syntax/clojure.vim#L18 |
| 19:10 | technomancy | noprompt: not sure; I didn't write it |
| 19:10 | noprompt | technomancy: oh :) |
| 19:10 | jouiswalker | man, i see tim pope's stuff everywhere |
| 19:11 | supersym | technomancy: looks cool, weren't protocols designed for this kind of interfacing though or wouldnt that work with vim/emacsen? |
| 19:11 | technomancy | noprompt: pjstadig has been merging some clojure-mode pull reqs too, so I could have missed it |
| 19:11 | noprompt | that's because tpope care's |
| 19:11 | technomancy | one way to find out |
| 19:11 | noprompt | *cares |
| 19:11 | technomancy | supersym: clojure protocols? |
| 19:11 | technomancy | supersym: I don't think there's any connection |
| 19:11 | supersym | yea |
| 19:12 | technomancy | there's no polymorphism going on here |
| 19:12 | supersym | no thats what I thought |
| 19:12 | jouiswalker | oh wow hes in here |
| 19:12 | noprompt | technomancy: cool. yeah, regex highlighting would be seriously nice. |
| 19:12 | technomancy | supersym: the clojure-side code is quite trivial; the tricky part is defining a minimal language which can feasibly be implemented across client runtimes |
| 19:13 | technomancy | where "language" is "vocabulary for describing operations, their arguments, and ways to display their return values" |
| 19:13 | supersym | I was actually thinking about something along these lines as well |
| 19:13 | hiredman | better bencode it |
| 19:17 | jouiswalker | technomancy: in your example, does doc have already definitions in vimscript and elisp? |
| 19:17 | supersym | so if I get it right, this is a layer that exposes meta-data basically right? but self-describing in a generic fashion so people can hook to it, like a REST API almost? or did I get that wrong |
| 19:17 | jouiswalker | already have* |
| 19:18 | noprompt | hmm... guess i was wrong. |
| 19:19 | tomjack | I see promises are weirder than I thought from a core.async perspective |
| 19:19 | tomjack | -- when is the put!/deliver! callback called? |
| 19:19 | tomjack | it's not CSP so it doesn't make sense with put!. maybe deliver! has no callback.. |
| 19:19 | tomjack | ..of course it doesn't, I guess |
| 19:20 | jouiswalker | noprompt: what do you need done in garden? |
| 19:23 | jouiswalker | technomancy: i dont see enough information in the example you gave to infer that a docstring needs to be displayed |
| 19:29 | cbp`` | Do you still to dl curl/wget on windows for the latest lein version? |
| 19:30 | cbp` | to use the latest lein* |
| 19:31 | decaf | cbp`: nope |
| 19:31 | cbp` | decaf: thank you |
| 19:32 | cbp` | Oh you can use upgrade now too :) |
| 19:32 | tomjack | (gofn [in-chan out-chan err-chan] (>! out-chan 42) (close! out-chan)) ? |
| 19:33 | tomjack | (gofn [{:keys [in out err]}] (>! out 42) (close! out)) |
| 19:37 | jouiswalker | technomancy: what about sending asts of maps and defining some primitive operations in vimscript/elisp |
| 19:39 | jouiswalker | technomancy: actually, probably easier just to do a map with an ast nested inside |
| 19:45 | technomancy | jouiswalker: all emacs commands have docstrings attached to them |
| 19:45 | technomancy | dunno about vim |
| 19:46 | jouiswalker | hmm |
| 19:46 | technomancy | supersym: yeah |
| 19:47 | jouiswalker | well, if we catalogued vim commands that fulfilled the same as the emacs commands |
| 19:47 | bbloom | technomancy: vim has excellent documentation. :help whatever |
| 19:48 | jouiswalker | it might be possible to just match from one source |
| 19:48 | technomancy | jouiswalker: no asts |
| 19:48 | technomancy | the point is to avoid writing elisp on a per-command basis |
| 19:48 | bbloom | technomancy: it uses external docs though. you don't put a doc string on a fn, you have docuementation with an annotation of keywords |
| 19:48 | technomancy | you just describe the data type you intend to return, and the client already knows how to display it |
| 19:49 | jouiswalker | would you consider a docstring a datatype? |
| 19:50 | technomancy | no, strings would be the data type |
| 19:50 | technomancy | jouiswalker: cemerick is convinced that we can describe enough return types to completely remove the need for custom elisp. I don't think that's realistic, but I think we can cover common cases. |
| 19:51 | jouiswalker | sort of like... process of elimination through argument list and return type? |
| 19:51 | technomancy | I don't folow |
| 19:52 | technomancy | follow |
| 19:52 | cemerick | I shall not be trolled :-P |
| 19:52 | jouiswalker | i dont see anywhere in the example that specifies that a docstring has to be returned |
| 19:53 | jouiswalker | but i'd personally be surprised if vim required more information to display a docstring than emacs does |
| 19:54 | jouiswalker | |
| 19:54 | jouiswalker | {:op "doc" |
| 19:54 | jouiswalker | :doc "Display the docstring of a given var." |
| 19:54 | jouiswalker | :arglist [{:prompt "Var: " :type :var}] |
| 19:54 | jouiswalker | :client-handler [:message]} |
| 19:54 | cemerick | can't.....resist... |
| 19:54 | cemerick | technomancy: the custom X (whether elisp, vimscript, java, python, or whatever else your tooling is written in) *will* be needed, it just shouldn't be the server's job to deliver it. |
| 19:54 | cemerick | (or, op implementation, whatever) |
| 19:54 | technomancy | cemerick: OK, works for me =) |
| 19:55 | technomancy | so upon re-reading this I don't think putting the return type on the op makes sense |
| 19:55 | technomancy | it should probably be included in the response itself |
| 19:55 | jouiswalker | thats clearer |
| 19:55 | technomancy | since a given op could return different types based on whether it succeeds or fails, etc |
| 19:55 | cemerick | it's probably reasonable to put it on the op as well, so tools can indicate support ahead of invoking an op |
| 19:56 | technomancy | maybe |
| 19:56 | cemerick | no reason why an op's "return types" can't just be a vector of whatever other values you're going to ship with a response |
| 19:57 | technomancy | should be optional |
| 19:58 | technomancy | RFC: http://p.hagelb.org/nrepl-discover.clj.html |
| 19:58 | Raynes | Ladies and gentleman, do not leave your seats, refheap and 4clojure will be returning momentarily. |
| 19:59 | technomancy | ^ the above assumes :value in the response is just a string unless :type is given |
| 19:59 | technomancy | not totally sold on :arglist ["var:var"] in particular |
| 20:00 | technomancy | basically it's saying use "var" as the prompt, and if you have any special completion UI for choosing an existing var, use that |
| 20:00 | Raynes | And we're good. |
| 20:01 | noprompt | w00t! yay! <3 <3 <3 |
| 20:01 | hiredman | why not just sexpressions? |
| 20:01 | hiredman | (var var) |
| 20:02 | hiredman | (or bencode it...) |
| 20:02 | noprompt | Raynes: i had to use a stinkin' gist today! :P |
| 20:02 | Raynes | noprompt: Oh the agony. |
| 20:02 | technomancy | hiredman: yeah, ("var" var) would probably be better |
| 20:02 | noprompt | literally tears running down my face. |
| 20:02 | noprompt | Raynes: did you enjoy the concert? |
| 20:02 | Raynes | noprompt: Oh goodness yes. |
| 20:02 | technomancy | hiredman: emphasizing that the first is a literal string and the second is symbolic |
| 20:03 | technomancy | or maybe ("Var: " var) |
| 20:03 | Raynes | noprompt: I've also won a lottery and get to be part of the audience on June 4th at a secret/private Imagine Dragons concert for the season 6 finale of Live From The Artist's Den |
| 20:03 | noprompt | awesome. i can't remember the last time i went to a show. miss those things. |
| 20:03 | technomancy | I was trying to avoid alists because they seem like an elisp bias, but they do seem to be a good fit here =) |
| 20:03 | noprompt | Raynes: say wut? damn, that's awesome dude. |
| 20:04 | technomancy | actually... maybe we need three values? user-visible prompt string, type, and argument name to put in the nrepl msg? |
| 20:04 | technomancy | user-visible string could be optional and default to the argument name |
| 20:05 | jouiswalker | that sounds like a good idea to me |
| 20:05 | hiredman | obviously you need reader literals to semantically tag things without specifying their concrete type |
| 20:05 | technomancy | :arglist [[var var "Trace: "]] |
| 20:06 | jouiswalker | are there types that var is limited to? |
| 20:07 | technomancy | jouiswalker: string, var, namespace, file, and position (file/line/col tuple) at least |
| 20:07 | technomancy | oh, and choose-one-of-a-predefined-set-of-options |
| 20:08 | technomancy | those are the main types I can think of for which the client can provide useful completion |
| 20:09 | jouiswalker | why position instead of int and tuple? |
| 20:10 | bbloom | dnolen: sooo cljs' tagged literals are fundamentally broken |
| 20:10 | bbloom | user=> '#inst "2000-01-01" |
| 20:10 | bbloom | #inst "2000-01-01T00:00:00.000-00:00" |
| 20:10 | bbloom | vs: |
| 20:10 | bbloom | ClojureScript:cljs.user> '#inst "2000-01-01" |
| 20:10 | bbloom | (js/Date. 946684800000) |
| 20:10 | technomancy | jouiswalker: because the client can just provide the current position of the cursor without actually prompting the user |
| 20:10 | dnolen | bbloom: this is not the first time I've heard that |
| 20:11 | technomancy | if you are going to ask for an integer, you can ship it as a string; it's not going to save the user any typing for the client to know it's going to be used as an int |
| 20:12 | brehaut | designers. sheesh |
| 20:13 | bbloom | dnolen: yeah, turns out that stratefied environments are really difficult to formalize with respect to metaprogramming…. |
| 20:14 | dnolen | bbloom: tho to be honest I don't really see the problem you're trying to demonstrate here since the literal just creates a java.util.Date |
| 20:14 | bbloom | dnolen: note the quoting |
| 20:14 | bbloom | dnolen: the main benefit of reader literals from a metaprogramming standpoint is that they are evaluated prior to quoting |
| 20:15 | bbloom | dnolen: clojure's extra syntax lets you sneak just a little bit extra info into macros -- something you can't do with just lists in scheme |
| 20:15 | bbloom | dnolen: tagged literals offer the same power: you can pass a date/time to a macro |
| 20:15 | jouiswalker | oh hold on |
| 20:15 | hiredman | dnolen: that completely undermines literals |
| 20:15 | jouiswalker | you dont mean excluding tuple or int |
| 20:15 | tomjack | curious what you're trying to do :) |
| 20:16 | jouiswalker | youre just saying you could leave position in there to simplify things |
| 20:16 | hiredman | dnolen: you are supposed to be able to read #inst "2000-01-01" and get a date without an eval step |
| 20:17 | technomancy | jouiswalker: right; arglist types would all be about convenience to the user |
| 20:18 | jouiswalker | gotcha |
| 20:18 | dnolen | bbloom: hiredman: right, though I never considered that anything but a bit of odd convenience of Clojure JVM implementation. |
| 20:18 | dnolen | bbloom: what do you need that behavior for in CLJS? |
| 20:19 | hiredman | dnolen: it is the whole shooting match regarding literals, expanding in to something requires eval is *not* a literal |
| 20:20 | bbloom | dnolen: i've got a pretty big macro that i want to work in cljs, but i have 2-ish custom types i need to pass to the macro. tagged literals are perfect on clj, but on cljs, i need to use metadata.. however i can't put metadata on numbers or keywords or anything, so i need to basically use a wrapper vector, it's awkward: ^MyType [theValue] |
| 20:20 | hiredman | having reading literals turn in to forms takes the e out of edn |
| 20:20 | dnolen | hiredman: right |
| 20:20 | bbloom | dnolen: yeah totally agree w/ hiredman |
| 20:21 | tomjack | hiredman: (defn foo [] #inst "2012"). in cljs, foo does return a js date. did you already know this? |
| 20:21 | dnolen | bbloom: is this not something we can get around by treating reader literals specially in the presence of quoting? |
| 20:21 | bbloom | tomjack: (defmacro literal-type [x] (str (type x))) |
| 20:21 | jtoy | how can I use lein to run a single command and quit out? |
| 20:21 | hiredman | tomjack: shh, I'm talking to people |
| 20:21 | bbloom | tomjack: try that in both clj and cljs, in clj you'll get a inst, on cljs, you'll get a list |
| 20:22 | tomjack | no.. |
| 20:22 | bbloom | dnolen: in order to get this to work, we need a custom macro system |
| 20:22 | bbloom | dnolen: we can't use clojure's macro system |
| 20:23 | bbloom | dnolen: but even still, the result of a reader literal would need to be something that is serializable. ie you can't emit a java.util.Date |
| 20:23 | dnolen | bbloom: I don't really understand, macro gets a java date via a literal, compiler emits a js/Date |
| 20:23 | hiredman | bbloom: I don't see how that is correct? |
| 20:23 | hiredman | bbloom: literals are a reader thing |
| 20:23 | dnolen | or a goog.date.Date |
| 20:24 | hiredman | I guess the problem is if the macro emits a quoted form passed to a function |
| 20:24 | dnolen | bbloom: works well enough for Regex, why can't it work for date literals |
| 20:25 | hiredman | so the compiler needs to walk quoted forms and effectively unquote forms that are the result of a reader literal |
| 20:25 | bbloom | this is yet another reason i think there needs to be a TaggedLiteral type…. read time is too early to decide if you want a java date or a js date |
| 20:26 | brehaut | bbloom: the correct answer is you want neither :P |
| 20:26 | tomjack | couldn't the cljs reader read with its own default handler that uses a TaggedLiteral? |
| 20:26 | bbloom | i could write a macro that takes a date as an argument to make a decision, or i could write a macro that takes a date and emits that date in the expansion |
| 20:26 | tomjack | I mean the clojure-for-cljs reader |
| 20:27 | jouiswalker | lol. stu saying "i dont feel the absence of a debugger" ironically drew a lot of attention to debuggers for clojure |
| 20:27 | dnolen | bbloom: I still don't see the problem |
| 20:28 | dnolen | bbloom: looks like cljs.tagged_literals.clj is just doing the wrong thing |
| 20:28 | dnolen | should always convert to Java types and not move around lists of symbols as it is now |
| 20:28 | dnolen | then you can convert during emission |
| 20:28 | tomjack | there is no way to register an unreader |
| 20:29 | bbloom | dnolen: that's certainly an improvement over what is there now |
| 20:29 | tomjack | if you do that you lose the 'e' completely? |
| 20:29 | dnolen | we *already* emit Java types all the time and there's not much of an issue |
| 20:29 | tomjack | oh I guess there is a way, print-method :) |
| 20:29 | dnolen | I don't see how literals aer any different |
| 20:29 | bbloom | dnolen: no, you're right. i was just elaborating on the nature of the problem |
| 20:30 | dnolen | bbiab |
| 20:30 | bbloom | dnolen: i guess then the rule is that data readers always produce values in the compiler's environment, not the target environment. and therefore we also need pluggable emission for emit-constant |
| 20:31 | hiredman | readers |
| 20:31 | bbloom | hiredman: does that sound sane to you? |
| 20:32 | hiredman | I dunno, thinking about it, how can literals work in a mixed environment like clojurescript? |
| 20:33 | bbloom | hiredman: just 10 minutes ago, i'd have said that they can't work… but i think dnolen is right… they would work like this: |
| 20:33 | hiredman | if I define a clojurescript type and a clojurescript reader literal, what type does the clojrue reader create? what types do macros in clojure get? |
| 20:34 | bbloom | there are two readers: the clj and the cljs reader |
| 20:34 | bbloom | you need to write two different functions for tagged literals in both |
| 20:34 | bbloom | the first one, is used at compile time & the literals always return java types |
| 20:34 | bbloom | but you ALSO need to have an emit-constant method |
| 20:34 | hiredman | so the clojurescript compiler pr-strs and read-strings? |
| 20:34 | hiredman | err, pr-strs and emits read-strings? |
| 20:35 | bbloom | no, the cljs compiler calls emit, which produces js code |
| 20:35 | bbloom | AFTER macro expansion |
| 20:35 | hiredman | right, but the macros can pass through and result in arbitrary types in forms |
| 20:35 | bbloom | yeah, there is just an extra layer: the translation from clj -> cljs |
| 20:36 | hiredman | (which is why I guess the clojure compiler does this thing) |
| 20:36 | bbloom | or clj -> js, more specifically |
| 20:37 | hiredman | like, if I have a java type Foo, how does the cljs compiler now how to conver that in to js? it doesn't it has to pr-str it and use read-string to reconstruct it on the js side |
| 20:37 | bbloom | hiredman: no, it doesn't emit edn strings, it emits js code |
| 20:37 | hiredman | it can't |
| 20:38 | bbloom | literals (should) yield :op :constant AST nodes |
| 20:38 | hiredman | Foo is an arbitrary object resulting from macroexpansion |
| 20:38 | bbloom | yeah, macro expansion occurs during the analysis phase, prior to code emission |
| 20:38 | bbloom | no strings involved yet |
| 20:39 | hiredman | right, an instance Foo comes out of a macro, and now the compiler wants to emit js, what does it do? |
| 20:40 | bbloom | currently: calls emit-constant and throws a no matching method error :-) |
| 20:40 | hiredman | https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4561-4586 the clojure compiler has to deal with the same thing |
| 20:41 | tomjack | wow |
| 20:42 | tomjack | I was just wondering why a macro returning a date didn't blow up with "can't embed object in code" |
| 20:42 | hiredman | I think I have a branch somewhere where I added an IConstant to clojure |
| 20:43 | bbloom | interesting. |
| 20:45 | hiredman | you can actually use IType I think, which if you extend it lets you sort of control how the type is embedded |
| 20:45 | hiredman | IConstant I think just effected the type of the final field used as a "constant" table |
| 20:45 | bbloom | seems like *tagged-readers* needs a matching *type-emitters* |
| 20:46 | hiredman | a protocol like IType maybe |
| 20:46 | bbloom | yeah something like that |
| 20:46 | hiredman | feh |
| 20:47 | hiredman | the itype interface is empty now? |
| 20:47 | bbloom | i'm not familiar with this part of the clj compiler |
| 20:47 | bbloom | a protocol or a multimethod would do the trick really |
| 20:47 | hiredman | at one point there was some interface (which I think was IType) that had a getBasis method that would return a vector of field names |
| 20:48 | bbloom | emit-constant is currently a multimethod, but if you use a fn or multimethod, then you'd want that in a dynamic var |
| 20:48 | hiredman | the compiler would, for that type, emit a constructor call with the values of those fields |
| 20:48 | hiredman | it looks like it still does, but it calls getBasis reflectively |
| 20:49 | hiredman | https://github.com/hiredman/clojure/blob/reflection-method-caching/src/jvm/clojure/lang/Compiler.java#L4422-4444 |
| 20:50 | hiredman | oh, whoops, that is my branch, it may be old |
| 20:51 | bbloom | haha |
| 20:52 | hiredman | nah, hasn't changed much on clojure master |
| 20:52 | bbloom | dnolen: i think we can just delete *cljs-data-readers* and replace it with *cljs-constant-emitters* |
| 20:56 | dnolen | bbloom: hmm I don't see a need to get rid of *cljs-data-readers*, bootstrapping is in our future |
| 20:56 | dnolen | bbloom: but yeah, *cljs-constant-emitters* that just explains how to convert Java types |
| 20:57 | dnolen | you'll have to define your readers twice (compile-time / dynamic runtime reads), but this solves the issue you're talking about |
| 20:58 | dnolen | bbloom: I'm willing to take a patch for that, perhaps a clojure-dev mailing list post is order just to get a little more feedback |
| 21:00 | bbloom | dnolen: i'll send you a patch if it ever becomes a real problem for me. in the meantime, should i just make a ticket? |
| 21:01 | dnolen | bbloom: sure, this may actually duplicate cemerick's tickets |
| 21:01 | bbloom | ok, i'll search |
| 21:02 | dnolen | bbloom: actually unrelated, go ahead an open a ticket |
| 21:03 | noprompt | i/ |
| 21:13 | akurilin | Quick question: I'm trying to grok the whole idea behind moving past OO. Specifically with regards to methods. Is the idea that instead of having methods be part of the types I define, operating on their state, I should rather extract that method into a function in a namespace somewhere, and pass the object to it? |
| 21:14 | akurilin | I think it's interesting to see something like moment. js and clj-time do very similar operations on time types, yet the former is all about methods and the latter is the reverse. |
| 21:15 | bbloom | akurilin: OOP & methods still makes sense with mutable objects, hence why deftype defprotocol, all that jazz exists. but they are tools for a different set of problems than most business logic deals with. by default, you should be working with immutable data & free functions |
| 21:15 | brehaut | akurilin: your question is quite general. methods / objects bundle a bunch of different things together into a single mechanism. there are multiple different things to do the job of methods in clojure/FP |
| 21:17 | technomancy | akurilin: are you using "method" to mean defmethod or just "a procedure attached to an object"? |
| 21:17 | hiredman | ~#9 |
| 21:17 | clojurebot | 9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. -- Alan J. Perlis |
| 21:17 | brehaut | akurilin: btw, clj-time is a slim wrapper around Joda Time, which is a java lib that uses methods everywhere (because it has to) |
| 21:17 | akurilin | technomancy, procedure with implicit self/this as first parameter |
| 21:18 | akurilin | brehaut, I get that, but doesn't it try to make the underlying operations more idiomatic with respect to Clojure? |
| 21:18 | technomancy | akurilin: ok, makes sense |
| 21:18 | jouiswalker | dnolen: have you read doug hoyte's let over lambda? |
| 21:18 | bbloom | akurilin: have you ever asked yourself "what class does this method go on?" and then realized a sensible argument could be made for either? you shouldn't make an arbitrary factoring decision like that unless you're getting some benefit from doing so |
| 21:18 | hiredman | akurilin: see that is part of the problem, that is actually a very small part of what you get from most oo systems (and not all of them, I believe python doesn't have implicit selfs) |
| 21:18 | dnolen | akurilin: I don't think looking at a project that demands polymorphism is a good intro into Clojure |
| 21:18 | dnolen | jouiswalker: nope |
| 21:18 | brehaut | akurilin: well, yes, but the fundamental immutable datamodel is in java, no clojure. |
| 21:19 | akurilin | bbloom, is there a good way to know when methods are indeed the right way to go, if you say in most cases they aren't? |
| 21:19 | hiredman | methods often also introduce polymorphism |
| 21:19 | jouiswalker | dnolen: just curious ;p |
| 21:19 | dnolen | jouiswalker: yeah, it just sounded like CL drivel |
| 21:19 | bbloom | akurilin: when you are just learning clj, methods are NEVER the right way to go :-) |
| 21:19 | dnolen | jouiswalker: and I like macros a lot |
| 21:20 | jouiswalker | dnolen: it sort of was. there was some interesting performance related stuff he did in it though |
| 21:20 | bbloom | akurilin: but the reason to really use methods is when you want fast single dispatch by type |
| 21:20 | bbloom | akurilin: that's basically the only reason |
| 21:20 | jouiswalker | dnolen: it didnt take long for his words to go over my head though lol |
| 21:21 | akurilin | bbloom, is the idea to replace those with multimethods that can operate on a set of supported types? |
| 21:22 | dnolen | jouiswalker: I find Art of the Object Metaprotocol a more interesting exposition on the power of macros since it about combining well designed functions with well designed macros |
| 21:22 | brehaut | ~polymorphism |
| 21:22 | clojurebot | genuine need for polymorphism just isn't very common |
| 21:22 | hiredman | feh |
| 21:22 | hiredman | technomancy: says you |
| 21:22 | bbloom | akurilin: multimethods are more flexible than methods, but are also more complicated than regular functions |
| 21:22 | bbloom | akurilin: the question you need to ask is whether or not you need open dispatch |
| 21:23 | trptcolin | jouiswalker: saw your note about an `lein repl` + backspace issue. is this lein 2.2.0? |
| 21:23 | jouiswalker | dnolen: i'll take a look. i've been in this swapping in between on lisp and paradigms of artificial intelligence for about two years xD |
| 21:23 | technomancy | hiredman: on a regular basis |
| 21:23 | bbloom | akurilin: you can always do (cond (fn? x) y (number? z) w …) |
| 21:23 | dnolen | jouiswalker: both good books |
| 21:23 | jouiswalker | trptcolin: yes |
| 21:23 | akurilin | bbloom, not familiar with the term, google isn't revealing anything either |
| 21:23 | jouiswalker | trptcolin: but it was present before that as well |
| 21:24 | brehaut | hiredman: its certainly not as necessary as its place in OO might suggest |
| 21:24 | hiredman | brehaut: sure, ala carte |
| 21:24 | jouiswalker | dnolen: thanks for the book recommendation |
| 21:24 | clojurebot | brehaut is ‽ |
| 21:24 | bbloom | akurilin: in this case "open" means accessible for other people to extend |
| 21:24 | brehaut | WTF clojurebot |
| 21:25 | bbloom | akurilin: an cond block sn't open to extension, you can't add more cases to it |
| 21:25 | bbloom | akurilin: but a multimethod lets you add more cases without changing the code |
| 21:25 | bbloom | akurilin: if you don't need open extension, start off with cond |
| 21:25 | hiredman | it's not about prevalence, it is about disconnecting decisions about polymorphism from decisions about namespacing, etc |
| 21:26 | dnolen | akurilin: jumping back a bit, the idea in Clojure is that polymorphism should come a la carte - not stuck inside of some object or a feature of some class, this emphasizes value oriented programming which the important thing. |
| 21:26 | dnolen | akurilin: even in projects that make heavy use of protocols, you're still trying building things up to the point where you can get to simple value oriented programming. |
| 21:27 | trptcolin | jouiswalker: sure. my xterm seems happy. so the two possibilities i see: ~/.inputrc setting overriding default keybindings or some keystroke is unmapped by jline |
| 21:27 | decaf | (do (def alphabet (char-array "abc")) (class alphabet)) returns "[C" without quotes. am I hitting a giant bug here? |
| 21:27 | brehaut | decaf: no; arrays are primatives |
| 21:27 | hiredman | that is the internal jvm type of an array of characters |
| 21:28 | decaf | we should get something more readable like char[] |
| 21:28 | jouiswalker | cat .inputrc : set editing-mode emacs, set keymap emacs |
| 21:28 | jouiswalker | |
| 21:28 | technomancy | decaf: it is pretty ridiculous |
| 21:28 | hiredman | we? |
| 21:28 | technomancy | but it's JVM ridiculousness, not clojure-specific ridiculousness |
| 21:29 | jouiswalker | trptcolin: its sort of interesting, since using the repl within xterm works just fine |
| 21:29 | akurilin | dnolen, sounds great, thanks for clarifying. I've actually not run very much into need for polymorphism just yet because of how small my projects' scope generally is. |
| 21:29 | akurilin | dnolen, I'd certainly love to know basic rule of thumbs I can follow until I've gotten enough experience that I can judge well on my own. |
| 21:29 | decaf | hiredman: we, clojure programmers, especially newcomers. english is not my native language. |
| 21:29 | jouiswalker | trptcolin: after i exit the repl using (exit), i'm able to do weird stuff like |
| 21:29 | jouiswalker | trptcolin: aoeu^H^H^H^H |
| 21:29 | jouiswalker | bash: $'aoeu\b\b\b\b': command not found |
| 21:29 | jouiswalker | |
| 21:30 | trptcolin | jouiswalker: oh, so this is after exiting the repl |
| 21:30 | jouiswalker | trptcolin: yes |
| 21:30 | bbloom | akurilin: that's what i was trying to provide. just work with pure functions & clj data structures until you have a problem you just don't know how to solve without them. then you can figure out which tool solves precisely the problem you have |
| 21:30 | bbloom | akurilin: and feel free to come back here and ask about a specific case, it's harder to understand these things in the abstract |
| 21:31 | akurilin | dnolen, I think the closest I'm going to get to needing polymorphism soon is dealing with models in a MVC pattern. I might need a protocol possibly for something :) |
| 21:31 | akurilin | bbloom, for sure. |
| 21:31 | dnolen | akurilin: I wouldn't mess with much protocols - stick with the standard API, reach for multimethods if you need some polymorphism. At some point you might find a use for protocols. |
| 21:31 | akurilin | bbloom, appreciate it. |
| 21:31 | dnolen | akurilin: well, hopefully Clojure will convince you MVC is not really a great idea |
| 21:31 | hiredman | decaf: I don't think optimizing for newcomers is a good use of time and energy, since it is almost entirely subjective and tends to degenerate in to just people expressing their opinion and saying it is good for newcomers |
| 21:31 | jouiswalker | trptcolin: out of xterm, urxvt, terminology and terminator, xterm is the only one i have observed with this problem |
| 21:32 | callen | Raynes: home sweet home |
| 21:32 | akurilin | dnolen, unfortunately most of my experience with writing web apis comes from the Rails world, so that's my point of reference. I'd certainly LOVE to shave off whatever extraneous layers I can. |
| 21:32 | callen | technomancy: I survived LA |
| 21:32 | decaf | I was just explaining what I meant by saying "we" |
| 21:32 | dnolen | akurilin: it's a bit of slog IME, but you'll eventually being very averse to the kinds of engineering decisions and libraries that continue to be popular. |
| 21:34 | callen | akurilin: counter-point, I find separation of concerns (often but not always manifesting as MVC) works fine and has improved with Clojure, but what changed is how I compose and "build up" my projects that stands in stark contrast with my older Rails and Django projects. |
| 21:34 | jouiswalker | trptcolin: ahh, another interesting thing is that re-entering the repl fixes the problem, but that it returns again after you exit :/. |
| 21:35 | callen | akurilin: namely, less assuming of some kind of core (large) framework, more, "here's a bag of tools, do as thou wilt" |
| 21:35 | callen | akurilin: but I'm pretty fascist about keeping my libraries focused. *shrug* |
| 21:35 | trptcolin | jouiswalker: yeah, my xterm is still fine. i suspect there's an stty setting differing there that's causing issues. would appreciate a GH issue with details on OS, terminals, & results of `stty -a` before launching any repl (in the working state), and after exiting lein repl (in the broken state): https://github.com/trptcolin/reply/issues |
| 21:36 | jouiswalker | trptcolin: i'll do that now. thanks! |
| 21:37 | akurilin | callen, same here, I get pretty anxious when I don't know exactly what's in my app. Things like ActiveRecord can be pretty magical and hard to understand. |
| 21:38 | akurilin | callen, basically at this point I'm doing the key parts of Rails by combining together little pieces of functionality from here and there, which seems to be what almost every other web application does out there, at least from what I've seen in repos |
| 21:40 | akurilin | On the api note, does anybody know if there's any kind of accepted standard for passing sql-like query conditions to a rest api, or does everybody do something custom every time? |
| 21:42 | akurilin | So something like a GET on /repositories with "contributors > 5" |
| 21:43 | akurilin | What's neat about korma is that it should be pretty doable to map those to korma's DSL |
| 21:43 | akurilin | (watch me get sql injected on day 1) |
| 21:49 | jouiswalker | trptcolin: it looks like stty -a revealed a lot about the problem |
| 21:49 | jouiswalker | trptcolin: erase somehow gets set to something else outside the repl |
| 21:55 | callen | akurilin: activesupport always bothered me more than activerecord. |
| 21:55 | callen | akurilin: I have an example clojure web app here: github.com/bitemyapp/neubite/ you can take some cues and ideas from there. It's based on Luminus. |
| 21:56 | callen | technomancy: do you read the Culture novels? |
| 21:57 | akurilin | callen, awesome, thanks, always good to have more sources for inspiration. I do look at Luminus occasionally as well. |
| 21:57 | akurilin | Gotta run folks, thanks for your responses |
| 22:14 | callen | Raynes: what happened to Refheap? |
| 22:15 | callen | oh, Linode. |
| 22:15 | callen | balls. |
| 23:38 | tieTYT | i was forbidden from writing clojure at work today |
| 23:38 | ehaliewicz | why is that? |
| 23:39 | egghead | too much power |
| 23:39 | bbloom | ehaliewicz: it might make him less fungable? |
| 23:39 | bbloom | fungible* |
| 23:39 | callen | tieTYT: why? |
| 23:40 | tieTYT | i wrote some code in < half the lines it would take to write in java but I was told that my coworkers can't maintain it and, "the needs of the many outweigh the needs of the few" |
| 23:40 | callen | ehaliewicz: interchangeability of resources (nb: PEOPLE) is highly prized in the gentry class. |
| 23:40 | xeqi | it would lead down to the downfall of the semicolon industry |
| 23:40 | callen | tieTYT: to whit, wouldn't that mean firing his lazy ass so the many (company) can benefit from the higher productivity? |
| 23:40 | xeqi | and that is too big to fail |
| 23:41 | tieTYT | actually he's pretty good w/ lisp |
| 23:41 | tieTYT | he was thinking of everyone else at the company |
| 23:41 | tieTYT | we already use drools though in some project. I think it's a pretty similar thing to bring into the company ecosystem |
| 23:41 | bbloom | right, like i said, fundability :-) |
| 23:41 | ehaliewicz | the way he said it suggested to me that he was normally allowed, but temporarily banned |
| 23:41 | ivan | ego-protective behavior, assuming everyone else is too dumb |
| 23:41 | bbloom | er fungibility |
| 23:41 | bbloom | i can't type |
| 23:42 | tieTYT | ehaliewicz: no, permaband |
| 23:42 | callen | I really dislike drools. |
| 23:42 | bbloom | ivan: i didn't say dumb |
| 23:42 | ivan | I never implied such ;) |
| 23:42 | tieTYT | callen: I don't know much about it |
| 23:42 | egghead | I work at a corporate company and we still silo all clojure to internal tools, I still don't get to use it on the larger projects for just that reason tieTYT |
| 23:42 | tieTYT | but if you compare the two, both require you to think differently and program in a way that's different from java |
| 23:42 | bbloom | ivan: somebody way smarter than me is less likely to be able to understand my dense expressive code than my boring mechanical code |
| 23:42 | tieTYT | egghead: at least you get to use it on the internal tools |
| 23:43 | bbloom | even if the guy who takes my job is way smarter than me, he would rather i wrote some vanilla boring stuff |
| 23:43 | ehaliewicz | tieTYT: write clojure code that generates java |
| 23:43 | tieTYT | ehaliewicz: ha, yeah that'll fly |
| 23:43 | ehaliewicz | they won't even know |
| 23:43 | tieTYT | now the incident is on the radar, they'll get real pissed if I did that |
| 23:44 | egghead | you can very easily write stuff in java or groovy that a future maintainer wouldn't understand |
| 23:44 | egghead | seems like they are just neophobes |
| 23:44 | egghead | change is scary!!! |
| 23:44 | ehaliewicz | tieTYT: but you're supposed to get back at them |
| 23:45 | ehaliewicz | :D |
| 23:48 | tieTYT | egghead: yeah I agree. I like comparing it to drools. I don't know drools at all, but if I had to maintain their drools code I'd be expected to learn it and wouldn't consider it ridiculous |
| 23:48 | tieTYT | where do you draw the line? Am I not allowed to use CollectionUtils? |
| 23:49 | tieTYT | the fucked up thing is I wrote teh code in clojure then rewrote it in java (half way). I had all the unit tests in place and it still took twice as long and i'm not even done |
| 23:49 | tieTYT | you people understand me :) |
| 23:51 | callen | tieTYT: better to beg forgiveness next time? |
| 23:51 | callen | ecallen: hello doppleganger. |
| 23:52 | tieTYT | callen: That is how I approached it |
| 23:52 | tieTYT | i wrote the clojure first |
| 23:53 | tieTYT | now i'm off to learn about clojure script |
| 23:53 | talios | sweet :) cheers |
| 23:56 | tieTYT | i must say it's really hard to find out how to get started with clojurescript |
| 23:56 | tieTYT | the "getting started" guide's first paragraph tells you you shouldn't follow it |
| 23:58 | bbloom | tieTYT: lein cljs-build is the easiest way to get started |
| 23:58 | tieTYT | yeah I'm going to start checking that out |
| 23:59 | callen | tieTYT: I hope you like pain :) |
| 23:59 | tieTYT | can I use CCW with it? Do I need to use piggyback or something? |
| 23:59 | tieTYT | callen: why? |