#clojure log - Sep 19 2012

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

0:01 tomoj: hmm

0:01 well, (class Post) is probably Class

0:01 did you try just Post ?

0:02 (class (class Post)) is also Class, though, so I don't know why that wouldn't work

0:02 oh

0:02 you may have to pass the varargs in an array

0:02 maybe try (.fetchConnection fb "boobs" Post (object-array []))

0:04 do you really want to use restfb? seems like it shouldn't be hard to use a clojure http client

0:12 loliveira: tomoj: i thougth restfb was easier.

0:12 but i think i 'll give a try.

0:13 ... to http-client

0:14 tomoj: clj-http is popular

0:19 loliveira: i know clj-http client, but somehow I didn't realize that could be better to call their api directlly. I make this kind of miss judgement all the time.

0:19 =)

0:21 dnolen`: tomoj: I have no idea how that would work.

0:25 Sgeo: Hmm, clj-http does something called throwing a Slingshot stone

0:25 * Sgeo should read up on that

0:26 technomancy: Sgeo: it's basically an ex-info

0:26 Sgeo: ex-info?

0:26 technomancy: but it predates ex-info so you can use it in older clojures

0:26 ,(doc ex-info)

0:26 clojurebot: "([msg map] [msg map cause]); Alpha - subject to change. Create an instance of ExceptionInfo, a RuntimeException subclass that carries a map of additional data."

0:26 technomancy: slingshot offers much nicer exception catching, but on the throwing side you should just use ex-info

0:27 with slingshot you can actually destructure an exception, which is hot

0:27 tomoj: dnolen`: well, say you can look at the analyzer output and determine where locals aren't needed anymore (I _think_ that's feasible). then you can stick some extra (set! local nil) into the analyze output before it gets emitted, right?

0:27 Sgeo: Is it possible to resume from an exception with Slingshot?

0:27 technomancy: no, a condition system is orthogonal to slingshot

0:28 Sgeo: :(

0:28 technomancy: slingshot is just about enhanced catch

0:29 well, it's good to be orthogonal

0:29 amalloy: technomancy: it's not parallel, but i don't think it's orthogonal either. enhanced catch seems closely related to resuming

0:29 technomancy: but yes, it's a shame that no one's gone to the trouble of building a condition system apart from the old problematic error-kit

0:30 Sgeo: error-kit?

0:30 clojurebot: error-kit is http://pragprog.com/magazines/2009-07/when-things-go-wrong

0:30 technomancy: an abandoned condition system that tried to do too much

0:31 in particular, it embedded an object system in itself or something?

0:31 Sgeo: I think my primary use of a condition system would be for developing, can fix an error and just continue

0:31 technomancy: the other problem is a condition system is fairly useless unless everyone uses it

0:32 Sgeo: Does the JVM or Clojure have anything like that?

0:32 technomancy: ritz might

0:32 for dev-time only

0:33 not sure why nobody has tackled that; it doesn't seem like an error-kit-lite would be terribly tricky to implement

0:34 probably because people realize the implementation is the easy part and getting people to actually use it is the difficult part

0:34 * Sgeo is wondering if an Either monad could store a continuation in the Left part

0:34 frio: clojure seems to be better than other languages ive come across in that regard though

0:34 politically, i mean

0:35 people seem to converge faster on a given solution

0:35 Sgeo: Although, in some cases, the solution can be bad.... ok, not going to rant, not going to rant

0:35 frio: but yes, i was about to ask -- what is the preferred clojuric way for error handling? are people using monads?

0:35 technomancy: Leiningen could actually really benefit from conditions, but it's completely impractical because (at least in the case I'm thinking of) Maven would have to be involved too

0:35 frio: ex-info is a wonderful thing

0:36 frio: (id like to rewrite a small app ive used in monadic style :))

0:36 technomancy: plus if you're doing nontrivial catches, slingshot's try+ is really slick

0:36 Sgeo: frio, I'm starting to be disliked here for ranting about how much I dislike clojure.algo.monads

0:36 technomancy: Sgeo: you do understand that not many people actually do like it, right?

0:36 frio: technomancy: so i should look at slingshot? ill google ex-info now :)

0:37 Sgeo: technomancy, of the people who want to do monad stuff?

0:37 technomancy: frio: ex-info is more important IMO, but if you have nontrivial requirements slingshot is great too

0:37 frio: Sgeo: :<. is it just not a good monadic implementation? (i saw a blog post recently about part of it violating the monad laws)

0:37 Sgeo: frio, well, I did the reddit post and bug report

0:37 frio: small world Sgeo :)

0:38 thanks technomancy, ill take a look at ex-info

0:38 technomancy: Sgeo: well in my experience people introducing monadic styles to a Clojure codebase bifurcate things unnecessarily without adding any expresivity or flexibility

0:38 Sgeo: That part though is just one of the provided monads, not the workings of algo.monads itself

0:38 Although, if you're used to Haskell, and are insisting on algo.monads, do note that domonad works differently from do in Haskell: There's an implied return around the last part

0:39 frio: what's wrong with algo.monads? i haven't looked at it yet

0:39 im mainly looking to control flow through a series of expressions, several of which may error out

0:40 so the Either monad seemed a good idea (but the old adage of "when you're used to a hammer, everything looks like a nail" applies, and i do want to investigate to find a more idiomatic clojure solution :))

0:41 Sgeo: maybe-m breaks the monad laws and is less useful than Maybe in Haskell (because you can't do Just Nothing), domonad should have a large warning for Haskell users, m-lift should be a function, and, less about algo.monads and more of a general thought, I think there should be a more general mechanism for doing the sort of thing that algo.monads does

0:41 cark: sgeo : not in a dynamic language

0:42 if you want to do monads like in haskell, use haskell ...or maybe scalla

0:42 Sgeo: I

0:42 cark: -l

0:42 Sgeo: I'm thinking about how to do something like return-type polymorphism in Clojure

0:42 frio: ah right, I remember the Just Nothing thing now (and being surprised at people saying that was fine)

0:42 Sgeo: frio, where are people saying that that's fine to not support Just Nothing?

0:42 cark: Sgeo: well, look at defmonadfn =P

0:43 frio: HN iirc Sgeo

0:43 tomoj: hmm

0:43 I am implementing a monad and also currently can't have M M a

0:44 Sgeo: frio, any link? If the monads law breakage thing was more than a few days ago, it wasn't me

0:44 cark, yeah, that's another thing that irks me, but unsure how to fix it

0:44 cark: what's to fix ?

0:44 that's why we're doing lisp, so that we can have macros that provide functionalities not available in the language

0:45 frio: bleh, i cant find it Sgeo

0:45 lost in the morass of the internet

0:45 cark: can'rt have return value polymophism ? rool your own !

0:45 roll*

0:45 Sgeo: cark, sure, but needing a different macro for defining functions that use monad functions seems inelegant. And what happens when I want to use a different sort of thing that needs the same sort of macro

0:46 frio: thanks for the thoughts above though; ill take those into account when i look at rejigging my code soon

0:46 cark: roll your own, or generalize what you have

0:46 Sgeo: Rolling my own defblahfn could mean I can't write a function that uses both monad functions and my own functions

0:47 technomancy: ex-info really is the coolest thing to happen to Clojure in a while

0:47 Sgeo: I would be somewhat satisfied with a more generalized defsomethingfn, but I still think it's a bit ugly

0:47 technomancy: actually, it's the only thing I can think of off the top of my head since 1.2 that I actually use

0:47 require/refer I guess? yawn.

0:48 frio: technomancy: that's still used with try/catch/etc., right?

0:48 it just captures more data?

0:48 technomancy: frio: yeah

0:48 you can use ex-data to get the map back out, or destructure it automatically with try+ in slingshot

0:48 frio: cool :)

0:49 cark: Sgeo: the easy way out is to use dynamic vars

0:49 technomancy: oh, deref timeouts are the other thing I use

