# #clojure log - Jan 21 2013

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

0:05 TimMc: Anyone want to help me redesign my high-level circuit simulator? (Sequential circuit, functions as combinatorial logic blocks, registers.) I have a working version, but it's a little limited in design and I think it could be nicer. https://github.com/timmc/feedback

0:06 tomoj: kind of something like this https://www.refheap.com/paste/9bd8650fb60801977f3eec825

0:06 needs to support conj though, hmm

0:11 whoahbot: wait, no i meant WuHoUnited

0:12 TimMc: industrial-sounding at first, then very circuit-bendy

0:14 TimMc: tomoj: What does it mean for an infinite sequence to be reversible?

0:14 muhoo: reversible infinity... start at the end and work backwards... um, wait...

0:15 TimMc: I can't think of a meaningful invariant that is defined on infinite seqs.

0:15 tomoj: hmm

0:15 (= cycle (rseq (rseq cycle))) obviously

0:16 oh, my impl has (= (first cycle) (first (rseq cycle)))

0:16 which does seem weird

0:18 TimMc: Even then, I still don't think Reversible is appropriate.

0:21 tomoj: Anyway, what's the use-case?

0:22 tomoj: ring buffer

0:24 real use case is reusing dom nodes for a list

0:33 I guess it's like a deque

0:34 to move right, you pop-left and conj-right, to move left, you pop-right and conj-left

0:36 TimMc: tomoj: So you really want a completely filled, fixed-size ring that you can navigate left and right in?

0:37 (first (left 3 ring))

0:39 tomoj: I dunno, that's what I thought I wanted

0:39 TimMc: (->> ring (left 3) (set "hi!"))

0:40 Reversible would make sense if you made the seq finite.

0:40 tomoj: now that I think about it more the real use case seems more complicated, so maybe it's moot

0:42 how about: (= (reverse (drop-last coll)) (rest (reverse coll)))

0:42 warz: went ahead and reformatted to ubuntu, heh.

0:45 tomoj: .. uh, where drop-last is the identity on cycles

0:46 well that's a semantic equality anyway, obviously not going to call reverse on a cycle

0:46 TimMc: (defn reversible? [coll] (if (empty? coll) (empty? (rseq coll)) (and (= (first coll) (last (rseq coll))) (reversible (rest coll)))))

0:47 *reversible?

0:47 clerksy: So, If I am attempting to use the case macro, but the test constants are static fields from a java class, what would be the best way to handle that?

0:47 TimMc: or (= (nth coll x) (nth (rseq coll) (- (count coll) x 1)))

0:48 tomoj: are there things which fail those that pass my test?

0:48 clerksy: Ohh, I should be using (cond), huh?

0:48 TimMc: clerksy: Yeah, I don't know if case can handle Java static fields as compile-time literals.

