#clojure log - May 12 2011

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

0:05 sorenmacbeth: anyone? bueller?

0:11 intlkleinblue: exit

0:31 scgilardi: sorenmacbeth: what did you try? could be done with loop/cond/recur

0:42 sorenmacbeth: I got it done with reduce

0:57 tomoj: oh, of course filter isn't variadic

0:57 sorry, whoever I told that

0:59 sorenmacbeth: nope, I take it back, reduce doesn't quite do what I want

1:00 scgilardi: I'll look into loop/cond/recur

1:00 tomoj: &(->> ["7" "7 elements" "7 elements landing" "7 elements landing page" "add"] (partition 2 1 nil) (remove (fn [[a b]] (and b (.contains b a)))) (map first))

1:00 sexpbot: ⟹ ("7 elements landing page" "add")

1:00 nick001: hi, what is the preferred website used here to show code snippits in? (its been a while)

1:00 tomoj: wonder if this just happens to work in that case

1:02 nick001: gist is popular, and it's got clojure highlighting. preferred? dunno

1:03 nick001: thanks!

1:06 hippiehunter: why are long and double the only primative type hints supported?

1:11 markoman: I have a nested vector or sequence produced by recursive function and Id like to flatten it by certain criteria

1:11 dnolen: hippiehunter: exponential number of interfaces to support, 4 args (Object, long, double) and return (Object, long, double) is 300+ Java interfaces. interfaces used to get the fastest perf of the JVM.

1:12 sorenmacbeth: tomoj: thank you! that's works

1:13 markoman: [[['a 'b]['b 'c]]['a]] should become [['a 'b]['b 'c]['a]]

1:14 tomoj: is it a 1.3 thing that only long/double are supported?

1:14 hippiehunter: it doesnt mean anything pre 1.3

1:15 markoman: levels of nests can be deeper too, but result should always be a vector containing vector of items. with flatten I always get only one level

1:15 dnolen: tomoj: yes.

1:16 tomoj: oh, I saw ^floats and was confused, but that's different

1:16 dnolen: hippiehunter: 1.2 doesn't have much in the way of good primitive arithmetic support.

1:16 in 1.3 primitives can flow freely without ever getting boxed.