0:49 frio: ill definitely take a look at it. i shy away from try/catch-style exception handling when i can fwiw, but using try/catch and ex-info is probably a better fit for the little app im scrapping together now (it'll apply easier than rewriting things monadically, at least, and i need to be focussing on starting to write clients now)

0:50 Sgeo: cark, that makes sense, and have been thinking along those lines, but then there's difficulties with closures that get run outside of the context of the bindings of the dynamic vars

0:50 technomancy: ex-info means nobody will have to gen-class for custom exceptions anymore

0:50 frio: ooooooh

0:50 technomancy: (which was never a good idea anyway)

0:50 cark: Sgeo: mhh true

0:50 frio: that's excellent :D

0:51 Sgeo: frio, oh, I have one more objection to algo.monads: it lumps in things like lifting and fmap with monads, instead of separating it out

0:52 frio: yeah, i saw fmap in there and was a little perplexed. i guess monads are functors, but yeah, it seems like that should be somewhere else

0:52 Sgeo: cark, my most recent thinking has been along these lines: Have functions that are polymorphic on the return essentially return a function, and that function gets passed a type, or perhaps something else, and then the result of that is the final result

0:53 cark: Sgeo: that's what defmonadfn does...kinda

0:53 Sgeo: but doing what you say literally ... that would'nt be very usable

0:54 Sgeo: Not sure about that. A naive function can be wrapped with a lift-like thing that helps process the arguments if some of them may be of these polymorphic things

0:54 frio: hrmmm

0:54 clojure.contrib.condition -- largely unused, im guessing?

0:55 cark: haha maybe there's a monad that could help with this return value polymorphism thing =)

0:55 Sgeo: Although, I don't know if it's possible to access type hints of arbitrary functions

0:55 cark, amusingly, I'm thinking that this is at least a Functor and possibly an Applicative Functor

0:57 Is there any documentation about what metadata is available in general?

0:57 ,(meta (fn [^String somestring] somestring))

0:57 clojurebot: nil

0:57 cark: right, wrap you function in another one which binds the *current-monad* var to the value saved at its creation time

0:58 (wrap-in-current-monad f) would produce it

0:58 Sgeo: cark, that seems more for the dynamic variable thing?

0:58 cark: yes

0:59 oh you want a general solution to return value polymorphism ?

0:59 good luck with that !

0:59 technomancy: frio: c.c.condition is a subset of slingshot

0:59 same author

1:00 frio: ah ok, thanks technomancy

1:00 ill need to check out slingshot then

1:00 Sgeo: cark, easier than trying to dispatch on a function's return type without calling it

1:00 frio: ive unearthed a post from 2007 where rich hickey is against the introduction of a condition system (sensibly: clojure runs on the jvm, therefore using the JVM's idiom makes sense and there were bigger fish to fry)

1:01 but im guessing 5 years on it might be worth revisiting

1:01 cark: CL's condition system is nice, but i found that i was always using it like standard exceptions

1:02 Sgeo: cark, even when the debugger caught the error and allowed you to resume?

1:02 frio: fair enough cark :)

1:02 cark: tho peter seibel had some nice talks about practical uses for conditions

1:03 frio: like I said (and sparked the monad debate off :p), the Either monad is my current local maxima (I don't really like try/catch as a pattern), but it seems like it's not very clojuric :)

1:03 cark: frio : it's fine, whatever helps you is good enough =)

1:04 go for the end product, don't worry too much about details, or nothing ever gets done

1:04 frio: for sure. i get vaguely OCD about doing things The Right Way, but yep -- what you just said

1:04 the price i pay is that i never actually finish anything :p

1:05 cark: hehe i have to fight it too

1:05 Sgeo: Hah, so I can get at the type hints

1:06 But... I did it not by looking at the function itself, but at the var made by defn

1:06 :(

1:06 Why isn't arglists associated with the fn?

1:06 Is there a way to get that data from an fn?

1:07 technomancy: frio: the problem is you'll never get total coverage since you'll be calling out to Java

1:07 cark: Sgeo: i seem to remember there's some macro trickery that can get that

1:07 frio: yeah, you're right technomancy

1:08 this has all been very informative, ty all :)

1:08 technomancy: so you have to choose between the conceptual integrity of a single system and the extra functionality of a dual system

1:08 cark: i think either and maybe are better suited for code that does not interact with anything

1:08 Sgeo: Oh, metadata can specify the return-type of a function

1:08 cark: like a parser or a datastrcture

1:08 Sgeo: you got it backwards again

1:08 Sgeo: I think maybe is supercedable by either in a dynamically typed language

1:09 cark: Sgeo: you want the function to act differently depending on the expected return value

1:10 Sgeo: cark, I was thinking of dispatch on types of different parts of a->b

1:10 But that's not especially needed for monads or functors or applicatives

1:11 cark: ok well, it looks like you need to create your own language

1:11 =)

1:11 technomancy: frio: part of rich's argument was also that with dynamic binding you don't need to build a condition system into the language; it's easy to implement in a library

1:12 and while that's technically true it ignores ecosystem issues

1:12 Sgeo: You don't need to build comp or partial into the language either

1:13 or map or filter or ->

1:13 technomancy: yeah, I don't think it's a good argument; just throwing it out there

1:28 Sgeo: Hmm http://stackoverflow.com/questions/1696693/clojure-how-to-find-out-the-arity-of-function-at-runtime

1:31 cark: Sgeo: that may help : http://blog.jayfields.com/2011/02/clojure-and.html

1:32 Sgeo: I once wanted something like &whole or &form for functions in Common Lisp. Funnily enough, it was because I wanted to fake a Clojure feature, and there was no way that I knew of to do the equivalent of setting arglists in CL

1:36 Ah, clojure.reflect is interesting

1:36 But... I don't think it actually shows the type-hints

1:39 What I don't understand is why it's metadata on the var and not the function itself

1:39 Function itself makes more sense to me

1:47 amalloy: one reason, not that i've considered this carefully, is that vars can hold things that can't have metadata, eg (def ^:doc "blah" x 3)

1:48 unlink: If you want the metadata on the function, just write (def f ^{...} (fn [x] ...))

1:51 amalloy: unlink: try that, i dare you. a dollar says it doesn't work but (with-meta (fn [x] ...) {...}) does

1:51 unlink: wfm

1:52 amalloy: sigh, metadata is confusing. it's a good thing i don't bet more than i can afford on these things

1:52 &(meta ^{:x 1} (fn []))

1:52 lazybot: ⇒ nil

1:53 amalloy: ,(meta ^{:x 1} (fn []))

1:53 clojurebot: {:x 1}