0:49 &(let [x Long/MAX_VALUE] (case x Long/MAX_VALUE :can :can't))

0:50 lazybot: ⇒ :can't

0:50 TimMc: tomoj: reverse will fail on a cycle

0:51 tomoj: well, yeah

0:51 I mean the semantics of reverse

0:51 TimMc: (oh, you said that)

0:51 tomoj: semantic `(reverse (drop-last cycle))` would be implemented by (rseq cycle)

0:52 but anyway your functions assume finitude

0:52 TimMc: It's true.

0:52 tomoj: uh, finiteness

0:53 TimMc: finity?

0:53 clojurebot: is too infinity +1!

0:53 TimMc: ...

0:54 muhoo: so says.... godel? or was it cantor?

0:54 TimMc: tomoj: You can't ask for last on an infinite sequence, so you can't ask for first on the reverse of one.

0:55 tomoj: hmm, yes, these aren't sequences

0:55 TimMc: Given a general rseq, (defn last [x] (first (rseq x)))

0:56 tomoj: they have a rest and an unrest

0:56 TimMc: unrest :-P

0:57 Is Cycle going to implement Counted?

0:57 tomoj: heh

0:58 TimMc: (counted? cyc) ;;= true / (count (seq cyc)) ;; infinite...

0:58 tomoj: well it has to be an int

0:59 so no

1:01 if they have a first, rest, and unrest, then they have a first and rest, so the can be ISeq. Reversible does seem possibly strange

1:05 n_b: How do you seq a BufferedReader by char rather than line?

1:05 Do I have to go down to using the java.io stuff?

1:08 TimMc: n_b: How are you currently getting a seq from a BufferedReader?

1:08 n_b: line-seq, but given my input it's not very convenient

1:10 TimMc: (defn char-seq [br] (let [c (read br)] (when-not (= c -1) (cons c (lazy-seq (char-seq br))))))

1:10 Should work?

1:11 Oh, change that to (cons (char c) ...)

1:11 Cribbed from the line-seq implementation.

1:12 tomoj: (take-while pos? (repeatedly #(.read br))) ?

1:12 TimMc: ooh

1:12 n_b: ooh

1:13 TimMc: Replace pos? with (complement neg?), though.

1:13 Otherwise you'll start dropping NULs.

1:13 tomoj: oh yeah

1:13 #(not= % -1) is probably good

1:14 yunfan: hi, can lein repl hook those use fail error, and install that library ?

1:16 TimMc: &(let [br (java.io.StringReader. "foo")] (->> (repeatedly #(.read br)) (take-while #(not= % -1)) (map char)))

1:16 lazybot: ⇒ (\f \o \o)

1:17 TimMc: yunfan: That would be an interesting modification. You'd need pomegranate (or similar) to add stuff to the classpath, and some other hook with a database of namespaces -> Maven coordinates...

1:19 I'm not sure how you'd go about detecting #'use failures, though.

1:19 yunfan: TimMc: because i am reading someone's handbook on clojure, which the code sample use many library that i dont have

1:22 n_b: TimMc: Thanks for the hel

1:22 (conj p *1)

1:23 same to you tomoj

1:37 johnmn3_: trying to convert a piece of java here: while(true){if((line=br.readLine())==null)continue; post(line);}

1:37 I don't think I can do it with a clojure while

1:37 tagrudev: morning

1:37 johnmn3_: can I just take-while on a br?

1:38 morning tagrudev

1:38 or is there a best highlevel function to consume the buffered reader?

1:40 tomoj: should `continue` be `break`?

1:41 johnmn3_: tomoj... that's what I'm seeing... continue.. this while happens to be within an inner class which is also running a while(while) true... not sure if that's why a continue is used

1:41 I'm not familiar with it.

1:42 sorry, it is an inner class which calls another inner class, both of which have while(true)

1:42 and this second, sub while(true) has the continue

1:42 nakkaya mentions using a line-seq on a buffered reader

2:03 TheBusby: johnmn3_: isn't that filter?

2:05 johnmn3_: I suppose filtering on nil would consume the sequence for me.

2:09 TheBusby: (->> br line-seq (filter identity))

2:14 johnmn3_: well, because I had to call post, I went with (->> br line-seq (map #(post %) ))

2:19 xumingmingv: I want to add a hook for `lein repl`

2:19 TheBusby: jhowarth__: remember map is lazy

2:19 whoops, sorry

2:20 xumingmingv: The doc: https://github.com/technomancy/leiningen/blob/stable/doc/PLUGINS.md says I needs to add a namespace lein-repl/plugin.clj

2:20 TheBusby: johnmn3_: remember that map is lazy

2:20 also you removed the filter...

2:21 johnmn3_: won't it just stop mapping once it hits nil?

2:21 TheBusby: ah, I see your point

2:22 johnmn3_: I'm hoping the seq will be consumed

2:22 TheBusby: doall?

2:22 johnmn3_: I guess I'll throw a doall in front of it... sometimes I don't need to though

2:23 TheBusby: I think the chunksize for some sequences is ~32? So if it's less than that likely not, but otherwise...

2:23 your java was an endless loop, so not sure how to handle that here

2:25 johnmn3_: I'm putting it in a function and I'll be calling repeatedly on that function in a thread

2:26 hoping that will work

2:37 if a library I'm using has a (def foo (atom nil)) in it and I require that namespace in two separate namespaces of mine, do each of my namespaces have unique atoms? or do they share the same one?

2:43 amalloy: the same

2:45 johnmn3_: they're "thread local" right? But the loading of my namespaces will all take place in the same thread, so they'll share the same atoms?

2:58 semisight: hey does anyone here have any experience with clojure and sql?

2:58 amalloy: there is no thread locality involved

2:59 semisight: I'm having a really weird problem with it

2:59 here's my code: https://gist.github.com/4584333

2:59 I can't insert multiple records using clojure's builtin map?

3:00 amalloy: ~map

3:00 clojurebot: map is slightly retarded

3:00 amalloy: hm

3:00 more importantly it is LAZY

3:01 semisight: wat

3:01 that completely makes sense

3:02 thank you so much!

3:03 so would the best strategy be to wrap the map in a dorun call?

3:06 amalloy: meh

3:06 that's fine, though i'd personally use doseq. but it looks like insert-records already does exactly what you want?

3:07 semisight: the problem with the batch insert is that I really need an upsert

3:08 I am guaranteed that there will be multiple rows of data with the same primary key

4:14 Wraithan: So is there something I could do so my template files are lazy loaded? https://github.com/wraithan/leech-tracker/blob/master/src/leech_tracker/handler.clj

4:16 So, my problem is I have to bounce my server to see changes to my templates, which makes working on them terribly inconvenient

4:19 ro_st: you'd have to touch handler.clj as well, and ensure ring reloads files with wrap-reload

4:20 Wraithan: Sure, that is a terrible solution though, I know I could touch a clojure file to make it reload as well

4:20 ro_st: otherwise handler must load them every time they're used

4:21 Wraithan: I come from other languages and expect it to load the file from disk each time it executes

4:21 ro_st: congratulations :-)

4:22 two option's i've presented are the shortest-path solutions on offer to you

4:22 Wraithan: I don't want to come off as combative, but you didn't.

4:23 ro_st: apologies. it appears that you want it to do something magical. my point is, there is no magic :-)

4:23 Wraithan: You offered one solution (touching handler.clj) and then you mentioned exactly what I am looking for without an sort of solution, just a restatement of what I want.

4:23 ro_st: if you want it to load after initial compilation (as it does now) you need to write code to produce that effect

4:24 brainproxy: Wraithan: have you looked into the reload middleware for ring?

4:24 Wraithan: What would code that loads it from the file system each time look like?

4:24 brainproxy: it already reloads on clj files changing if that is what you mean?

4:24 brainproxy: w/ the lein-ring plugin you can get the effect pretty easily with an option set in project.clj, but I'm not sure it's exactly what you want

4:25 ro_st: the issue is that they're html files. if they were clj files, it'd just work

4:25 brainproxy: Wraithan: ring reload middleware checks whether certain files have changed since the last request came in

4:25 and if so, the file and dependent namespaces are reloaded

4:26 lein-ring also exposes an auto-refresh? option, so changes on disk will trigger a browser refresh

4:26 which then kicks off the namespace reload

4:26 ro_st: yes. but this mechanic only works for .clj files. you have to touch the relevant .cljs, or, move your loading logic into a function that gets called on each request, rather than once during compilation (as (def) forms)

4:26 brainproxy: ah I see

4:26 ro_st: s/cljs/clj

4:27 Wraithan: I just don't see why it loads at compilation time rather than at execution time

4:27 brainproxy: well auto-refresh? w/ lein-ring watches other things too

4:27 ro_st: Wraithan: (def …) is evaluated once

4:27 brainproxy: e.g. I change a file in resources/public/stylesheets/...

4:27 a .css file

4:27 then the browser will refresh

4:27 Wraithan: ro_st: so it automatically memoizes?

4:27 ro_st: brainproxy: interesting. i've not experienced this behaviour

4:28 oh, that's the browser. we're talking about updating stuff in memory on the server side

4:29 Wraithan: yes. if you put (render-file "…") into your (GET "/" [] ?) directly, you should see that it updates properly

4:29 or

4:29 (defn get-index [] (render-file …)) and (GET "/" [] (get-index))

4:29 Wraithan: I see

4:30 brainproxy: i see, didn't realize the redner file issue

4:30 basically, the old stuff is stuck in memory

4:31 * brainproxy needs to go to bed, neurons getting fuzzy :p

4:31 Wraithan: ro_st: thanks, that fixed it

4:32 ro_st: excellent

4:33 Wraithan: Also, now I understand the difference

4:33 ro_st: of course, in production, you'd want some sort of only-load-if-actually-necessary mechanic to prevent excessive disk usage

4:33 Wraithan: That supposes a high load

4:33 this should be super low load (10-20 requests a day)

4:33 ro_st: indeed

4:34 i see you're in portland! are you attending ClojureWest?

4:34 Wraithan: Unlikely

4:34 Actually definitely not

4:34 It is during PyCon

4:34 ro_st: ah

4:35 Wraithan: Just playing with clojure in my spare time

4:35 I am a python hacker for Mozilla

4:35 ro_st: nice

4:36 Wraithan: Also hard to justify 350 for a hobby side language

4:39 ro_st: true :-)

4:46 muhoo: 350?

4:46 oh right, cljwest fee

5:44 piranha: I've changed drip wiki a bit: https://github.com/flatland/drip/wiki/Clojure/_compare/8733641e714006f8da8ab1cb081f7a0bf6d6e23d...f953a9221f8b6f3f772b3a05903aa70746a58bad

5:44 I hope I actually fixed it and wrote what was intended from the start :)

5:51 borkdude: is it possible to have a two-line title in org-mode?

5:52 not really important though

6:08 ucb: borkdude: not afaik; if you find otherwise please let me know though :)

6:11 borkdude: I'm trying to go from latex to org-mode, so far I like it

6:16 * ucb <3 org-mode

6:16 ucb: borkdude: check out todo items, archiving and calendars (and tables!); your mind will be blown!

6:48 borkdude: ah, org-mode and jekyll looks like an exciting combination

7:38 rasputnik: have a simple Ring REST service packaged via uberjar, and need to supply it with some config (DB urls, etc). Is there an idiomatic way to parse config files etc.?

7:39 e.g want to run it as "java -jar restything.war config.json" or similar

7:41 borkdude: anyone happen to know this one? http://stackoverflow.com/questions/14438582/org-mode-highlighting-using-minted-for-latex-and-htmlize-for-html

7:57 augustl: how do I load a schema from a .sql file with clojure.java.jdbc?

8:00 it works fine if I just have one CREATE TABLE and pass it to do-commands, but I get syntax error when I have multiple

8:00 the file works fine when being executed with "mysql" itself

8:01 borkdude: is it possible to create a listing with a reference/label in org-mode?

8:01 augustl: also wondering why 0.2.4 isn't out yet, 0.2.3 seems quite old and there are lots of improvements in 0.2.4

8:06 borkdude: ah got it: <<code-reference>>

8:07 I wonder why this has a different notation, but it works

8:12 augustl: isn't there a way to make the threading macro pass the previous value as a argument I specify, instead of the first argument?

8:12 the use case is to end the threading with a (remove predicate insert-prev-value-here)

8:13 scottj: piranha: were you able to see a speedup in lein? which commands?

8:14 piranha: scottj: lein cljsbuild once <target> was 18 seconds vs 5 seconds

8:14 when I just had -drip it was always 18 seconds

8:15 ucb: augustl: you also have ->> which places the value as the last arg.

8:15 augustl: afaik those are the two only options

8:16 scottj: piranha: ahh, I was running lein not lein2 :) thanks for the edit!

8:16 piranha: np :)

8:17 augustl: ucb: I see

8:22 figured out how to load a sql schema - split the sql file on #";" and run them as individual commands ;)

8:46 dignati: Hey clojurists! Would someone mind to check out this function and tell me if it is idiomatic/good code? I read a lot of CL code recently and think I got confused with functional/non-functional code. https://gist.github.com/4585871

8:50 ucb: dignati: why do you define an anonymous fn only to call it immediately?

8:51 dignati: The function recurs to it. I needed more function params to keep track of my state

8:52 * ucb wonders whether there's a better way to do this

8:52 xeqi: loop

8:52 ucb: that'd be the one

8:52 ChongLi: hmm, nested js obj property access is really ugly in cljs

8:52 is there no macro for this?

8:53 dignati: xeqi: of course I can loop over it but I looked for a recursive solution

8:54 ChongLi: dignati: function params to keep track of your state? just use a map

8:56 ucb: dignati: I think he meant the loop/recur construct; you can have recursion with loop

8:56 xeqi: dignati: loop just sets bindings and creates a recur point. its the same effect as immediately calling the anon fn

8:56 dignati: ChongLi: Ah, now I know what "params to keep track of state" reminded me of. I have no idea how to do it in this but might have to take a look

8:57 ChongLi: dignati: a map is an extremely useful data structure

8:57 it stores keys and their associated values

8:58 dignati: ucb: xeqi: Okay I check this out. Thanks!

8:58 ChongLi: Oh I thought you meant #'map

8:59 ChongLi: more like this: {:key value :key2 3} etc.

8:59 dignati: Okay thanks for your help, I'm going to rewrite it with loop

8:59 ChongLi: maps in clojure can be nested as well

9:00 dignati: ChongLi: Got that ;)

9:00 ChongLi: you can put a very big tree of program state entirely within one map

9:02 xeqi: \$findfn [1 2 3 4 5] [3 4] true

9:02 lazybot: [clojure.set/superset? clojure.core/not= clojure.core/distinct? clojure.core/every?]

9:02 xeqi: \$findfn [1 2 3 4 5] [3 4] [3 4]

9:02 lazybot: [clojure.set/select clojure.set/intersection clojure.core/max-key clojure.core/cond clojure.core/dosync clojure.core/sync clojure.core/char-escape-string clojure.core/*data-readers* clojure.core/filterv clojure.core/default-data-readers clojure.core/filter cloju... https://www.refheap.com/paste/8832

9:02 aroemers: ChongLi: I am still pondering whether a big state map is a good idea. I think for one it is good for "trampolining" functions, but still.. the entire state passing around..

9:03 It feels wrong somehow.

9:03 Any opinions on this?

9:06 ChongLi: aroemers: what do you mean the entire state passing around?

9:06 all that passes around is a reference

9:07 you don't pass the entire thing to every function, that would force every function to traverse the state to get what it needs

9:08 aroemers: Sure, but it may complicate undestanding simple functions that have this reference. It starts with all this state available. Less state in a function is desirable.

9:08 ChongLi: it's not really state

9:08 since it's not mutable

9:08 it's just a value

9:08 a simple function would operate on a simple value

9:09 aroemers: Hmm, assuming you know up-front what part of the state the function needs (and what the nested function calls need)

9:11 For instance, in a parses I've written, I have to pass the entire state to a simple function, because that simple may call another function that needs most of the state. Thus, more state is available in the simple function than necessary.

9:11 *parser

9:12 Ah well, still in doubt whether this is a bad thing.

9:12 ChongLi: well, you can pass the state around, stick it in an atom or go the monad route

9:13 monads have been used in parsers in the past

9:14 aroemers: True, if you put it like that, passing the state around is actually a good choice. :)

9:32 borkdude: hmm, I'm having this in a .org file: src_clojure{[1 2 "a" "b"]}

9:32 but it doesn't translate well to latex

9:37 borkdude: aroemers I'm using minted

9:37 aroemers: Ah, don't know that one

9:38 borkdude: aroemers It has better highlighting for clojure

9:41 aroemers: Clojure highlighting is listing takes some work indeed, but it is doable. I'll check minted the next time though

9:42 *in

9:47 borkdude: =[1 2 "a" "b"]= in org-mode becomes [1 2 äb"] in latex…

9:49 maybe it's just better to not inline code

10:14 xumingmingv: need a little help here

10:14 ,(= (quote a) (quote a nil))

10:14 &(= (quote a) (quote a nil))

10:14 lazybot: ⇒ true

10:14 clojurebot: true

10:14 xumingmingv: why (quote a) == (quote a nil) ?

10:17 algernon: xumingmingv: because quote quotes a form, "a nil" is two forms, not one

10:17 xumingmingv: so the `nil` here is just ignored?

10:17 algernon: yes

10:17 &(quote a b)

10:17 lazybot: ⇒ a

10:17 xumingmingv: ohh, thanks

10:31 borkdude: can you have TODO items in org-mode which aren't headings

10:32 I just want to add some TODO remarks to my text, without it being a section, and exclude it on export

10:33 qz: how do i pass java methods as predicate to filter? say i want to call .isFile, wrap it in anonymous function #(.isFile %) ?

10:33 aroemers: qz: Yes, that's how I do it anyway.

10:34 qz: aroemers: i see, thanks

10:40 tmciver: Has anyone else had a problem with nrepl where loading a file (C-c C-l) stops working apparently after a previous attempt at loading a file failed with an exception?

10:41 I'm using 0.1.5. I should probably try out 0.1.6.

10:41 NeedMoreDesu: How do I add jar to the project? I wish it would be somewhere in project dir.

10:43 augustl: are there any general tips for calling macros inside macros? Trying to call "binding" within a macro, getting "Can't embed object in code, maybe print-dup not defined:" all of a sudden

10:45 jweiss: i think i might have asked this before, but is it possible to alias a namespace without requiring it? i don't want to load it, i just want to refer to namespaced keywords

10:45 i mean in the ns form. i am aware of alias fn

10:46 aroemers: NeedMoreDesu: install the library in your local repository, it's the best option. It is intentional that you cannot add a jar to the project easily.

10:53 augustl: can preconditions alter the arguments? For example, I want a precondition that validates that something is a date, and to do that I need to create a date object. Would be nice if I could just pass on that date object so I don't have to create a new one

10:55 nDuff: ...why would you need to create a Date to validate whether something _is_ a date?

10:55 Do you mean validate that something can be used as an argument to one of Date's constructors?

10:56 NeedMoreDesu: aroemers: thanks. I think I'm getting how does it work now.

10:56 augustl: nDuff: it was probably not a good example. But in some cases, you want to parse something and check if the parse result was A OK, and use that parsed object.

10:57 nDuff: Sounds like a precondition just isn't the right construct.

10:58 Move the parsing into your function, and then it's moot. Could make a macro or HOF that automates it for you, of course.

10:59 augustl: yeah it's in the function now

10:59 it's called preconditions, not pre-operations, after all :)

11:37 gfredericks: is it normal that `lein run` takes a few minutes to return if I use a future? i.e., a few minutes past the last future finishing

11:37 I assume `shutdown-agents` is related to this...

11:37 just curious about the long delay

11:40 nDuff: gfredericks: ...right -- if you shut down the pools yourself, you should be able to avoid that delay.

11:42 gfredericks: Anybody know why the delay is necessary?

11:42 craigbro: gfredericks:

11:43 gfredericks: a few minutes islonger than I have experienced, but I have seen such delays. I explicitely System/exit

11:43 gfredericks: it may be shorter, I'm timing it now

11:43 craigbro: I had a -main method that called some code that use pcalls and it added tens of seconds or more to calling that module, unless I did System/exit

11:44 gfredericks: I didn't investigate why, I just did that because as a unix dork I was like, "err, waiting on children, exit will round em up."

11:45 gfredericks: after timing once with and without, it is strikingly close to exactly one minute

11:46 clgv: gfredericks: do you use shutdown-agents?

11:46 gfredericks: clgv: it finishes 60 seconds sooner with shutdown-agents

11:46 this is tricky because I'll need to make sure that I have no more things to run

11:46 explains it 8)

11:47 gfredericks: craigbro: oh nice, thanks

11:48 craigbro: one would expect dereferencing the future should kill it's thread eh?

11:50 the jira bug is illuminating

11:50 nDuff: craigbro: I wouldn't tend to expect that. Starting and shutting down threads is expensive.

11:52 gfredericks: is it odd that there's no mechanism to register a deliverance callback with a promise?

11:52 nDuff: Hmm. That _could_ be useful.

11:52 Seems like something you could do yourself

11:52 ...not hard to wrap something but still keep it implementing IDeref

11:52 gfredericks: without holding up a thread on a deref?

11:53 clgv: gfredericks: put a deref of that promise in a future ;)

11:53 gfredericks: clgv: I'm naively assuming that's unideal to keep a thread occupied in that

11:53 clgv: gfredericks: huh? it does not do anything actively

11:54 gfredericks: clgv: sure. I don't know about the impl details. E.g., is there a fixed-size thread pool that we're hogging a thread from?

11:55 clgv: gfredericks: futures use an unbounded threadpool

11:55 gfredericks: then do I have to worry about doing this hundreds of times?

11:57 * nDuff somewhat wishes for something equivalent to send/send-off to determine whether to use bound or unbounded thread pool for a future. Granted, one might need to make it illegal for bounded-thread-pool futures to deref each other to prevent deadlocks, but that seems like it should be doable.

11:58 craigbro: yah, I didn't realize futures use a pool

11:59 I had a problem with futures accumulating (ring file upload handler) it would blow up under load testing

12:00 so I assumed that each future was it's own thread

12:25 technomancy: gfredericks: lein used to shut down the thread pool, but it had some weird effects on programs that relied on the fact that the thread pool was keeping the JVM running

12:27 gfredericks: technomancy: oh that's reasonable; I wouldn't expect lein to monkey with this. Would have broken my code I'm pretty sure.

12:29 technomancy: it wouldn't be a problem if Clojure actually exposed the thread pool and allowed you to restart it, but it's all hard-coded and yucky

12:31 Morgawr: hello... I started using clojure a few days ago and I decided to give leinigen a try... I created a new project and I can add functions and stuff to my core.clj file

12:31 however I want to have multiple files .clj

12:31 if I give them all the same namespace, I can't still find the functions loaded in the repl

12:31 how do I make lein recognize multiple different .clj files in my src folder?

12:32 nDuff: Morgawr: First -- your files should each have their own namespace.

12:32 Morgawr: ...the namespace names need to correlate to the filenames.

12:32 Schaefer: Morgawr - Each file should be in its own namespace. Also, the file name should match* the namespace. Are you familiar with java packages and class files?

12:32 nDuff: Morgawr: once that's done, you should be able to require or use them.

12:33 Schaefer: *match - as you're learning, stay away from special characters in namespaces like the dash "-"

12:33 Morgawr: Schaefer and nDuff ah okay... I get it, so I have this file called mytest.clj in my src/tests/ directory

12:33 I do (require 'tests.mytest) (I have the right namespace in the file)

12:33 and it still can't find the function I declared

12:33 * gfredericks uses dashes in his namespace names all the time

12:34 nDuff: Morgawr: so, require doesn't automatically bring references into the current namespace.

12:34 Morgawr: so, how are you trying to use it? If it's tests.mytest/myfunction, that should work.

12:34 Morgawr: oh.. okay, using that it worked :)

12:34 nDuff: Morgawr: ...likewise, if you want a shorter name, you can (require '[tests.mytest :as mytest]), and then it's just mytest/myfunction.

12:34 Morgawr: thanks, I was getting a bit confused by this :)

12:34 technomancy: Morgawr: might want to read `lein help tutorial`; it offers some pointers there

12:35 Schaefer: i'm having trouble with lein's injections and CCW. should i expect ":injections [(prn (into {} (System/getProperties)))" to print out the system properties with i start a CCW repl session?

12:35 technomancy: Schaefer: it'll put it to stdout; where that goes is CCW's business

12:35 Morgawr: technomancy: I read the tutorial, I was really confused because I couldn't find any reference to this specific case of having multiple files.. but yeah, might have been me

12:36 trying to do project euler stuff, having a namespace for each problem :)

12:36 technomancy: Morgawr: oh, it has a link to the 8th light article instead

12:36 bozhidar: technomancy: sorry to bother you, but I was wondering if you'll be able to spare some time to review the dozen of PRs for clojure-mode and give it some love :-)

12:37 muhoo: it's starting to get annoying that nrepl-eval-last-expression keeps trying to eval in the user namespace, not the namespace of the file

12:37 nrepl-set-ns does not fix it

12:38 but evaling the ns declaration in the file does.

12:38 Schaefer: technomany: i don't think the injections is getting evaluated at all. i have changed my project def to include ":injections [(use 'clojure.pprint)]" but when i try (pprint "test") on the repl, i get an unable to resolve symbol error

12:38 * nDuff looks at the channel topic, and... oh, this isn't the one with the "NO PROJECT EULER" rule. Maybe that's #python?

12:39 muhoo: nDuff: i thought it was here, actually. #python has the "NO LOL" rule

12:39 bozhidar: technomancy: In particular https://github.com/technomancy/clojure-mode/pull/128 fixes a small error I made when I converted clojure-mode to a derived mode and people living on the edge are getting a byte-compilation warning

12:39 Morgawr: is there a way to force lein to re-load a file? because I am editing a file and I am still in the repl

12:39 gfredericks: man returning from inside a ruby block has got to be the ultimate example of an impure "function"

12:39 bozhidar: muhoo: just use `C-c C-k`

12:40 muhoo: Morgawr: (require 'foo :reload) ?

12:40 Morgawr: muhoo: thanks!

12:40 bozhidar: muhoo: we're having some problems deciding on the behaviour of nrepl-eval-last-expression

12:40 muhoo: bozhidar: great, thanks, that worked

12:40 tomoj: b

12:47 muhoo: ok next... is there some way to force stencil to refresh its core.cache?

12:48 ah got it invalidate-cache-entry

12:54 hmm, i could swear i've seen a lein plugin somewhere that watches moustache templates and invalidates the cache entry if they get updated on disk

12:55 Morgawr: okay.. got another question for lein and repl.. I have a "(def mylist (range 1 20))" (just something, doesn't matter what it is), if I require the correct namespace inside my lein repl, why can't I do (mynamespace/mylist)? it says undefined reference

12:58 oh nevermind =_= I'm an idiot I was using the wrong namespace name sorry

13:14 tmciver: technomancy (or anyone else): how do I tell emacs to load the nrepl elisp I cloned from github rather than the version I had installed through package.el?

13:17 hyPiRion: tmciver: M-x package-list-packages, remove the nrepl you got there first

13:18 tmciver: bpr: Yeah, I can try that. I was hoping that it would load automatically as the current version of nrepl does.

13:18 hyPiRion: tmciver: Put it in your emacs.d/init.el file

13:19 tmciver: hyPiRion: I don't have that file. I wonder how nrepl gets loaded now.

13:23 bpr: tmciver: you can create it

13:23 technomancy: tmciver: if you're not planning on updating your git checkout often, M-x package-install-file is an easy way to do it

13:24 muhoo: don't get me started on the namespacing problems of nrepl.el; it's completely bonkers

13:24 muhoo: here's a workaround: (add-hook 'clojure-mode-hook (defun nrepl-fix-buffer-ns () (when (clojure-find-ns) (setq nrepl-buffer-ns (clojure-find-ns)))))

13:24 jonasen: Do I have to do something special when starting an nREPL server (programmatically) to redirect *out* to the response map? https://www.refheap.com/paste/8838

13:24 tmciver: technomancy: ah, that sounds like the solution I was looking for.

13:25 technomancy: do I have to re-run package-install-file each time I update it?

13:26 technomancy: tmciver: yeah, better to use load if you're updating frequently

13:26 tmciver: k

13:26 beffbernard: Is there such a thing as a reusable promise?

13:27 nDuff: beffbernard: What do you mean by that? You can re-deref them and get the same result more than once after they've done their work.

13:28 beffbernard: nDuff: I want to be able to set it more than once..

13:28 nDuff: my use case to hold a socket in that promise

13:28 and the socket can and does change

13:29 nDuff: beffbernard: I'm not sure that promises are the right abstraction for that, then.

13:29 tomoj: 'set a promise more than once' = 'break a promise'

13:29 beffbernard: I guess the semantics I want is to block if the resource is nil

13:29 nDuff: beffbernard: almost sounds more like you want an agent than a promise to me.

13:29 beffbernard: and have the convenience of deref

13:29 nDuff: beffbernard: ...if I'm understanding your use case correctly.

13:30 * nDuff is not at all certain of that understanding.

13:36 beffbernard: nDuff: doesn't quite fit my use case I think

13:37 yedi: how can i find the most recent version numbers for cljs

13:42 hyPiRion: Oh lord, my hair's on fire. I'm sad I can't use Leiningen for c projects.

13:52 muhoo: hmm, what's the difference between :injections and :init in lein?

13:52 technomancy: muhoo: :injections is composable; :init is kind of leftover from 1.x

13:52 muhoo: cool, thanks

13:54 gfredericks: is there any straightforward way to check if something is a promise?

13:54 probably good enough for me to use (instance? clojure.lang.IPending ...), but it's weird there doesn't seem to be anything else

13:56 muhoo: beffbernard: there was some stuff in lamina that looked like it could be used for that purpose

13:58 TimMc: gfredericks: When would you want to know that it's one type of IPending versus another?

13:58 bpr: beffbernard: maybe this is what you want: http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/

13:58 TimMc: Oh, do you also want to check for futures as well?

13:58 gfredericks: TimMc: IPending is fine for me; there might not be an actual use case

13:59 assuming that IPending is what it sounds like at least

13:59 unfortunately it has no docstring :)

13:59 heck, I'm not even sure it's not just an implementation detail

14:00 technomancy: when in doubt, it's an implementation detail

14:00 gfredericks: technomancy: okay then. How do I tell if something is a promise? :)

14:01 ,(instance? (type (promise)) (promise))

14:01 clojurebot: true

14:01 gfredericks: I guess that's bound to work

14:01 technomancy: I dunno; TBH you'd never really get anywhere in Clojure without relying on implementation details

14:02 gfredericks: whether or not something is an implementation detail is an implementation detail

14:02 technomancy: ...!

14:02 muhoo: meta

14:03 technomancy: yeah actually even the "keys and vals are guaranteed to use consistent ordering on the same instance" is somewhat apocryphal

14:03 gfredericks: "Legends of Clojure: implementation details you can count on"

14:04 technomancy: heh

14:04 technomancy: I smell a conj talk?

14:04 gfredericks: haha

14:04 technomancy: this talk will feature live documentation coding

14:05 technomancy: gfredericks: for extra living dangerously points: live attempts at using Jira

14:05 gfredericks: it's not an implementation detail if you can trick stuarthalloway into merging in your docstring patch

14:05 muhoo: clojure seems not nearly as implentation-detail-heavy as, say, android, which has a huge layer of folklore built on top of its otherwise good documentation

14:06 hyPiRion: Have anyone here programmed in C++? Then you'll know implementation details.

14:06 muhoo: good point

14:09 oh gawd, i just realized that after a decade of dealing with autotools. unix itself is pretty much one big implementation detail.

14:09 apt-get hides all that, but it's there.

14:09 * gfredericks makes a joke about apt-put

14:10 technomancy: I've started to notice these weird parallels between the monthly "everyone hates jira" threads on the clojure mailing list and the monthly "everyone hates bzr" threads on emacs-devel.

14:13 aaelony: a strange thing just started happening in lein-swank. I compile my ns, which returns nil, but then it is as if it didn't load in any of the require and import statements. For example, I'm importing java.io.BufferedWriter but it reports "Unable to resolve classname: BufferedWriter" If I do a lein repl outside of emacs, and run the same ns statement and run the functions, everything is fine. [lein-swank "1.4.5"] is in my

14:13 ~/.lein/profiles.clj under :user then under :plugins. Any ideas?

14:13 clojurebot: Gabh mo leithscéal?

14:15 mmitchell: anyone using nrepl and auto-complete in emacs? I keep getting this error when connecting: clojure.lang.Compiler\$CompilerException: java.lang.ClassNotFoundException: complete.core, compiling:(NO_SOURCE_PATH:1)

14:16 hyPiRion: mmitchell: I do

14:17 not sure if this helps, but I have https://github.com/hyPiRion/emacs.d/blob/master/hypirion-clj.el#L21-29 for setting up ac

14:18 muhoo: can :init-ns be used elsewhere except in :repl-options?

14:19 * gfredericks feels like he needs a new concurrency construct

14:19 amalloy: technomancy: phases of the moon, perhaps?

14:19 muhoo: i don't want to define :repl-options in the project and have it clobber what's in profiles.clj

14:20 keep getting burned by non-recursive merges in lein

14:21 * muhoo goes to read PROFILES.md again a few more times

14:22 mmitchell: hyPiRion: thanks! unfortunately i'm still getting that error hmm

14:23 i don't even know where to get "complete.core" ?

14:23 muhoo: oh cool. it merges them. yay lein pprint

14:25 gfredericks: so future is guaranteed to inherit dynamic var values right? No ambiguity there?

14:25 muhoo: mmitchell: https://github.com/ninjudd/clojure-complete ?

14:25 gfredericks: s/ambiguity/edge-cases/

14:29 muhoo: hmm, nrepl doesn't seem to honor :init-ns

14:29 always get user

14:30 thrashy thrashy bang bang

14:30 technomancy: :init-ns might be specific to reply

14:30 * muhoo carries on beating stuff with a hammer

14:31 technomancy: cemerick might know if there's a way to set that stuff on the server side

14:32 muhoo: wait, i'm totally confused now. sample.project.clj says that :injections gets evaled on every form, but then it implies elsewhere it gets evaled on every repl

14:33 "Forms to prepend to every form that is evaluated inside your project."

14:33 technomancy: oh, that should be "every eval-in-project invocation" instead

14:33 amalloy: muhoo: from lein's point of view, the repl is one form

14:33 (in-the-project (run-a-repl))

14:33 muhoo: ah, cool. confusing way to put it tho

14:33 technomancy: what amalloy said, but that's an implementation detail that the docs shouldn't assume

14:35 muhoo: maybe i should take a step back. here's what i'm trying to do:

14:35 1) set the namespace for every new repl to go into (hmm. maybe :injections might work for that)

14:35 2) set some code to run on every repl invocation

14:36 technomancy: 1) would need to be handled by nrepl; I'm not sure how it's done

14:36 muhoo: 3) have some form to evaluate in-project whenever the project loads, not on every repl, i.e. (myns.server/-main)

14:36 technomancy: if 2 means on every `lein repl` invocation then :injections inside the :repl profile should do it

14:37 and 3 should work as :injections in the base project map

14:37 muhoo: ok, so two different injections, get evaled at different times?

14:37 depending on where they are in the map?

14:38 by 2) i mean every time i connect to the repl over :repl-port

14:38 via nrepl

14:38 gfredericks: so I'm about to write some code that manages running async jobs (via future), particularly giving functionality to wait for all jobs directly or indirectly started from this thread to be done

14:39 am I reimplementing something that already exists in clojure/jvm?

14:39 was just going to wrap future with code that registers the job and notes when it's done, and use a dynamic var to track what thread it originated in

14:39 technomancy: muhoo: oh, ok that's different then for 2

14:39 that would be an nrepl question rather than leiningen; unfortunately I'm not familiar

14:40 muhoo: fair enough, thanks

14:40 jeremyheiler: gfredericks, there is java.util.concurrent.CyclicBarrier

14:41 technomancy: muhoo: I agree that we should document though

14:41 just haven't figured it out yet

14:41 muhoo: technomancy: the bummer is though, i thought i was told never to shadow the :repl profile in the project.clj

14:41 because it clobbers it

14:41 but i'll try base project map, that may do it

14:41 technomancy: muhoo: yeah, I think hyPiRion fixed that

14:42 muhoo: oh cool

14:42 technomancy: because you're right that it's confusing

14:43 amalloy: (doto (f x) (-> (->> (g y)) (h z))) ;; i love arrows and doto, but i really can't bear to put this in my program

14:44 hyPiRion: muhoo: https://github.com/technomancy/leiningen/issues/520

14:44 muhoo: technomancy: sorry, i've got more dumb :injections questions

14:44 why would :injections be exploding with "Unable to resolve symbol: do" ?

14:45 technomancy: muhoo: that's strange... is it being syntax-quoted?

14:45 muhoo: i'm trying :injections (do (require 'myns.server) (myns.server/-main))

14:45 ah i see, it wants a vector

14:46 technomancy: oh, yeah you need that in order to combine injections from multiple profiles

14:46 gfredericks: jeremyheiler: that sounds like an interesting google, thanks

14:46 technomancy: muhoo: we should probably put a warning on non-vectors there; feel free to open an issue

14:47 Schaefer: hi. i'm having trouble using cemerick's piggieback + clojurescript with CCW. i get "Can't change/establish root binding of: *cljs-repl-options* with set" .

14:48 amalloy: make sure it's as helpful as the error message for (defn foo (vector bar baz)), technomancy

14:48 technomancy: amalloy: necessarily

14:48 amalloy: for the lazy: "Parameter declaration vector should be a vector"

14:49 muhoo: well in my case, "RTFM" would have been a sufficiently useful error message

14:50 technomancy: it's not as clear as it should be

14:50 muhoo: ah, yay, it works. all is bliss.

14:51 technomancy: just need to stalk cemerick to get those nrepl tips from him

14:52 Schaefer: thanks. do you happen to know if CCW using lein to start the repl? i can't figure out if it honors :repl-options in the project definition

14:54 ah... i bet i know the problem: the current release of CCW fails on some dependency. i thought i had a workaround but possibly not

14:57 gfredericks: that unified update model is quite slick.

15:00 craigbro: ccw?

15:00 clojurebot: ccw is http://github.com/laurentpetit/ccw

15:01 amalloy: (inc clojurebot)

15:01 lazybot: ⇒ 15

15:01 craigbro: ah, eclipse

15:02 amalloy: gfredericks: yeah, it's great. it's also the only time i can call a single function with seven or eight arguments and not feel filthy

15:02 mmitchell: muhoo: hey thanks, i'll check that out

15:02 frozenlock: Any advice on how to handle states in cljs? (Libraries or best practice) I've just begun to deal with them and I'm pretty sure I'm digging myself in a hole :/

15:03 mmitchell: muhoo: do you know how i use that?

15:03 gfredericks: amalloy: yeah that's what sparked the thought :)

15:03 mmitchell: muhoo: the clojure-complete lib w/emacs and auto-complete?

15:03 amalloy: gfredericks: the only thing i don't like is that if i write something like (apply swap! x vary-meta update-in :logs concat) i lose track of the fact that i'm applying by the time i get to concat

15:03 gfredericks: it kind of makes me want a (map coll func & args)

15:04 therealadam: what is the go-to http client for clojure?

15:04 gfredericks: clj-http

15:04 mmitchell: muhoo: oh i see

15:05 muhoo: mmitchell: last i checked, if you have nrepl and lein installed and working, autocomplete just works

15:05 muhoo: which isn't to say i have either, so i'm still M-/ 'ing by habit

15:05 amalloy: states like: california, a state machine, or mutable state throughout your application?

15:06 therealadam: gfredericks: is https://github.com/mmcgrana/clj-http still the canonical repo?

15:06 derp, n/m

15:06 mmitchell: muhoo: ok good to know. I'll remove a bunch of my emacs config and see what happens

15:07 gfredericks: curious if anybody thinks this is terrible or knows an easier way: https://www.refheap.com/paste/8840

15:07 borkdude: Does anyone using org-mode to write the answer to this one? http://stackoverflow.com/questions/14446157/writing-a-document-in-org-mode-is-it-possible-to-refer-to-a-code-fragment

15:08 amalloy: gfredericks: line 14 is crying out for fnil

15:08 gfredericks: I've never once thought to use fnil

15:08 you have to admit though that fnil technically creates a set that might not get used :P

15:08 frozenlock: amalloy: If your question was for me, it's mutable states.

15:08 gfredericks: but yeah it's a lot more readable

15:08 amalloy: and `wait` has a race condition that leads to deadlock

15:09 i recommend using useful.state/wait-until, which doesn's

15:11 gfredericks: (let [conj (fnil conj #{})] (defn run-job ...)) ;; now the set is only made once, you whiner

15:13 gfredericks: amalloy: oh I misunderstood how to use fnil there then

15:13 amalloy: well, i wasn't suggesting you actually do that. but if creating a set that might not get used bothers you, you can do this instead

15:13 gfredericks: I imagined a #{job-id} getting created but you're right

15:13 amalloy: amn't figuring out what the race condition is

15:14 amalloy: hmmmm, there might not actually be one because the keys in the map are thread ids

15:15 but i think there is. line 27 runs, sees there's still a job waiting. so it creates a promise, then gets interrupted. some other thread finishes the last job, and updates the atom. now the first thread adds a watcher and blocks on it, but nobody ever updates the job list again

15:16 gfredericks: ah right

15:16 so another check before line 34 would do it?

15:17 amalloy: gfredericks: yes. that's basically what i do at https://github.com/flatland/useful/blob/develop/src/flatland/useful/state.clj#L54

15:17 gfredericks: I was reading that

15:17 owengalenjones: can anyone explain why ( or point me in the direction of explanations why ) recur in this situation hangs the repl: http://d.pr/n/fOGk

15:17 amalloy: owengalenjones: recur points at your lambda, not at tree?

15:18 owengalenjones: amalloy: is there a way to have it escape the scope?

15:18 amalloy: no

15:18 owengalenjones: so in this situation you would always have to specify the parent fn

15:18 TimMc: gfredericks: So run-job fires off a job, and wait "joins" on all the jobs?

15:18 amalloy: recur doesn't consume stack space; there is no way to write what you want without stack space (ignoring CPS)

15:19 thus, you can't use recur

15:19 owengalenjones: ok thanks

15:22 TimMc: gfredericks: It would be nice if this code were commented with descriptions of e.g. what the atom is supposed to contain, what invariants you expect to hold...

15:23 gfredericks: TimMc: yes and yes

15:23 well

15:23 wait joins on all jobs that originated from the current thread

15:23 TimMc: Mmm, I see.

15:24 gfredericks: come to think of it I don't actually have a use case for ignoring things from other threads

15:24 but just in case I even do... :)

15:24 s/even/ever/

15:26 TimMc: Is the following correct? #'jobs is an atom containing maps of thread IDs to sets of IDs of jobs that may or may not have started yet, but definitely have not finished.

15:26 Sgeo: #'jobs is (var jobs) which is a var

15:27 TimMc: Yes, it's a var of an atom of a map of...

15:27 I don't know why she swallowed the fly... I guess she'll die!

15:28 amalloy: TimMc: i think it's just as accurate to say the jobs have definitely started as to say they have definitely not finished. the process is like: (1) add to set; (2) run job; (3) remove from set. so there's space on either side of (2)

15:29 nDuff: Damn -- using Clojure gets me spoiled on having its features available.

15:29 * nDuff is doing Python right now, and really regretting not having thread-local var bindings. (Yes, it'd be easy to port, and I'm likely to do that)

15:32 TimMc: gfredericks, amalloy: I *think* that if the when-not empty? is moved to just be around the deref, then it's all good.

15:32 However, I'm not entirely sure what the thread safety of watchers is.

15:33 amalloy: TimMc: sure. as i note in the comments of useful/wait-until, which i linked to, the first deref is only a performance optimization

15:34 TimMc: Haha, you're using the promise itself as the watch-key? Pretty non-obvious.

15:36 amalloy: TimMc: what else would you use?

15:36 TimMc: A gensym, as gfredericks did.

15:36 amalloy: feh

15:36 TimMc: I don't see anythign wrong with using the promise, I just would have made that choice more explicit.

15:37 I also don't like the idea that the promise is escaping that scope.

15:37 Seems dangerous.

15:38 amalloy: your first objection seems reasonable enough, but i don't understand what you mean by escaping that scope

15:39 TimMc: It's ending up in a watcher.

15:39 Who watches the watchers?

15:40 amalloy: it has to end up in the watcher, or else the watcher couldn't deliver to it?

15:40 you're objecting to it being a key in the map as somehow more dangerous than being closed over by a funciton that's a value in that same map?

15:41 TimMc: In gfredericks' version, the watcher holds a closure over the local scope, but someone outside that scope can't actually touch the promise.

15:41 amalloy: okay, fair enough

15:42 TimMc: I can't build a solid case for how that might make a program go pear-shaped, but I have this general sense that something might try to str-ify the promise somehow.

15:42 (I don't worry that somthing would deliver to it.)

15:43 muhoo: wow, that's just bizarre. lein trampline :repl works on machine 1, but on machine 2, it gives a bizarre jboss error that 8080 is already in use, and doesn't actually start the nrepl listen port

15:43 amalloy: i'm not really worried about that. not least because, in order to get a list of all watchers on a ref, you have to use undocumented interop methods

15:43 muhoo: same profiles.clj, same version of lein. different versions of java though

15:46 Sgeo: o.O fogus is now into Racket

15:46 ....What's the name of that effect where you learn a word and now everyone is using it?

15:46 Sgeo: I feel like I play with a programming language and then a little while later I see others playing with it

15:46 TimMc, I think so

15:50 wink: Sgeo: but, most importantly: did you use Racket... before it was cool? :P

15:51 Sgeo: I wish there was a language with Racket as the language and something Smalltalk-like as the environment

15:51 I like Racket for the language (mostly) and Smalltalk for the IDE

15:53 wink: as I've never written any for-money production code in all those languages I find so cool.. I still can't say whether I find them practical or just nice :(

15:53 gfredericks: has anybody seen korma apply a transform function to a whole result set rather than one row at a time?

15:54 dnolen: wink: plenty of people have put Clojure code into for-money production

15:54 wink: dnolen: that's not at all what I was hinting at :P

15:54 * gfredericks is putting clojure code into for-money production

15:54 AimHere: Don't you find Clojure cool?

15:55 * AimHere shines the desk lamp in wink's face.

15:55 wink: dnolen: for example I see no way in hell to even try to write any clojure code without quitting my day job

15:55 much less anything like CL or Racket

15:55 dnolen: wink: sorry I missed some backlog context

15:55 "sorry if" I mean

15:56 wink: dnolen: didn't say much before :P it was just about using/hearing about Racket

15:57 dnolen: wink: I see, doesn't Naughty Dog use Racket for all their game scripting (I get your point about the day job)

15:58 wink: dnolen: yeah, think so

15:59 maybe I need a "just get shit done" job instead of a "write maintainable code" one :P

16:00 CrawfordComeaux: I'm trying to debug https://github.com/nathanmarz/storm-deploy, but I've never used clojure before (though slightly familiar with lisps). I'm reading that I can drop a repl in where the exception's coming up, but I'm not sure how to do that

16:01 gfredericks: amalloy: TimMc: thx for comments

16:03 wink: CrawfordComeaux: least specific way would be to \$ lein repl and start your boilerplate code by hand

16:03 CrawfordComeaux: wink: not even sure what the boilerplate code would be...any other things I could try?

16:06 wink: CrawfordComeaux: https://github.com/nathanmarz/storm-deploy/blob/master/src/clj/backtype/storm/provision.clj is zthe enty point

16:07 afaict ;)

16:07 CrawfordComeaux: so load up the repl & c/p lines from the source?

16:08 amalloy: CrawfordComeaux: nobody can help with "X doesn't work", for any X. at least a description of what's going wrong is necessary, and ideally a stacktrace and/or what you're doing that causes a problem

16:08 CrawfordComeaux: amalloy: this was an attempt to get a stack trace

16:08 but the bug's already been id'd....

16:08 it's me :P

16:09 wrong argument when executing a command

16:16 seangrove: Hrm, really struggling here - it seems like clojurescript is affecting the javascript runtime globals

16:17 Without my script, rapportive loads fine and does its thing. As soon as my script is injected into the page, rapportive falls apart - even if it's a delayed injection

16:18 * gfredericks shakes fist at korma

16:20 TimMc: technomancy: Where did "locative1" come from as an example password?

16:21 dnolen: seangrove: sounds like a bad bug, we try to avoid messing with native prototypes (there are a couple of remaining cases), but I'm not aware of any global clobbering.

16:22 seangrove: would be helpful if you could isolate.

16:22 seangrove: dnolen: Really struggling to isolate it. Will continue to try

16:22 dnolen: seangrove: the one place where much with native prototypes is String, we add an apply method.

16:22 "where we muck"

16:23 devn: ls

16:23 lazybot: boot etc lost+found mnt opt proc root sbin srv swap sys tmp usr var

16:23 * devn facepalms

16:23 arrdem: rm -r /

16:23 Bronsa: i laughed pretty hard

16:24 seangrove: Hrm, wonder if that could be it. Rapportive calls .apply on objects for type-checking to see if they're objects, functions, strings, etc.

16:24 dnolen: seangrove: yes that propably is, but checking JS types that way sounds awful :P

16:24 amalloy: muahaha. lazybot strikes again

16:25 arrdem: ,({:foo :bar} :foo)

16:25 clojurebot: :bar

16:25 dnolen: seangrove: there is an open ticket for the String issue

16:25 seangrove: Yeah, looks like it's going to mistakenly think that strings are objects... not sure if that's the root cause or not though

16:25 dnolen: Yeah, awful, but I have to find a way to be compatible with it, which is a bummer

16:26 dnolen: seangrove: http://dev.clojure.org/jira/browse/CLJS-381

16:26 seangrove: Any other changes to prototypes like that?

16:26 dnolen: seangrove: nope

16:26 seangrove: definitely useful for knowing where to look next

16:27 dnolen: seangrove: it's there to support keyword invokes. The ticket outlines the temporary solution. Real keywrods & symbols is the proper fix.

16:27 seangrove: hrm, is there someway I can hijack that extremely early on, e.g. (set! (.-apply js/String) nil), to test out if that's the cause

16:28 dnolen: seangrove: I don't see why not, you can probably do that before you load rapportive

16:28 seangrove: Alright, let me give it a try...

16:30 gfredericks: underscore had a type-check that got broken by cljs, but they took a patch to allow for it

16:30 (wrt the string prototype)

16:33 dnolen: gfredericks: that was nice of them

16:33 gfredericks: it was nice of them.

16:33 I think there was some alternate argument for why it was a good idea as well

16:33 but I was only interested in cljs compat

16:34 dnolen: gfredericks: checking for apply is a horrible idea in general yes

16:35 gfredericks: in case anybody is curious: https://github.com/documentcloud/underscore/commit/2206092e25f66f3a0dbb05c24509a7831b1863fe

16:36 dnolen: gfredericks: oh yeah, checking for call is a terrible idea too

16:36 gfredericks: nice patch!

16:38 arrdem: can I (:require :only :as)?

16:38 gfredericks: s/:only/:refer/, yes

16:39 arrdem: my favorite is (:require [jayq.core :refer [\$] :as \$])

16:40 * arrdem has no idea what that would do and returns to porting clisp to clojure

16:40 seangrove: Rapportive has: _.isFunction = function(obj) { return !!(obj && obj.constructor && obj.call && obj.apply); }

16:40 dnolen: seangrove: I looked a bit closer at what would be involved in a quick fix - I don't see one.

16:41 seangrove: yes that's completely broken

16:41 seangrove: uhg

16:41 dnolen: seangrove: should (typeof obj == "function")

16:41 should be

16:41 seangrove: not much we can do CLJS side

16:42 seangrove: well .. actually we can, but somebody needs to do the Symbol & Keyword work.

16:42 seangrove: dnolen: Other than not touching String ;)

16:42 dnolen: not a particularly small project

16:42 seangrove: no can do w/o breaking every CLJS project.

16:42 seangrove: Yeah, let me see if this is the root cause first though

16:43 arrdem: gfredericks: isn't that eqivalent to (:use [ ... :only [\$]])?

16:43 dnolen: seangrove: but really you should also file a bug w/ them.

16:43 gfredericks: arrdem: probably; :use is quasi-deprecated to :require

16:43 dnolen: switching symbol/keyword to a deftype breaks old projects?

16:43 dnolen: seangrove: or overwrite _.isFunction if you can.

16:44 gfredericks: I guess it means changing how IFn works too?

16:44 dnolen: gfredericks: no it wouldn't break old projects

16:44 seangrove: dnolen: It's inside of an anonymous function

16:44 dnolen: gfredericks: sorry to confuse - I just meant we can't just stop monkeypatching String. If we're going to fix it we need real Keywords & Symbols

16:44 seangrove: Interop between apps in js is unbelievably bad

16:45 gfredericks: dnolen: oh gotcha

16:45 dnolen: seangrove: seriously that implementation of _.isFunction makes no sense.

16:46 seangrove: the whole thing should be replaced w/ typeof check

16:46 seangrove: dnolen: Yeah, but it is what it is. I'll email them and ask about their reasoning, but they're crazy slow to get back, so I always try to find a way to do it without going through them

16:46 technomancy: TimMc: the username in that example is Milgrim from https://en.wikipedia.org/wiki/Spook_Country, a book partly about locative art

16:47 who works for Blue Ant and https://en.wikipedia.org/wiki/Hubertus_Bigend

16:48 seangrove: I guess it's a bit more complicated. JS sucks.

16:48 technomancy: "he wears a suit in the color International Klein Blue which he likes because it is a color that cannot be represented on most computer monitors."

16:49 seangrove: dnolen: Yeah, I've come to rely on goog.isObject/Function/String/etc.

16:50 daviddpark: In a leiningen project, is it necessary to add some dependency for java libraries? I am getting "Unable to resolve classname: Properties" error when I attempt to run a repl with code: (ns myproj.core (:import (java.util Properties)))

16:52 amalloy: daviddpark: no, anything in the java core is already on the classpath

16:52 probably you're running your repl in the user namespace, and so the myproj.core namespace clause doesn't matter

16:53 dnolen: seangrove: it boggles the mind how there can be so much variance in typeof behavior across JS implementations

16:53 but perhaps it's not well defined in the spec ...

16:55 seangrove: dnolen: Yeah, it reminds me of this post, which is pretty upsetting http://www.futurealoof.com/posts/balance.html

16:55 gfredericks: I was about to start hacking on keywords/symbols until I remembered the concern about memory leaks

16:55 seangrove: "There is a balance to be found between correctness and accessibility and node.js seems to be finding it. Living with JavaScript, and all its faults, seems to have built an understanding in the community that nothing will ever be perfect. By embracing the warts of the language and of various operating systems node.js lives in a harsh reality"

16:55 gfredericks: I don't remember if there was an alternative approach to interning everything

16:56 daviddpark: amalloy: I am attempting to interact with system properties, and so need to import java.util.Properties in my leiningen project. The import statement is in the ns declaration since it is in myproj/core.clj

16:56 brehaut: gfredericks: i *think* that keyword interning now uses weak refs to avoid a space leak

16:56 gfredericks: brehaut: yes this is wrt cljs where I don't expect weak refs exist

16:56 brehaut: gfredericks: ah. my bad.

16:57 gfredericks: would punting on interning work, just having a separate copy like how it works now with strings? As long as hash and eq are defined correctly it'll still work?

16:58 I would think you could even intern the ones in the source code if that gives any advantages

16:58 therealadam: I'm trying to wrap my head around ->; it seems like (-> 1 inc #(inc %)) should give me 2 but it bonks trying to cast a symbol

16:59 seangrove: Yeah, appending: delete String.prototype.apply to the compiled cljs brings rapportive back to life

16:59 amalloy: ,'(-> 1 inc #(inc %))

16:59 seangrove: Wow that was a long and crazy snipe hunt

16:59 brehaut: gfredericks: i think weakmaps are coming as part of 'Harmony', and mozilla might have an imp?

16:59 clojurebot: (-> 1 inc (fn* [p1__27#] (inc p1__27#)))

16:59 brehaut: gfredericks: aha https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/WeakMap

16:59 dnolen: seangrove: good to know, I've been wanting to remove that wart from CLJS for a long time - but haven't had time for that particular mid-sized project.

17:00 amalloy: &(clojure.walk/macroexpand-all '(-> 1 inc #(inc %)))

17:00 lazybot: ⇒ (fn* (inc 1) [p1__26306#] (inc p1__26306#))

17:00 seangrove: dnolen: Well, you have a lot on your plate

17:00 Would love to see source maps too

17:00 seangrove: I think that ticket is probably above my skill level for now though, or I'd go after it

17:00 dnolen: seangrove: I'm suprised that fixed it, don't you need to replace .call too?

17:00 therealadam: amalloy: no :( I looked at the macroexpanded version earlier and don't see an obvious problem

17:01 dnolen: seangrove: oh right, their _.isFunction checks call & apply

17:01 amalloy: (fn (inc 1) [x] (inc x)) doesn't look at all wrong to you?

17:01 therealadam: the arglist is out of place?

17:01 amalloy: there's an (inc 1) in a totally nonsense place

17:02 amalloy: i think you're imagining that -> is function composition

17:02 but it's not; it's a macro that rewrites your forms at the source-code level

17:02 amalloy: because of which, putting a lambda in generally results in nonsense

17:02 seangrove: dnolen: There's another call that checks for .call, so deleting that causing Rapportive to be fully healthy again

17:02 Obviously kills my app though

17:03 * seangrove sighs

17:03 bbloom: dnolen: i'll be in town next week, we should get together and try to get the keywords/symbols stuff working. i have an old branch we can use as a guide, but i'd appreciate your expertise in optimizing it

17:03 seangrove: I think we'll just have to cancel rapportive compatibility with this new release, I don't see much else we can do

17:04 therealadam: amalloy: so `comp` is for replacing f(g(x)) and `->` is for replacing a(b(c())) ?

17:04 amalloy: -> is best for functions that take multiple arguments

17:05 (-> x (conj 10) (disj 20))

18:46 bbloom: dnolen: well haskell relies on it's type system to eliminate all the thunks, so i don't see why it wouldn't be possible to make it perform comparably on something like v8

18:47 i dunno what (if any) runtime optimizations modern haskell implementations do

18:51 dnolen: bbloom: yes I don't see why it couldn't be done, but I would like to see it :) Fay is going down that path but as far as I can tell doesn't do much thunk elimination yet.

18:53 bbloom: dnolen: the more i experiment with factjor, the more i believe that the haskell approach to isolating side effects (monadic style) is a neat trick but an evolutionary dead end

18:53 dnolen: it makes much more sense to me to figure out how to compose strict and impure programs and use functional abstractions to generate those programs for evaluation

18:54 there are types of stateful operations that have properties that are similar to pure functions.... idempotent operations, for example

18:55 dnolen: bbloom: that maybe, don't have any opinions yet - just started really digging into Haskell a few days ago. It's fun.

18:57 bbloom: agreed, the file reloading is a necessity because 'def is really a side effect

18:57 dnolen: it's also funny that people complain about Clojure errors, Haskell type errors are pretty cryptic for a beginner as well.

18:57 ibdknox: dnolen: few people will ever make it to haskell :p

18:57 bbloom: dnolen: i think that the ppl complaining about clojure errors are mostly people coming from ruby/javascript/java/python

18:57 ibdknox: in terms of the language funnel

18:57 technomancy: ocaml compilation errors are pretty good except for the fact that they're translated from french

18:57 dnolen: technomancy: ha!

18:58 bbloom: technomancy: lol

18:58 ohpauleez: hahaha

18:59 ibdknox: ohpauleez: does your cljs impl of pprint exist somewhere?

18:59 dnolen: ohpauleez: yeah, what's story w/ that ;)

19:00 bbloom: ibdknox: i just grepped my fipp project for '\(\.' and got no hits... soo it should be trivial to run on cljs

19:00 :-)

19:01 ohpauleez: dnolen: ibdknox: I was just walking through it with brenton ashworth a couple weeks ago

19:01 I would go with bbloom's fipp if it fits the bill

19:01 ibdknox: bbloom: oh? I thought I looked at it when you mentioned and there were some classy things in there

19:01 if not

19:01 /win

19:02 ohpauleez: my port was only for the absolutely necessary parts to make the cl-format work

19:02 bbloom: ibdknox: do you need code-dispatch too? or just simple-dispatch (edn)?

19:02 ohpauleez: I went back and started porting the rest

19:02 ibdknox: bbloom: edn is sufficient for now

19:02 ohpauleez: but it's essentially like porting CL to Clojure

19:02 ibdknox: ohpauleez: lol yeah, not so much fun

19:03 ohpauleez: yeah, so I was re-writing parts of it - fipp is pretty close to what I was coming up with

19:03 I kept some of the CL stuff

19:03 bbloom: ibdknox: the only "classy" things in there are in edn.clj which refers to the types from clojure.lang

19:03 you can probably just rename clj to cljs and then rename those 5 or 6 class entries and it would work

19:03 should take 5 minutes & if it takes any longer, let me know & i can tweak it

19:03 ohpauleez: I'd be more than happy to give people the cl-format piece, but it's probably not what most people want

19:04 ibdknox: bbloom: awesome. I'll let you know

19:04 ohpauleez: ibdknox: Yeah, not fun at all haha

19:04 technomancy: pretty sure cl-format only got into clojure because pprint needed it

19:04 like clojure.walk

19:04 bbloom: i'm probably not going to do code-dispatch until i decide on some way to do something stylesheet-like

19:04 ibdknox: I <3 clojure.walk

19:04 bbloom: i want it to be trivial for people to supply indentation rules and the like for their libraries

19:05 ibdknox: bbloom: that's also something I would be really interested in at some point :)

19:05 anyone going to ICSE?

19:05 bbloom: ibdknox: i'll get to it eventually, it's very low priority now. all i needed was the damn pretty printer to be much much faster for some local diff tests that i'm doing :-)

19:06 ibdknox: I actually think that'd be useful at the community level

19:06 technomancy: ISTR clojure.walk has been disowned by its author?

19:06 ibdknox: it's one thing I thought they did very nicely for Go

19:06 bbloom: i also want to pretty print other stuff, like CSS or whatever

19:06 technomancy: not that it's bad from a user perspective; just the implementation

19:07 bbloom: and i'd also like colored output and other niceties

19:07 ohpauleez: technomancy: Yeah, those libs are pretty terrible, even for CL-style code

19:07 bbloom: but all that stuff is queued up behind real work ;-)

19:07 ibdknox: lein format would be nice :)

19:08 damn priorities ;)

19:08 bbloom: ibdknox: yeah it would :-)

19:08 technomancy: bbloom: wait, does yours work in a comment-preserving fashion?

19:08 I thought only sjacket did that?

19:09 bbloom: technomancy: i don't have a parser of any kind

19:09 technomancy: that's another reason i haven't done code-dispatch

19:10 bbloom: i want to be able to re-use the formatting rules for data-structures->pretty-printed as well as string-or-file->ast->pretty-printed

19:11 i need some time to think about how to do stylesheets. it needs to 1) be data 2) be easy to create new styles 3) compose cleanly 4) perform well during printing

19:14 ibdknox: what are your pretty printing needs for LT?

19:14 ibdknox: CLJS results right now :)

19:15 bbloom: ibdknox: ie repl results?

19:15 ohpauleez: ibdknox: Strict edn?

19:15 pbostrom: does anyone run lein on an amazon ec2 micro instance? it seems like it takes up to 10-15 minutes to start up, but ec2 small instances run fine, I'm wondering if there's something I need to tweak, I've tried a few -Xmx and -Xms opts in vain

19:15 ibdknox: ohpauleez: it may contain non-printable things that could be [object object] or whatnot, but yeah more or less

19:15 bbloom: more or less, yes

19:16 bbloom: ibdknox: so i assume you need controls like depth, item limits, etc ? fipp doesnt do that yet

19:18 ibdknox: bbloom: at some point those things would be nice, but there are other ways for me to deal with that in the mean time :)

19:18 meantime*

19:19 bbloom: ibdknox: heh, mental image of an angry clock

19:19 ibdknox: haha

19:20 bbloom: ibdknox: both of those things should be relatively easy to add, but again, i was waiting until i thought about stylesheets b/c i want those things to be stylable

19:20 ibdknox: ie argument lists are vectors, but they should never be elided if you set the list print limit to 6 or whatever

19:20 ibdknox: makes sense

19:21 bbloom: ibdknox: we probably have a lot of stuff in common... i think it's possible that I'm gonna be building the Blend to complement your Visual Studio, heh

19:22 lots of *needs* in common, in terms of components, that is

19:22 ibdknox: yeah probably :)

19:23 seangrove: bbloom: What're you building?

19:23 * bbloom winks

19:24 cheezey: all right guys

19:24 oops wrong channel

19:37 seangrove: bbloom: Well, I suppose I'll see it when I see it then :)

19:40 bbloom: interestingly, angular does a fair amount metaprogramming to achieve optimal performance. There are places where they call Function(...) with a string of code

19:55 seangrove: bbloom: Are you using angular from cljs?

19:56 bbloom: seangrove: no, i'm just studying it

19:56 i've used it from coffeescript

19:57 seangrove: Yeah, I've heard good things about it, but haven't thought much about how it would fit in the cljs world

19:58 I hate debugging javascript in firefox, it's such a bad experience: http://dl.dropbox.com/u/412963/Screenshots/a-.png

20:01 SegFaultAX: seangrove: In fairness, javascript can be painful to debug in general. :)

20:01 seangrove: SegFaultAX: True, and this is with the caveat that I've sworn off IE as a target at all for now

20:02 So I suppose it gets worse

20:02 SegFaultAX: I find the browser that gives me the most trouble is usually opera.

20:03 I think it's because they are more "standards-nazis" than the other vendors.

20:03 Although I definitely don't do a lot of javascript development day-to-day, so that could just be my suckiness.

20:05 bbloom: callbacks are the real source of hard to track bugs

20:06 kovas: I'm getting into angular these days

20:06 my theory re: cljs is

20:06 that its all about defining the directives, rather than the controllers

20:07 defining the directives using js is a pretty shitty experience

20:07 but we can do a lot better

20:11 bbloom: kovas: you gonna be at clojure/west ? we can talk about what "better" looks like

20:11 kovas: bbloom: yup will be there

20:11 bbloom: my immediate concept of better is: macros

20:12 bbloom: that eliminate the 100 ways to shoot yourself in the foot

20:12 bbloom: heh

20:12 kovas: bbloom: have you seen the angular videos

20:12 bbloom: i'm thinking bigger :-)

20:12 no, which videos?

20:12 kovas: bbloom: its basically one example of a gotcha after another

20:12 kovas: one sec

20:13 i mean, i give them a ton of credit for understanding the problems

20:13 bbloom: kovas: sheesh, long videos :-P but definitely a topic i'm interesting in, so i'll probably get around to watching them at some point

20:13 kovas: but making JS do the things they want is a feat

20:13 yeah

20:14 bbloom: in terms of doing better, they are an enumeration of the flaws

20:14 bigger is better

20:14 but its hard to see the bigger picture when bogged down in all the incidental complexity

20:15 bbloom: kovas: in your opinion, what are the primary sources of incidental complexity?

20:15 at the directive level, that is

20:16 kovas: bbloom: the way scope is set up is kindof a mess

20:16 bbloom: since they can't introduce a higher level language construct

20:16 SegFaultAX: So is Backbone.js dead?

20:16 (And did Angular kill it?)

20:16 bbloom: SegFaultAX: it's not dead, it's just a simpler tool for smaller problems

20:17 SegFaultAX: backbone is great for a few rich components on top of a REST API

20:17 SegFaultAX: but it always has been woefully inadequate for large apps

20:17 talios: brehaut: nice blog post :) one thought tho - an HttpRequest and DatabaseRecord are still types, mostly modelled as maps with extras, so you can still do static typing there - maybe not CustomerRecord tho

20:18 kovas: being able to define your own tags always seemed like the missing thing to me

20:18 bbloom: kovas: i agree that the scopes are complex. i think it's mainly an attempt to preserve the javascript mutable getter/setter experience for working with models

20:18 kovas: which is more pleasant than the model.get('prop') approach

20:19 kovas: bbloom: i think conceptually they are doing the right thing, its just the expression of the concept that is a disaster

20:19 bbloom: kovas: i wouldn't call it a disaster

20:19 kovas: watch the videos :)

20:19 bbloom: i will :-)

20:19 brehaut: talios: thanks. the bit i glossed over is that if your code is marshalling from HttpRequest to DatabaseRecord with only a tiny bit of logic in the middle (ie from roughly two different Universal types), theres boiler plate you gain is traded off against everything else

20:19 bbloom: kovas: my goal is to have the "scope hierarchy" be a single immutable data structure and that it's accessed via update-in or assoc-in etc

20:19 kovas: I'm gonna watch them again and take notes. theres about 10-15 wacky things

20:20 bbloom: so you bind to paths

20:20 i think it will enable pretty fast dirty checking too, since we have fast equality for our data structures

20:20 talios: brehaut: true, but if you're mapping directly from request->database query, are you not also walking into a Ruby On Rails style security f**k up? ( potentially )

20:20 kovas: bbloom: that would be pretty cool. i spent a lot of time last summer trying to do something similar but couldn't figure it out

20:21 bbloom: kovas: it's a really hard problem, but i have some cool stuff actually working

20:21 kovas: bbloom: awesome

20:21 bbloom: kovas: i feel like i wouldn't have been able to pull it off if i didn't have the very particular (and very unlikely) collection of past professional experiences :-P

20:22 kovas: bbloom: is it the times that make the man, or the man that makes the times

20:22 brehaut: talios: i dont disagree that there is potential for bugs. i would however be leary of any system that pushes all security concerns to the type system

20:23 kovas: bbloom: my pov is that if you can crack the directives, you can then program them to fit with clojure datastructures

20:23 bbloom: rather than the other way around

20:24 bbloom: also if you have a nice high-level directive language, thats interesting to everyone doing angular dev

20:24 bbloom: kovas: well, my though is that there are really multiple classes of directives

20:24 brehaut: talios: tbh, i think the bigger issue with not having static types is that systemic changes over the long term can be harder

20:24 talios: brehaut: depending on how you model it, if you did (let [db-record (map request db-func)] ...) you can still type shift/validate/sanitize there, or it could just return a modified/restructured map

20:24 bbloom: kovas: there are those that work with the dom and then there are higher level ones that operate in the domain of applications

20:24 s/though/thought/

20:25 brehaut: talios: oh absolutely, not validating and sanatizing the data would be mental

20:25 kovas: what would be an example of the latter?

20:25 bbloom: kovas: i expect that a macroexpand-like behavior for templates/views/whatever can be leveraged to mean that writing "directives" is often really simple, unless you need to directly interface with the dom

20:25 talios: brehaut: true, the counter to that is you get fast-fail of API breakages - if/when you break APIs. if you silently change a map structure, you leaving that to the hope that someone else also has tests covering it, not only you having tests

20:25 bbloom: kovas: examples of non dom interacting directives?

20:25 kovas: yeah

20:25 bbloom: basically anything that doesn't need to, itself, bind event handlers

20:26 brehaut: talios: thats exactly what im saying.

20:26 bbloom: you need some higher level concepts that are missing from angular currently

20:26 kovas: but if they bind data, they are also interacting with the dom right

20:26 bbloom: kovas: not directly

20:26 consider, Triggers in WPF for example:

20:26 bbloom: kovas: http://wpftutorial.net/Triggers.html

20:27 talios: brehaut: lack of typing is good to starting up, getting going, but on the long term I'm not so sure.

20:27 bbloom: kovas: that sort of stuff can be expressed *abstractly* and different backends can be provided

20:27 talios: brehaut: overheard a conversation here yesterday about naming, and about clojures re-match functions etc. etc. if you're prepending function names with type information, you may as well have types :)

20:27 kovas: ok, i think i understand

20:28 bbloom: talios: those name prefixes also help in reading and understanding

20:28 talios: true

20:28 bbloom: talios: types aren't necessarily apparent at the call site

20:28 names, generally, are

20:29 kovas: bbloom: by abstractly, you mean as a protocol, as a element tag, or as something else?

20:29 bbloom: kovas: something else

20:29 kovas: i'm separating directives into two concepts: properties and passes

20:29 kovas: bbloom: a pass is some metaprogramming transform?

20:29 bbloom: kovas: pretty much

20:30 kovas: cool

20:30 bbloom: kovas: the premise is that you have a schema that defines facts about properties. how to validate them, how to compose them, how they are inherited via hierarchy or via templating, etc

20:30 kovas: yeah, the interaction between directives seems like one of the under defined aspects of angular

20:30 bbloom: kovas: then you define passes, which effectively macro expand properties until you get properties in terms of the target platform

20:31 kovas: interesting

20:31 bbloom: and once you have that data structure in the fully expanded form, you need a runtime to operate on it

20:31 and that runtime is what does the real event binding

20:31 kovas: right

20:31 bbloom: and each pass captures its inputs and outputs, such that expansion can be resumed at any point in the transformation

20:32 so that you can efficiently re-expand only the bits that have chnaged

20:32 kovas: at runtime?

20:32 bbloom: yup

20:32 kovas: thats great

20:32 bbloom: i'm excited about it :-)

20:32 it's A LOT OF WORK to get it all designed right

20:32 kovas: symbolic programming FTW

20:32 bbloom: been working on it for months

20:32 i've got about 2,000 lines of production quality code haha

20:32 getting all the abstractions right is really difficult

20:32 kovas: no doubt

20:33 github that baby :)

20:33 bbloom: kovas: you worked at wolfram for a while, right?

20:33 kovas: bbloom: yup

20:33 bbloom: i'll open source it eventually :-)

20:34 kovas: symbolic everything, huh? haha

20:34 kovas: symbolic all the things

20:34 bbloom: yeah, i'm becoming a big believer in that

20:34 kovas: recursive substitution is powerful

20:34 bbloom: i'm not really sold on rewrite systems though, although they make a ton of sense for algebraic systems

20:35 kovas: rewrite systems will never perform like function calls

20:35 bbloom: yeah, it's recursive substitution, but not generalized pattern matching & rewrites

20:35 kovas: but i truly believe its a higher level paradigm

20:35 bbloom: each "pass" has a special set of behavior for substitution and for delegating to the next pass

20:35 kovas: interesting

20:36 i've been thinking a lot about how to do that in clojure

20:36 bbloom: after i write a whole bunch of passes, i'll see what i can do about a more generalized rewrite mechanism for making it easier to create passes

20:36 kovas: is that something that happens in your concatenate language, or in this unpublished library?

20:36 bbloom: i've only got 6 or so passes right now and they are pretty different

20:36 unpublished

20:36 kovas: thats interesting stuff

20:37 seems relevant for the cljs compiler as well

20:37 bbloom: the concatenative library is being used in the platform-specific runtime layer, not in the expansion/substitution system

20:37 kovas: i see

20:37 is it all about core.walk?

20:37 bbloom: yeah, i think the approach is generally applicable: in theory the tree being expanded could be something like an AST. if you can capture the inputs you could incrementally recompile

20:38 but i'm focused on user interfaces for v1

20:38 kovas: by capturing the inputs, you mean caching them and associating with the output?

20:38 bbloom: yes

20:38 which is what i need to do for performant data binding

20:38 kovas: so this is like recursive substitution & dynamic recomputation

20:38 bbloom: precisely what it is

20:39 i assume mathematica does all that internally :-)

20:39 kovas: mathematica takes the easy way out

20:39 you tell it what the recompilation points are explicitely

20:39 bbloom: re-expand/substitute from the root?

20:39 kovas: with Dynamic[]

20:39 bbloom: ah, i see

20:40 kovas: its powerful, but still a hack

20:40 it only applies to rendered content, rather than to general expressions

20:40 bbloom: the goal is: model <-> view-model <-> view <-> platform

20:40 where view-model == angular scopes basically

20:40 and model is optional for really simple systems

20:40 kovas: right

20:40 bbloom: and the <-> arrows express two way communication

20:41 and it's intentionally linear

20:41 kovas: linear?

20:41 bbloom: ie platform doesn't talk to view-model

20:41 it talks through view

20:41 it's a bidirectional pipeline, but it's a pipeline, not a cyclic system

20:41 kovas: what is the platform in the case of the browser

20:42 is it the dom?

20:42 bbloom: yes

20:43 kovas: nice. well I'm glad this is getting solved without me doing the work :)

20:43 bbloom: haha

20:43 it's complex stuff, but it's fun

20:44 my hope is that i can build a pretty bitching UI toolkit with this, but you're right, this could be even more broadly applicable

20:44 kovas: the symbolic substitution is definitely a general tool

20:45 i won't be totally happy with clojure until we have that

20:45 but UI is the immediate need

20:45 I'm dying here

20:45 bbloom: kovas: ha! yeah, my stuff would hopefully be very useful for session

20:45 i think that UI is an immediate need in general

20:45 it's sorta like an unsolved problem

20:45 kovas: i just started rewriting session in angular

20:45 bbloom: it's just *fucking hard*

20:46 kovas: yup

20:46 bbloom: that's a bummer, but understandable

20:46 kovas: thats the bottleneck right now

20:46 bbloom: hmm, are you NYC based too?

20:46 kovas: i think its just gonna take a weekend. (famous last words)

20:46 for another week or so

20:46 then i move to bay area

20:46 where are you?

20:47 bbloom: heh, aw, we'll just miss each other. i'm moving to NYC next week :-)

20:47 kovas: I'm gone on the 1st

20:47 same deal?

20:48 bbloom: nah, like 29th ha, but i'll be pretty busy the first few days

20:48 kovas: no doubt

20:50 bbloom: are you gonna release this b4 clojure west?

20:50 bbloom: kovas: unlikely, but i'll probably have something to demo there

20:51 kovas: bbloom: ok, i will continue my rewrite then ;)

20:51 bbloom: haha

20:51 kovas: please keep some notes & share them with me, i'm curious how it goes

20:53 akhudek: bbloom: that sounds very interesting. Looking forward to learning more!

20:54 kovas: wiill do

20:55 bbloom: akhudek: i'll be sure to make lots of noise about it when it's ready to show off :-)

20:56 kovas: bbloom: i suggest doing that prior to the conf

20:56 ibdknox: bbloom: we should talk again

20:56 kovas: bbloom: lets other announcements suck up the oxygen

20:56 lest

20:56 ibdknox: bbloom: because I'm thinking even bigger I believe ;)

20:57 bbloom: ibdknox: free free to talk here or msg me

20:58 kovas: i don't expect to have anything to announce or release until some time after the conference

20:59 ibdknox: what's "bigger"? :-)

20:59 ibdknox: a different programming paradigm :)

20:59 gdev: what's going on?

20:59 bbloom: ibdknox: heh, i'm not quite there yet. one step at a time :-P

21:00 AtKaaZ: where are the logs? cause sounds interesting

21:00 akhudek: bbloom: any similarity to http://goo.gl/lIOWF

21:00 akhudek: ?

21:00 kovas: I'm pretty convinced symbol rewriting is the simplest programming paradigm possible

21:00 AtKaaZ: thanks;)

21:00 kovas: and pretty ideal for working with on e.g. an ipad

21:01 bbloom: akhudek: i'll take a peek at that paper, give me a sec

21:01 ibdknox: kovas: example?

21:01 what I've been thinking (and prototyping) is also ideal for an ipad

21:02 akhudek: different application, but some of your descriptions above sounded similar to basic technique

21:02 kovas: ibdknox: i'm thinking about a simplified version of the mathematica language

21:02 bbloom: ibdknox: i figure that declarative UIs in edn is a reasonable starting point & that the implementation is totally secondary to getting the abstractions right

21:02 ibdknox: if you magically come up with another programming paradigm that lets me get the same behavior and perf with less code, i'll be happy to evaluate it :-)

21:03 kovas: ibdknox: something like scratch, but far more powerful

21:03 bbloom: akhudek: i don't really have time to dig into this paper now. is there something in particular you thought paralleled what i'm talking about?

21:04 kovas: ibdknox: if the UI is represented symbolically, then you can see the substitutions in code simultaneously with their visual interpretation

21:04 gdev: sounds like light table

21:04 bbloom: kovas: and you can provide single-step debugging of the expansion process :-)

21:04 ibdknox: kovas: yep, I'm making that work

21:04 bbloom: expansion -> substitution

21:04 kovas: ibdknox: aww yeah

21:04 bbloom: i guess it can *shrink* not just expand, but 90% of the time it expands haha

21:05 akhudek: the basic idea there is to compile a query by a sort of step-wise graph expansion. You stop expanding when you've mapped the input concepts to the target concepts.

21:05 that's a gross simplification, but sounded a lot like what you were describing with passes

21:05 bbloom: heh, that's an interesting parallel to a thought discussed in IRC a week ago or so: reducers don't always reduce, sometimes they expand: ie mapcat

21:05 and similarly, macroexpand doesn't always expand

21:06 ,(macroexpand '(-> 1))

21:06 clojurebot: 1

21:06 bbloom: :-)

21:06 substituters and macrosubstitute doesn't really have the same ring to them

21:07 kovas: yeah I've been struggling with good names for that as well

21:07 bbloom: akhudek: yeah, that's what i'm describing, but that's similar to any symbolic program... in particular: compilers

21:07 kovas: the words are hopelessly overloaded

21:08 bbloom: names are fucking hard

21:08 that's why haskell people just give up and pick some symbols

21:08 heh

21:08 akhudek: bbloom: yes, though the devil is always in the details. :-) Proving that you've genuinely achieved a correct mapping under your constraints is the hard part.

21:09 brehaut: yup, its one of the two hard problems, along with cache invalidation and off by one errors

21:09 akhudek: nevermind the graph search problem itself

21:10 bbloom: akhudek: luckily, there is no *correct* mapping in UIs

21:10 ibdknox: kovas: this is a relatively new endeavor, but I was hoping to maybe demo something at the liveprogramming workshop: http://liveprogramming.github.com/2013/

21:10 bbloom: akhudek: consistency is more important

21:10 akhudek: as long as the expansion process is clear, understandable, consistent, and produces testable output, then the developer can tweak until they get a UX they like

21:11 akhudek: unlike queries, which are being optimized, there is no consistent output

21:11 kovas: ibdknox: cool. I'm gonna hit that up

21:11 bbloom: ibdknox: can you give a couple sentence overview?

21:13 akhudek: Interesting. Still looking forward to seeing what you've cooked up. :-)

21:14 ibdknox: bbloom: your program as a datastructure ;) Basically what would a truly declarative approach to building *real* software look like? And more interestingly, what does that allow you to do with tools?

21:14 bbloom: ibdknox: very cool. it's definitely something i have extreme interest in

21:14 kovas: if you program is declarative, that makes it a lot more trivial to share

21:14 craigbro: van roy? haridi?

21:14 ibdknox: the demo I was thinking of for ICSE is building todoMVC

21:15 on a touch screen :)

21:15 craigbro: am I correct to think you mean something other than declartive programming?

21:15 bbloom: ibdknox: HA! I have a (mostly) working todoMVC

21:15 it seems we are playing in the same sandbox :-)

21:15 my thought is that declarative programming for real software is strictly harder than declarative UI, and real tools need real UI

21:16 in the chicken and egg cycle, one of us has chosen the chicken and the other has chosen the egg, ha

21:16 i also have a pong game :-)

21:16 ibdknox: I agree, though I think there's an underlying solution that actually addresses both

21:16 bbloom: ibdknox: i think that underlying solution is symbolic expansion

21:16 kovas: declarative UI quickly devolves into declarative programs

21:16 you need to save the state somewhere, first of all

21:17 ibdknox: kovas: yeah, that's what I ran into

21:17 kovas: ibdknox: i gave up until datomic free came out

21:17 bbloom: kovas: nah, you can isolate that into "commands" where the declarative bit is only what named command (1) to execute on what path in the state data structure (2), with what arguments (3)

21:17 ibdknox: bbloom: any reading you can suggest on symbolic expansion?

21:17 bbloom: ibdknox: install mathematica :-P

21:17 kovas: +1

21:18 ibdknox: why don't we use mathematica for everything?

21:18 bbloom: b/c it is largely backwards compatable with v1

21:19 looong before persistent data structures were common place :-)

21:19 ibdknox: but you think they've solved the underlying problem?

21:19 kovas_: its slow and proprietary

21:19 bbloom: no, i think that mathematica is the best known example of symbol substitution

21:19 and hence mathematica is worth studying

21:19 craigbro: commercial example...

21:19 kovas_: and doesn't have the abstractions that go down to the platform

21:19 ibdknox: got it

21:20 craigbro: matlab

21:20 bbloom: this topic is extremely interesting to me, but sadly, i gotta run

21:20 kovas_: ibdknox: if you implement Manipulate, that will be considered a heroic act

21:21 later!

21:21 bbloom: Manipulate is super cool

21:21 kovas_: & ibdknox: we should all definitely get together and talk about this the next time i'm in the bay area

21:21 kovas_: would love to

21:21 ibdknox: sure thing

21:22 kovas_: as in turning values into sliders and such? That's manipulate?

21:22 craigbro: present/

21:22 accept

21:22 kovas_: ibdknox: theres maybe 3 aspects

21:22 craigbro: seperates presentation types from data types

21:22 kovas_: ibdknox: first is auto-generating an interface that is relevant to the parameters being manipulated

21:22 craigbro: is in effect a declarative layer sitting on top of a procedural layer for UI

21:23 kovas_: ibdknox: second is rendering values as UI without any intermediate nonsense

21:23 craigbro: CLIM was totally baroque tho

21:23 kovas_: ibdknox: third is the dynamic recomputation

21:23 ibdknox: got it

21:23 well

21:24 from watching these couple videos and from what you guys are saying, that sounds like what I intended to be able to do

21:24 lol

21:24 I prototyped an engine for this stuff this weekend, just really simple stuff

21:25 working on what primitive notions you need to build the vast majority of programs

21:25 kovas_: sweet

21:25 what are the primitives?

21:27 ibdknox: I've been thinking of it as a system that has two things in it

21:28 you need to define the "things" in your program - objects

21:28 and then you need to define the relationships between them

21:29 the things in your program are sinks for IO basically

21:29 kovas_: this is for all programs, or mainly UI-driven ones?

21:29 ok

21:29 ibdknox: I've been primarily thinking about the entire web stack, which encompasses both UI and non-UI things

21:30 I was focusing on figuring out the types of relationships that exist, because I think there are very very few

21:30 kovas_: are the relationships constraints, or rules for evolution

21:31 ibdknox: more akin to constraints I think

21:31 though again, this is a first pass

21:31 kovas_: how do you make it run?

21:32 ibdknox: feed the datastructure into the (run ...) function, of course ;)

21:32 kovas_: right :)

21:32 ibdknox: every program has to have some entry point, something that kicks it off

21:32 craigbro: really?

21:32 kovas_: but in terms of turning constraints into updates i mean

21:32 craigbro: could just start a listener

21:32 ibdknox: craigbro: then the thing that kicks it off is that listener firing

21:33 bind your listener in run

21:33 and wait

21:33 craigbro: the litener need not be part of the program

21:33 akhudek: this sounds exactly like the project I've been part of for the last two years at UW, complete with IO black boxes. It's not an easy problem to solve, especially update.

21:33 ibdknox: kovas_: delayed binding of listeners

21:33 craigbro: if my program is a combination of a data structue, some more declaration of how to dispaly aspects of it etc..

21:34 ibdknox: craigbro: I'm not sure I understand what you mean by the listener need not be part of the program. Can you give a concrete example?

21:34 craigbro: an html page

21:35 ibdknox: an html page runs

21:35 craigbro: the browser runs it

21:35 the onload in this case is a procedure description

21:36 kovas_: ibdknox: so what are the identified relationships so far?

21:36 ibdknox: push, associate, and update

21:36 craigbro: but, this semantic distinction is, an aside

21:37 another example would be a NetLogo program

21:37 kovas_: is delete a special case of update?

21:37 craigbro: it's a blob of code, and a description of a UI

21:37 no code is run until a user clicks on a button that calls something

21:37 ibdknox: kovas_: update can send messages

21:38 kovas_: ibdknox: how is it different from _just_ sending messages?

21:38 craigbro: this distition of what is inside and outside the program is important when you want the program to run in lots of different contexts

21:39 the same netlogo model can be run interactively, or run in the "lab" which will run in N times where N is the number of combinations of different parameters you tell the lab to run it with

21:39 ibdknox: kovas_: what are you referring to with "it"

21:40 kovas_: ibdknox: update

21:42 ibdknox: kovas_: it depends on how you define the end points, but fundamentally it's a form of message passing

21:43 kovas_: update is a triggered push

21:43 a push relationship keeps all dependents in sync automatically

21:44 craigbro: that's just a property of the runner though, right?

21:44 kovas_: ibdknox: i see. and assoc?

21:45 ibdknox: does that change the topology or something?

21:45 ibdknox: kovas_: you need a way to say that this thing has a copy of something

21:45 kovas_: each todo needs its own copy of a representation that is bound correctly and such

21:45 kovas_: right

21:46 so assoc is for inserting identities, push is for inserting values. is that the idea?

21:46 ibdknox: yep

21:46 kovas_: nice

21:47 ibdknox: very early still, but with just those, you can get surprisingly far

21:47 kovas_: is update a pure function?

21:47 ibdknox: all pure functions

21:48 craigbro: ibdknox: Dclarative UIs are all about where you draw the distinction between the program, and the container, or "runner"

21:48 kovas_: so the contract is update produces new state that you can perceive and hang out to (rather than arbitrary side effects)

21:48 craigbro: ibdknox: HTML is a perfect example of a declarative UI, which can do all kinds of things, even without js

21:48 ibdknox: kovas_: I think that's how it's going to play out

21:49 kovas_: sounds pretty clean

21:49 craigbro: ibdknox: but I'm not so sure the point I'm making is germane to your experiment, or in any way a "revelation" in regards to it

21:50 ibdknox: craigbro: haha :) My thought is that I don't want to think about the container if I don't have to

21:50 craigbro: ibdknox: where cootainer is your mishmash of procedural/functional jQuery and clojurescript to make the pixels on the screen?

21:50 ibdknox: the completely ridiculous demo I want to do is to by changing one of the directives in my todoMVC it goes from a completely local (just an HTML page) program to spinning up a server and running remotely serving that and communicating changes back

21:52 kovas_: hmm

21:52 that would be impressive

21:52 ibdknox: I agree - now to make it work :)

21:52 kovas_: but its hard to know what conclusion to draw from that in terms of general capabilities

21:53 or is the point really the easy transition between client and server

21:53 ibdknox: no, more that it's able to figure that out

21:53 what do you think would show the more general capabilities?

21:53 kovas_: by directive you mean like html tag?

21:54 ibdknox: I have a collection of todos, I change a piece of metadata on it from :local to :remote

21:54 kovas_: i see

21:54 ok, that would be pretty sweet

21:55 ibdknox: basically that transition would cause a near complete rewrite in the normal case

21:55 kovas_: right

21:55 ibdknox: because no matter how hard you try you must take architectural dependencies

21:55 but if you stop saying "how" and start saying "what" it doesn't matter

21:55 the architecture is decided JIT

21:56 kovas_: right

21:57 interesting compilation problem

21:57 craigbro: CLIM again 8^)

21:57 kovas_: do you have to analyze it at the source code level?

21:58 craigbro: (present my-todo-lisp 'todo-presentation-type +swing+)

21:58 ibdknox: haha

21:59 craigbro: (present my-todo-lisp 'todo-presentation-type (merge +htmlserver+ {:base-url "/todo" :authhandler (reify...))

21:59 ibdknox: kovas_: I haven't thought too far down how that level of transformation will work yet :)

21:59 craigbro: to handle events you have input and output streams that read/write presentation records

22:00 ibdknox: but you have complete information, I believe it's possible

22:00 kovas_: ibdknox: i imagined it as tagged literals rather than metadata. then its easy to bind the interpretation. but TLs not great for code-like things.

22:00 craigbro: i have a lightweight presentation system we use for our web apps, that renders to just a hiccup view

22:01 metadata is a pain in the ass

22:01 especially if you do symbolic operations on your data

22:02 kovas_: what kind of operations?

22:02 craigbro: eq?

22:02 clojurebot: @ splices in a seq and foo# is a symbol, not a seq

22:02 craigbro: hehe

22:03 kovas_: because it ignores metadata?

22:03 craigbro: for example, i tagged some symbol names for one data type with metadata

22:03 I always have to go back to the original symbol object to get the metadata

22:05 kovas_: i see.

22:05 you want them to be more like vars then

22:05 craigbro: it gets to be a pain when you are doing thigns like spitting stuff out to a file

22:05 and reading it back in

22:06 kovas_: because every instance of the symbol is a distinct entity

22:06 craigbro: you want them to be more like vars then

22:06 err

22:06 trying to trigger clojurebot there

22:06 eq?

22:06 kovas_: I agree its a shame you can't directly attach stuff to symbols as identities

22:07 that would make things more symbolic for sure

22:07 craigbro: symbol properties!

22:07 common lisp again

22:07 lord save us all

22:07 kovas_: i mean, its easy enough to do it yourself

22:08 without some programmatic meaning to the properties, its not that useful

22:08 but if its integrated with macros, then it is very useful

22:09 craigbro: programmating meaning to the properties?

22:09 programmatic..

22:10 kovas_: yes, like mathematica attributes

22:10 craigbro: not familiar

22:10 kovas_: its trivial to make symbols thread over lists by setting the attribute Listable

22:10 arrdem: ,\f

22:10 clojurebot: \f

22:11 unfortunately in mathematica attributes are not extensible by the user

22:11 but they cover many of the cases we use macros for

22:11 in a much easier to use way

22:12 "Sometimes, however, you need to specify general properties of functions, without necessarily giving explicit values."

22:12 actually this is also relevant to ibdknox 's project

22:13 so what id like to figure out is how to have the concept of Attributes be made extensible

22:13 by attached metadata on the symbol, combined with some kind of macro protocol

22:14 craigbro: getting to be one too many transformation layers for my tastes

22:14 kovas_: its more of a natural completion of the abstractions we have now

22:14 why can't macros have protocols?

22:14 that would make them a lot more interoperable

22:15 and symbols could specify what their own macro expansion should be

22:15 under a given macro

22:15 as it is, its pretty broken from the "program against abstractions" pov

22:16 if you want (foo [a b c]) -> [(foo a) (foo b) (foo b)]

22:16 its silly to not have an abstraction you can apply to the symbol foo to get that behavior

22:17 craigbro: write the function that way

22:17 kovas_: craigbro: so layers of transformation is good for CLIM, but not for general programming ;)

22:18 craigbro: don't hide it in a property...

22:18 kovas_: its more declarative as a property

22:18 "what, not how"

22:19 you can set the attribute in the function definition, so its not off somewhere else

22:20 craigbro: map is as much what as how

22:21 so this is not decl. vs anything else

22:21 syntactic mutability

22:23 can't you not alrady do this with tagged literals?

22:23 kovas_: i wish

22:23 craigbro: sure you could

22:23 kovas_: i don't think so

22:24 craigbro: for listable

22:24 kovas_: i don't think TLs capture scope the way you want

22:25 i should play with that again, but theres some tricky issues

22:25 i mean, you can do it with a macro right

22:26 at least thats what we end up doing

22:26 but that isn't extensible.

22:26 the macro can't know, for each symbol, which positions should be listable

22:26 craigbro: seems to me you could do it in the fn itself

22:27 a macro (listable-body...

22:27 kovas_: yes, but then that information is lost to the symbol level

22:28 its just "this happens to be the behavior of the function, buts that a black box"

22:29 it wouldn't be so bad if you could have multiple function forms with the same arity

22:29 if you have a 1-arity function, you have to have a conditional first before you figure out if you map, or if you do the base case

22:29 craigbro: you could us your own defn

22:29 since you're just talking about fns...

22:30 we don't have symbol macro expansion anyways

22:30 kovas_: i think we should

22:30 craigbro: sure, I do to actually

22:30 your defn would be a fine way to experiment with this

22:31 kovas_: yes thats a good point

22:31 craigbro: i do macros like that all the time

22:31 kovas_: you mean like custom defns?

22:31 craigbro: a macro that defines a fn as the vlaue of the symbol, but also sets up alot of bookkeeping

22:33 I prefer a global ref to a map

22:33 keys on the symbol

22:33 keyed...

22:33 kovas_: yeah that solves your other problems

22:33 i gotta run

22:33 ttyl!

22:34 craigbro: latah

22:54 yedi: wow clojurescript up and running is a super quick read

22:56 ChongLi: yedi: yeah, it is

22:57 I hope they update it at some point when the tooling becomes more developed

22:58 setting up a browser repl in particular is a tricky process

23:21 TimMc: ibdknox: The difference between local and remote is more than just an implementation detail. You suddenly have to deal with network outages where before there was a simple function call.

23:22 bbloom: TimMc: agreed, i think that a more likely first step is something akin to the "himera model" that fogus talks about here: http://blog.fogus.me/2012/03/27/compiling-clojure-to-javascript-pt-3-the-himera-model/

23:23 that's what i'm going for: in that model<->viewmodel<->view<->platform chain, i want to be able to pick and choose where i draw the line on what parts of the pipeline go on which endpoint

23:25 ie a mobile app may choose to run everything but the platform rendering on the server

23:25 a desktop app may run everything on a single node

23:25 a web app may run only the underlying model on the server

23:26 yedi: whats the decision process for making a library a core lib?

23:27 technomancy: yedi: it basically doesn't happen any more

23:27 ibdknox: TimMc: I'm not sure I understand the distinction you're drawing. There are well defined strategies for dealing with the network, I would just employ one of those?

23:28 yedi: so a core.matrix might be out of the question?

23:28 bbloom: ibdknox: i think the point he's making is that sometimes there are genuine *what* questions, not just *how* questions, to be answered about the behavior of an app in the face of latency

23:28 cjfrisz: So...is there documentation for Domina anywhere?

23:28 TimMc: ibdknox: What I mean is, suddenly there are parts of your program that have to know about non-local execution.

23:28 cjfrisz: Or is it all documentation by example?

23:29 technomancy: yedi: you mean a contrib?

23:29 ibdknox: bbloom: TimMc: can you give an example?

23:29 bbloom: ibdknox: like when you post a comment on facebook, it's rendered optimistically, but if the request times out, then the input form shows back up. however, there are options you wouldn't want to render optimistically, for example a sale of stock

23:30 technomancy: TimMc: are you referring to rich's "why Clojure isn't like Erlang" post?

23:30 TimMc: Well, it does depend on where you draw the app/framework boundary, but at a certain point you want to have business logic involved in error handling.

23:30 technomancy: No, but that sounds like interesting reading. :-)

23:31 bbloom: ibdknox: when you introduce a partition, you introduce latency and failure. when you introduce latency and failure, you need to make decisions about trade offs and behavior

23:31 ibdknox: bbloom: that's a good one. I'll have to think about it

23:32 cark: technomancy: is that post on the mailing list ?

23:32 technomancy: TimMc, cark: http://bc.tech.coop/blog/081201.html

23:32 TimMc: thx

23:32 cark: thanks !

23:32 technomancy: search down to "I chose not to use the Erlang-style actor model for same-process state management in Clojure for several reasons:"

23:32 yedi: technomancy: nvm, was getting the two confused

23:35 bbloom: technomancy: that's a good read

23:35 technomancy: yedi: I don't know what the process is, but I know it involves not completely hating Jira and trying to figure out how to get Hudson working with Maven and Sonatype OSS... so... yeah.

23:36 TimMc: I'll read that tomorrow.

23:36 It looks interesting, but so does my bed.

23:37 amalloy: if your bed looks interesting, probably time to clean up, mate

23:38 bbloom: craigbro: thanks for mentioning CLIM, i hadn't seen it before. i'll study it

23:39 TimMc: amalloy: The fact that it contains my spouse probably factors in here somewhere. :-)

23:40 craigbro: bbloom: lots to pick from the cold cold corpse of common lisp

23:41 TimMc: shush, you don't want to remind people of CORBA with all this talk of the difference btween local and remote

23:45 arrdem: do we have a -> that short-circuits on `nil`?

23:45 craigbro: not that I know of, but sounds innaresting

23:45 hmmm

23:45 arrdem: it could be a 1.5.0 feature, but I know I've heard of it.

23:45 craigbro: can't you just do

23:46 oops never mind

23:46 there are a bunch of threading macros added in 1.5.0 right?

23:47 some->

23:47 bbloom: craigbro: yeah, in particular cond-> is awesome

23:47 craigbro: there ya go

23:47 bbloom: i <3 them :-)

23:48 i really enjoy thinking in steps

23:48 craigbro: (as-> I dig

23:48 bbloom: it makes it really easy to test some more complex multi-step algorithms

23:48 craigbro: and could totally use

23:48 that clj-http wrapper I wrote uses them alot

23:48 arrdem: (some->) is what I want..

23:48 mmkay.

23:48 craigbro: the idea is you thread a map that represents a browser session

23:49 arrdem: if you look around I bet you can find implementations you can load into 1.4.0

23:49 thru a bunch of calls that requests urls, save cookies or params, fill in forms, etc...

23:50 bbloom: hmmm no as->>

23:50 frozenlock: cljs: I have a js function with a callback. However the function I want to pass in the callback is inside a remote-callback (fetch) and is asynchronous. Is there a way to remain into the callback until the fetch is completed?

23:50 bbloom: frozenlock: you mean block?

23:50 TheBusby: anyone else following the drama in the clojurescript contribution thread on the ML?

23:51 noprompt: quick question about namespace naming conventions: is it ideal to use singular or plural names? i.e., if i have a ns that contains types should it be (ns foo.types) or (ns foo.type)

23:51 frozenlock: bbloom: I think... "By the nature of JavaScript letrem is an asynchronous block"-Fetch library

23:52 bbloom: noprompt: http://programmers.stackexchange.com/a/75929

23:52 frozenlock: I could set an atom, then wait until the atom is changed... but it seems.. yuck

23:52 noprompt: bbloom: thanks :)

23:53 Is there domina documentation anywhere?

23:53 frozenlock: cjfrisz: besides the github readme?

23:54 noprompt: so just to make sure i'm understanding this, in this case i'm looking for (ns foo.type) since it only contains records?

23:55 cjfrisz: frozenlock: yes, besides that

23:55 And I already looked through ClojureScript One

23:56 technomancy: TheBusby: it appears with fairly predictable regularity

23:56 cjfrisz: Maybe I'm just having trouble coming at it from not having done much JavaScript

23:56 technomancy: it's getting to be more predictable than the "hey guys what if we did clojure but with whitespace instead of parens" posts

23:56 cjfrisz: Not good enough at guessing the translation from JS to CLJS+domina

23:56 arrdem: technomancy: oh gods you get those?

23:57 technomancy: arrdem: used to be every 6 months

23:57 TheBusby: technomancy: don't imagine it'll be going away either. :(

23:57 technomancy: but it's been a while

23:57 frozenlock: cjfrisz: I don't think there's anything else. But there's an API section in the source code which is quite straightforward https://github.com/levand/domina/blob/master/src/cljs/domina.cljs#L108

23:57 technomancy: TheBusby: not till every last potential contributor's hope is crushed

23:57 TheBusby: haha, we'll see

23:57 arrdem: I guess if you use Python-style four space indentation... but I'm thoroughly revolted.

23:58 TheBusby: I was curious if you can submit patches to core members and have them take care of it?

23:58 technomancy: arrdem: "you know, for newbies" http://www.dwheeler.com/readable/sweet-expressions.html

23:58 TheBusby: maybe if you submit them along with a bribe

23:59 TheBusby: technomancy: a nice scotch maybe? or Sake?

23:59 cjfrisz: frozenlock: thanks

23:59 technomancy: TheBusby: try it and let me know if it works =)

23:59 arrdem: I mean... it's a solid syntax proposal... but for the part where you count whitespaces.

Logging service provided by n01se.net