1:16 markoman: could I surround the final level of vector with something, that it keeps the "shape" ?Im thinking something like : [[{['a 'b]}{['b 'c]}]{['a]}]

1:17 hippiehunter: dnolen: does that include things like map, filter, etc

1:18 dnolen: hippiehunter: that's forward looking but yes, part of the reason for the changes were wanting to allow higher order usage that can operate efficiently on collections of primitives.

1:19 hippiehunter: primitives can flow, and we have vectors that can hold primitives, but some more stuff to sort before we get there.

1:24 markoman: im thinking something like: (for [x (flatten [[{:set ['a 'b]}{:set ['b 'c]}]{:set ['a]}])] (:set x))

1:55 tomoj: markoman: are you flattening it just to get the answer or do you use the nested version for something?

1:55 just curious, maybe you can produce it flattened in the first place

1:55 amalloy: (inc tomoj)

1:55 sexpbot: ⟹ 1

1:55 amalloy: that is very often the better way

1:59 markoman: I need to use recursive function to get data but I also need to preserve last shape of vectors

2:00 last shape means any of these [1 2] [1] [1 2 3] ...

2:00 amalloy: markoman: so? make the recursive function return a seq of the meaningful seqs

2:01 when it recursively calls itself it can splice them in rather than re-nesting

2:03 markoman: hmh... I have a for structure inside recursive function too. combination of these makes I cant get flatten to work as I want

2:03 amalloy: &(letfn [(thing [n] (condp = n, 0 '(base), 1 (into '((item1)) (thing 0)), 2 (mapcat thing [1 0])))] (thing 2))

2:03 sexpbot: ⟹ (base (item1) base)

2:03 amalloy: &(letfn [(thing [n] (condp = n, 0 '((base)), 1 (into '((item1)) (thing 0)), 2 (mapcat thing [1 0])))] (thing 2))

2:03 sexpbot: ⟹ ((base) (item1) (base))

2:04 amalloy: turn the for into a mapcat, or (apply concat (for...)), and you can

2:11 markoman: hmh, thats new to me, it might work here

2:55 * raek changes his saved twitter search from "#clojure" to "#clojure -nujkcom"

2:55 raek: ah, the silence!

2:59 amalloy: raek: you can just block nujkcom

2:59 i blocked him when someone (stuart s?) mentioned he was clogging the clojure feed, though i don't actually follow #clojure

3:09 raek: last time I tried I got the impression that a block hides tweets directed to you but not that person's tweets from searches

3:11 TheBusby: amalloy: After implementing what we discussed, and porting the loading parsing to JNI, I finally figured out where all the memory was going...

3:11 amalloy: raek: you could be right

3:12 TheBusby: amalloy: I was dealing with roughly 125M strings, and evidently Java has a massive overhead dealing with String (38B + 2B per char).

3:14 my input file was utf-8 (primarily single byte characters), so just storing the data as a string doubled the size (1GB to 2GB), and with the overhead of storing each field you're looking at another 4.4GB of memory consumption

3:14 * raek tweaks the search to "#clojure -from:nujkcom"

3:14 no_mind: Is there a way to execute more than one expression inside an if clause ?

3:15 TheBusby: use "do"?

3:18 amalloy: yah, (do a b c) is what you want. or you can use (when test a b c) if you don't need an else clause

3:20 Derander: my desk is literally covered in paper

3:20 this is wonderful

3:20 cais2002: hello guys

3:23 wrt java interop, how do I deal with generic type? e.g., a java method with a signature methodA(List<String> p1) , how do I invoke it from Clojure?

3:44 amalloy: cais2002: generics are a figment of javac's imagination. pass them objects, you'll be fine

3:44 ie, (.methodA whateverTarget ["string1" "string2"]) will work

3:44 roamer01: hi, i am trying to get a library to run, this one "enlive", i am fairly new, example on https://github.com/cgrand/enlive/wiki/getting-started , i installed enlive using leiningen, (also ran lein deps) however, when i try to run : user=> (ns x (:use net.cgrand.enlive-html)) i get could not locate init class, the lib dir is on my path, and the enlive jar is also there

3:46 zmila: how to check if input is sequence or not?

3:46 ;(seq? [])

3:47 cais2002: amalloy, thanks.. got the method name wrong while testing it.. :|

3:47 amalloy: zmila: (sequential? x) is usually good enough, with some caveats

3:48 zmila: thanks, amalloy!

3:48 cais2002: what's the best way to inspect an object to discover what methods are available? I sometimes got "No matching method" exception or "No matching ctor found for class" but have no clue what goes wrong..

3:50 amalloy: cais2002: (use '[clojure.contrib.repl-utils :only [show]]) (show foo)

3:53 zmila: if this is java object, then you may call (bean object) - it returns map

3:57 thorwil: roamer01: the ns form is for files, on the repl one usually uses require or use directly. (use 'net.cgrand.enlive-html) or (require '[net.cgrand.enlive-html :as en])

3:58 cais2002: show works well

4:17 neotyk: Good morning everyone!

4:27 markoman: Good noon :)

4:29 clgv: $source pcalls

4:29 sexpbot: pcalls is http://is.gd/JyjUUT

5:02 raek: rowth: how did you start clojure? lein repl?

5:03 oh, sorry. wrong person

5:03 oh, roamer01 left

6:30 no_mind: I have a function in another file and I am loading that file with load-file . I want to know if there is a way to check if the namespace/file has been previously loaded and avoid loading the file everytime the function is called ?

6:38 fliebel: Is there a clean way to do select-keys on a vector?

6:39 no_mind: find-ns ?

7:05 mduerksen: fliebel: select-keys does work on vectors, but it probably doesn't have the result you'd expect. (select-keys [1 3 5] [1 2]) => {2 5, 1 3}, rather than [3 5]

7:07 fliebel: mduerksen: I know, so I had (vals (select-keys)) but then it gets out of order. so (vals (into (sorted-map) (select-keys))) would work, but who wants that?

7:12 mduerksen: fliebel: true. if your vector is short, you could just use destructuring with some _ for the indeces you dont need. but when your vector is longer than 4 or so, it would be ugly and not very readable since you'd have to count to find out which indeces your actually selecting

7:13 fliebel: With assoc, you can do multiple associations in one, I wonder why get doesn't do that.

7:16 mduerksen: you could do this: ((juxt #(get % 1) #(get % 2)) [1 3 5]). in combination with apply, you could create a fn multiple-get that does that

7:16 fliebel: $source assoc

7:16 sexpbot: assoc is http://is.gd/hulXLR

7:17 fliebel: So basically just some recursive version of get would work. Only the default argument would need to leave.

7:18 (map (partial get m) [1 2 3]) would work as well.

7:19 mduerksen: ((apply juxt (map (fn [idx] (fn [v] (get v idx))) [1 2])) [1 3 5])

7:20 i think your is simpler and does the job

7:21 *yours

7:28 raek: ,(let [v [1 3 5]]] (map v [1 2]))

7:28 clojurebot: Unmatched delimiter: ]

7:28 raek: ,(let [v [1 3 5]] (map v [1 2]))

7:28 clojurebot: (3 5)

7:28 fliebel: true :) I forgot vector is ifn also.

7:29 s/(partial get m)/m/g

7:41 raek: $findfn [1 3 5] [1 2] [3 5]

7:41 sexpbot: [clojure.core/map clojure.core/replace clojure.core/pmap clojure.core/keep]

7:42 raek: wait what? replace?

7:42 hrm

7:42 ,(replace [1 3 5] [1 2])

7:42 clojurebot: [3 5]

7:42 raek: ,(replace {0 1, 1 3, 2 5} [1 2])

7:42 clojurebot: [3 5]

7:43 Chousuke: heh

8:07 mec: anyone gotten durendal to work with clojurebox?

9:18 saml: hey, do you like OSGi?

9:18 does clojre need osgi?

9:20 joly: I'm playing with core.logic and an example that's similar in form to the zebra puzzle. Is there something like not-membero so I can say something like (not-membero ['spaniard _ _ 'snails _] hs) ?

9:20 should be two separate underlines instead of one long one...

9:21 chouser: saml: clojure does not require OSGi. There have been various attempts to make clojure work with OSGi, and I'm not sure what state any of those efforts are in.

9:21 saml: i don't even know what OSGi tries to solve

9:21 it looks like java complication

9:21 cemerick: odd to ask about it then ;-)

9:22 saml: i mean.. but i might be just stupid. do you have use cases for OSGi?

9:23 cemerick: module systems like osgi make it possible to update/modify long-running systems built with static components.

9:23 technomancy: osgi is one of those things like dependency injection where you can read words that describe it without having those words convey any particular impression of meaning to your mind.

9:24 cemerick: Very little to do with Clojure, or Clojure-idiomatic practice.

9:26 saml: osgi is trouble. hot swapping means bugs won't be apparent during deployment

9:27 you deploy bundle Foo.. until you deploy bundle Bar, bugs won't appear

9:27 cemerick: It doesn't really work like that.

9:27 But, I don't really want to talk about osgi, either. :-P

9:28 saml: no.. that's how i experienced it. deployed foo.jar to staging. worked fine. pushed foo.jar to production. works fine.. now someone deploys bar.jar.. it breaks

9:28 there's no dependency.. just they both exports same package :P

9:29 Fossi: pfft, dependency injection... i like "inversion of control" better. at first you have control, then...

9:34 technomancy: add-classpath is the only dependency injection I need, amirite?

11:40 malkomalko: I see (clojure.string/replace) but when I try to access it from the repl it's not able to find that namespace.. I'm on 1.2.0, am I doing something wrong?

11:42 mec: malkomalko: did you (require 'clojure.string)?

11:43 malkomalko: thought so, I think I required something wrong

11:43 *face palm*

11:43 :)

11:43 manutter: malkomalko: what was it?

11:44 malkomalko: I wasn't calling the required ns properly

11:44 and I wasn't reading things correctly and was getting back the wrong version of replace

11:54 ilyak: hi *

11:55 Is there some kind of wrapper over proxy to proxy one-method, one-class, empty-constructor classes or interfaces?

11:56 something along the lines (proxy [Work] [] (execute [conn] (use-conn conn))) -> (proxy-one Work execute [conn] (use-conn conn))

11:56 I understand that I can probably write that myself as a macro

11:59 mec: if its an interface you can (reify Work (execute [conn] (use-conn conn))) but theres nothing specifically for what you're asking

12:07 amalloy: ilyak: no, i don't think there is. you could write the macro yourself, but it saves you about five characters and doesn't really add any readability

12:23 fliebel: ##((juxt 0 2) [:a :b :c]) or ##(map [:a :b :c] [0 2]) should both work

12:23 sexpbot: ((juxt 0 2) [:a :b :c]) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

12:23 (map [:a :b :c] [0 2]) ⟹ (:a :c)

12:23 amalloy: oh, except the first one :P

12:26 manutter: That's weird, I didn't know you could use map like that

12:26 or maybe I didn't know you could use vectors like that

12:28 amalloy: manutter: probably vectors

12:29 &([:a :b :c] 2])

12:29 sexpbot: java.lang.Exception: Unmatched delimiter: ]

12:29 amalloy: &([:a :b :c] 2)

12:29 sexpbot: ⟹ :c

12:31 Kototama: how can i read a clojure file and have its content represented in a sequence (as a tree) ?

12:33 amalloy: (read-string (slurp file)) if it's just one data structure

12:34 Kototama: it's not, i would like to read a whole program

12:35 amalloy: &(with-in-str "(def a 1) (inc a)" (doall (take-while (complement #{::done}) (repeatedly #(read *in* false ::done)))))

12:35 sexpbot: ⟹ ((def a 1) (inc a))

12:35 amalloy: Kototama: that is the general idea

12:36 you can use with-open and a reader on the file instead of with-in-str if you don't want the whole thing in memory at once, but it's probably not worth the effort

12:37 Kototama: https://github.com/xebia/clj-metrics/blob/master/src/clj_metrics/core.clj#L24 is maybe the correct tricks

12:38 amalloy: sure, that looks easier, i suppose. i think you should probably *understand* how to use the reader for more sophisticated things, even if "tricking" it with some extra parens is the solution that's easier

12:41 Kototama: yes you're right, i didn't see that posted code actually, thanks for that

12:50 mec: (read-string (str "[" (slurp file) "]")) ;p

12:50 technomancy: (take-while #(not= % ::done) (repeatedly #(read rdr false ::done)))

12:50 mec: oh, which is exactly whats in the file

12:55 amalloy: technomancy: isn't that just what i did?

12:56 (though i like (complement #{::done}), even if it is like twice as long)

12:56 technomancy: amalloy: yeah... I only read like 5 lines of back-chat.

12:56 heh

12:56 * amalloy makes a note to add five lines of drivel every time he says something bad about technomancy

12:57 Kototama: and how can I know if something is an 'atom' (in the common lisp sense) ?

12:58 amalloy: (complement coll?) is close

12:58 but since clojure doesn't really have the atom-vs-list dichotomy it's not a perfect mapping

12:59 ilyak: Is there a page with simple macro examples somewhere?

13:01 mec: ilyak: http://java.ociweb.com/mark/clojure/article.html#Macros or http://en.wikibooks.org/wiki/Learning_Clojure/Macros have some simple ones

13:04 no_mind: I am building a module based application where each module has its on namespace. I have 2 questions 1) Is this correct approach to keep every module in a separate namespace or there are other approaches ? 2) I want each module to register a function for receiving events. How do I make modules register for events at the start of application ?

13:06 technomancy: no_mind: for #2 you would either have to list them in a config file or search the classpath and keep it in namespace metadata

13:06 I strongly favour the latter approach

13:07 amalloy: for contrast, sexpbot searches the classpath but doesn't use namespace meta; it just looks for a function called load-this-plugin or something

13:08 technomancy: yeah, actually there is a bug in the clojure compiler where ns metadata is lost when you AOT compile, so probably a def in the ns would be better

13:08 no_mind: technomancy: I cant understand the first part, searching the classpath

13:08 technomancy: no_mind: relevant: https://github.com/technomancy/slamhound/blob/master/src/slam/hound/regrow.clj#L93

13:11 something like this would work once you've pre-loaded everything on the classpath: (doseq [n (all-ns) :when (ns-resolve n 'receiver)] (register (ns-resolve n 'receiver)))

13:13 amalloy: technomancy: use a :let before the :when to avoid duplicated code?

13:20 technomancy: yeah

14:16 has anyone used the junit output adapter for clojure.test for hudson/jenkins reporting?

14:17 S11001001: technomancy: our team has, specifically, the test-out lein plugin

14:18 technomancy: S11001001: so you can get more detailed failure stats over time? that sounds handy.

14:23 I wonder if test-out could be made to work with test-selectors. hopefully it can be made more composable.

14:30 shortlord: clojure and lisp in general are oviously very close to a raw syntax tree. it's trivial for (+ 1 2) wich is the node + with 1 and 2 as the leafs. But how can ((partial + 1) 2 3) be displayed as a syntax tree? (or any other expression where the first list item is itself a complex expression)

14:34 technomancy: shortlord: there's no reason the first position in the AST has to point straight to a function

14:34 as long as it evaluates to a function

14:35 TimMc: shortlord: + isn't the node, it's the first child

14:36 shortlord: technomancy: but that makes it quite hard to display in a graphical tree, right? I was thinking about visualizing clojure code, but I have no idea how I could put something like that into a tree structure

14:37 TimMc: why? I mean, "+" is the first 'child' in the list, but after evaluating the expression, it would be the node of the syntax tree, wouldn't it?

14:38 * technomancy defers to SICP

14:39 TimMc: shortlord: If you're doing a strictly algebraic reduction of the tree, then you would replace the node with the results of the evaluation.

14:40 I think you're conflating values and syntax at this point, though.

14:41 shortlord: TimMc: hmm, you might be right. Seeing the opening list parenthesis as the node would also solve the problem of displaying the tree

16:00 dnolen: cemerick: I fear that you've only caused more confusion.

16:01 cemerick: dnolen: hopefully only revealed it?

16:01 dnolen: cemerick: yeah, the problem is what people *thought* was happening before.

16:02 cemerick: Rich was banging the drums from the start that hints weren't type declarations. *shrug*

16:02 The concept of hints is pretty foreign to most, I'd say.

16:02 dnolen: cemerick: but you talking about return types doesn't help that's a fiction.

16:03 hiredman: also, everyone is chiming in, even if they have no idea what they are talking about

16:04 obviously everyone needs javap-mode and should read the bytecode their clojure code is compiled to

16:04 cemerick: hiredman: good luck with that

16:05 hiredman: :)

16:05 cemerick: dnolen: Yeah, I'm never as precise as I should be.

16:06 That's often true, more true these days as I'm trying to synthesize reasonable ways to describe these things to people that will never (and don't want to) grok the subtleties involved.

16:07 dnolen: cemerick: the key is that in 1.2.0 *expressions* can be hinted. defn is no exception. no return type enters *anywhere*

16:08 cemerick: in 1.3.0 you can define real *signatures*. I don't see how that be reconciled with expression hinting w/o work.

16:10 cemerick: dnolen: I promise I understand. But you keep talking about semantics of implementation details; my thread only cares about syntax.

16:10 If the different hints really are different in order to communicate the semantic distinction, then they need to be *more* different.

16:12 dnolen: cemerick: the other problem is you state the problem. no path to solution, no discussion of pitfalls, no solutions around those pitfalls. the tension is that 1.3.0 brings real types into a primarily dynamically typed language.

16:14 cemerick: my fear is that conversation will thus die, with many parties further in the dark then they were before.

16:14 cemerick: I don't have any solutions; I was only hoping to be educated and maybe provoke some clarifying discussion so everyone could better understand rationales, etc.

16:15 dnolen: I don't think the balance of the world rests in that thread. :-)

16:15 dnolen: cemerick: no of course not :)

16:15 cemerick: It's all bleeding edge stuff that may or may not get swapped out for whatever is in the oven now — no way to know.

16:18 dnolen: cemerick: heh in Clojure time 7-8 months ain't bleeding edge.

16:19 cemerick: heh, yes and no :-)

16:21 dnolen: Just something to think about: for all intents and purposes, _everyone_ thinks type hints are type declarations. If you come at it from that perspective, 1.3.0's use of hat-syntax just seems strange.

16:27 dnolen: cemerick: then the problem is false expectations, right?

16:27 seancorfield: technomancy: quick lein Q - is there an easy way to run tests wrapped in with-junit-output so i can run my clojure tests as part of an ant build and treat them just like normal junit tests (for xml output)

16:28 dnolen: cemerick: it's why I don't really buy your argument. If you remember that Clojure is through and through untyped, 1.3.0 isn't that confusing.

16:28 technomancy: seancorfield: yeah, I was just asking about that a few hours ago

16:28 apparently there's a lein test-out plugin

16:28 I haven't tried it myself, and it looks like it doesn't honor test selectors

16:28 but it should get you what you want

16:31 seancorfield: thanx... i'll go look at that

16:38 chouser: while we're harping on var meta tags and syntax, it may be worth remembering that even in that (simple, relative to primitives declarations) case, the meaning is under contention.

16:38 seancorfield: aweseome technomancy works like a charm!

16:38 chouser: the tag on a var can mean either the type that the var *is*, or the type that the var would *return* if called as a function.

16:38 technomancy: seancorfield: are you using it with hudson/jenkins?

16:39 seancorfield: it does complain about eval-in-project's handler argument is deprecated.

16:39 i will be using it with hudson, yes

16:39 but right now i just want to get my ant build running the lein tests

16:40 and i'm already running mxunit tests (junit for cfml effectively)

16:41 technomancy: yeah; I was just wondering what the hudson history looks like

16:42 and yeah, the test-out plugin needs to be tweaked to be more composable. it should leverage the existing test forms, I think.

16:44 dnolen: chouser: but is that really true? you have invoke expression which use their fn expression which is a var expression to determine what their own tag will be. var always *is*. the invoke expression steals it's tag from it.

16:53 hiredman: dnolen: thats an interesting point I wonder if (def ^String x inc) (map x (range 10)) would emit some kind of cast of x to String

16:53 I guess it only would if you tried to do something like call a method on x

16:57 chouser: (def ^Long x {:a 1}) ; I promise to only put Longs in the this map

16:57 (.byteValue (x :a)) ; so I can do this without reflection

16:58 (.get x :a) ; but if I wanted to *this* without reflection, I should have used ^java.util.Collection or some such instead

16:59 the tag on that var is used to mean two different things. An unfortunate conflation in a language that succeeds in avoiding so many more common conflations.

16:59 And of course that's a silly example as I should just use 'get' instead of '.get', but the nevertheless the conflation remains.

17:17 technomancy: hm; it would be easy for me to add the functionality of the test-out plugin straight to lein

17:17 could be done in ~5 LOC, but I would have to change the signature of leiningen.test/form-for-testing-namespaces

17:23 http://p.hagelb.org/junit-out.html <= 10 LOC and it works, but grooooooss

17:23 dnolen: chouser: yes the essential ambiguity is that the *expressions* (x :a) and x both have the tag Long. but it has nothing to do with whether x is called as function or not.

17:23 chouser: (do (set! *warn-on-reflection* true) (.byteValue (apply x [:a]))), reflection warning.

17:24 technomancy: seancorfield: are there any other use cases for wanting junit output besides hudson?

17:25 and does anyone use TAP output?

17:27 chouser: dnolen: but isn't that example just because apply strips the tag entirely?

17:28 my point is that one could imagine the expression x using metadata like :eval-tag, and (x :a) using :return-tag, and then both could be declared when defining the var

17:29 dnolen: chouser: my point is that all higher order uses of type hinted fns show that the notion that type hints are somehow about return types completely falls apart.

17:30 chouser: so what is ^Long in my example above, if not a hint on the return type of x when called as a function?

17:31 dnolen: chouser: a limited convenience, since ^Long is meaningless in higher order usage.

17:31 gfrlog: $findfn -3 3

17:31 sexpbot: [clojure.core/unchecked-negate clojure.core/-]

17:31 chouser: ah, fair enough. limited convenience, but nontheless one explicitly supported by the current clojure compiler.

17:31 gfrlog: there's really no (abs)?

17:32 dnolen: ,(Math/abs -1)

17:32 clojurebot: 1

17:32 gfrlog: ,(Math/abs -39829842984892949829849829843979724972849232)

17:32 clojurebot: java.lang.ExceptionInInitializerError

17:32 gfrlog: ,(Math/abs -8.83)

17:32 clojurebot: 8.83

17:32 gfrlog: good enough

17:34 chouser: dnolen: are we going to have logic programs that deduce the return types of high-order expressions to avoid reflection?

17:34 dnolen: chouser: man wouldn't that be awesome :)

17:34 chouser: :-)

17:34 gfrlog: chouser: what's the return type of (apply partial (repeat partial))?

17:35 hiredman: IFn

17:36 gfrlog: you're asking the type system to tell you if a program halts

17:36 gfrlog: ah, not paramaterized then

17:36 I am?

17:36 chouser: apply has no return tag

17:37 hiredman: gfrlog: if you generate a fn from an infite seq of fns, and you want a strict haskellish signature, yes

17:37 gfrlog: I was just about to ask if such a function could exist in haskell

17:39 I find that function hard to reason about. Like could it have a recursive type that always returns itself?

17:39 hiredman: you are effectively creating a program that infinitely recurses, which is no different from so a fib program with a broken base case that never terminates

17:40 gfrlog: only if I pass it to trampoline...

17:40 (on a side note, when I pass it to trampoline the stack overflows, and I'm not sure why that's the case either)

17:41 hiredman: gfrlog: it depends, I am kind of interpolating what you mean, because the code pasted doesn't actually express any interesting properties

17:41 because it doesn't do what you think it does

17:41 gfrlog: I think that it returns a function that returns a function that returns a ...

17:42 hiredman: nope

17:42 gfrlog: at some point it does not return a function?

17:43 pjstadig: infinitely recursive types exist all over the place

17:43 a cons cell is infinitely recursive

17:44 gfrlog: that makes sense. So I would assume that's the type of the function, but hiredman is telling me I don't understand it.

17:44 so I probably don't understand it.

17:44 hiredman: gfrlog: *shrug* I may be misreading it too

17:44 clojurebot: Excuse me?

17:46 gfrlog: in the repl it keeps returning functions

17:50 because (apply partial (repeat partial)) should be equivalent to (partial partial partial partial ...)

17:50 which is a function that ought to return something equivalent to (partial partial partial partial partial ...)

17:50 etc.

17:56 amalloy: gfrlog: so it's a function that evaluates to itself. it's not clear what impact this has on type systems of any kind

17:56 rather: when called, returns itself

17:56 gfrlog: not much. I had gotten past that and was now trying to figure out why hiredman thought I didn't understand what it did.

17:56 amalloy: it's equivalent to (fn x [& _] x)

17:57 i think

17:57 gfrlog: I understand that it's not interesting for type systems

17:57 amalloy: you started the discussion with "what is the type of (apply partial (repeat partial))

17:57 so that is probably the angle hiredman was working from

17:58 gfrlog: well when I said that it was a function that returns a function that returns ..., he said that was incorrect

18:07 amalloy: well, it's clearly true that that's what it does

18:08 &(nth (iterate #(%) (apply partial (repeat partial))) 5)

18:08 sexpbot: ⟹ #<core$partial$fn__3684 clojure.core$partial$fn__3684@e9e439>

18:09 gfrlog: yep.

18:09 amalloy: as long as you don't imagine that those partials get invoked as functions in any way other than something like this iterate, you're not wrong

18:09 gfrlog: I tried passing some other args to the functions to see what would happen, and it didn't seem to change anything

18:09 amalloy: gfrlog: no, because they get added to the end of the infinite seq

18:10 which is why i said it's basically equivalent to (fn x [& _] x)

18:10 ignore args, return self

18:10 &(take 5 (iterate #(%) (apply partial (repeat partial))))

18:10 gfrlog: right

18:10 sexpbot: ⟹ (#<core$partial$fn__3684 clojure.core$partial$fn__3684@d95700> #<core$partial$fn__3684 clojure.core$partial$fn__3684@ded3e6> #<core$partial$fn__3684 clojure.core$partial$fn__3684@129be35> #<core$partial$fn__3684 clojure.core$partial$fn__3684@186a0bd> #<core$partial$f... http://gist.github.com/969581

18:10 amalloy: you do get different objects, though; they just behave the same

20:18 AardMark: hey hey hey

20:20 why doesn't anyone talk in here?

20:20 it's a ghost town

20:20 duck1123: sometimes

20:21 it all depends if anyone has anything to say

20:21 AardMark: how are you duck?

20:21 im a haskeller, but i bough programming clojure the other day

20:21 gonna give it a shot

20:21 duck1123: annoyed that I still can't find my keys, just gave up to do some coding

20:21 AardMark: bought*

20:22 duck1123: that was a good book, has it been updated yet? it's probably somewhat out of date

20:22 AardMark: ya, i got it at a used book store

20:22 its a few years old

20:22 i have the pdf of the joy of clojure

20:23 not read either one yet though

20:25 dnolen: AardMark: it's all ebb and flow in this channel.

20:25 duck1123: hmm... it appears that lamina, clojure 1.3, and numbers like 1e3 don't get along

20:29 amalloy: eg clojure.contrib.duck-streams is like whoa old

20:29 (sorry if i sent that twice; seem to be having client issues)

22:37 technomancy: boston clojure group hacks: https://github.com/technomancy/quickbeam

23:05 stirfoo: If I try to add $HOME/.m2/repository/org/clojure-contrib/1.1.0/clojure-contrib-1.1.0.jar to the CLASSPATH var of ~/.lein/bin/swank-clojure, swank-clojure fails with a long trace

23:10 symbole: When building ad-hoc hierarchies, why must keywords be namespace qualified?

23:17 cemerick: symbole: to make it difficult for unrelated hierarchies to interfere with each other

23:19 symbole: What interference could there be if one were to use unqualified keywords?

23:21 cemerick: symbole: Library A and library B would then both be defining relationships over the same keyword space.

23:21 That remains possible with namespaced keywords, but you need to rightly be explicit about it.

23:23 symbole: For library A and library B to both be using the same keyword space, wouldn't they need to use unqualified keywords?

23:24 jedi: isn't that what you asked?

23:24 symbole: jedi: I asked, why do keywords need to be qualified, as opposed to not being qualified.

23:25 cemerick: symbole: no, library A can refer to namespaced keywords used by library B

23:26 The answer to the "why" question is "to enforce sane idiomatic usage".

23:28 symbole: So from a semantical perspective, the behavior is the same regardless of whether or not qualified or not qualified keywords are used?

23:29 hippiehunter: the more i'm getting into this the more i'm having a problem, char is not a first class primative in 1.3, I cant type hint it nor does it promote to long, not having char makes writing a parser very hard.

23:29 cemerick: symbole: yes, if namespace-less keywords could be used within hierarchies.

23:31 hippiehunter: You need primitive char returns for your parser?

23:32 hippiehunter: returns are nice but parameters are more important

23:32 cemerick: hippiehunter: why?

23:33 hippiehunter: because im parsing one char at a time then dispatching to finish the token

23:34 i had grown to accept that long wouldnt really be much of a problem on 64bit but char doesnt seem to play nice with long

23:34 I might just be misunderstanding whats going on though

23:35 cemerick: hippiehunter: I still fail to understand why you need primitive chars?

23:35 hippiehunter: one object per char in a large file feels like its going to be a little slow

23:36 cemerick: very unlikely

23:36 char boxing is _very_ fast, since a constant pool is used

23:37 hippiehunter: oh, that sounds nice

23:37 is that specific to hotspot or jvm's in general?

23:37 hiredman: you can also do stuff like use definline

23:37 cemerick: hippiehunter: JVM's in general, IIRC

23:38 hiredman: which tells the compiler to inline your functions, so you don't box at the function boundries

23:38 cemerick: hippiehunter: "If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2." http://java.sun.com/docs/books/jls/third_edition/html/conversions.html

23:38 so…

23:38 ,(identical? (first "f") (first "f"))

23:38 clojurebot: true

23:40 hippiehunter: well i guess you learn something new every day

23:40 cemerick: :-)

23:41 Code first, optimize later. And if you really need to, hiredman's suggestion will bail you out.

23:41 s/to/it

23:45 hippiehunter: cemerick: i'm usually the first to quote that to people but there just a few things i cant bring myself to ignore. constant costs on O(n) where n is known to be excessively high are one of those things. Also im really a CLR guy and we dont have the optimization :p

23:46 still getting used to the cost differences on jvm

23:56 symbole: cemerick: I think I understand the reason behind qualification. It makse sense.

23:59 cemerick: symbole: OK. To be sure, consider the potential otherwise: I say (derive :a :z), and you say (derive :b :z), and our libraries are loaded in the same VM. We'll both be surprised by the results of (ancestors :a) or (ancestors :b), depending on which one we're concerned with.

Logging service provided by n01se.net