1:53 amalloy: ,(meta (macroexpand-1 ' ^{:x 1} (fn [])))

1:53 clojurebot: {:x 1}

1:53 amalloy: i thought for sure the metadata would get dropped in the macroexpansion

1:54 unlink: I only know this because I recently extensively evaluated using metadata to solve a problem I was facing.

1:55 amalloy: ah, i see that defn has special code in it to compensate for the fact that metadata is normally dropped in macroexpansions

1:55 unlink: (Due to the lack of a built-in equivalent to Python's functools.wraps, I opted not to encode the information with metadata.)

2:17 biscarch: Has anyone run a geoNear command with the Monger library?

2:21 Sgeo: I think I have a solution, but it's uglier than I'd like

2:23 All I have to do is coerce the IPolymorphicValue or whatever right before the first naive function uses it

2:24 I think, if Clojure had a condition system and threw TypeErrors or something that specified the desired type whenever it gets it wrong, I would be in business with something more elegant

2:28 tomoj: amalloy: know why it's different between bots?

2:28 amalloy: tomoj: the macroexpander i wrote for lazybot's sandbox is no good

2:28 tomoj: ah

2:33 oh, d'oh, you can't just set vars to nil to do locals clearing in cljs, of course. hmm

2:36 .. or can you? Compiler.java is fun..

2:36 amalloy: no?

2:36 clojurebot: no is tufflax: there was a question somewhere in there, the answer

2:38 tomoj: (let [coll (iterate inc 0)] (map #(* % %) coll))

2:39 seems like you can do something about that

2:43 Sgeo: ,(map #(* % %) (range))

2:43 clojurebot: (0 1 4 9 16 ...)

2:43 Sgeo: ^^(range) being a trick I saw on here I think

2:43 nsxt: is there a function like clojure.wal/walk that doesn't require the outer argument?

2:44 tomoj: right, iterate was stuck in my head because I have my own iterate. but the point is that the #(* % %) closes over the coll local and so you hold the head

2:44 Sgeo: ,(iterate #(* % %) 0)

2:44 clojurebot: (0 0 0 0 0 ...)

2:44 Sgeo: ,(iterate #(* % %) 1)

2:44 clojurebot: (1 1 1 1 1 ...)

2:45 Sgeo: Ok, so maybe I need some sleep

2:45 Ah, I see your point

2:45 Wait, no

2:46 Why would #(* % %) close over a thing that it doesn't reference?

2:46 ,(doc resolve)

2:46 clojurebot: "([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"

2:46 tomoj: in clojure it doesn't

2:46 in clojurescript, I think it does

2:46 Sgeo: o.O

2:46 tomoj: I should double-check, I just ran my cljs program and saw unbounded memory growth and took that as confirmation

2:47 but it wasn't a very simple program

2:48 biscarch: anyone use monger for a geoNear command?

2:52 or are there order-preserving maps in clojure?

2:54 cark: like sorted-map ?

2:54 amalloy: biscarch: there is a library providing them, but i encourage you to rethink whether you actually want ordered maps - often if you care about order you just want a seq of kv pairs

2:55 cark: or finger-tree ?

2:55 tomoj: hmm

2:55 Sgeo: ,(first {:a 1})

2:55 tomoj: a simpler test seems to show that you don't hold the head

2:55 clojurebot: [:a 1]

2:55 Sgeo: ,(-> {:a 1} first class)

2:55 clojurebot: clojure.lang.MapEntry

2:56 Sgeo: Does it make sense for someone to make their own MapEntries, to represent a kv pair?

2:56 biscarch: amalloy: thanks, I'll look into seq of kv

2:56 amalloy: $google flatland ordered

2:56 lazybot: [flatland/ordered · GitHub] https://github.com/flatland/ordered

2:56 amalloy: in case you decide you want an ordered map after all

2:56 Sgeo: Or do vectors make more sense for that case?

2:57 cark: ohh do these keep the complexity garantees of sets and maps ?

2:57 amalloy: cark: almost

2:57 dissoc is slow

2:58 i could have made everything O(log2(n)), but it turns out to be a lot faster if you let dissoc get slow, and it's rare to need to dissoc in an order-preserving map, in my experience

2:59 tomoj: dissoc is O(n) or what?

2:59 cark: interesting nevertheless

2:59 amalloy: tomoj: i don't remember. expensive

2:59 tomoj: hmm

3:00 amalloy: might be n^2, but n seems more likely

3:00 tomoj: wah?

3:00 cark: n^2 is not just slow =)

3:00 amalloy: i wrote it over a year ago, man, i don't remember what i did. the code is on github if you find yourself actually using dissoc

3:00 tomoj: it looks like it just does a dissoc on a map and an assoc on a vector

3:01 well and a get on the map

3:02 amalloy: oh. okay, so *that* compromise (there were a lot of options i had to choose between) makes everything fast (i think), but lets the thing grow without bound

3:02 tomoj: yeah I see

3:03 amalloy: ie, the vector containing a sorted view of the items will inset a nil in the middle

3:06 tomoj: huh, (nth (map #(* % %) (range)) 1e8) blows the stack in cljs

3:07 (take 10 (drop 1e5 (map identity (range)))) works

3:08 but (nth (map identity (range)) 1e5) blows the stack

3:08 (nth (range) 1e8) works

3:08 Sgeo: I was about to ask why the map identity, but I see

3:08 o.O

3:09 biscarch: amalloy: unfortunately I can't use sequences. I'm using a mongodb driver that throws an error if I try to use a seq.

3:09 amalloy: biscarch: but i don't think mongodb cares about the order of the map

3:10 biscarch: amalloy: that's what I thought. but when running a command using the Monger library, it re-orders my map and then returns 'near' is not a command

3:11 { "near" : 50 , "test" : 430 , "num" : 10 , "geoNear" : "bars"}

3:11 is what it changes to

3:11 and it comes back with: "no such cmd: near"

3:12 so my assumption is that the first entry is the command

3:12 amalloy: biscarch: instead of assuming, i'd say to look up the mongodb query/command api

3:13 tomoj: pretty weird. nothing jumps out at me in the source for nth or map

3:13 Sgeo: Would Clojure be an unusually bad starting language, due to having to learn Java interop at the same time as Clojure?

3:13 biscarch: amalloy: the syntax is correct in the mongodb docs, which is what the driver docs point to.

3:16 tomoj: would be nice if I got a stack trace..

3:20 ah, fixed :D

3:20 linear-traversal-nth is tail recursive but does not call recur

3:22 Sgeo: Is Javascript also not TCO?

3:23 What's with all these non-TCO languages?

3:23 ivan: no TCO in any JS engine I've heard of

3:24 Sgeo: :(

3:25 I guess making it a thing that someone might inadverdantly rely on would be bad

3:25 "Oh hey, my function works well on this JS engine, I assume it's good enough for the web"

3:28 amalloy: ah, well spotted tomoj. i didn't look at defn nth, but only at the protocol versions

3:33 biscarch: Sgeo: you can kind of do tco in js manually

3:33 Sgeo: dece article: http://paulbarry.com/articles/2009/08/30/tail-call-optimization

3:35 Sgeo: biscarch, uh, that looks like an explanation of TCO, not how to do TCO in JS

3:36 But yeah, you could at least write a trampoline like in Clojure

3:36 biscarch: Sgeo: that's about the best you get in js

3:37 Sgeo: biscarch, I don't think the article even mentions trampolining

3:40 biscarch: Sgeo: The idea in js would be to return a value so that the recursive function doesn't need to keep the previously call on the stack.

3:41 Sgeo: biscarch, the point is that if Javascript is not tail-call optimized, then even though it shouldn't need to keep the previous call on the stack, it will.

3:41 Oh, are we speaking past each other?

3:42 biscarch: Sgeo: true, and I think we are.

3:44 Sgeo: I don't see a workaround for Javascript's lack of tail-call optimization in that article.

3:44 biscarch: Sgeo: you would return a value so that the next time you call the recursive function, it doesn't have to wait and keep the previous call on the stack

3:46 Sgeo: Return a value from where to what?

3:51 hum_ph: hiyas

3:51 Sgeo: HI

3:51 *Hi

3:51 hum_ph: looking for some strategies for handling some java integration if anyone has 5 mins?

3:52 Rough background - I have a Map<String, Object> of inputs, and a Set<String> of output names, and a String script - need to return a Map<String, Object> of outputs - based on the supplied names...

3:52 Sgeo: In general, don't ask to ask, just ask. Although no guarantee that any person will stay talking and responsive for 5 minutes.

3:52 hum_ph: heh

3:52 Raynes: ~anyone

3:52 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

3:53 Raynes: :D

3:53 hum_ph: my current thinking is (with-local-vars ...) to bind the inputs, and outputs to nul - then unbind and rewrap on the way out

3:54 Sgeo: ,(map identity (constantly 5)) ; Unrelated

3:54 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$constantly$fn__2351>

3:54 hum_ph: so two questions: 1) is that a reasonable approach, or is there a saner way; and 2) if that's appropriate - what's the best way to get from a Map<String, Object> to those bindings - can't seem to get the String->var conversion thing happening

3:54 Sgeo: Why was I expecting that to work?

3:54 hum_ph: all of which I'm sure is my lack of experience understanding

4:05 amalloy: hum_ph: no, with-local-vars is nuts; really the only reason to ever use it is if you're rich hickey. but i can't see any way to solve your problem given the data you have provided, in clojure or any other language. what does the set of output names do? you seem to have a Map<String, Object>, which is your goal output, and no obvious way to get a new Object from a given String

4:06 hum_ph: amalloy: the java method is something like "public Map<String, Object> eval(Map<String, Object> inputs, Set<String> outputNames, String script) {..}"

4:06 amalloy: where the result map is expected to have keys from outputNames

4:07 tomoj: I'm thinking you don't actually hold the head in cljs with (let [coll (range)] (map #(* % %) coll))

4:07 amalloy: having a "script" String in clojure seems absurd. this whole thing just looks like a function that takes a map and returns a map

4:08 Sgeo: amalloy, I don't see what's wrong with with-local-vars, except possibly being unnecessary. It reminds me of the ST monad, similarly to transients.

4:09 ,(with-local-vars [foo nil] foo) ; Trying to leak

4:09 clojurebot: #<Var: --unnamed-->

4:09 hum_ph: amalloy: it's a plugin to an external server's scripting interface - so [admin] user can throw in arbitrary code through the browser and have it "do stuff" - or scheduled tasks can be scripted, etc etc

4:18 tomoj: hah

4:18 my memory leak is because of *1

4:31 Sgeo: I wonder if anyone here has used (partial comp blah ...)

4:32 Seems like it could be useful

4:41 mpenet: Is there a way to share code between builds using cljsbuild? I don't see an obvious way to do it reading at the docs

4:43 tomoj: isn't the normal thing to share code?

4:44 mpenet: it should be, from what I can see you are meant to have it all in a single file. I need to try the :lib option still, there might be a way to get around that

4:44 tomoj: not sure what you mean, single file? you have some external js code?

4:45 mpenet: no it is all cljs: i have a "common" namespace that I want to use in 2 separate builds

4:45 tomoj: oh, I see

4:46 well I guess you could symlink it as a workaround..

4:46 mpenet: yeah I thought about that, feels dirty though, but it could be good enough

4:47 Sgeo: How far up skit's creek would I be just using lein repl and Notepad++?

4:48 tomoj: hmm

4:48 cljs.closure seems to have no problem with a vector

4:48 did you already try :source-path ["foo" "bar"] ?

4:49 mpenet: nope I didnt try it

4:49 tomoj: don't really expect it to work

4:49 I think cljsbuild would need to be patched

4:50 mpenet: yep it seems, it tries to coerce the vector to a java file I think

4:50 tomoj: actually, cljs.closure's vector ICompilable does something different

4:51 so it might not even be possible without patching cljs?

4:51 mpenet: hmm

4:51 Sgeo: Is there a reason for the ordering of comp's arguments, other than tradition?

4:52 ,(doc comp)

4:52 clojurebot: "([] [f] [f g] [f g h] [f1 f2 f3 & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

4:52 tomoj: maybe you wouldn't need to change cljs, but certainly cljsbuild :/

4:55 Sgeo: Oh hey I'm not the first to notice maybe-m's brokenness

4:55 http://rhebus.posterous.com/learning-monads-in-clojure-a-warning

4:57 mpenet: tomoj: cljs I think :( it s sent to cljs.closure/build which accepts a single source path or sexp

4:58 but that seems odd, given the error, I might be wrong

4:59 tomoj: well

4:59 cljsbuild could implement a new ICompilable which just compiled multiple dirs

5:00 then you just have to go patch the places where cljsbuild thinks it's a string

5:05 amalloy: Sgeo: ((comp f g h) x) is (f (g (h x))): comp is in the same order as N literal invocations would be

5:05 Sgeo: Ah

5:05 Makes se

5:05 *sense

5:08 mpenet: tomoj: yes, this seems like a good solution, I'll try that.

5:10 tomoj: I had thought of providing a way to specify :only/:exclude namespaces, but multiple source dirs would actually cover my use cases I think

5:14 mpenet: this would also work with multiple file-path not only dirs

5:24 tomoj: great

6:36 mpenet: How does cljsbuild ("support" dir) end up bundled with the leiningen lein-cljsbuild plugin ?

6:39 kral: Arrr everyone.

7:45 Cheiron: Hi, i'm trying to use liberator. how to assign a function to :get request method and how to assign a function to :post request method?

8:18 zepard: hey

8:39 gfredericks: hello

8:41 Sgeo: Hi

8:41 ljos: Hi - I am having a problem with noir and wondered if there was someone who could help me. I am trying to serve the content of a few csv files. Right now I have this: http://pastebin.com/7KV6vjer . The problem is that when I press the link it will not present the file, I have to refresh the page. Anyone who can tell me what I am doing wrong?

8:44 In the browers I only get "undefined".

8:44 gfredericks: I can't imagine that the (into [] ...) is necessary on line 2, but that wouldn't be your problem

8:45 ljos: Yeah. It is not. I had something else there before and forgot to remove that.

8:45 gfredericks: also a <br> inside an <a> is weird

8:46 ljos: I just had it there because of how the for acts. I can try to move it out though.

8:46 ludston: gfredericks: Having a hyperlink on more than 1 line won't matter.

8:46 ljos: still the same problem

8:46 gfredericks: ludston: I wasn't suggesting that was his problem

8:47 ludston: How are you accessing the page you want the file on?

8:47 ljos: So what I want to do is press the link and have the file presented.

8:47 gfredericks: presented? you want it to download in the browser?

8:48 ljos: No, served. So it gives me the download option.

8:48 It does that if I refresh the page after I get an "undefined"

8:48 gfredericks: what exactly happens when you 'get an "undefined"'?

8:49 ljos: I press the link and it says "undefined" without quotes in the upper left corner.

8:49 Cheiron: hi, any body is using liberator here?

8:49 ljos: If I reload the page with the undefined it serves the file.

8:50 gfredericks: ljos: have you tried hitting the download URL with curl?

8:50 ludston: I have this bizzare theory, that could be entirely wrong

8:51 But could it have something to do with http? When you refresh the page, is it acting as a post-back rather than a get request?

8:52 ljos: gfredericks: It works perfectly fine if I do a (noir.util.test/send-request "/data/file.csv").

8:53 gfredericks: wget works as well.

8:53 gfredericks: ljos: what if you wget with a POST like ludston theorizes?

8:54 ljos: ludston: The developer tools in chrome desribes it as a GET request.

8:54 ludston: Is there any other data in the GET request when you click on the hyperlink?

8:55 Anything in the session or something stupid like that?

8:56 ljos: ludston: actually there is some difference between the two. I will investigate...

8:57 ludston: I'd be interested to know if you figure it out. I've barely touched noir

9:00 ljos: It actually gets served, there is something wrong with something else.. maybe a part of the header.

9:10 aib: what are the practices for unit testing numeric functions? I not only want (is (= [1 2 3] [1.0 2 3])) but also (= 1.99999 2)

9:12 ludston: aib: I'm not sure what you're asking. Are you asking about test frameworks, or how test those in such a way that their values will be true?

9:13 aib: ah, forgot to specify. I was asking about clojure.test

9:15 ludston: aib: I'm still not sure if you're asking about how to use the clojure.test api in general, or what the results of the tests you've defined are.

9:17 aib: I'm asking how people have solved the floating-point-equation/epsilon problem, as well as the problem that (long 0) does not equal (double 0) - regarding the clojure.test framework

9:17 naeg: core.logic: tried to put some goals into a function, but it doesn't behave as it should: http://bpaste.net/show/D4ey8nx5BhwhaFxaLJvT/

9:18 aib: should I roll my own operators? is there some clojure.test.contrib? am I approaching this the wrong way, i.e. should I test my result /types/ as well?

9:18 you know, standard practices. what the world is going with nowadays

9:19 naeg: aib: how are you testing those two numbers?

9:19 ,(== (long 0) (double 0))

9:19 clojurebot: true

9:20 aib: naeg: (= [1 0 0] (some function which returns [1.0 0 0.0])) currently

9:20 ,(== [1 2 3] [1.0 2.0 3.0])

9:20 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>

9:21 Sgeo: ,(map == [1 2 3] [1.0 2.0 3.0])

9:21 clojurebot: (true true true)

9:22 Sgeo: ,(every? (map == [1 2 3] [1.0 2.0 3.0]))

9:22 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$every-QMARK->

9:22 aib: ,(and (true true true))

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

9:22 aib: ,(and '(true true true))

9:22 clojurebot: (true true true)

9:22 aib: hmm

9:22 Sgeo: ,(doc every?)

9:22 clojurebot: "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

9:22 ludston: ,(= [1 2 3] [1.0 2.0 3.0])

9:22 clojurebot: false

9:22 duck1123: a symbol is a truthy value

9:22 ljos: ludston: This is so strange, there is no difference that I can find between pressing the link and reloading the page... :(

9:23 Sgeo: ,(every? identity (map == [1 2 3] [1.0 2.0 3.0]))

9:23 clojurebot: true

9:23 Sgeo: ,(every? identity (map == [1 2 3] [1.0 2.0 3.1]))

9:23 clojurebot: false

9:23 Sgeo: That every? identity is ugly

9:23 ,(doc any?)

9:23 clojurebot: Pardon?

9:23 Sgeo: ,(doc any)

9:23 clojurebot: Huh?

9:23 Sgeo: ,(doc some)

9:23 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

9:23 aib: ,(doc all)

9:23 clojurebot: It's greek to me.

9:23 jowag: ,(doc ==)

9:23 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

9:24 ludston: ljos: It must be some noir specific thing then. Try returning just "file" as the content of the webpage and see what happens.

9:24 Sgeo: ,((comp (partial every? identity) (partial map ==)) [1 2 3] [1.0 2.0 3.0])

9:24 clojurebot: true

9:26 chronno: ,(every? true? (map == [1 2 3] [1.0 2.0 3.0]))

9:26 clojurebot: true

9:26 Sgeo: ...there's a true? why?

9:26 ,(true? 5)

9:26 clojurebot: false

9:26 aib: ,(doc partial)

9:26 clojurebot: "([f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & ...]); Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args."

9:27 loliveira: ,42

9:27 clojurebot: 42

9:27 aib: partial = curry?

9:27 clojurebot: I don't understand.

9:27 Sgeo: aib, yes

9:27 chronno: I guess to complement "false?", not sure though

9:28 ljos: ludston: there is something wrong with the link... I still get undefined, but now when I reload it it gives me the filename.

9:29 ludston: ljos: What happens when you take the :class "" out of :href?

9:29 Shouldn't the :class be in the anchor tag?

9:32 aib: this is hard to search for: is there a is-vector? pred?

9:32 ljos: ludston: This is what I get for being a smartass. I figured it out. It was a piece of javascript library that interacted with the href I think. Now it works.

9:32 chronno: ,(doc vector?)

9:32 clojurebot: "([x]); Return true if x implements IPersistentVector"

9:32 aib: thanks

9:32 ljos: ludston: thanks for your help.

9:33 ludston: ljos: So it WAS the :class? Or did you override the GET request with javascript?

9:33 chronno: aib: np

9:34 ljos: ludston: In an effort to remove as much code as possible to show to you guys, I removed the common/layout I had in my code. The layout imports some javascript that I think is doing strange things to my a-tag or href.

9:34 chronno: aib: You can use find-doc to search the doc strings

9:35 aib: chronno: good tip :) thanks

9:35 chronno: aib: make sure you are have clojure.repl available and then (find-doc #"vector")

9:35 ljos: ludston: I have been using that javascript just fine for buttons and other things through the <a :href="link"> but it didn't linke this.

9:36 ludston: ljos: I'm glad you worked it out. Time to sleep.

9:44 aib: what does map apply to? IOW, what's the definition for (can-apply-map? x) where (map _ x) is valid?

9:49 chronno: aib: in the case that was shown earlier, map was given two vectors so it applies "==" to elements at the same position for each vector

9:49 aib: yes, but why restrict my function to vectors when it can do much more? :)

9:50 https://gist.github.com/3749769

9:51 lotia: does the future macro take an optional timeout and optional return value in case of timeout anymore, or is that supposed to be done via deref?

9:51 aib: simply replace (vector?)s with (is-mappable?)s and it can work with anything that map can. Haskell practice :)

9:51 chronno: :-)

9:51 clgv: aib: you are aware that clojure data structures are compared by value and so a simple = is sufficient to compare them?

9:52 aib: *anything that map and eq-fn can work with :)

9:52 clgv: yes, but

9:52 ,(= (long 0) (double 0))

9:52 clojurebot: false

9:52 aib: ,(== (long 0) (double 0))

9:52 clojurebot: true

9:53 chronno: I'm a noob also, but I think the abstraction you are looking for then would be sequences

9:53 aib: I'll also need "nearly==" soon for floating-point "equality" checks, e.g. 1.99999 vs 2

9:53 ludston: Clojure has a "Close enough is good enough" predicate?

9:55 clgv: midje has `roughly`

9:55 aib: I'd still need a recursive check to do (rougly== [x1 y1] [x2 y2])

9:56 unless the "predicate" itself is recursive ("descending"), in which case I don't need anything else

9:57 naeg: some core.logic users here? Having strange behaviour: http://bpaste.net/show/OKOVq8ydgcZylMh3iayB/

9:57 no idea where that exception comes from

10:05 clgv: aib: anyway, you can use sequential? or coll? as check

10:06 Cheiron_: hello, any one using liberator?

10:08 ludston: Cheiron: What's liberator?

10:08 Cheiron: https://github.com/clojure-liberator/liberator

10:12 aib: clgv: ahh, coll?. thanks

10:25 gfredericks: dangit naeg left

10:33 augustl: is there a way to "rewind" an IO object prior to (slurp)? Currently getting nil from a slurp because I slurp something that has already been fully read.

10:33 the object I'm slurping is a org.eclipse.jetty.server.HttpInput, which is a java.io.InputStream

10:36 is there a convention of some sort for middlewares that slurp the :body of a request so that other middlewares can also read it later?

10:36 gfredericks: augustl: I think you could replace it with the string result

10:36 maaaaybe

10:37 but generally I think what you're talking about would defeat the purpose of using streams

10:37 since you'd probably end up with the whole thing in memory at once

10:37 unless you wrote it to disk instead

10:37 duck1123: what about using mark and reset?

10:37 * gfredericks goes away as the conversation is now over his head

10:37 augustl: it does make sense to only read the body once, yeah

10:38 duck1123: looking at the docs, there are 2 methods called mark and reset http://download.eclipse.org/jetty/stable-7/apidocs/org/eclipse/jetty/server/HttpInput.html

10:39 I don't know if HttpInput supports it

10:40 augustl: also, what's a good way to test that something is a slurp-able object (not a string with an URL or a path)?

10:44 duck1123: probably has something to do with IOFactory

10:46 grettke: Question for Windows Emacs users: If you are using V24... from where did you get it? I don't see it on the gnu site.

10:48 duck1123: grettke: I always use http://ourcomments.org/Emacs/EmacsW32.html on windows

10:48 eriko: grettke: it's under the windows folder, you have to scroll a bit: http://ftp.gnu.org/pub/gnu/emacs/windows/

10:49 grettke: eriko: I think they haven't released v24 yet :(

10:50 eriko: Windows build I mean

10:50 duck1123: oh ok, thanks

10:51 duck1123: I'm not sure what version that actually is now. (I couldn't find it on the site) but that one worked well enough for me

10:51 eriko: grettke: maybe I'm missing something but I see emacs-24.2-bin-i386.zip there. I haven't tried it, though. Sorry if it's nosie.

10:53 grettke: eriko: I could be looking in the wrong place? I'm looking here: http://ftp.gnu.org/pub/gnu/emacs/windows/ . Is that where you are looking?

10:54 eriko: Weird, the emacs home pages links to a different folder, http://ftp.gnu.org/gnu/emacs/windows/ has what you are pointing out

10:55 eriko: Thanks I thought I was losing it.

10:55 eriko: grettke: Yeah, not sure what's up there. Mirrors, maybe? Anyway, hope that's the right one.

10:59 grettke: eriko: It is perfect. Thanks!

11:01 ro_st: ckirkendall: sup

11:33 jro_: How do you prefere pointing 'matrix' elements, (([[1 2] [3 4]] i) j) looks bit clumsy to point element i,j?

11:34 i.e. is there shorthand for applying for example (defn e [m i j k] (((m i) j) k))

11:35 scriptor: ,(get-in [[1 2] [3 4]] 0 0)

11:35 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

11:35 ohpauleez: get-in

11:35 scriptor: ,(get-in [[1 2] [3 4]] [0 0])

11:35 clojurebot: 1

11:36 jro_: thanks

12:32 jcromartie: what's the state of zippers?

12:33 Is this the latest? http://clojure.github.com/clojure/clojure.zip-api.html

12:33 and what's the difference between clojure.data.xml and clojure.xml

12:34 obviously clojure.xml is older

12:34 clojure.data.xml does not appear on the official API docs despite appearing to be an official Clojure library

12:45 powrtoc: whats the best way of getting started with clojurescript, nrepl and leiningen these days?

12:45 is there a template?

12:45 clgv: I get an AbstractMethodException with proxy. is it because of overriding some method?

12:48 can I implement an abstract method via `porxy`?

12:48 *proxy

12:49 nsxt: powrtoc: https://github.com/cemerick/piggieback maybe?

12:49 raek_: clgv: I think so, since you can implement interfaces with proxy

12:50 clgv: are you sure that the method arity is correct, etc?

12:50 powrtoc: am I right in thinking that even within emacs, swank-clojure is now deprecated in favour of nRepl?

12:50 clgv: raek_: proxy doesnt need an explicit "this" right?

12:50 jcromartie: dang, don't try to print a zipper

12:50 raek_: clgv: yes. 'this' is magically bound in the body of the method

12:51 check out the macro expansion

12:51 technomancy: powrtoc: swank-clojure isn't going to break, but it's not getting any further development

12:51 Cheiron: Hi clojurians! any fella uses liberator rest toolkit?

12:52 powrtoc: technomancy, cool... what are people using these days? ritz?? It's been a while since I've done any clojure/clojurescript

12:52 technomancy: ritz and nrepl.el should both work nicely

12:53 clgv: raek_: damn! you were right. I did a mistake with a macro and thus one method was missing in the proxy form :(

12:53 technomancy: I haven't done any clojurescript myself, but it sounds like lein-cljsbuild is more or less the way to go

12:53 powrtoc: technomancy: yeah, that seems to be what people are running with...

12:53 raek_: clgv: you can also use the underlying functions instead of the 'proxy' macro

12:56 clgv: example of a "function version" of proxy: https://gist.github.com/1098101

12:57 (I used that in one of my project to get proxy methods which would pick up updated function defs)

12:59 jcromartie: in Xpath I can make compound predicates like [foo and bar]

12:59 is there any equivalent in a the xml-> zipper filter?

12:59 powrtoc: hmm when trying to run lein nrepl I get: Warning: profile :jpda not found. Exception in thread "main" clojure.lang.ArityException: Wrong number of args (1) passed to: nrepl$start-jpda-server

13:11 velvia1: newb question: how do I insert a sequence in the middle of another sequence?

13:12 I couldn't find any built in function that does that

13:13 technomancy: combination of take, drop, and concat

13:14 velvia1: something like this?

13:14 (defn insert [n list list2] (concat (take n list) list2 (drop n list))

13:14 thought there would be something shorter than that

13:14 casion: you want the members of the sequence in the new sequence, or you want the sequence itself inserted as a member of the sequence?

13:14 velvia1: members of sequence in new sequence

13:20 antares_: velvia1: then your concat-based code is what you need

13:20 velvia1: I see, thanks

13:21 grettke: is marmelade the best place to pull down clojure-mode and all its requires from using elpa?

13:21 technomancy: grettke: yeah, definitely

13:22 grettke: technomancy: thank you

13:22 jweiss: am i missing an easier way to implement 'juxtcat'? https://www.refheap.com/paste/5158

13:25 S11001001: jweiss: (mapcat #(apply % args) fs)

13:25 powrtoc: will nrepl ever use edn?

13:26 jweiss: S11001001: ah of course, thank you

13:26 i knew 3 apply's couldn't be right :)

13:38 naeg: dnolen: hey, I'm the one who just wrote you that email about contributing to core.logic. No, I'm sadly not going to Strange Loop, too far away

13:40 dnolen: will that session be recorded so I can watch it too?

13:41 dnolen: naeg: it will hopefully get recorded! I'll try my best to make that happen.

13:42 ro_st: ckirkendall: i'm back

13:44 naeg: dnolen: that would be great. Also, while you're around, could you probably take a look at my problem? I asked before, but nobody could help me: http://bpaste.net/show/OKOVq8ydgcZylMh3iayB/

13:44 ro_st: dnolen: how is your adventure with sourcemaps going? -curious-

13:45 naeg: I'm trying to implement conways game of life in core.logic and I'm able to generate all neighbours with neighbouro. The two runs are both trying to find out whether the given coordinate has 3 living neighbours (the first one would be the correct run but fail with an exception and the second one is incorrect since there are only two distinct living neighbours)

13:58 dnolen: naeg: sorry, don't have time to really look at that this second.

13:59 ro_st: been a bit to busy prepping for strange loop talks to work on that.

13:59 cemerick: powrtoc: cljsbuild + piggieback for the REPL stuff is the best combo for an nREPL ClojureScript environment at the moment.

13:59 naeg: I'll play around with it again these days, maybe it solves itself

14:00 ro_st: dnolen: no worries. just thought i'd check in :-)

14:02 hiredman: cemerick: that depends what you want, if you want to embed a clojurescript repl in a browser, I dunno that piggieback would work well for that

14:02 dnolen: naeg: I'll try to take a look at it later this evening - probably something simple

14:03 hiredman: if you want to pass clojurescript to nrepl, and get compiled js back you can use https://github.com/hiredman/nrepl-cljs-middleware

14:03 naeg: dnolen: maybe, can't really tell. played around with it for hours. you got my email if I shouldn't be around then

14:03 cemerick: hiredman: True; though it sounded like powrtoc was aiming to do all his programming from emacs (or lein or whatever).

14:05 hiredman: re: drawbridge nREPL client in cljs, that should be pretty straightforward given jquery or whatever bits the goog stuff provides, yah?

14:05 hiredman: does nrepl.el have some way to register handlers for messages?

14:05 cemerick: https://github.com/hiredman/drawbridge-cljs

14:06 cemerick: hah!

14:06 beautiful

14:06 hiredman: I haven't done any clojurescript in a month or two, so who knows if it still works

14:06 cemerick: man, I just can't gin up any motivation to learn those goog APIs though

14:07 hiredman: yeah, that requires a lot of poking around and scanning the docs and examples

14:07 drawbridge-cljs started on jquery ajax stuff, until I figured out how to do with the goog stuff

14:08 (le goog stuff?)

14:08 cemerick: I almost always have jquery coming in somewhere anyway, so…it's just too easy to not bother.

14:08 That's app stuff, of course.

14:11 * ro_st 's production js app comes in at under 250kb right now, and over half of that is fonts

14:11 ro_st: that's over the wire with gz

14:12 no jquery, because it'd add 15% to the download!

14:13 using just enfocus and plain cljs to do dom stuff

14:13 and shoreleave for glue and remotes

14:13 does cljs repl allow the use of stuff like shoreleave and enfocus?

14:14 cemerick: why wouldn't it?

14:14 cark: ro_st: that's with advanced compilation

14:14 ?

14:14 ro_st: yeah

14:15 i guess the repl only works in whitespace mode?

14:15 cark: that's quite a lot =/

14:15 cemerick: That's probably right.

14:15 ro_st: cark, that's 250kb total page weight

14:15 cark: oh right

14:15 ro_st: js, css, fonts, and the startup html

14:16 cark: any images in there ?

14:16 anyways i mean : what's total size of your js ?

14:16 ro_st: one sprite

14:16 80kb over the wire, 290kb on disk

14:17 cark: 290k is with minification ?

14:17 i mean adavnced compilation

14:18 dnolen: ro_st: how many lines of your own ClojureScript?

14:22 ro_st: 2150 lines of app code

14:22 and then enfocus (and domina) and shoreleave (remotes, browser, pubsub)

14:23 cark: yup, advanced minification

14:23 dnolen: ro_st: so lots :)

14:24 ro_st: yup

14:24 cark: ro_st: thanks for sharing those numbers

14:24 dnolen: ro_st: and the gzipped JS is around 50k-60k or so?

14:24 ro_st: 80kb

14:25 1,890,250 main-debug.js

14:25 291,131 main.js

14:25 dnolen: ro_st: not bad - I think CLJS strategy really pays off when you want to use really rich libraries w/o worrying too much about the final payload.

14:25 ro_st: whoa, 1.8 millions lines of JS?

14:25 cark: yes i find those numbers quite acceptable

14:25 ro_st: bytes :-)

14:25 dnolen: ro_st: whew k

14:26 ro_st: i'm delighted. this is a v2 build of an app originally done with flex and air

14:26 dnolen: ro_st: sweet!

14:26 ro_st: try a 3.2mb swf on for size.

14:27 we have a working mvp up now at under 5kloc from the datomic schema through to the cljs

14:27 cark: what about browser compatibility, how far back do you go with all these libraries ?

14:27 ro_st: clojure is awesome.

14:27 we're not using any html5 stuff yet

14:27 it's all working in ie8+

14:27 cark: kk

14:28 so that's windows 7 onward, right ?

14:28 ro_st: plan to do the pjax thing, though, which does mean some fiddly bits

14:28 xp goes to ie8

14:28 cark: ok

14:28 ro_st: vista onward support 9

14:28 cark: good ebnough then

14:28 ro_st: yup

14:28 cark: enough*

14:29 ro_st: and we have very little to do for ipad. quite a lot to do for mobile, though

14:29 this is way, way better than the bloody flash player

14:30 i've been pretty spammy with this, so forgive me if you've already seen it: https://github.com/robert-stuttaford/demo-enfocus-pubsub-remote

14:34 ckirkendall: ro_st: how you doing

14:34 ro_st: good, tx, and you? any luck? :-)

14:34 ckirkendall: ro_st: I think I understand what is happening but it looks like a bug in FF and Chrome

14:35 ro_st: oh dear

14:35 can it be worked around, or are we toast?

14:35 ckirkendall: the dom is being clone and there is no value="" attribute being placed on the item. However the value property is getting updated on the cloned one when you update the input on the screen if no value exists. Its not a clean clone there is still some form of connection with the value property.

14:36 ro_st: crap brb

14:37 ckirkendall: This problem seems to also exist for jquery

14:37 ro_st: daughter wailing head off

14:37 ckirkendall: oh no

14:49 jbarrios: is kingtim/nrepl.el the version to use?

14:50 ah, I don't have marmalade.. let's try that

14:53 ro_st: apologies

14:53 2 year old. still learning to fall asleep on demand :-)

14:53 ok, ckirkendall, what are our options?

14:54 the input bug was the easiest way to demonstrate the issue, but we've had it with normal divs too

14:56 ckirkendall: Not sure I understand it with divs. That woudl contradict what I found. I think I can fix input in two ways. We can store the cache as text and serialize them out each time or we can run stuff through a transform before we hand it back that sets the property to the value of the attribute value.

14:57 jbarrios: aight, I just needed to upgrade nRepl to 0.1.4

14:57 ckirkendall: ro_st: I inspected the dom in chrom and it was true that value attribute was blank

14:57 ro_st: the text option sounds cleaner to me

14:58 ckirkendall: ro_st: me too but there is a performance hit on that one.

14:58 ro_st: i thought the cache was text to begin with

14:58 ckirkendall: no its a dom fragment that we call cloneNode(true) on

14:58 ro_st: aha

14:58 perhaps we could support metadata on defsnippet to control text vs nodefragment caching?

14:59 ckirkendall: what is odd is that clone is cloning the dom but for form elements it seems some properties stay link until a value exists.

14:59 that might work

14:59 ro_st: unrelated, i tried the :compiled option on deftemplate and cljsbuild exploded :-)

14:59 stracktrace as long as my arm

14:59 ckirkendall: hmmm

15:00 just on deftemplate or did you try it on both.

15:00 ro_st: i can file a formal issue for you so you can take a look when yo have a mo

15:00 ckirkendall: I have defsnippet compile in most of my test cases.

15:00 ro_st: deftemplate. the docs and the source seemed to suggest that ony deftemplate supports it

15:00 ckirkendall: I will can you include your cljsbuild setup and clojure version

15:01 ro_st: oh! i'll give that a try then

15:01 sure

15:01 ckirkendall: both support it

15:01 ro_st: just to confirm, it's (defthing :compiled sym "path" [args] …) right?

15:01 that's the order

15:01 ckirkendall: I am going to do some profiling to see what the performance impact is for text

15:02 if its not that huge I may default to that

15:02 yes

15:02 wait let me look

15:03 sym should be before the :compile

15:04 I deconstruct it with sym first

15:04 ro_st: ah, then your readme is wrong

15:05 see what i mean?

15:05 :compiled after the sym works!

15:06 ok. we're going to continue forcibly reseting the things we find need to be reset and we'll see how things go once you manage to get to the text cache

15:07 thanks for your prompt attention. bugs aside, enfocus is a great pleasure to use

15:08 ckirkendall: thanks for finding these, these edge cases are what need to weeded out before we get to 1.0 status.

15:09 mpenet: ckirkendall: not sure it is a bug, isnt it a matter of prop vs attributes? at least .value and .checked (maybe even other) do not update the node attribute


15:10 at least from the dom api perspective, not to say it's not weird, but at least it something documented

15:10 ckirkendall: mpenet: its a bit more complicated than just not updating the node attribute. it look like on first clone the value properties are still linked between the clone and the orignal. So when the clon is updated the original now has a new value.

15:11 its really ugly

15:11 abalone: is there an online clojurescript repl for random people to try things?

15:11 mpenet: aww ugly indeed

15:11 ro_st: abalone: himera

15:11 abalone: thanks!

15:11 ro_st: ckirkendall: on first clone. are subsequent clones clean?

15:12 ckirkendall: It seems only on first clone the value is linked.

15:12 that is why it keeps going back to the first value entered

15:12 ro_st: what if you throw away the first one?

15:13 ckirkendall: I might do that on load and see what happens.

15:13 ro_st: that would be awesome if it works

15:13 ro_st: kinda like the first beer. just a lining for the rest

15:13 ckirkendall: lol

15:14 ro_st: may i suggest you start there? it might just sort it out

15:15 i like that i can compile snippets. means i can cut our start up request count down to 10 :-)

15:19 hmm. "(em/defsnippet context-toolbar :compiled" "java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.String"

15:22 ckirkendall: i've tried :compiled after defsnippet, after the sym, and after the template path. each time i get cljsbuild exceptions

15:22 jro_: I'm defining a compojure route: (defroutes app-routes (GET "/rest/v1/throw" [] (throw (Exception. "ex")))). How I can define a handler which logs the exception thrown?

15:23 ro_st: jro_: a ring middleware, maybe?

15:23 weavejester: jro_: You mean a middleware function?

15:23 jro_: yes

15:23 weavejester: jro_: e.g. (defn wrap-catch-ex [handler] (fn [req] (try (handler req) (catch Exception ex (log ex))))

15:26 ro_st: ckirkendall: does :compiled work with keyword selectors?

15:26 ckirkendall: ro_st: odd, I will take a look

15:26 ro_st: ckirkendall: i'm using keyword selectors, not string selectors.

15:26 ckirkendall: it should

15:26 ro_st: switching to string selector fixes it

15:27 ckirkendall: hmmmm

15:27 That would be a bug

15:27 ro_st: no! i apologise

15:28 i'm using a reference to a (def templates "some-path") instead of a string

15:28 if i use the string, it works

15:28 if i use the ref to the string, it dies

15:29 ckirkendall: yes that make sense

15:29 because I don't have access to the value of the ref during compile time.

15:29 ro_st: is it because this is happening at compile time and it's not resolving htat reference

15:29 ahh

15:29 ok

15:29 ckirkendall: I need to update the documentation to make sure people realize that

15:31 ro_st: confirmed. working

15:32 yikes. not such a good idea ito filesize. js now 604kb, or 603kb with gzip!

15:33 or 2.2mb with no minification

15:33 i think i'll keep the extra web requests :-)

15:33 ckirkendall: lol

15:34 right now defsnippet brings in the whole file.

15:34 I can fix that but I have to add a dependency to enlive.

15:35 I am planning on that fix but it going to be a little while.

15:36 ro_st: that's ok. i'm happy to stick to a runtime load. browser caches it just fine, and it means that we can use the templates from enlive if we want

15:40 ckirkendall: would you mind pinging me on twitter when you want me to give something a try?

15:40 gotta go. thanks again :-)

15:42 ckirkendall: np

15:54 jro_: somehow I cannot catch exceptions: the context is here, where I try to define an exception logger: (defn wrap-catch-ex [handler] (fn [req] (try (handler req) (catch Exception ex (.error logger ex)))))

15:55 https://github.com/jrosti/ontrail/blob/master/src/ontrail/core.clj#L69-70

16:18 gfredericks: jro_ is gone?

16:29 noidi_: I'm supposed to talk a bit about functional programming and code reuse to a bunch of Java programmers

16:29 what do you think about this example https://gist.github.com/3751951

16:30 I hope they'll be able to get the gist of the functional code even with all those horrible parentheses everywhere :)

16:31 Iceland_jack: noidi_: maybe introduce #() a bit later on

16:32 scriptor: yea, it's not strictly necessary

16:32 explicit names keeps things clearer

16:34 Iceland_jack: #() is nice when you're better acquainted with the language, I can imagine that it would feel like a ternary operator to people that aren't familiar with folds or anonymous functions in the first place

16:35 gtrak: is there something akin to maven submodules and a reactor build in lein? I want to reference an undeployed project version in another project that builds a zip distribution

16:38 noidi_: Iceland_jack, you're probably right, thanks

16:38 amalloy: scriptor: are you skipping min-key and max-key on purpose?

16:38 scriptor: amalloy: er, what's the context?

16:39 amalloy: oh, i was just misreading who said what :P

16:39 i meant noidi_

16:39 noidi_: I even considered doing the whole thing in JavaScript, but I'd rather show Clojure as "the better java"

16:40 amalloy, simple reason: I didn't know about them :)

16:41 scriptor: noidi_: the implementations for them are pretty simple, so you can just wrap up by rewriting your code using them and then explaining how min-key and max-key themselves work

16:42 amalloy: noidi_: http://amalloy.hubpages.com/hub/What-is-Clojure has a bit on the same topic; feel free to steal some of it

16:42 noidi_: amalloy, thanks!

16:45 scriptor, I don't know if that's necessary. The point I'm trying to convey is that when you solving a very specific problem using FP tends to lead to a very generic solution.

16:46 s/when you//

16:58 brainproxy: if any of you folks are already in St. Louis, i.e. you've arrived early in anticipation of Strange Loop, please know you're welcome to come hang out tomorrow night at STLJS

16:58 http://www.stljs.org/events/68051712/

16:58 I'm the organizer, and though the meetup's focus is on node.js / javascript, many of the folks who attend are into all sorts of other stuff, like clojure / clojurescript

16:58 including me, of course

17:00 irctc423: Hi Clojure fans - question about interop and overloaded methods...

17:00 I'm trying to call submit with a clojure fn

17:00 but I can't make it choose the Callable version of the submit method, without reifying a Callable.

17:01 nDuff: Isn't IFn Callable?

17:01 irctc423: Is there a way to force it to choose the right version with type hints or anything?

17:01 It is Callable, but it is also Runnable

17:01 and submit has overloaded implementions with both.

17:01 nDuff: Ahhh.

17:02 * nDuff doesn't know offhand of ways to do that that aren't evil and reflection-y.

17:02 irctc423: this works: (.get (.submit exe (reify Callable (call [_] ((fn [] (+ 1 1)))))))

17:02 this doesn't: (.get (.submit exe (fn [] (+ 1 1))))

17:03 hiredman: irctc423: type hint your function as callable

17:03 (.submit exe ^Callable foo)

17:04 irctc423: hiredman - I still get nil when I try that: (.get (.submit exe ^Callable (fn [] (+ 1 1))))

17:05 hiredman: irctc423: you can't type hint a fn like that, you have to pull the fn out in to a let

17:05 irctc423: Ahh...

17:06 S11001001: shouldn't type of a lambda be known, due to fn* being special?

17:08 irctc423: thanks hiredman - I'm going to concentrate on getting my type hints to stick.

17:09 nDuff: S11001001: It's known to be IFn, but irctc423 wants to be more specific than that.

17:09 hiredman: https://github.com/hiredman/clojurebot/blob/master/src/hiredman/schedule.clj

17:10 S11001001: nDuff: can fn* yield a non-AFunction?

17:11 hiredman: if you type hint a fn form like ^Callable (fn ...) I am pretty sure you end up typehinting the return value of the fn, but if you bind the fn to a name like foo, then ^Callable foo will type hint the value of the name, which is the fn

17:14 irctc423: I still can't get it, but I see your example - I must be doing something wrong...Thanks a lot for the help.

17:15 nDuff: irctc423: (let [^Callable your-fn (fn [] + 1 1)] (.get (.submit exe your-fn))))

17:16 irctc423: nDuff: That gives you a result? I get nil on 1.4.0

17:16 amalloy: S11001001: fn yields something that is both Callable and Runnable, and the .submit function is overloaded to accept either

17:17 the compiler can't decide at compile time which one you want to call, so it defers the decision to runtime

17:17 nDuff: irctc423: Haven't tested it -- didn't get enough context to know how to reproduce. What's "exe" supposed to be?

17:17 irctc423: nduff: sorry: (def exe (Executors/newSingleThreadExecutor))

17:17 S11001001: amalloy: ah, I see

17:20 nDuff: ; (let [exe (java.util.concurrent.Executors/newSingleThreadExecutor)] (let [^Callable your-fn (fn [] (+ 1 1))] (.get (.submit exe your-fn))))

17:20 irctc423: that returns 2 for me.

17:23 irctc423: nDuff: Me too! Now to figure out exactly how that is different from all the very similar attempts I have which don't work :)

17:23 Thanks for the help...

17:27 nDuff: The only difference is that you have the executor defined in a let, and I have it in a def...

17:29 nDuff: ...is that to say that you can reproduce the issue with only that one change? If so, is the var you create with that def marked dynamic?

17:30 irctc423: Yes - just that one change. The exe var is not dynamic

17:36 S11001001: :r

17:36 yep

17:37 irctc423: nDuff: Thanks for the help - signing off now. Might clean up my example and post to the group. a bientot

17:57 y3di: what are some examples of apps that use storm?

17:59 lnostdal: y3di: https://github.com/nathanmarz/storm/wiki/Powered-By ?

18:00 y3di: cool thanks

18:44 tomoj: well, this turned out pretty useless http://tomoj.s3.amazonaws.com/cljsprotos.html

18:51 I also didn't consider extend-type/extend-protocol :(

20:27 gjcourt: is there an easier way to do lazy connections than using an atom? ie: something like this? http://dl.dropbox.com/u/2110/Screenshots/0ht.png

20:29 nDuff: gjcourt: Depends on how much support you want to have for reconnecting on failures. If you don't care so much about that, there's delays

20:29 gjcourt: ...if you _do_ care about that, I've been known to abuse agents for the purpose.

20:30 * nDuff realizes that such is, in fact, considered abuse... well, kinda' -- there _is_ state being maintained, and one _does_ often need to have only one thread at a time interacting with the connection, so such things aren't a completely awful fit.

20:31 gjcourt: right, nDuff that makes sense

20:45 tomoj: dnolen: think there are any important cljs-specific tests to add for clojure.data, or just porting the clojure tests OK?

20:47 I considered adding a test or two for every primitive type but it seems somewhat silly. I guess it can't hurt though

20:49 dnolen: tomoj: hmm I'm not sure why there'd need to be specific cljs tests - a port of the clojure tests should suffice.

20:50 tomoj: btw, have you actually found yourself needing locals clearing in CLJS?

21:02 * gfredericks wonders what locals clearing is

21:03 * gfredericks finds out with google

21:19 TimMc: I ran up against locals clearing in Chrome the other day.

21:20 I was stopped in some 4-level-deep closure in the debugger, and it insisted that some local in the outermost fn scope was undefined. It took me 15 minutes to figure out why. >_<

21:27 gfredericks: ,((apply comp (repeat 10000 identity)) 42)

21:27 clojurebot: 42

21:28 cark: now that's what i call doing work =P

21:28 gfredericks: gotta keep the bots alert

21:28 cark: =)

21:36 tomoj: dnolen: re locals clearing, no. I thought (let [coll (range)] (map #(* % %) coll)) held the head because the #(* % %) could have closed around coll. the real problem was just *1

21:38 ..and locals clearing wouldn't help there even if that was a real problem, I guess

21:39 TimMc: you mean Chrome does its own locals clearing?

21:39 TimMc: tomoj: Yeah, this was straight-up JS.

21:41 tomoj: that's comforting, I was worried that I would eventually run into weird head-holding problems

21:46 danielglauser: Why do folks sometime define functions with an opening paren before the vector of arguments and sometimes not?

21:46 For example

21:47 (defn my-func "Documentation is cool" ([arg & more-args] …))

21:47 vs

21:47 eggsby: danielglauser: usually it's because the second way let's you do multiple arities

21:47 metellus: with parens around the args, you can define the function for different numbers of arguments

21:47 brehaut: danielglauser: the function may have at some point had multiple arities

21:47 danielglauser: (defn my-func "Documentation is cool" [arg & more-args] ...))

21:47 got it

21:48 tomoj: three answers before the question was finished :)

21:48 danielglauser: Cool, thanks!

21:48 gfredericks: just in case nobody else answered your question, the reason is that that way you can have multiple modies for different arities

21:48 eggsby: hi brehaut sup phraseology buddy

21:48 danielglauser: gfredericks: You're like waaay too slow :)

21:48 brehaut: phraseology?

21:48 gfredericks: danielglauser: I mean I can't know for sure why any particular person would do it

21:48 danielglauser: but if I had to guess what the most plausible reason was

21:48 brehaut: gfredericks, are you mocking my slow ping?

21:49 eggsby: brehaut: just that we worded it almost exactly the same :)

21:49 gfredericks: danielglauser: it would be the one I stated

21:49 brehaut: eggsby: aha :)

