#clojure log - Mar 25 2012

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

0:00 alandipert: mk: (doseq [x xs] (println x)) would do it

0:01 mk: alandipert: why wasn't my (map println [1 2 3]) working as expected?

0:02 alandipert: it returns the seq of println mapped over 1 2 3, and println always returns nil

0:02 doseq always returns just nil

0:03 (it's for side effects like printing, vs. map, which is for working with values)

0:04 mk: ah, which means map is lazy

0:04 alandipert: thanks

0:05 yoklov: you could (dorun (map println '(1 2 3)))

0:05 alandipert: mk: right, and np.

0:05 yoklov: (which returns nil instead of a seq of nils)

0:07 mk: interesting. It seems like those are effectively equivalent?

0:08 yoklov: oh

0:08 mk: (I don't actually know if they are, but it seems they do the same thing, since dorun is for producing effects)

0:09 yoklov: they are no

0:09 t

0:09 ,(doseq [a '(1 2 3)] (prn a))

0:09 clojurebot: 1

0:09 2

0:09 3

0:09 yoklov: ,(dorun (map prn '(1 2 3)))

0:09 clojurebot: 1

0:09 2

0:09 3

0:10 mk: ...are you sure?

0:10 yoklov: i mean

0:10 (map prn '(1 2 3))

0:11 retuns a seq

0:11 which when e forced prints some stuff

0:11 dorun takes that and forces everything

0:11 wheras doseq takes a seq, and does some stuff to it, forcing it in the process

0:12 with dorun your seq could be produced elsewhere

0:13 mk: ,(time (dorun (map prn '())))

0:13 clojurebot: "Elapsed time: 0.145 msecs"

0:13 mk: ,(time (doseq [a '()] (prn a)))

0:13 clojurebot: "Elapsed time: 0.964 msecs"

0:13 yoklov: also doseq is a macro, and dorun is a function

0:13 i'd assume their performance is the same and clojurebot is being weird

0:14 maybe not.

0:14 mk: factor of 10:1 on my repl. Interesting

0:16 yoklov: by the way, how was your port of the game turning out?

0:17 yoklov: haha, i haven't gotten too far, gonna work on it more tomorrow. friends of mine who were worrying for my sanity convinced me i should go out tonight instead of just staying inside and writing code :p

0:18 Frozenlo`: And he calls himself a friend? tsss

0:18 mk: pfft, some friends you have ;)

0:18 yoklov: seriously, what jerks

0:23 mk: hmm, there's no set of all namespaces?

0:24 ,*ns*; only shows the current, while (all-ns) returns a seq...

0:24 clojurebot: #<Namespace sandbox>

0:27 yoklov: just do (set (all-ns))?

0:30 mk: yoklov: I was thinking of trying to break things by messing with the real *all-ns-set* - looks like it's hidden behind clojure.lang.Namespace/all, though

0:35 yoklov: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Namespace.java yeah i don't think you can get at that

0:36 cgag: how do I set a property in clojurescript?

0:38 yoklov: oh

0:38 qbg: Hmm... Calling a function with ints boxed in a mutable wrapper is only 50% slower than calling a function that takes primitive ints it looks like

0:38 yoklov: (set! (.-prop obj) val)

0:38 i think

0:38 should work.

0:41 cgag: that worked, thanks

0:41 yoklov: awesome

0:41 cgag: are there any resources on clojurescript? i didn't seem much on the documentation on the repo

0:42 yoklov: i don't really know, to be honest. i've been going mostly by code in libraries and knowledge of clojure

0:44 cgag: yeah that's what i've been doing so far

0:50 yoklov: also the compiler is in clojure so its fairly readable

0:51 dunno how helpful it is, but its certainly interesting

1:35 mk: (doc +')

1:35 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Supports arbitrary precision. See also: +"

1:37 mk: ,'+'

1:37 clojurebot: +'

1:38 mk: strange, the ccw repl seems broken. I get +\n#<Exception java.lang.Exception: EOF while reading> when trying '+'

1:39 amalloy: that was not valid syntax in 1.2, so the ccw repl is probably running on 1.2

1:40 mk: hmm, yes: "1.2.0"

1:40 that's rather annoying - how can I update?

1:41 amalloy: *shrug* ask someone who knows anything about ccw. maybe cemerick or lpetit?

1:44 mk: amalloy: I might try switching to something else. Thanks for catching that

3:25 muhoo: i've got some functions i tend to use a lot in the repl, what's the best way to have them around? create a project, make a jar of it, and add it to project.clj? or is there some other way?

3:29 or just ln -s the file in, and then require it?

3:33 Raynes: muhoo: Lein 2?

3:33 muhoo: If you're using lein 2 you can edit ~/.lein/profiles and add it to your :user profile.

3:34 Now go upgrade if you haven't already.

3:49 amalloy: muhoo: i recommend making a utility project for them

3:49 then you can use them in actual programs you write, not just repl experimentation

3:50 muhoo: amalloy: that's what i kind of thought, thanks.

3:51 amalloy: if you want, you can start by forking mine from http://github.com/flatland/useful - it probably includes some of the things you want already, and should provide a reasonable base for adding more

3:53 muhoo: i saw that, it was very, er, useful. i'm pretty sure the stuff i'm doing is a lot more pedestrian

3:54 like, my stuff is baby steps still, and i'm sure i'll end up using useful at some point.

3:55 e.g., this is the kind of stuff i ended up typing over and over again and decided, finally, to make a library of it: https://refheap.com/paste/1358

3:56 like a blind man feeling his way around a dark room with a single candle, still.

3:57 oh, so that's where assoc-in! is!

3:58 i saw clutch examples used assoc-in! and i couldn't find it anywhere. i guess it was in useful all along.

3:58 amalloy: i doubt if cemerick is using useful; it's probably someone else's

4:01 muhoo: Raynes: yes, i'll try lein2 at some point. as of now, i'm still trying not to change anything that'll confuse or disorient me any more than i already am :-)

4:14 Raynes: Man.

4:14 Utility libraries make me want to stab myself in the face.

4:15 mk: Raynes: why's that?

4:17 Raynes: Because they do nothing but grow. They start out as "Here is a few of my favorite things!" and turn into giant libraries of unrelated things. The best you can hope for is some semblance of structure and organization, but in the end it is still a giant mess of things someone has thought up over the past two years.

4:18 "Ah, this is a nice function. But there are a thousand other nice functions. My options are to depend on this giant utility library or copy this code and thus duplicate functionality. My head. IT BURNS!"

4:21 mk: I think that's a problem of organization. I'm not a fan of huge files. If there's something that can be used independently, it should have its own file

4:24 I'd just copy the code if I were you

4:30 Znudzon: Hi i have installed clojure 1.3 but now i would like to install contrib libs. I 've made everything from the install instructions but i still dont have the .jar file but a lots of directories with lisb . What now ?

5:18 gtuckerkellogg: can one run tests on a leiningen project from swank?

5:19 amalloy: gtuckerkellogg: you probably want clojure-test-mode

5:20 gtuckerkellogg: amalloy, that does sound like somethnig i would want, doesn't it!

5:20 thanks

5:20 and btw, amalloy, i like your clojopts rep

5:21 amalloy: that makes one of us!

5:21 gtuckerkellogg: :)

5:25 amalloy, that is one fantastic mode. wow

5:29 amalloy: then i should learn to use it :P. i'm still in the stone age of testing

5:36 gtuckerkellogg: i create a lot of bugs, so i like testing

5:54 khaliG: anyone alive?

5:55 I need to recur twice in a function but the compiler says can only recur from tail position

5:55 AimHere: Well both places you're recurring from ought to be the tail position

5:55 khaliG: http://pastebin.com/fdjMBhMG

5:55 clojurebot: Huh?

5:56 AimHere: What 'tail position' means is that no operations are happening to the results of the recur before the result is returned

5:56 khaliG: impossible, gotcha :)

5:56 now to figure out how to write inline java *grin*

5:57 AimHere: Well often you can rewrite functions to be tail recursive, or make slightly-different functions that do the same job (the 'loop' function helps with this)

5:57 the latter being functions that take a bunch of parameters

5:58 Not sure how you'd do it for your function though

5:58 *different bunch of parameters

5:58 khaliG: yeah dunno im probably using the wrong language

6:00 hm wait there isn't any issue if I don't use the recur keyword

6:00 which i suppose is where I went wrong

6:00 thanks AimHere

6:02 AimHere: Well that code, if it works at all, seems to be out of the functional-idiom; I can't tell because I don't know what merge* does, though

6:03 khaliG: right, it's basically mutating the array A recursively. I got it out of a textbook

6:04 AimHere: Fair enough; Clojure tends to default to functional style, and would just return a new merged array from the old rather than mutating things

6:04 At least it's users would ;)

6:04 khaliG: hmmm understood :)

6:38 deobald: Anyone around? swank-clojure is barfing on `Unable to resolve classname: BufferedReader` on a friend's Mac (1.6.8). I can run JRuby's irb and `lein repl`, so Java's not completely broken. Is swank-clojure looking for the Java classes in the wrong place somehow?

8:22 hyperboreean: how do you sort a list of maps by a key's map in clojure? (I am looking for something like python's sorted(lst, key = lambda t: t['price']). Should I use a sorted map instead ?

8:23 map's key that is

8:48 kij: Hey, The reductions example here, http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci#Recursive_Version seems be self-referencing, was that valid as some point? and what would the syntax be now ?

9:15 gfredericks: kij: that doesn't work?

9:16 AimHere: I just tried it, it works

9:17 gfredericks: another mystery solved

9:17 AimHere: kij > The trick with that is that you don't need the self-reference for the first two members of the sequence, and the laziness stops the sequence from being an infinite regression at any one point in time

9:20 Well okay, the second variant, with the reductions doesn't work

9:20 * AimHere must brush up on his reading comprehension.

9:22 AimHere: kij > (lazy-cat [1] (reductions + ....) works

10:10 wmealing: i have a class with a dash, but the file name that midje tests/looks for has an underscore. Is this expected ?

10:10 should there be no dashes in clojure filenames ?

10:10 gfredericks: wmealing: correct; from the java side all dashes are underscores

10:11 that's filenames and class/package names mostly

10:11 wmealing: ok

10:11 not what i expected, but as long as its across the board.

10:11 thanks gfrederi`

10:11 oops, gfredericks

10:11 gfredericks: yessir

10:12 huh I must be logged on somewhere else o_O

10:50 Scorchin: Is it possible to use regex with (case ..) ?

10:52 gfredericks: your question is ambiguous but I expect no either way

10:52 * gfredericks runs off

11:16 mmajchrzak: Is there any gui lib for clojure ? I know that i can still use libs from java but for my its too complicated with bigger aps.

11:17 AimHere: Seesaw is a clojureish wrapper around swing, which might make some things neater for you

11:18 mmajchrzak: thak you I will check this on google :)

11:18 RickInGA: here's a cool seesaw tutorial http://blog.darevay.com/2011/12/a-seesaw-tutorial/

11:26 Frozenlock: How does one get the value of a class? By that I mean the value written when doing 'C-c I' in slime.

11:26 Or rather let met explain my master plan. Perhaps I have the wrong approach.

11:26 I have multiple 'properties' all stored with different java classes. Here is an example on how I need to access the data with the current library: (-> data-storage (.get object-ID Property-ID)). I would like to transfer all this info into a map of this form: {:object1 {:Property1 value :Property2 value} :object2...

11:26

11:27 In addition, I would like to drop all the special classes in the process. For example, for the CharacterString class, I would like to simply store the string such as "this is my string" instead of #<CharacterString this is my string>.

12:08 mk: Frozenlock: did you solve your problem?

12:08 Frozenlock: yes and no... I'm making a function that retrieves every properties. It might take a while. :)

12:09 And usually when it takes a while, I'm doing something wrong.

12:09 dnolen: core.logic occurs-check is way more expensive in JS than on the JVM

12:11 mk: Frozenlock: what did you mean by the value of a class? getClass?

12:19 Frozenlock: I wasn't clear, I apologize. Say I have this object PropertyIdentifier/presentValue (of the class PropertyIdentifier). I would like to get the value shown when I inspect it with 'C-c I'. In this case, its value is "Present Value".

12:20 andre27: ciao

12:20 Frozenlock: I'm still new to all this object/class/method thing, I really might confuse them...

12:22 mk: Frozenlock: you want to get the return value of a method?

12:22 or is that an attribute?

12:22 Frozenlock: Not a method, so I would say attribute.

12:23 Ok wait, I have an example

12:23 mk: (also called a property, I guess)

12:23 Frozenlock: Say (def test1 "hello")

12:24 Its value is "hello" when inspected with 'C-c I' (obiously).

12:24 I could just type test1 in the REPL and get the answer.

12:24 mk: Frozenlock: I don't use emacs, but I follow you so far

12:25 Frozenlock: However with my PropertyIdentifier/presentValue, I get a java object returned in the REPL

12:25 --> #<PropertyIdentifier Present value>

12:25 How can I get the 'Present value' part?

12:27 In other words, I want to get rid of the java part and only keep a string or symbol 'Present value'.

12:29 mk: Frozenlock: is PropertyIdentifier/presentValue simply a static field, like Math/PI ?

12:30 Frozenlock: I suppose so.

12:30 mk: what's (type Prope...) ?

12:30 Frozenlock: ..type.enumerated.PropertyIdentifier

12:31 But when you type Math/PI, you get the value, not simply --> #<Math PI>

12:31 mk: Frozenlock: right, because:

12:32 ,(type Math/PI)

12:32 clojurebot: java.lang.Double

12:32 raek: Frozenlock: do you have a link to the javadoc?

12:33 Frozenlock: Yes, brb.

12:33 mk: so your class Prop..Id.. has a static field of type PropId. Presumably the toString method returns a string, which you see in your repl

12:33 raek: java only has fields and methods. I supspect these properties are objects defined by the library

12:34 Frozenlock: http://sourceforge.net/projects/bacnet4j/files/bacnet4j/1.2/

12:34 raek: yeah, when you see #<Foo bar> in the repl, it means that you have an object of class Foo whose toString method returns "bar"

12:35 Frozenlock: So I could use toString? Let met try that...

12:35 Oh wow.

12:35 So simple.

12:35 Yet I was so far away.

12:35 raek: Frozenlock: if the javadoc of PropertyIdentifier says you should use toString do it

12:35 mk: Frozenlock: it might be easier to get the field that toString uses

12:36 Frozenlock: mk: how can I get this field? .getfield or something like that?

12:37 raek: Frozenlock: do you have any java code example for what you are trying to do?

12:37 it's much simpler if we can see some sort of documentation of how these classes are supposed to be used

12:37 mk: Frozenlock: I'm looking at the class docs, and it's a class with many static members

12:37 Frozenlock: raek: Indeed... I see now that .toString is the only method for this class in the doc.

12:38 raek: your questions are not anymore about java in general, but specifically about this library

12:38 Frozenlock: raek: I'm sorry, I still don't see where the line is between java/libraries.

12:39 raek: Frozenlock: are you sure the PropertyIdentifier actually holds the value?

12:39 Frozenlock: I do have examples on how the java code works. No problem there, I've translated most of what I needed.

12:40 mk: Frozenlock: are you writing out every single property in the PropertyIdentifier class? you don't need to

12:40 raek: and that it isn't some key of some sort that is used to extract a value from another object

12:40 Frozenlock: raek: it's exactly that.

12:41 raek: then you can't get the value using only the property identifier, I gess?

12:41 Frozenlock: But I want to put everything in a map with my own keys. {:present-value data}

12:42 raek: No. I have the key associated value. What I wanted was the PropertyIdentifier name, so I could use it in making my own map.

12:42 mk: Frozenlock: ok, so the PI object has a bunch of static fields - acceptedModes, ackedTransitions, etc., about 50 of them. You want to use those as your keys

12:42 raek: well, if I understand you correctly, then :present-value corresponds to PropertyIdentifier/presentValue

12:42 Frozenlock: mk: yes

12:42 Yes it does.

12:42 raek: and you're asking how to perform something like (get m :present-value)?

12:43 but we don't know what m corresponds to in the java lib

12:43 mk: however, whoever made this library ... ok, wow, yeah.

12:44 raek: you're probably looking for something like (.getProperty some-object PropertyIdentifier/presentValue)

12:44 Frozenlock: raek: No, I was asking at the very beginning if there was a way to easily transfer the info to a map. Then I asked a more precise question with the goal of obtaining the present-value key, which I did, thanks to you :)

12:44 raek: ok, I didn't see the whole backlog

12:44 Frozenlock: mk: wow in which direction? Wow ugly, wow great?

12:45 mk: what's a decent pastebin for clojure?

12:45 raek: mk: refheap

12:45 Frozenlock: so which class does the map-like object have?

12:45 mk: Frozenlock: "wow this could be done totally differently in clojure"

12:46 raek: you can probably transform that object into a map pretty easily

12:46 mk: https://refheap.com/paste/1359

12:46 raek: but the solution will be spicific to this library

12:46 mk: that's the source of the object

12:46 Frozenlock: raek: Class PropertyValues

12:46 Bronsa: wow.

12:47 raek: yikes.

12:47 I'm glad we have macros in clojure-land

12:48 Frozenlock: raek: At least I can! :D

12:48 I wouldn't want to stay in those java calls...

12:48 * Frozenlock shivers

12:49 scriptor: is any of that code generated?

12:49 I don't use java at all, but I've heard ide's like eclipse now do a good bit of code generation and manipulation for you

12:49 mk: ...this class extends 4 further classes

12:50 scriptor: I'll hazard a guess and say "no"

12:50 scriptor: damn

12:50 raek: Frozenlock: I think I misunderstood your original question. were you asking how to go from an instance of PropertyIdentifier for present value to something like :present-value?

12:51 and back again?

12:51 Frozenlock: raek: only the first part. But both ways could be handy too :P

12:51 mk: raek: I think Frozenlock wants the tostring values of each PI that the PI lists as a static field

12:52 * Frozenlock now realizes he might not have choosen the easiest library to learn clojure and java

12:52 raek: right.

12:52 I was confused by "the value of a PropertyIdentifier"

12:52 the toString method seems to solve the problem

12:52 Frozenlock: I apologize, like I said, I do not master the vocabulary yet.

12:53 Indeed.

12:53 raek: but you could also use reflection to get the name of the class as a string

12:53 Frozenlock: PropertyIdentifier

12:53 Is there a way to list all static fields?

12:53 raek: Frozenlock: no worries, everytihng is clear now... :-)

12:53 mk: raek: rightly so - its value is, for some strange reason, implemented strictly as its toString value

12:53 raek: yes

12:53 reflection

12:54 mk: Frozenlock: yes, I'm looking up the reflection code you need

12:54 raek: the java reflection api is a bit verbose

12:54 Frozenlock: Thanks to you both, I really appreciate your help :D

12:58 raek: there are some convenient methods in clojure.lang.Reflector to go from class + name of field to value of field

12:58 mk: how does one get the Class of a class?

12:59 raek: it will always be java.lang.Class

13:00 mk: right, but how do I get the instance?

13:00 raek: (the generic parameter does not exist after compilation in java)

13:00 mk: just write java.lang.Class

13:00 or (class (class some-object))

13:00 Frozenlock: http://www.jarvana.com/jarvana/view/org/clojure/clojure/1.3.0/clojure-1.3.0-javadoc.jar!/clojure/lang/Reflector.html#getStaticField(java.lang.String, java.lang.String)

13:01 ,(class (class 123))

13:01 clojurebot: java.lang.Class

13:01 mk: I want the class of ScaryPropertyThing without having to do SPT.field.getClass

13:01 raek: or did you mean the Class object given its name?

13:01 mk: roughly, yes

13:02 raek: in clojure you just write the class name directly in the code (if you know it when you write)

13:02 if you need to do the translation programatically, you need to use reflection

13:03 ,(class 123)

13:03 clojurebot: java.lang.Long

13:03 raek: ,java.lang.Long

13:03 clojurebot: java.lang.Long

13:03 raek: ,(class java.lang.Long)

13:03 clojurebot: java.lang.Class

13:03 mk: oh, well then :)

13:03 raek: the repl prints classes like symbols...

13:04 Frozenlock: raek: with this I can use getStaticField to get the fields, is that right?

13:04 raek: but the reflection way is pretty simple too: (Class/forName "java.lang.Long")

13:04 Frozenlock: if the property is a field, then yes

13:05 oh sorry

13:05 yeah

13:06 PropertyIdentifier/foo = (Reflector/getStaticField "com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier" "foo")

13:06 Frozenlock: ^

13:07 or simply (Reflector/getStaticField PropertyIdentifier "foo")

13:07 Frozenlock: Wait wait, I'm still trying to require the Reflector library...

13:08 mk: ,(map #(.getName %) (.getFields (Class/forName "java.lang.Math")))

13:08 clojurebot: ("E" "PI")

13:08 raek: (ns ... (:import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier clojure.lang.Reflector))

13:08 or (import 'com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier) (import 'clojure.lang.Reflector)

13:09 Frozenlock: It's not in clojure core?

13:09 (I need to dowload it?)

13:09 mk: you probably don't need the reflector. Just use the toString method

13:09 raek: no, it's in the implementation of clojure

13:10 mk: you actually can't get the value of the object any other way, since toString generates the value based on an int

13:10 Frozenlock: Oh I need to 'import'!

13:10 raek: mk: yes, but I still think reflection is needed for the reverse case (string to PropertyIdentifier instance)

13:11 mk: raek: I don't think it's possible to do that in that way, the string values are inside toString

13:12 raek: yes, but using getStaticField you can go from "foo" to the value PropertyIdentifier/foo would return

13:13 so the internal string is not used

13:13 only the name of the field

13:13 mk: so you're talking about a mapping from the key to the PropIdent object - gotcha

13:14 raek: yikes. that author has really missed the whole enum thing

13:14 Frozenlock: How can I list every static fields?

13:15 mk: Frozenlock: I pasted the code above

13:15 * Frozenlock scrolls up

13:15 Frozenlock: ,(map #(.getName %) (.getFields (Class/forName "java.lang.Math")))

13:15 raek: this is essentially what the java compiler generates when you type public enum {foo, bar}

13:15 clojurebot: ("E" "PI")

13:16 raek: except that you ca[1~ w[1~ except that with enums you can go from string to instance too :-)

13:16 Frozenlock: mk: works flawlessly, thanks!

13:17 raek: automatation FTW

13:18 Frozenlock: Yeah, I was worried I would have to hardcode every single field.

13:18 raek: if you want to be really pedantic you can filter the fields to only see the static and public ones

13:22 (for [field (.getFields java.lang.Math), :let [mod (.getModifiers field)], :when (and (Modifier/isPublic mod) (Modifier/isStatic mod))] (.getName field))

13:22 mk: what's the code for doing a map, but keeping the map? (??? identity '(1 2)) -> {1 1 2 2}

13:23 raek: zipmap maybe?

13:23 &(let [coll (range 5)] (zipmap coll (map str coll)))

13:23 lazybot: ⇒ {4 "4", 3 "3", 2 "2", 1 "1", 0 "0"}

13:24 Frozenlock: raek: modifier?

13:24 mk: zipmap zips two collections - I want a version of map that keeps the mapping

13:24 raek: Frozenlock: java.lang.reflect.Modifier

13:24 sorry :-)

13:24 mk: and also produces a map instead of a lazy sequence?

13:24 mk: (map inc (1)) gives (2), I want {1 2}

13:25 raek: &(into {} (map (juxt identity inc) (range 5)))

13:25 lazybot: ⇒ {0 1, 1 2, 2 3, 3 4, 4 5}

13:26 raek: you need (apply hash-map ...) (zipmap ...) (into {} ..) or something similar to get a map

13:27 I would use zipmap if I had a sequence, a function and wanted to contruct a map from x to f(x)

13:29 Frozenlock: another pedantic thing to do would be to limit the results to the fields that have the correct type: (= (.getType field) Property.Identifier)

13:30 but that's probably overkill in this case

13:30 Frozenlock: Better safe than sorry, thanks!

13:32 raek: mk: afaik, there is no function f in clojure.core that does (f str [1 2 3]) => {1 2, 2 3, 3 4} I'm afraid

13:33 s/str/inc/

13:34 AimHere: raek > It's very easy to roll your own

13:35 ,((fn [f a] (zipmap a (map f a)) inc [1 2 3])

13:35 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

13:36 AimHere: ,((fn [f a] (zipmap a (map f a))) inc [1 2 3])

13:36 clojurebot: {3 4, 2 3, 1 2}

13:36 raek: I can agree that it would be a useful function to have in the standard library though

13:37 mk: ok, here we go:

13:37 ,((fn [classname] (into {} (map (juxt #(.getName %) #(.toString (.get % nil))) (.getFields (Class/forName classname)))) )"java.lang.Math")

13:37 clojurebot: {"E" "2.718281828459045", "PI" "3.141592653589793"}

13:37 raek: ah cool :-)

13:37 Frozenlock: Ohhhh that's sexy!

13:49 mk: ,(flatten '("one" "two"))

13:49 clojurebot: ("one" "two")

13:50 mk: ,(into {} (flatten (map #(list (.getName %) (.toString (.get % nil))) (.getFields java.lang.Math))))

13:50 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Character cannot be cast to java.util.Map$Entry>

13:50 mk: whats going on there?

13:51 oh, I see

13:52 gfredericks: ,(->> "java.lang.Math" Class/forName .getFields (map (juxt #(.getName %) #(.toString (.get % nil)))) (into {}))

13:52 clojurebot: {"E" "2.718281828459045", "PI" "3.141592653589793"}

13:52 * gfredericks thinks ->> is usually sexier

13:54 mk: ,(into {} (map #(vector (.getName %) (.toString (.get % nil))) (.getFields java.lang.Math)))

13:54 clojurebot: {"E" "2.718281828459045", "PI" "3.141592653589793"}

13:54 * gfredericks thinks there ought to be a function called 'victor

13:56 mk: what would it do?

13:57 gfredericks: maybe it could be the map-from-fn function we've all been wanting

13:58 mk: it has a bit of a priorityqueue or sorted feel to it

13:59 the-kenny: Like (victor identity inc [1 2 3]) -> {1 2, 2 3, 3 4} ?

14:00 gfredericks: the-kenny: that suggests interesting vararg possibilities

14:00 the-kenny: but no, I was thinking the identity was implicit

14:00 so just (victor inc [1 2 3])

14:00 mk: gfredericks: what sort of possibilities?

14:00 gfredericks: either multiple functions or multiple collections

14:01 the-kenny: gfredericks: Yeah, just added this for more possibility

14:01 mk: the multiple collections would serve as params?

14:01 gfredericks: maybe?

14:01 the-kenny: I like the idea of having 2-arg and 3-arg versions

14:02 mk: that's what map does

14:02 the-kenny: gfredericks: Yeah

14:03 gfredericks: (defn victor ([f coll] (victor identity f coll)) ([f1 f2 coll] (zipmap (map f1 coll) (map f2 coll))))

14:09 yoklov: hm, is there a list of the functions in the clojure api which aren't in clojurescript?

14:09 gfredericks: I doubt it; could be interesting to see how easily that could be generated though

14:11 the-kenny: There's a wiki page "Differences between Clojure & Clojurescript"

14:12 However, it's missing some things. Clojurescript sadly doesn't have `sorted-map' :(

14:12 yoklov: `shuffle` is also unimplemented

14:12 which isn't documented anywhere i think

14:12 which is why i asked haha

14:12 gfredericks: shuffle would be easy to add

14:13 yoklov: yeah, thats why i was surprised it hadn't been done

14:14 lynaghk: yoklov: Fisher-Yates in-place shuffle is implemented by Closure in goog.array.shuffle

14:14 yoklov: if you are okay with dropping down to JS

14:15 dnolen: emezeske: is there an easy way to get lein-cljsbuild to use a custom version of the clojurescript compiler?

14:15 yoklov: i am, how can you convert a collection to a js array (sorry, new to clojurescript)?

14:16 lynaghk: dnolen: thanks for that pointer to the LEARN PROLOG NOW! book, I've been reading that plus finally getting into the Reasoned Schemer copy that I got at the Conj.

14:16 donkeykong: hello, emacs newbie here... im trying to play with labrepl to get the hang of clojure. using emacs and clojure-jack-in. the repl starts fine and i can navigate to the labrepl webpage. however, when i evaluate (doc println) in the repl i get a "Unable to resolve symbol: doc in this context [Thrown class java.lang.RuntimeException]"

14:16 gfredericks: donkeykong: try (use 'clojure.repl) first

14:17 dnolen: lynaghk: np, Prolog lit really clarifies a lot of things, I'm thinking about putting together a core.logic basic that illustrates how to do basic conversions.

14:17 Frozenlock: donkeykong: with emacs, you should do 'C-c C-d d' on what you want more details.

14:17 lynaghk: yoklov: (array 1 2 3) will make a js array [1, 2, 3]. If you have something in CLJS, you can (apply array my-seq)

14:17 dnolen: core.logic basic wiki page I mean.

14:17 yoklov: lynaghk, thanks

14:17 Frozenlock: donkeykong: Or even M-. if you want to see the source

14:17 donkeykong: gfredericks: that works! thanks much.

14:17 lynaghk: dnolen: that would be pretty rad. Especially now that you have it working in CLJS---props on that, by the way.

14:18 donkeykong: Frozenlock: ok il keep that in mind. lots of keybindings to pick up, one step at a time!

14:18 Frozenlock: The joy of emacs :P

14:19 dnolen: lynaghk: thanks! Yeah I'm excited, interestingly core.logic seems to run equally fast under all the browser nightlies. I think people could actually design some really interesting logic libs that normal JS libs can consume.

14:20 qbg: It would be cool if the CLJS compiler could be compiled to JavaScript

14:20 Frozenlock: donkeykong: I also hope your on IRC with Emacs :P

14:20 lynaghk: dnolen: yeah, I haven't done much in the way of making CLJS libs accessible from plain JS, but I'll be figuring that out soon on a client project.

14:20 Frozenlock: *you're

14:20 lynaghk: I expect it's just a lot of ^:export

14:20 gfredericks: lynaghk: depends on if you want data structure translation too

14:21 donkeykong: Frozenlock: yes and it greets me with "Be happy for Emacs. Emacs is your life." -- Omar Khayyam

14:22 dnolen: qbg: probably possible and not that much work. I think once we have performant data structures, it will be more interesting to pursue.

14:22 lynaghk: gfredericks: yeah, that was the incredibly annoying lesson learned from cljs-d3 and one of the main reasons I rewrote it in plain Clojure

14:22 qbg: dnolen: Imagine ClojureScript as a browser plugin

14:22 No external deps!

14:22 gfredericks: lynaghk: I messed with that once. My solution was to generate an API namespace that had a wrapper for each public function and also did the data translation

14:23 I was talking to emezeske about whether or not that would be useful in cljs-build

14:23 part of the issue is there's no easy way to generate a separate namespace using cljs code or macros

14:24 lynaghk: gfredericks: some kind of macro that would automatically throw together a namespace with certain functions in it and wrap their args in translations?

14:24 gfredericks: lynaghk: yeah that's what I was thinking, but you can't really emit a namespace

14:24 at least not with the current compiler

14:24 so hooking into cljs-build would probably be the most straightforward option, whether that's by adding it to the cljs-build project proper or cljs-build providing hooks

14:26 lynaghk: gfredericks: I've been thinking about that problem in the context of clj/cljs code sharing; I'm working on something that would just emit generated sources, so you'd be free to make up as many new namespaces as you want

14:26 gfredericks: yeah I think that's how I did it initially; I can't remember if lein-cljsbuild existed at that point or not

14:27 lynaghk: what're you trying to achieve there that the cljsbuild crossovers don't?

14:27 dnolen: qbg: would be cool, probably inevitable really :)

14:28 qbg: Almost zero barrier to entry :)

14:28 lynaghk: gfredericks: there are some transformations that need to happen beyond just copying the files. For instance, in Clojure you extend clojure.lang.IFn with invoke. In ClojureScript it's IFn and -invoke

14:29 gfredericks: ah right

14:30 lynaghk: gfredericks: I've been looking into using Kibit to do those kind of rearrangements, and also filtering based on metadata so you can remove entire toplevel forms if necessary. E.g., in the source you'd define two sqrt functions; one annotated with ^:clj that uses (Math/sqrt x) and one annotated with ^:cljs that uses (.sqrt js/Math x).

14:30 gfredericks: lynaghk: I wonder if symbol macros together with a cljs? function would suffice for most cases?

14:31 lynaghk: but, uh, kind of taking a detour to learn logic programming so it might be a few weeks before I can get something working out the door.

14:31 gfredericks: that is Evan's approach right now. We talked about this problem at Clojure/West a fair bit, and we're going to just try both and see what feels better.

14:32 gfredericks: one of the reasons I want to use metadata over macros is so that I can use the JVM Clojure REPL as much as possible.

14:32 gfredericks: hmmm

14:33 what about metadata on arbitrary forms?

14:33 where the form itself gives the clojure version and in the metadata you give a cljs replacement

14:34 (defn sqrt [x] #^{:cljs (.sqrt js/Math x)} (Math/sqrt x))

14:34 lynaghk: gfredericks: that's an interesting idea. I feel like that would make my editor super angry.

14:34 gfredericks: haha why?

14:34 qbg: gfredericks: A compiler-cond macro?

14:35 gfredericks: qbg: eh? not sure what that means

14:35 lynaghk: gfredericks: dunno, just shoving a lot of forms around I guess. That might be a cool addition, but I definitely want to have the basics (like this clojure.lang.IFn -> IFn) work out of the box automatically.

14:35 qbg: cond, but evaluates at macroexpansion time

14:35 gfredericks: qbg: are you suggesting that's what I'm doing, or suggesting an alternative?

14:36 qbg: It would be a bit more general of an alternative\

14:36 mk: is there a categorized list of all of clojure core?

14:36 gfredericks: $google clojure cheatsheet

14:36 lazybot: [Clojure - cheatsheet] http://clojure.org/cheatsheet

14:36 qbg: But it is basically a (poor) reimplementation of reader conditionals from CL

14:36 gfredericks: mk: ^ seen that?

14:37 lynaghk: gfredericks: I just added you to the collaborators list for this repo, if you want to watch how it develops. I'll writeup the README a bit more and open source it when it's barely usablable.

14:37 gfredericks: qbg: also there's always #=(if cljs? 'js/Math 'Math/sqrt)

14:37 mk: yep, it's open in a tab, but I think it's missing things, and was hoping for something a bit more parsable

14:38 qbg: Can we do better than #+ and #- from CL?

14:38 gfredericks: qbg: what do those do?

14:38 mk: there's also using the ns functions to get all the vars

14:38 that's not too categorized though

14:39 qbg: Depending on *features*, conditionally ignore the next form

14:39 mk: gfredericks: yeah, I actually just did (sort (keys (ns-publics (the-ns 'clojure.core)))) :)

14:40 qbg: http://www.lispworks.com/documentation/lw50/CLHS/Body/24_aba.htm

14:41 dnolen: hmm I thought I could just run 'lein install' from a project, did this chagne?

14:42 fprefect: ,(class (char-array [\x \y \z]))

14:42 clojurebot: [C

14:44 dnolen: ooops, 'lein install' works just fine

14:48 * gfredericks wonders what `lein in stall` would do

14:48 gfredericks: lynaghk: how does cljx relate to cljsbuild?

14:49 lynaghk: gfredericks: it doesn't; assuming I can get it to something useful, it'd be a lein plugin that generates clj and cljs from "cljx" source files. You'd still use cljsbuild, but you wouldn't need to do anything with crossovers.

14:50 gfredericks: lynaghk: ah hah;

14:50 very nice

14:50 lynaghk: gfredericks: if by "very nice" you mean "terrible terrible hack" = )

14:51 mk: how can I use booleans?

14:51 gfredericks: mk: um

14:51 how do you want to use them?

14:51 mk: (booleans ???) -> something that isn't an error

14:52 gfredericks: ,(type true)

14:52 clojurebot: java.lang.Boolean

14:52 gfredericks: ,((juxt type identity) (boolean 15))

14:52 clojurebot: [java.lang.Boolean true]

14:52 mk: I want to use the booleans function in particular

14:52 gfredericks: oh wait there is a 'booleans function

14:52 I see

14:52 ,(doc booleans)

14:52 clojurebot: "([xs]); Casts to boolean[]"

14:52 gfredericks: ah right; arrays; what fun

14:52 ,(booleans [true false true])

14:53 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to [Z>

14:53 gfredericks: &(-> [true false true] (make-array) (booleans))

14:53 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$make-array

14:53 mk: nice try! ;)

14:53 gfredericks: &(->> [true false true] (apply make-array) (booleans))

14:53 lazybot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Character

14:53 gfredericks: consarnit

14:53 &(doc make-array)

14:53 lazybot: ⇒ "([type len] [type dim & more-dims]); Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects f... https://refheap.com/paste/1362

14:53 gfredericks: &(doc to-array)

14:53 lazybot: ⇒ "([coll]); Returns an array of Objects containing the contents of coll, which can be any Collection. Maps to java.util.Collection.toArray()."

14:54 gfredericks: (->> [true false true] to-array booleans)

14:54 &(->> [true false true] to-array booleans)

14:54 lazybot: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Z

14:54 qbg: &(->> [true false true] (into-array Boolean/TYPE) (booleans))

14:54 lazybot: ⇒ #<boolean[] [Z@d94042>

14:54 * gfredericks hates everybody

14:55 gfredericks: every time I need to work with arrays there's always five functions that do mostly the same thing and I always try the right one last

14:55 mk: ,(into-array Boolean/TYPE [true false true]) ; I get the impression that the use of booleans was superfluous there, qbg...

14:55 clojurebot: #<boolean[] [Z@1ad13ee>

14:55 qbg: mk: It is

14:56 type hinting is the only reason to use booleans

14:56 (basically)

14:57 * gfredericks wants to build an ideal dialect of clojure that exposes no host

14:57 qbg: But Clojue's philosophy is to be close to the host...

14:58 gfredericks: yeah :)

14:58 I didn't mean that it'd be compatible with clojure's goals or anything

14:58 qbg: Ignoring the host isn't good enough?

14:58 mk: so... ok... core has some really silly-looking infrequently-used functions

14:59 dnolen: emezeske: hmm, how can I install lein-cljsbuild from the repo locally?

14:59 gfredericks: qbg: well an ideal dialect could be guaranteed to execute the same on all hosts

14:59 mk: qbg: thanks for solving the mystery of booleans

14:59 gfredericks: mk: yeah it does have a lot of those

14:59 qbg: booleans in the end is just return (boolean[])o;

14:59 mk: gfredericks: like the intersection of what you can expect all the hosts to implement

15:00 gfredericks: mk: and maybe some other non-performant modifications like always promoting to bigints (or rather semantically bigints everywhere -- not exposing a distinction)

15:00 qbg: mk: Examples that you think are silly?

15:02 gfredericks: qbg: could go even further and make it pure-functional, I think

15:02 mk: qbg: ffirst and its ilk, apparently most of these array casts... *1 *2 should be in the repl, that sort of thing

15:03 devn: what am i doing wrong with seesaw here? It seems like my keystroke listener works in the nth instance (-> f show!), but then fails in new instances

15:03 qbg: mk: Wait until you see CL...

15:03 mk: qbg: CL?

15:04 devn: common lisp

15:04 gfredericks: common lisp

15:04 qbg: With the ca*d*r functions

15:04 mk: right. Yeah, there might be quite a wait on that ;)

15:04 qbg: ed is my favorite

15:05 Basically not implemented in the impls I used

15:05 mk: ed?

15:05 clojurebot: ed is the standard editor!

15:05 Iceland_jack: ed.

15:06 qbg: http://clhs.lisp.se/Body/f_ed.htm

15:06 irc2samus: hi guys, in order to test if a given instance implements some interface is it rigth to use "instance?"?

15:07 gfredericks: ,satisfies?

15:07 clojurebot: #<core$satisfies_QMARK_ clojure.core$satisfies_QMARK_@14dd46d>

15:07 mk: if that's the scheme editor, it's the reason I stopped messing about with learning scheme

15:07 gfredericks: irc2samus: I think that does it ^

15:07 qbg: irc2samus: Yes

15:07 gfredericks: oh wait

15:07 I read 'protocol' instead of 'interface'

15:08 irc2samus: oks thanks!

15:11 gfredericks: so do CL/scheme have a single stringy-thing while clojure has three?

15:11 qbg: stringy-thing?

15:11 gfredericks: string/symbol/keyword

15:12 qbg: CL has all of those

15:12 AimHere: Scheme has strings and symbols, at least

15:12 gfredericks: hell also char-seqs

15:12 qbg: CL strings are mutable

15:13 gfredericks: then there are also vectors of futures of atoms of length-1 strings

15:13 which are what I use most of the time

15:14 qbg: CL has zero dimensional arrays

15:14 And arrays which point to the contents of other arrays

15:14 gfredericks: it has more than one of them?

15:15 qbg: It has real multidimensional arrays

15:15 Not just arrays of arrays

15:15 A 1 dim array which shares the contents of a 2d array is fun

15:16 gfredericks: that's funny I have the opposite opinion

15:16 qbg: There was a C implementation for the lisp machines

15:17 That would really show how "portable" your C code is!

15:25 gfredericks: does erc have a built in thing for keeping track of mentions and such?

15:40 mk: what's the difference between = and ==?

15:41 muhoo: &(doc =)

15:41 lazybot: ⇒ "([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) ... https://refheap.com/paste/1363

15:41 gfredericks: ,(doc ==)

15:41 muhoo: &(doc ==)

15:41 lazybot: ⇒ "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

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

15:41 gfredericks: man I don't know what that means

15:41 muhoo: me neither *shrugs*

15:42 mk: ,(== 1 1)

15:42 clojurebot: true

15:42 mk: "returns non-nil"

15:42 * gfredericks didn't even know there was clojure.core/==

15:42 gfredericks: ,(== 1 1.0)

15:42 clojurebot: true

15:42 muhoo: ,(= 1 1.0)

15:42 gfredericks: ,(= 1/3 0.3333333333333333)

15:42 clojurebot: false

15:42 false

15:42 muhoo: AHA!

15:42 gfredericks: oh wow

15:42 muhoo: == is type independent

15:42 gfredericks: didn't expect (not= 1 1.0)

15:42 muhoo: like it says

15:43 gfredericks: yet ##(= [3] '(3))

15:43 lazybot: ⇒ true

15:43 gfredericks: &(= [3] '(3.0))

15:43 lazybot: ⇒ false

15:43 muhoo: &(== [3] '(3.0))

15:43 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

15:43 muhoo: realy?

15:44 gfredericks: &(== [3] [3.0])

15:44 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

15:44 gfredericks: ???

15:44 lazybot: gfredericks: How could that be wrong?

15:44 muhoo: " if nums"

15:44 so == can only handle numbers

15:44 gfredericks: ooh

15:44 Bronsa: == is just for numeric comparison

15:44 gfredericks: you learn something new every minute

15:44 ((juxt = ==) 0.75 3/4)

15:44 &((juxt = ==) 0.75 3/4)

15:44 lazybot: ⇒ [false true]

15:45 muhoo: what i like about clj si that the new things i learn make me go "ooh" not "wtf".

15:46 gfredericks: muhoo: like ##(#'and true false true)?

15:46 lazybot: ⇒ true

15:46 muhoo: &(and true false true)

15:46 lazybot: ⇒ false

15:46 mk: this is new in 1.3 it seems, since 1.2 gives true on (= 3 3.0)

15:47 muhoo: what's the #' do?

15:47 Bronsa: you call and as a function, not as a macro

15:47 gfredericks: ,(= #'and (var and))

15:47 clojurebot: true

15:48 muhoo: why would you do that?

15:48 gfredericks: you wouldn't so it's not a very good example :)

15:48 Iceland_jack: why indeed

15:48 Bronsa: when a macro is called &form and &env are implicitly passed

15:48 gfredericks: clj does indeed have less WAT than js

15:48 Iceland_jack: WATs per minute

15:48 Bronsa: if you call it as a function, you need to pass them manually

15:48 muhoo: spm

15:48 wpm

15:49 Iceland_jack: also WTF's per minute, that's how I measure my software

15:49 Bronsa: so (#'and true false true) is really (and true)

15:49 muhoo: interesting

15:50 gfredericks: js is like a practical joke that got out of hand

15:50 muhoo: could be worse.

15:50 you could be coding in php and java for a living

15:51 which have more "oh christ i want to stab my eyeballs with a fucking pencil!" per minute, IME

15:51 gfredericks: OCIWTSMEWAFP

15:51 //m

15:52 hard to start a message with a slash

15:52 muhoo: /like this

15:52 gfredericks: yes like that

15:52 mk: ,[(compare "a" "z") (compare 1 26)]

15:52 devn: weee, i now have a fancy capslock keyboard for overtone

15:52 clojurebot: [-25 -1]

15:52 * devn wonders if this already exists

15:53 gfredericks: &(doc compare)

15:53 lazybot: ⇒ "([x y]); Comparator. Returns a negative number, zero, or a positive number when x is logically 'less than', 'equal to', or 'greater than' y. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable"

15:53 muhoo: hah, a comparator. what's next, an op-amp?

15:53 maybe a schmitt trigger

15:54 mk: it's strange that it returns the alphabetic diff of the first char

15:54 gfredericks: &(compare "aa" "az")

15:54 lazybot: ⇒ -25

15:54 gfredericks: &(compare "aa" "ba")

15:54 lazybot: ⇒ -1

15:55 muhoo: i guess it's just supposed to be negative, zero, positive, and the actual value isn't meaningful?

15:55 mk: uhm.

15:55 gfredericks: yeah

15:55 mk: why?

15:55 clojurebot: Why is why

15:55 gfredericks: so it's quicker to return the diff than check it first

15:55 gtrak: how do I override + within a macro?

15:55 muhoo: ,why

15:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: why in this context, compiling:(NO_SOURCE_PATH:0)>

15:55 gfredericks: with-redefs?

15:55 muhoo: `why

15:55 gtrak: I get, 'can't let qualified name'

15:56 gfredericks: gtrak: oh you're trying to (let [+ foo] ...)?

15:56 gtrak: yea

15:57 gfredericks: okay use ~'+ then

15:57 + will expand to clojure.core/+ otherwise

15:57 gtrak: ah, I see

15:57 muhoo: gtrak: ##(letfn [(+ [x y] (- x y))] (+ 3 4))

15:57 lazybot: ⇒ -1

15:57 gtrak: makes sense :-)

15:57 gfredericks: muhoo: he's already inside a macro

15:58 or backquote rather

15:58 muhoo: oh

15:58 gfredericks: ,`(let [+ -] (+ 3 4))

15:58 clojurebot: (clojure.core/let [clojure.core/+ clojure.core/-] (clojure.core/+ 3 4))

15:58 muhoo: cool

15:58 gtrak: just reinventing vector math :-)

15:59 * gfredericks invents victor math

15:59 beffbernard: if you have a java-source-path defined, can you reference your clojure code from java?

15:59 gtrak: there's no plusable unfortunately

15:59 beffbernard: in leiningen

16:01 yoklov: haha, persistent data structure heavy clojure code makes for very sloooow clojurescript code

16:02 devn: wee... time to figure out how to draw a keyboard with seesaw, heh

16:02 dnolen: yoklov: very :)

16:04 yoklov: yup, it does work though, which is a huge plus. shouldn't be too hard to make this quicker.

16:04 are clojurescript lists copy-on-write too?

16:05 qbg: yoklov: I think everything in CLJS is copy on write

16:05 gfredericks: what do people mean by "clojure doesn't have a cons cell"? Is it just that Cons requires a seq for the second part?

16:05 qbg: lists are easy to do persistent though; I'd be surprised if they were copy on right

16:05 qbg: gfredricks: I believe so

16:05 yoklov: yeah, thats why i asked

16:06 gfredericks: it'd almost be harder to do COR for lists

16:06 qbg: Yeah, I think I'm thinking of vectors

16:06 yoklov: gfredericks, yeah the cons cell from most lisps is just two objects, and it's only a list if the second one is a list

16:07 dnolen: yoklov: lists don't need to be copy-on-write

16:07 yoklov: right, but if they were i wouldn't want to use them

16:07 AimHere: yoklov > Don't you mean if the second one is a cons cell?

16:07 yoklov: no

16:08 (1 . (2 . (3 . 4))) is not a list

16:08 gfredericks: yoklov: so you meant it recursively

16:08 yoklov: yeah

16:08 gfredericks: a list is a cons cell whose second element is nil or a list

16:08 yoklov: (1 . (2 . (3 . (4 . ())))) is a list

16:08 right.

16:09 since nil is the empty list, it counts as a list

16:09 in those lisps

16:09 Iceland_jack: yoklov: (1 . (2 . (3 . 4))) is an improper list

16:09 yoklov: e.g. scheme is the one i can actually talk about because i haven't really ever written anything non-trivial in common lisp

16:10 Iceland_jack, i guess it depends on if you consider an improper list to be a type of list

16:10 gfredericks: I believe erlang also has cons cells in the same sense

16:10 Iceland_jack: Well in Common Lisp (1 2 3) and (1 2 . 3) are both considered lists; proper and improper lists respectively

16:10 Languages like Clojure/Haskel/ML et al don't allow improper lists

16:12 yoklov: yup, which is sorta nice. clojure has better data structures to fill that void

16:13 qbg: What is read-string in CLJS?

16:13 gfredericks: I'd expect the same as in clj

16:13 oh unless it doesn't exist

16:13 I'm always misinterpreting questions

16:16 ihodes: hmmm so there's got to be a better way of doing this... i've got a cond tree, and one of the test statements is something kinda complicated, and what returns (if it's logically true) is what i want cond to return... but i need to use cond. any ideas of what to do?

16:16 gfredericks: ihodes: that's only the case for one of your clauses?

16:16 ihodes: currently i'm just computing it twice; once to evaluate to true, and then once for the return value: e.g. (cond (something complicated returning true maybe) (same thing))

16:16 gfredericks: for a few of the clauses, but not all of them

16:17 gfredericks: ihodes: first thought is to set each of those up in a let wrapped around the cond, but with a delay

16:17 (let [x (delay ...), y (delay ...), z (delay ...)] (cond @x @x (foo) bar @y @y @z @z))

16:17 ihodes: yeah, i wanted to avoid that for aesthetic purposes, but maybe so

16:18 gfredericks: maybe the only way to clean it up is to write a macro

16:18 qbg: Use (some identity <lazy-seq>)?

16:18 ihodes: qbg: that's what i'm actually doing, but it's ugly

16:19 gfredericks: grrrr. it seems common enough that there'd be a way of handling it. but i guess i don't actually run into it that often

16:19 gfredericks: yeah I don't think I ever have

16:19 ihodes: haha something like (cond (my expression) :ibid)

16:20 qbg: Could use the ternary form of condp

16:20 But that would be a ugly

16:20 gfredericks: then there's an (or) with your other cases wrapped in ifs

16:21 qbg: Yeah, you could use or

16:21 Frozenlo`: Is there a function to make a key from a name? (the inverse of `name')

16:21 qbg: &(keyword "foobar")

16:21 lazybot: ⇒ :foobar

16:21 Frozenlo`: Thanks!

16:21 qbg: gfredericks: Probably no need for if

16:22 gfredericks: qbg: when he wants separate parts there would be...

16:22 qbg: or is short circuiting

16:22 gfredericks: (cond (x) (x) y z (w) (w)) becomes (or (x) (if y z) (w))

16:22 ihodes: exactly

16:23 hmmmmmmm

16:23 gfredericks: qbg: his main problem is he's mixing two kinds of clauses

16:23 unless he's a woman and then it's her main problem

16:24 ihodes: i'm a him. freenode should allow you to enter preferred pronoun. would solve all sorts of problems.

16:24 qbg: If (some identity ...) currently works, then or should work also

16:25 gfredericks: ihodes: man that'd make things even easier than face-to-face

16:25 ihodes: i could just use (or (x) (if y z) (w)). that might be the best way to do it without writing a macro.

16:26 gfredericks: with each clause on its own line it should be pretty readable

16:27 ihodes: i just hate having about 14 (if x y)s in there. so much repetition.

16:28 qbg: Maybe you can refactor that?

16:28 ihodes: meh i guess i can use a cond for all the ifs, within the or

16:28 gfredericks: yeah it totally depends on how mixed the types of clauses are

16:29 ihodes: yeah. at this point, i'm just trying to make it look nice. i think (or (x) (y) (z) (cond a b, c d, e f)) is the best way of handling it

16:31 thanks for the brainstorming gfredericks & qdb

16:34 * gfredericks nods majestically

16:34 muhoo: one of the nice things about reading the source of the cljwest slides is that i discoverd there's a slideshow mode for emacs

16:35 didn't know org-mode could do slides.

16:35 devn: org-mode can do...everything

16:36 mk: how can I check if something is a boolean, and also, do exception-throwing boolean casting?

16:36 gfredericks: mk: ##(assert (boolean? :foo))

16:36 lazybot: java.lang.RuntimeException: Unable to resolve symbol: boolean? in this context

16:36 gfredericks: wtf

16:37 qbg: mk: booleaning casting how?

16:37 mk: ,(int "a")

16:37 gfredericks: &(assert (instance? Boolean :foo))

16:37 lazybot: java.lang.AssertionError: Assert failed: (instance? Boolean :foo)

16:37 clojurebot: Execution Timed Out

16:38 gfredericks: &(assert :foo)

16:38 lazybot: ⇒ nil

16:38 devn: &(let [x false] (or (true? x) (false? x)))

16:38 lazybot: ⇒ true

16:38 mk: &(int "a")

16:38 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character

16:38 devn: gfredericks' is way better

16:38 mk: why did clojurebot time out?

16:38 devn: &(map char "a")

16:38 lazybot: ⇒ (\a)

16:39 devn: &(map (comp int char) "a")

16:39 lazybot: ⇒ (97)

16:39 mk: how do I pretty-print a 2d list as a table?

16:40 devn: cl-format

16:40 gfredericks: will pprint/print-table take integer keys?

16:40 * devn looks at some of his own code

16:41 devn: &(use 'clojure.pprint)

16:41 lazybot: ⇒ nil

16:42 gfredericks: how often does lazybot reset those ns ops?

16:42 devn: &(pp/print-table [:a :b] {:a [1 2 3], :b [4]})

16:42 lazybot: java.lang.RuntimeException: No such namespace: pp

16:42 devn: &(print-table [:a :b] {:a [1 2 3], :b [4]})

16:42 lazybot: ⇒ ======= :a | :b ======= | | ======= nil

16:43 devn: err

16:43 mk: ,`print-table

16:43 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class clojure.lang.RT>

16:43 devn: &(print-table [:a :b] {:a 1, :a 2, :a 3, :b 4})

16:43 lazybot: java.lang.IllegalArgumentException: Duplicate key: :a

16:43 mk: &`print-table

16:43 lazybot: ⇒ clojure.core/print-table

16:43 devn: &(print-table [:a :b] [:a 1, :a 2, :a 3, :b 4])

16:43 lazybot: ⇒ ======= :a | :b ======= | | | | | | | | ======= nil

16:43 gfredericks: &(print-table [2 1] [101 102 103] [[201 202 203] [301 302 303]])

16:43 lazybot: clojure.lang.ArityException: Wrong number of args (3) passed to: pprint$print-table

16:43 gfredericks: &(print-table [2 1] [[101 102 103] [201 202 203] [301 302 303]])

16:43 lazybot: ⇒ ========= 2 | 1 ========= 103 | 102 203 | 202 303 | 302 ========= nil

16:43 mephist0: an easy way to convert this [a b] [1 2] into this {a 1 b 2} please

16:44 gfredericks: mephist0: (into {} ...)

16:44 no

16:44 * gfredericks didn't read

16:44 devn: mephist0: zipmap

16:44 gfredericks: mephist0: zipmap

16:44 devn: &(zipmap [:a :b] [1 2])

16:44 lazybot: ⇒ {:b 2, :a 1}

16:44 mk: so how do I do the table thing, then?

16:44 dnolen: hmm is there any way to specify multiple source paths to leiningen?

16:45 gfredericks: mk: make sure you have vectors as the inner lists

16:45 mephist0: very good. Thank you devn gfredericks

16:45 mk: I can't resolve symbol print-table

16:45 devn: mk: you need to use or require clojure.pprint

16:45 gfredericks: and then (print-table (range (count (first vectors))) vectors)

16:45 muhoo: i kind of like incanter's way of printing tables

16:46 devn: i kind of dislike the print-table fn. i got a mild headache molding all of my data into what it expected

16:46 gfredericks: (-> seqs first count range (print-table (map vec seqs)))

16:46 mk: this is in clojure 1.3?

16:46 muhoo: if you tell it (view (to-datasource some-data-structure)) it does a pretty good job

16:46 gfredericks: mk: yeah

16:46 devn: mk: nod

16:46 mk: it would be helpful to show us the data you have as input

16:47 a sample of it, anyway

16:47 muhoo: sorry to-dataset

16:47 gfredericks: devn: how would you have done print-table?

16:48 mk: devn: [[12][213123 23][213123 234][9 9 9 9 9 9 9]]

16:48 (or some random similar arrangement)

16:49 devn: gfredericks: im not sure, it just seems like there should maybe be some general fns to make your data fit what print-table expects

16:49 gfredericks: for instance, if i want to just print-table of {:a 1, :b 2}, it seems like i should able to just do that

16:49 qbg: &(cl-format true "~{~s~%~}" [[1 2 3] [4 5 6] [7 8 9]])

16:49 lazybot: ⇒ [1 2 3] [4 5 6] [7 8 9] nil

16:50 gfredericks: qbg: what is this witchcraft?

16:50 devn: gfredericks: or if i have [:a [1 2 3], :b [4 5 6]], it feels like it should just "get it"

16:50 gfredericks: you havent joined the cult of the cl formatter?

16:50 &(cl-format nil "~R" 111)

16:50 lazybot: ⇒ "one hundred eleven"

16:50 devn: &(cl-format nil "~r" 111)

16:50 lazybot: ⇒ "one hundred eleven"

16:50 devn: &(cl-format nil "~@R" 111)

16:50 muhoo: that's pretty bad ass

16:50 lazybot: ⇒ "CXI"

16:51 devn: it's like learning a new mini language, though

16:51 qbg: &(cl-format nil "~:@R" 4)

16:51 lazybot: ⇒ "IIII"

16:51 simard: I call a static clojure function from java code. On my PC (Linux), it works fine, on another (Windows7), I get this error https://gist.github.com/2199626

16:51 devn: qbg: :)

16:51 muhoo: &(cl-format nil "~R" 1976)

16:51 lazybot: ⇒ "one thousand, nine hundred seventy-six"

16:52 devn: &(cl-format nil "~@R" 1976)

16:52 lazybot: ⇒ "MCMLXXVI"

16:52 qbg: &(cl-format nil ~:R" 1976)

16:52 lazybot: java.lang.RuntimeException: EOF while reading string

16:52 qbg: &(cl-format nil "~:R" 1976)

16:52 lazybot: ⇒ "one thousand, nine hundred seventy-sixth"

16:52 gfredericks: omg

16:52 simard: I tried to add some (println ..) from the top level of the clojure file and it's not working either, which lets me think an error happens at load time, not call time

16:52 qbg: Never NEVER use format to produce format control strings

16:52 gfredericks: that is obscene

16:52 qbg: You head will just die

16:52 devn: yeah. it might make people /angry/ at you

16:53 gfredericks: I wrote a whole library to convert numbers to words

16:53 devn: but if you're ever asked to do the roman numeral kata

16:53 just use cl-format ;)

16:53 gfredericks: how high does it go though?

16:53 devn: i think roman numerals kick out around 2500

16:53 &(cl-format nil "~@R" 2500)

16:53 lazybot: ⇒ "MMD"

16:53 muhoo: if someone asks you do do roman numerals,

16:53 gfredericks: no for the words one

16:53 devn: &(cl-format nil "~@R" 900)

16:53 lazybot: ⇒ "CM"

16:53 qbg: http://www.foldr.org/~michaelw/log/static/programming/lisp/format-automotivator.jpg

16:53 devn: &(cl-format nil "~@R" 9000)

16:53 lazybot: ⇒ "9,000"

16:53 muhoo: just tell them to quit screwing around and just give you the damn job

16:54 devn: &(cl-format nil "~@R" 3400)

16:54 lazybot: ⇒ "MMMCD"

16:54 devn: &(cl-format nil "~@R" 6500)

16:54 lazybot: ⇒ "6,500"

16:54 devn: binary search continues as an exercise for the reader

16:54 mk: ...I still have no idea how to make it draw a table from an arbitrary 2d seq

16:54 gfredericks: (cl-format nil "~:R" 100000000000000000000000000N)

16:54 ,(cl-format nil "~:R" 100000000000000000000000000N)

16:54 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: cl-format in this context, compiling:(NO_SOURCE_PATH:0)>

16:54 gfredericks: &(cl-format nil "~:R" 100000000000000000000000000N)

16:54 lazybot: ⇒ "one hundred septillionth"

16:54 devn: ,(use 'clojure.pprint)

16:54 clojurebot: nil

16:54 qbg: mk: try (cl-format true "~{~s~%~}" [[1 2 3] [4 5 6] [7 8 9]]) at the repl

16:54 muhoo: &(class cl-format)

16:54 lazybot: ⇒ clojure.pprint$cl_format

16:54 qbg: Good enough?

16:55 gfredericks: &(cl-format nil "~:R" (apply * (repeat 100 10N)))

16:55 lazybot: ⇒ "10,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000th"

16:55 muhoo: oh, it's in pprint

16:55 gfredericks: ah ha

16:55 &(cl-format nil "~:R" (apply * (repeat 50 10N)))

16:55 lazybot: ⇒ "one hundred quindecillionth"

16:56 mk: qbg: the rows aren't aligned

16:56 gfredericks: goes up to but not including 10^66

16:56 devn: &(print-table [:a :b :c] [{:a 1} {:b 2} {:c 3}])

16:56 lazybot: ⇒ ============ :a | :b | :c ============ 1 | | | 2 | | | 3 ============ nil

16:56 devn: mk: try that at the repl. is that better?

16:57 you may need to turn your data structure into something that print-table wants

16:57 muhoo: &(cl-format nil "~@R" 420)

16:57 lazybot: ⇒ "CDXX"

16:57 * devn facepalms

16:57 tomoj: &(cl-format nil "~:R" (apply * (repeat 70 10N)))

16:57 lazybot: ⇒ "10,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000th"

16:58 gfredericks: tomoj: goes up to 65

16:58 * Raynes palms devn's face

16:58 * devn sends Raynes to Palm Beach

16:58 tomoj: is the rest, uh.. nameless?

16:58 qbg: (cl-format true "~{~{~0,5t~s~}~%~}" [[1 2 3] [4 5 6] [7 8 9]])

16:58 tomoj: or is the implementation just incomplete?

16:58 qbg: How does that look?

16:58 muhoo: the yak, it is shaved.

16:58 qbg: (you'll probably need to modify the 5 to make sense for you

16:58 gfredericks: tomoj: I think that's as much as most dictionaries traditionally cover exhaustively

16:58 Frozenlo`: Another newbie question... The result of using `map' is of the form (item1 item2...). Is there a way to make it a map instead?

16:59 gfredericks: I think up to 10^303 is derivable? sorta...

16:59 devn: tomoj: how many numbers in your dataset are above 65 places?

16:59 (that you need to print readably)

16:59 qbg: A bit better: (cl-format true "~{~{~s~0,5t~}~%~}" [[1 2 3] [4 5 6] [7 8 19]])

16:59 mk: I just want the numbers. Without weird headers, and I don't actually know how many will be in there

16:59 gfredericks: Frozenlo`: it's not clear what that map would be of -- i.e. what are the keys and the values?

17:00 Frozenlo`: gfredericks: both are other maps :)

17:00 gfredericks: devn: he's just trying to make sure his code is scalable

17:00 Frozenlo`: maybe zipmap will do what you want? it's still not clear

17:00 e.g., if you're doing ##(map inc [3 5 183])

17:00 lazybot: ⇒ (4 6 184)

17:01 gfredericks: how would we make a map out of that?

17:01 mk: I suppose I need something to display matricies, rather than tabular data

17:01 tmciver: I just noticed this cl-format. What ns? I don't have it on my repl.

17:01 devn: &(partition 2 '(1 2 3 4 5 6 7 8))

17:01 lazybot: ⇒ ((1 2) (3 4) (5 6) (7 8))

17:01 devn: &(map zipmap (partition 2 '(1 2 3 4 5 6 7 8)))

17:01 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$zipmap

17:01 qbg: Documentation: http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm

17:01 tmciver: clojure.pprint

17:01 raek: Frozenlo`: if you have a sequence of map entries, use (into {} ...), if you have a seq of keys and a seq of values, use (zipmap ...), if you have a seq of alternating keys and vals, use (apply hash-map ...)

17:01 tmciver: qbg: thanks.

17:02 Frozenlo`: raek: thanks, trying now.

17:02 raek: ...and a map entry is a vector of two elements

17:03 devn: &(let [sequence '((1 2) (3 4) (5 6) (7 8)), keys (map first sequence), vals (map second sequence)] (zipmap keys vals))

17:03 lazybot: ⇒ {7 8, 5 6, 3 4, 1 2}

17:03 tomoj: devn: I don't need cl-format at all, just curious about the names

17:04 devn: tomoj: yeah, if you check out the source it goes to....

17:04 vigintillion

17:04 http://en.wikipedia.org/wiki/Names_of_large_numbers

17:04 10^63

17:05 tomoj: lol @ centillion

17:05 gfredericks: there's an interesting one mentioned in that article that grows double exponentially I think

17:05 i.e., gets qualitatively higher on fewer names

17:05 devn: "some scientists say there may even be larger numbers!"

17:05 10^303 + 1 ?

17:06 gfredericks: lol

17:06 $google 24 is the highest number

17:06 lazybot: [Mr. Show - 24 is the Highest Number - YouTube] http://www.youtube.com/watch?v=RkP_OGDCLY0

17:07 qbg: mk: Try something like (cl-format true "~{~{~8@A~}~%~}" [[1 3424 2] [4 5 6] [7 8 19]])

17:08 mk: qbg: spaces between small numbers are too huge. I'm working on taking the max string length of each column and using that...

17:09 qbg: mk: Have you thought about using ClojureScript and generating a table element? :p

17:09 * gfredericks has written a function that spits things into org-mode tables

17:10 mk: qbg: yeah that'll look great in the repl ;)

17:10 qbg: Visual repl is the future!

17:10 mk: qbg: I agree! I hope you're thinking of writing one

17:10 devn: as long as we're talking about cl-format, i remember thinking this was interesting when i first picked up clojure

17:10 &(+ (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*) (*)(*))

17:10 lazybot: ⇒ 42

17:10 qbg: Visual repl is the past! See CLIM

17:11 gfredericks: devn: boobs?

17:11 devn: im ashamed of you, gfredericks

17:11 mk: how do I do a double-map? I have a [] of functions

17:11 gfredericks: well otherwise you could've done that more compactly

17:12 simard: refresh: https://gist.github.com/2199626

17:12 devn: ,(+(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*)(*))

17:12 clojurebot: 42

17:12 qbg: &(reduce #(map %2 %1) [1 2 3] [inc #(* 2 %) dec])

17:12 lazybot: ⇒ (3 5 7)

17:13 gfredericks: devn: I mean mixing (*) and (+)

17:13 emezeske: dnolen: There's no easy way to use a custom clojurescript compiler with cljsbuild. Someone else was asking about that, I think, but I haven't come up with a decent solution yet.

17:13 qbg: mk: Something like that?

17:13 devn: gfredericks: sure

17:13 gfredericks: somewhere I wrote some code that would take a number and output that sort of expression

17:13 emezeske: dnolen: As far as installing cljsbuild locally, you just need to "lein install" from support/ and then plugin/

17:14 devn: gfredericks: ha, i was going to write that this morning, but then thought better of it

17:15 &(*(+(*)(*)(*)(*)(*)(*))(+(*)(*)(*)(*)(*)(*)(*)))

17:15 lazybot: ⇒ 42

17:15 mk: qbg: (dec identity inc) (3 4) -> ((2 3)(3 4)(4 5))

17:15 gfredericks: devn: my judgment is worse than yours

17:15 now I have to try to find it...I hope it wasn't in ruby

17:15 devn: back in a bit

17:16 qbg: &((fn [fns coll] (map #(map % cols) fns)) [dec identity inc] [3 4])

17:16 lazybot: java.lang.RuntimeException: Unable to resolve symbol: cols in this context

17:16 qbg: &((fn [fns coll] (map #(map % coll) fns)) [dec identity inc] [3 4])

17:16 lazybot: ⇒ ((2 3) (3 4) (4 5))

17:16 gfredericks: qbg: maybe (map (apply juxt fns) colls)?

17:18 qbg: gfredericks: I think you'd need to transpose the result

17:19 gfredericks: hmm

17:19 cannot find my silly +/* expression code

17:19 probably the world is better off for it

17:20 qbg: gfredericks, devn: Sounds like a job for core.logic :)

17:20 Maybe

17:20 mk: qbg: thanks, that seems to work

17:21 gfredericks: qbg: oh crap that's a great idea

17:21 qbg: Probably will need cKanren extensions

17:21 For complicated stuff

17:21 gfredericks: though there was some number theory involved with trying to keep it small

17:22 dnolen: emezeske: thanks, actually got it sorted out.

17:25 ibdknox: dnolen: nice work on the cljs core.logic stuff! :)

17:30 dnolen: ibdknox: thx! just in time for NYC.js and JSConf :)

17:33 emezeske: dnolen: Oh, wasn't there some bug or something in cljsbuild that you were worried about fixing before JSConf?

17:34 dnolen: I remember that coming up, but forgot what it was

17:35 dnolen: emezeske: nope, I think you're thinking of the :source-path issue :)

17:37 * emezeske looks through his #clojure logs.

17:37 emezeske: dnolen: You were asking about lein2 support, under which the REPLs are broken

17:39 dnolen: Are you just going with lein1 for now?

17:41 dnolen: emezeske: oh yeah, lein2 repl would cool, but it's not critical for me now.

17:46 emezeske: dnolen: Okay, good deal

17:56 mk: how can I get the name of a function?

17:56 qbg: &map

17:56 lazybot: ⇒ #<core$map clojure.core$map@151f412>

17:57 mk: can I get just map?

17:57 qbg: &(.getSimpleName (class map))

17:57 lazybot: ⇒ "core$map"

17:58 qbg: Would have to do regex from there

17:58 yoklov: wow, surprisingly drawing this to the canvas is slower than actually running the game

17:58 but both are absurdly slow.

17:59 mk: qbg: thanks

17:59 ibdknox: yoklov: drawing on the canvas should be pretty quick, depending on what you're drawing

18:00 yoklov: text

18:00 mostly

18:00 qbg: mk: That is only going to make sense for named functions

18:00 ibdknox: using cljs?

18:00 yoklov: yup

18:01 ibdknox: are you doing a loop with doseq or some other such seq mechanism?

18:01 yoklov: porting code from clojure to cljs. there are performance issues everywhere as it uses lots of persistant datatypes

18:01 yeah

18:01 doseq

18:01 should i be doing a loop/recur?

18:01 ibdknox: doseq is *way* too slow

18:01 you can't use seq

18:01 s

18:01 that's why money does weird things with arrays :(

18:01 monet*

18:02 qbg: mk: If you have a var, you could get the symbol from that

18:02 yoklov: right okay, hm, so what's the canonical way to loop over some range of numbers without using doseq?

18:02 loop/recur?

18:02 mk: qbg: gotcha

18:02 ibdknox: yeah

18:02 qbg: ,(.sym #'map)

18:03 clojurebot: map

18:03 qbg: ^ Hack though

18:03 ibdknox: ,(-> #'map meta :name)

18:03 clojurebot: map

18:03 ibdknox: qbg: ^

18:04 qbg: It would be nice if vars were named

18:10 yoklov: hrm. still pretty slow

18:10 clojurebot: excusez-moi

18:10 yoklov: 20 seconds to draw 100 frames

18:10 from 22

18:11 ibdknox: yoklov: gist?

18:11 yoklov: https://gist.github.com/2200308

18:12 qbg: Isn't dotimes available?

18:12 yoklov: tried reversing the iteration in the foolish hope that it would speed it up

18:13 hm. maybe the (set (map :pos monsters)) is slowing it down...

18:13 eh there are only ever 6 or so

18:14 ibdknox: can you add the generated js for that function too?

18:14 yoklov: absolutely

18:14 ibdknox: nothing obvious is jumping out

18:15 also, how are you calling draw?

18:16 dnolen: yoklov: did you try running the JS profiler (say in Chrome) to see where the time is spent?

18:16 yoklov: when i'm testing the speed it's in a reduce loop, however its still noticably slow when i call it at the end of an event

18:16 yeah

18:16 its in draw

18:16 :/

18:17 qbg: You looping through each pixel to see if something is there?

18:17 dnolen: yoklov: but it's not clear which thing in draw in slowing you down?

18:17 qbg: each block that is I guess

18:18 yoklov: https://gist.github.com/2200308 has the generated js

18:18 and as far as the slowness in draw its a lot of anonymous functions

18:19 eventually leading to cljs.core.hashmap, actually

18:19 *contains_key. hm.

18:19 ibdknox: all the gets

18:20 dnolen: yoklov: gets are punishingly slow at the moment

18:20 yoklov: that would explain it

18:21 and a lot.

18:21 dnolen: yoklov: you using regular maps right?

18:21 ibdknox: yeah he is

18:21 dnolen: yoklov: way to get massive speedup is to replace the map with you own record with those keys

18:22 yoklov: then you avoid all the avoid of hashing, array copying etc.

18:22 yoklov: err, so inline the lookup?

18:22 or… what?

18:23 oh like a record type?

18:23 ibdknox: yeah, an actual record

18:24 dnolen: yoklov: yes then you don't need to change the fns.

18:25 yoklov: well, that is certainly a hack in this case but i can deal if it offers massive speedup

18:25 dnolen: yoklov: even in Java you sometimes want to replace map use with defrecord if perf becomes an issue.

18:27 yoklov: hm. never really had performance issues in java, probably just because i don't do anything that intense

18:31 emezeske: Has anyone happened to make Google Closure externs file for RaphaelJS?

18:32 Or can anyone point me toward documentation on how to make an externs file?

18:36 gfredericks: emezeske: is there more to extern besides `Raphael`?

18:38 emezeske: gfredericks: I thought all the member functions, etc, had to be externed. I would love to be wrong...?

18:39 gfredericks: not knowing about any of these things too intimately, that would surprise me.

18:41 emezeske: Wouldn't references in my code to the public methods of the Raphael object be munged?

18:42 gfredericks: as in Raphael.foo(bar)?

18:42 irc2samus: guys how do you get an integer from a numeric string?

18:42 gfredericks: &(Integer/parseInteger "48929854")

18:42 lazybot: java.lang.IllegalArgumentException: No matching method: parseInteger

18:42 gfredericks: hmm

18:42 well there's something there

18:42 yoklov: &(Integer/parseInt "48929854")

18:42 lazybot: ⇒ 48929854

18:42 emezeske: gfredericks: Yeah

18:42 yoklov: :p

18:42 gfredericks: I was going to type that first but decided it looked too javascripty

18:43 emezeske: is that (Raphael/foo bar)?

18:43 yoklov: haha, i only know because i'm in college so most of the code i have to write is in java

18:43 gfredericks: oh I guess it's JS before it gets munged

18:43 so Raphael.foo(bar) then

18:43 emezeske: gfredericks: No, it would be like (.foo (js/Raphael ...) bar)

18:43 gfredericks: I would think if Raphael is externed then the compiler would pass over an expression with 'Raphael' at the front of it...

18:44 irc2samus: great! is it weird that it doesn't appear on clojuredocs?

18:44 gfredericks: but like I said I don't know much about these matters

18:44 irc2samus: it's pure java, so...not really

18:44 maybe unideally

18:44 emezeske: gfredericks: Well, Raphael/foo would be like a static member access

18:44 gfredericks: Mostly you just create a Raphael object, and then call members

18:45 gfredericks: Which are just object.whatever()

18:45 gfredericks: oh you mean on the instance

18:45 emezeske: gfredericks: Yeah

18:45 gfredericks: so (.foo my-raphale bar)?

18:45 emezeske: gfredericks: Exaclty

18:45 irc2samus: ohh I see, thanks

18:46 * devn read that as (. foo my-raphael bar) at first

18:47 gfredericks: hmmm; okay, so I guess it'd be hard (impossible) for the compiler to know if my-raphael is a raphael object, so the way that works is e.g. if you extern 'draw' then calling (.draw my-raphael) will not be munged and neither will calling draw on anything else but you don't lose much that way...

18:47 emezeske: yeah okay you've convinced me

18:47 * devn wonders what it would take to get ns-publics into cljs

18:48 gfredericks: devn: at compiletime or runtime?

18:48 emezeske: gfredericks: I just got things to compile with using raphael.js as the externs file, but the compiler produces warnings for like 5 minutes before it's done

18:48 devn: gfredericks: runtime

18:48 emezeske: gfredericks: I guess I just need to strip it down myself :(

18:48 gfredericks: emezeske: probably a regex could find all the functions declared eh?

18:49 emezeske: gfredericks: Maybe...

18:49 gfredericks: devn: that sounds complicated

18:49 emezeske: you have a problem, you think "I know, I'll use a regex", and then you use the regex to solve the problem

18:49 devn: now you have two problems

18:51 gfredericks: devn: that's an old wives' tail

18:52 irc2samus: ok, apologies for the basic question but why do I have to wrap Integer/parseInt on a fn in order to use it with map?

18:52 devn: gfredericks: i just recently re-read joy of clojure (wow, i missed a lot in my haste the first time around, what an incredible book)

18:52 gfredericks: hm

18:52 devn: does it condemn regexes?

18:52 ,Integer/parseInt

18:52 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer, compiling:(NO_SOURCE_PATH:0)>

18:53 irc2samus: got that same error

18:53 gfredericks: irc2samus: I guess otherwise the syntax would be ambigious between static fields and static methods?

18:53 devn: "Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems --Jamie Zawinski (aka jwz)

18:53 gfredericks: devn: that's what I was playing off of

18:54 devn: gfredericks: they just remark that they're sympathetic to the statement, but that regular expressions can be useful

18:54 i know people who have built really fragile code out of ornate regexen

18:54 then again, i use them quite often

18:54 gfredericks: irc2samus: I can't think of any particular reason, it's probably mixed up in compilers and reflection and performance and all that. But the Foo/bar syntax can only be used in the front of a list, it can't be evaluated by itself and passed around

18:55 irc2samus: ok, good to know thank you

18:55 gfredericks: devn: "Some people, when confronted with a problem, think "I know, I'll use an ornate regex to build fragile code." Now they have two problems."

18:56 devn: :) I was just about to say "I just said that."

18:56 until I noticed

18:56 gfredericks: irc2samus: I think there might be a macro to do what you're doing a little easier though

18:56 amalloy: the particular reason is that Integer/parseInt isn't a function

18:56 gfredericks: amalloy: well it could be compiled into one

18:56 amalloy: it's a method, which is not a first-class value in java

18:58 AimHere: As far as Integer/parseInt is concerned, 'read-string' does turn strings into numbers for you in a more first-class stylee, though it'll turn non-Integer strings into not-integers as well

19:20 yoklov: so, if I want to get some performance improvements by turning my maps into records, how should i be accessing the fields of those records? (:field a-record) still seems to be very slow

19:21 gfredericks: yoklov: I think (.field a-record) is the way to do it?

19:21 yoklov: hrm.

19:23 ibdknox: (.-field a-record)

19:23 yoklov: that's tough. short of (case :field (.field a-record), :otherfield (.otherfield a-record)), i dunno if that's gonna be possible, because just the symbol `namespace/field` will give an error as it doesnt exist… i think

19:25 ibdknox: yoklov: huh?

19:25 I didn't understand that

19:25 * gfredericks didn't either

19:25 ibdknox: as long as a-record is non-nil, everything will be fine

19:25 yoklov: err, sorry. i have the keyword :field stored somewhere

19:25 i could change that to a symbol and do (. a-record variable-resolving-to-field)

19:25 ibdknox: (aget a-record wooohoo)

19:25 yoklov: or… somethign weird? no that makes no sense.

19:26 oh

19:30 Lee__: New to this irc gizmo... Anyone here who can help with a classpath problem after upgrade to Clojure 1.3?

19:31 gfredericks: ~anyone

19:31 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 ..."

19:32 Lee__: Thx clojurebot.

19:32 yoklov: blergh. i guess i can't have destructuring if i want that speedup?

19:34 amalloy: yoklov: you get a noticeable speedup for free just by using records, i think. you get maybe another factor of four for using hinted .foo lookups instead of :foo, but it's highly unlikely that that's your bottleneck anyway

19:34 Lee__: With clojure 1.2 I was able to launch runs on linux with "java -cp ./*:./src/ clojure.main -i myfile.clj" and it would find required files in the same directory, but this isn't working with clojure 1.3... Anyone know why and/or a fix?

19:34 yoklov: amalloy: this is in clojurescript, actually

19:36 and i'm pretty sure it's my bottleneck because chrome's profiler says that it's in hash_key_exists_QMARK_ or something like that

19:36 gfredericks: Lee__: any particular reason you're not using leiningen?

19:36 ibdknox: yoklov: correct

19:37 amalloy: in CLJS that could easily be the bottleneck :(

19:37 gfredericks: ibdknox: because keywords are strings?

19:38 ibdknox: arguments is orders of magnitude slower :(

19:38 gfredericks: oh

19:38 yoklov: so hm

19:38 Lee__: gfredricks: I do use leiningen in other contexts, but for doing remote runs on a cluster I've just been using that java call... I guess one reason is that I actually throw more java options in the call, e.g. for parallel garbage collection on a 48 core node... Maybe I can do that with lein calls too? I just didn't ever bother to figure that out because this worked (before).

19:39 yoklov: i guess my best bet is to start rewriting this to pass more args separately and use more js arrays?

19:39 gfredericks: Lee__: okay that question is beyond me I think; hopefully someone else knows

20:00 Lee__: More generally: what changed between 1.2 and 1.3 re: how the classpath is searched? I've been unable to find any docs on this. With 1.2 I can launch java with "-cp ./*:" and it finds any required files in the launching directory, but not so with 1.3...

20:05 mk: Lee__: many people use lein, and things tend to just work

20:05 ...but I see that this was already suggested above

21:08 dnolen: yoklov: I feel your pain.

21:09 yoklov: haha

21:09 dnolen: yoklov: in core.logic I was well aware of the problems and avoided using anything map or record related.

21:09 yoklov: i actually just sped it up a bunch by calling name on a bunch of keywords and then using them in agets for the record types

21:10 what did you use instead?

21:10 dnolen: yoklov: in Clojure I used a map - it's ridiculously fast, but for core.logic in CLJS I switched back to lists which is what the original Scheme used.

21:11 yoklov: oh right

21:12 really my only really huge slowdowns are in the set-heavy areas of my code and in "draw", which accesses tons and tons of maps

21:12 or keys in maps, rather

21:13 devn: Lee__: What blows up with 1.3??

21:13 lazybot: devn: Definitely not.

21:14 devn: Lee__: As in, do you have a specific error? (If it's more than a line long please post it to a pastebin or gist.github.com)

21:17 dnolen: yoklov: k I looked into, there's something seriously wrong with record

21:17 yoklov: well, a I looked into a little

21:18 yoklov: oh?

21:18 dnolen: yoklov: if I make a type and I implement only the single arg -ilookup, 10000 lookups takes 8

21:18 which is reasonable

21:18 yoklov: if I use a record, 10000 lookups take 330ms which is not

21:18 yoklov: oh okay

21:19 thats interesting

21:22 dnolen: yoklov: arg, I see why

21:23 yoklov: the implementation of -ilookup for defrecord doesn't first check to see if it's one of the field keys with a cond/condp

21:23 yoklov: opening up a ticket, simple fix, I'll try to get to it this week

21:23 yoklov: so checking it would be faster?

21:23 dnolen: yoklov: near 40X faster or something.

21:24 yoklov: wow

21:24 that is somewhat unintuitive, wouldnt more checks slow it down?

21:24 dnolen: yoklov: if/else cascades are quite fast in JS

21:25 yoklov: right, but what is it otherwise? a thrown exception?

21:25 dnolen: yoklov: no, nil

21:25 just like maps

21:25 yoklov: and that's necessarially slower?

21:26 dnolen: what's slower?

21:27 yoklov: OH, i misread what you said above

21:27 or misunderstood what the alternative to it being a field key is

21:27 dnolen: (get (merge (hash-map ~@(mapcat (fn [fld] [(keyword fld) fld]) base-fields)) ~'__extmap) k# else#)

21:27 is the current implementation

21:27 yes that is a hash-map merge for every lookup

21:28 yoklov: alright that makes sense

21:28 yeah i forgot records could also contain arbitrary keys

21:29 dnolen: yoklov: I'm going to change that to cond/p + ext-map lookup for else clause.

21:29 yoklov: as i said, i've been working around this by doing (aget record (name field)) when possible, which has been working

21:29 even if it is a ugly hack

21:39 Lee__: devn: I no longer have the text of the error (it was the standard one about not being able to find a required file on the classpath) BUT I have solved it, by adding "$PWD:" to the start of the classpath in the java call. Whew. Thanks for the attention.

21:40 devn: Lee__: glad you figured it out. I'm so used to using leiningen I feel like I've lost some of the classpath foo that used to be required.

21:41 dnolen: did i see a bunch of protocol additions in clojurescript?

21:42 dnolen: devn: ?

21:42 devn: dnolen: nevermind, i might be thinking of a different project (probably clojure-scheme)

21:43 gtuckerkellogg: is lein-bin compatible yet with lein v2?

21:43 devn: Raynes: see above message

21:43 Raynes: Yikes. I forgot I even wrote that.

21:43 No, it isn't, but it wouldn't be hard at all to update it.

21:43 I didn't realize people actually used it or I would have already done it.

21:45 gtuckerkellogg: Yep, it gets used

21:46 dnolen: yoklov: fixed in master

21:47 yoklov: wow, that was fast

21:47 gtuckerkellogg: damn

21:50 devn: now entering dnolen country...

21:51 best part is, he's also really good at explaining things

21:51 (or worst part if you're jealous of his drunken master style)

21:52 yoklov: yup. extremely impressive.

21:53 devn: i'm talking about him while i'm in here so he'll either ignore me humbly, or say "aw, 'twas nothing", but david has kept the clojurescript train moving like a boss

21:53 everyone should send him gifts

21:54 (inc dnolen)

21:54 lazybot: ⇒ 5

21:58 Raynes: Damn it.

21:59 devn: That sucks. I just updated and released lein-bin 0.2.0 for that guy and he leaves. :(

21:59 I just wasted a whole 4 minutes.

22:00 dnolen: ibdknox: actually I'm not so sure any more, I may have been thrown off by benching defrecord once or something.

22:00 ibdknox: arguments performance hit is more like 2X, still that's pretty pervasive

22:04 devn: Raynes: <3

22:04 Raynes: he saw you were on the case

22:04 and since i'm handing out thank yous, thanks Raynes for maintaining the hell out of all of your projects

22:05 you're a boss.

22:05 Raynes: Yay! Bossness!

22:05 * devn is currently extremely excited to be going to euroclojure

22:06 devn: im a little scared about speaking -- the last slot and everything, yeesh.

22:07 Raynes: Wish I could be there to see it.

22:14 technomancy: devn: last slot is a drag =\

22:25 Raynes: technomancy: So is the 3rd.

22:29 mk: what is subseq supposed to do? ##(doc subseq)

22:29 lazybot: ⇒ "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true"

22:31 mk: what's it supposed to be used for?

22:42 devn: technomancy: i think it'll be okay. it's not patently technical, and i have a feeling (given the conf ends on a friday night) that it won't be the "last" "session"

22:49 MGT: hey, does anyone know what's going on here? I import clojure.string as string and do (replace "a" #"a" "\\"), then get an error instead of a string containing a forward-slash character

22:49 err, should be (string/replace "a" #"a" "\\")

22:49 devn: you mean require?

22:49 MGT: yes

22:50 xeqi: &(string/replace "a" #"a" "\\")

22:50 lazybot: java.lang.RuntimeException: No such namespace: string

22:50 xeqi: &(clojure.string/replace "a" #"a" "\\")

22:50 lazybot: java.lang.StringIndexOutOfBoundsException: String index out of range: 1

22:51 MGT: yep

22:52 devn: &(clojure.string/replace "a" #"a" "\\\\")

22:52 lazybot: ⇒ "\\"

22:52 devn: not what you want, I take it?

22:53 MGT: I don't think so

22:53 devn: you're trying to replace with just "\", yes?

22:53 MGT: well, I guess it is, actually

22:53 yes

22:53 thanks, think I understand now!

22:55 devn: &(s/replace "foo" #"f" "\\\\")

22:55 lazybot: ⇒ "\\oo"

22:56 devn: &(seq (s/replace "foo" #"f" "\\\\"))

22:56 lazybot: ⇒ (\\ \o \o)

22:57 devn: it's a bit long -- sort of like when you're lost and you turn around before you get to your destination

22:57 the required additional \\ is kind of like that IMO

22:58 holo: hi

22:58 MGT: yeah, makes sense

22:58 amalloy: there is at least one open ticket about that in jira, mgt/devn

23:00 alex_baranosky: is there anyway to pretty print (quote foo) as 'foo ?

23:10 mk: alex_baranosky: what would the function take as an argument? a single form?

23:14 dnolen_: yoklov: gotta run but that sounds good.

23:14 rhc: what's a good way in clojure to run a function after some period of time?

23:14 (future ((sleep ..) (do-function))

23:15 Raynes: (.start (Thread. (fn [] (Thread/sleep 2000) (somefunction))))

23:15 I wouldn't use future for this.

23:15 rhc: Raynes: thanks

23:16 so its generally better to use regular java threading over future when you don't care about the result?

23:16 Raynes: future contains any exceptions that occur in its body. They don't pop up until you actually try to use the value of the future. Unless you actually want the value, I'd avoid it.

23:16 Right.

23:16 mk: why not use an agent?

23:17 Raynes: Why not just sleep 2h && echo "foo"

23:17 ;)

23:18 rhc: mk: hmm, i'll look into that too, thanks

23:18 mk: it's strange to call java for something as common as "now start doing this in another thread"

23:19 any suggestions for good talks to watch?

23:57 devn: rhc: look at at-at

23:57 rhc: https://github.com/overtone/at-at

Logging service provided by n01se.net