21:49 gfredericks: brehaut: no just three people giving long identical simultaneous answers :)

21:49 brehaut: ah

21:51 gfredericks: I found myself, when in a time crunch, getting lazy about cljs function arities

21:52 e.g. treating (fn [a b] ...) like the second arg is optional

21:54 TimMc: Sounds pretty sketchy.

21:54 gfredericks: yeah; I felt dirty; I don't know if cljs plans to cause that to error in the future

21:57 tomoj: seems unlikely to me, wouldn't that be a significant perf hit?

21:58 gfredericks: probably; though you could tie it into *assert*

21:58 tomoj: I forget, can a fn tell the difference between undefined being passed and nothing being passed?

21:58 gfredericks: arguments.length maybe?

21:58 * gfredericks doesn't know

21:59 tomoj: yeah right

22:07 dnolen: whenever I think we have it rough in the the Clojure community I read a Node.js ML thread ...

22:07 danielglauser: Nice

22:07 * dnolen likes Node.js just fine

22:08 danielglauser: How are folks deploying Noir apps? lein war then stick it on Tomcat or Jetty or lein run up on the remote server?

22:09 Related why does noir.server use an old Jetty? 6.1.25 instead of 7 or 8?

22:10 Trying to figure out a good prod deployment for a Noir app. No legacy to deal with so I can do as I please.

22:12 cgag: ML thread?

22:12 xeqi: danielglauser: clojars runs nginx in front of a jar w/ -main, basically equivalent to `lein trampoline run`

22:12 also, it probably has jetty 6.1.25 due to ring-jetty-adapter bringing it in

22:13 gfredericks: cgag: mailing list

22:13 amalloy: 4clojure actually uses lein trampoline run, with nginx in front

22:13 xeqi: newer ring versions are on a 7

22:13 note, clojars uses compojure rather then noir, but the deployment would work the same

22:14 gfredericks: good old ring

22:15 danielglauser: Thanks folks

22:15 eggsby: looks like the latest noir uses jetty 7

22:15 via ring 1.1.1

22:15 danielglauser: eggsby: Ah, I thought I was on the latest Noir

22:24 Frozenlo`: I'm trying to convert some JS from a closure example to cljs. Unfortunately the 'this' argument is confusing me. How can I use it in cljs? https://www.refheap.com/paste/5167

22:25 TimMc: Frozenlock: js/this ?

22:25 xeqi: Frozenlock: you could use this-as https://github.com/clojure/clojurescript/commit/09ff093dc86b455e3090ce3612c5e01f3b5bada6

22:25 * TimMc has not used CLJS

22:26 TimMc: Oh right, it has to be raw.

22:26 Frozenlock: Oh so I can create a binding (this-as this (somefunction this...

22:29 tomoj: but how do you call Foo.call(this) ?

22:29 huh

22:30 (goog.fx.DragDrop this) seems to compile to the right thing

22:30 Frozenlock: --> (defn FooDrag [element] (this-as my-this

22:30 (js/goog.fx.DragDrop.call my-this element)))

22:30 ??

22:30 lazybot: Frozenlock: Definitely not.

22:30 Frozenlock: thanks lazybot

22:30 tomoj: oh, s/right/wrong/

22:31 you're not supposed to use js*, right?

22:31 Frozenlock: Well it works as well with a dot.

22:32 (.goog.fx.DragDrop.call my-this element)

22:32 tomoj: js/ is fine, I mean like (js* "goog.fx.DragDrop.call(this)")

22:32 xeqi: tomoj: correct, theres a thread on the mailing list about that

22:34 wschudy: Does anyone know if there's a way to get light-weight threads, greenlets, coroutines, or whatever you want to call them in clojure?

22:34 Frozenlock: How do you deal with optional data? Normally I would just use '&' argument-name, but is there something special I should do here?

22:35 tomoj: I want to extend a protocol to ISeq in cljs. two options: 1) instead define wrapper functions around the protocol fns which always check for ISeq satisfaction 2) extend the protocol to default and throw an error if not ISeq

22:36 gfredericks: tomoj: what are "the protocol fns" that you would wrap?

22:36 you have to put the impl somewhere and you can't actually extend to another protocol can you?

22:38 tomoj: I have a protocol like cljque's IFutureSeq, with -current and -later, where -current is like ISeq's first, and -later is like ISeq's rest but might return a promise of an IFutureSeq (where rest must always return an ISeq)

22:38 wschudy: Another question: I'm surprised that in transactions the "ensure" behavior isn't the default. Why not make the "ensure" behavior the default with the more dangerous option available for people who specifically request it?

22:39 tomoj: I have my own impl already, but ISeqs could be trivial IFutureSeqs

22:39 gfredericks: tomoj: now I'm curious what the use case is

22:39 i.e., I don't see what an IFutureSeq offers over an ISeq

22:40 tomoj: so option 1) is (defn current [coll] (if (satisfies? ISeq coll) (first coll) (-current coll)))

22:40 gfredericks: I guess if you get the promise you can tell it's not ready yet?

22:40 tomoj: well

22:40 it's not a clojure promise

22:40 cljque calls it an INotify

22:40 and this is cljs (hence the problem with extending a protocol to ISeq)

22:41 so (promise) can't work

22:41 you can't have ISeqs that wait on IO either, for example

22:41 gfredericks: since it's all async

22:42 I guess lazy seqs are a bad abstraction for data IO in JS

22:43 Frozenlock: JS: FooDrag.prototype.createDragElement = function.... CLJS: (set! js/FooDrag.prototype.createDragElement (some-fn))

22:44 WRONG

22:44 Of course.

22:44 xeqi: Frozenlock: (set! ... some-fn) ; without ()s around some-fn ?

22:45 gfredericks: I've never tried to set foo.bar.baz before

22:45 does (set! (.-baz (.-bar foo)) ...) work?

22:45 or do you need a local?

22:45 Frozenlock: xeqi: #<ReferenceError: FooDrag is not defined> :-(

22:46 xeqi: gfredericks: setting properties like that works, I've been playing with three.js like that

22:46 gfredericks: (let [foo (.-prototype js/FooDrag)] (set! (.-createDragElement foo) some-fn))

22:46 xeqi: oh nice

22:47 Frozenlock: Stacktrace says is translate in the correct JS: :as "FooDrag.prototype.createDragElement = "

22:47 I just need to find out why it's not defined. Back to the REPL!

22:48 s/is/it

22:49 tomoj: it's probably munged?

22:49 did you try just FooDrag ?

22:49 Frozenlock: Isn't this only when using advanced compilation?

22:50 Yes, I've defined it earlier. However if I type FooDrag in the console, it says undefined.

22:50 So the functions defined in the REPL aren't usable in the console?

22:50 tomoj: you need to prefix with whatever namespace you're in

22:50 Frozenlock: Oh I see

22:50 tomoj: cljs.user.FooDrag for example

22:53 Frozenlock: Oh wow. (set! cljscript-test.client.main/FooDrag.prototype.createDragElement +) worked.

22:53 Khaoz: enough clojure for today

22:53 Frozenlock: I don't like that I need to type the namespace...

22:53 Khaoz: complement, comp, partial and memoize just blowed my mind

22:53 cgag: :)

22:54 i love comp and partial

22:54 Khaoz: i need to read a little bit more about them

22:57 Good night for all.

22:57 well, it's late here in Brazil :)

23:09 tomoj: Sgeo: suppose that for some clojure abstraction (which is semantically a monad and a functor), (=<<) and fmap are fused into one function, which is of type both `(a -> m b) -> m a -> m b` and `(a -> b) -> f a -> f b` (and `(a -> m m b) -> m a -> m b` etc). is that obviously going to cause a lot of trouble? not using algo.monads. currently I also actually have `(a -> b) -> a -> m b` in there..

23:20 Sgeo: tomoj, what's the difference between an m a and an f a? I should note that if it's both (a -> m b) -> m a -> m b and (a -> b) -> m a -> m b, then that's just a bind that if it sees that the function isn't returning the right sort of value, does a return on it then proceeds with the bind.

23:21 Semantically, all monads should be functors.

23:22 tomoj: no difference, I just used f in the fmap type

23:22 Sgeo: Ah

23:22 tomoj: lambdabot tells me it's fmap, (=<<), (join .) . (=<<), ((join . join) .) . (=<<), etc

23:23 but what is `(a -> b) -> a -> m b` ?

23:23 actually currently I just have `(a -> b) -> a -> b`, so $

23:24 it seems convenient but it seems so wrong that I feel it must cause inconvenience somehow

23:24 Sgeo: \f a -> return (f a)

23:25 (Probably a more pointfree way to write that)

23:25 In what way is it convenient?

23:26 tomoj: (return .)

23:27 well, I don't see a need for values of type (m (m a)) etc

23:27 so I have one operator for the infinite list of operators above

23:29 Sgeo: Uh, does it support values of type (m (m a)) though?

23:30 Will join :: m m a -> m a do something sensible, or will it just be identity?

23:33 tomoj: it does the right thing

23:33 except I don't have a join currently

23:33 abalone: are folks ok with paredit treating the { in #{a b c} as the opening delimiter, moving only the { on a backward slurp -- since paredit is for multiple languages and #{ isn't always an opening delimiter?

23:34 tomoj: it's just baked into the one ($, fmap, =<<, (join .) . (=<<), etc) operator

23:34 by "right thing" I mean the joins in that operator respect the semantic monad morphism

23:35 which reminds me, actually, sometimes I find myself wanting the wrong thing, and that becomes inconvenient :)

23:36 Sgeo: Does your operator have special code to determine what to do? I guess I'm having trouble visualizing it

23:38 tomoj: yes, it has two satisfies? checks, one for (a -> m a) promotion and one for (m m a -> m a) demotion

23:38 Sgeo: ,(doc satisfies)

23:38 clojurebot: Pardon?

23:38 tomoj: ,(doc satisfies?)

23:38 clojurebot: "([protocol x]); Returns true if x satisfies the protocol"

23:39 tomoj: the operator is essentially `when` from https://github.com/kriskowal/q#the-middle

23:39 clojurebot: 'Sea, mhuise.

23:39 tomoj: clojurebot: forget the operator

23:39 clojurebot: the operator is essentially `when` from https://github.com/kriskowal/q#the-middle

23:41 tomoj: except I use $ in place of (return .)

23:42 wait, no. I use (return .) too

23:42 Sgeo: I have a question about it, but ... not entirely sure

23:42 What if the function you give it is an m a -> m b? Does it still correctly determine what it needs to do? What about m a -> m m b?

23:44 tomoj: well, if the function you give it is _really_ (m a -> m b), you surely get an error because it won't ever call the function with an (m a)

23:45 similarly for the other case

23:46 Sgeo: Even thought in principle it should be capable of the type (m a -> m b) -> m m a -> m m b?

23:47 tomoj: you mean because it has type (a -> b) -> m a -> m b ?

23:47 Sgeo: Yes

23:47 tomoj: right

23:47 (m m a) is essentially uninhabited

23:48 Sgeo: return (return 5)

23:49 tomoj: well, shit

23:50 (constantly (constantly 5)) is a value of type (m m Number) currently :)

23:51 confusing name, `immediately` maybe would be better

23:52 but that's a bug, my intent was that (immediately (immediately 5)) was the same as (immediately 5)

23:52 Sgeo: Just a general reflection, but m m a tends to be more useful than it looks at first glance

23:52 tomoj: yeah, that's what I fear

23:53 I can't think of any examples where I don't want to just join, yet

23:55 I wonder if that operator can be described more simply in terms of another typeclass

23:55 amalloy: abalone: if i ever did a backwards slurp i would object to that behavior

23:55 Sgeo: I _think_ if you want to satisfy the monad laws, you need bind to work properly with that sort of m m a thing.

23:56 amalloy: but it's not clear that it's possible to fix without a lot of work on paredit, since afaik it's built on the assumption that delims are a single character

23:58 Sgeo: tomoj, is it merely difficult to implement your operator to work with m m a properly?

23:58 amalloy: tomoj, Sgeo: i don't really understand this conversation, but it sounds like tomoj is saying (m m a) isn't a useful type? surely that's useful when m is List

23:58 tomoj: no, that's easy

23:59 (m m a) for a particular monad

23:59 Sgeo: amalloy, he's not saying in general, but for the specific Monad he's working on

23:59 tomoj: I guess the monad laws must contain the answer to my question

23:59 Sgeo: I think it's definitely a questionable assumption, though. m m a tends to be surprisingly useful sometimes.

23:59 tomoj: but I need to stare at them for a while..

Logging service provided by n01se.net