0:13 Chouser: Well, that worked. Ugly as sin, but it worked. Bedtime.
0:45 ericthor: anyone having problems with meta data in the latest build?
0:46 (def #^{:a "tag"} f 1)
0:46 (meta f)
0:46 yields nil
5:45 arbscht: is there a clever naming convention for clojure-relevant projects?
5:50 bgeron: something with a J in the middle maybe?
5:50 arbscht: j is worth 8 points in scrabble
5:50 this is not easy to do
14:50 Chouser: clojure is just too much fun
15:05 hoeck_: what are you doing with clojure?
15:20 Chouser: Screen-scraping web pages to generate email notifications.
15:21 But what makes it fun is the ease with which I can invent a task-specific mini-language and use it mixed in with regular clojure code.
15:22 Once I've got the generic HTML/XML parsing and querying, URL parsing, and email functions all set up, the specific task at hand can be written in under 50 lines
15:23 That's navigating through three pages, picking up context as I go, parsing the final page, generating a little report, and sending it off as email.
15:28 anyway, fun.
15:28 :-)
15:29 rhickey_: almost finished with proxies, which will let you derive from a concrete/abstract class
15:29 Chouser: rhickey_: cool! I'll be happy to banish my few lines of Java.
15:31 hoeck_: are there situations in clojure where one will need this?
15:31 Chouser: need to derive from an Java class?
15:31 rhickey_: it's forced by some library designs
15:31 hoeck_: yes
15:32 rhickey_: they fail to use interfaces
15:32 Chouser: I need it in order to use the javax.mail package. I don't think I would ever try to use it in the design of a clojure app.
15:34 hoeck_: oh, luckily, i never touched such a library where i need to subclass something
15:36 Chouser: heh, ew. Is there a better way to do this: (. mystr (replaceAll (str "[ " (char 160) "]+") " "))
15:37 I've got these annoying char 160s I want to treat like whitespace. I think they're s or something.
15:37 Anyway, the regex \s doesn't match them.
15:54 hoeck_: chouser: you could use \u00A0 in the regex
15:54 nsinghal_: i want to see if m2 is subset of m1.
15:54 (defn subset? [m1 m2]
15:54 (= (select m1 (keys m2)) m2))
15:54 I wanted this to work for any structure passed in, list, vector, maps
15:54 I tried converting it to the sequences and then do the comparison.
15:54 (defn subset? [m1 m2]
15:54 (let [s1 (seq m1)
15:55 s2 (seq m2)]
15:55 (every? #(let [item = %] (some #(= item %) s2)) s1)))
15:55 This function returns REPL:1749: Bad binding form, expected matched symbol expression pairs. What is wrong here?
15:55 rhickey_: item = % is bad syntax
15:56 nsinghal_: sorry let me try agina
15:56 Chouser: hoeck_: ok, that would be a bit better.
15:59 arbscht: \xA0 rather
16:09 nsinghal_: user=> (= {:a 1} {:a 1})
16:09 true
16:09 user=> (= (first s1) (first s2))
16:09 false
16:09 user=> (first s1)
16:09 <:a 1>
16:09 user=> (first s2)
16:09 <:a 1>
16:09 user=> (= (first {:a 1}) (first {:a 1}))
16:10 true
16:10 When i am comparing (= (first s1) (first s2)) it returns false
16:10 (first s1) evaluates to <:a 1> and (first s2) evaluates to <:a 1>
16:17 hoeck_: nsinghal: i guess comparing "< >" is not implemented yet
16:17 Chouser: how are you setting s1 and s2? I used two separate defs, and (= (first s1) (first s2)) returns true for me.
16:18 hoeck_: chouser: i used two literal maps, it returned false
16:18 nsinghal_: (= (first (seq {:a 1})) (first (seq {:a 1})))
16:18 this evaluates to true
16:18 (= (first (seq {:a 1 :b 2})) (first (seq {:a 1 :b 2})))
16:18 this evaluates to false
16:23 Chouser: ok, I see. Pretty squirrley.
16:23 true: (= (first {:a 1}) (first {:a 1}))
16:23 false: (= (first {:a 1 :b 2}) (first {:a 1 :b 2}))
16:28 rhickey: map entries don't have value semantics (yet)
16:29 but you should always be careful with (first amap), unless it's a sorted map
16:30 Chouser: careful in what way?
16:30 nsinghal_: when we convert map to seq each seqeuence can have different order
16:30 rhickey: there's no guaranteed order
16:30 Chouser: I'm not comparing map entries, but I'm using first and rest to iterate
16:30 nsinghal_: but if we cache the seqeunce and perform the match - still returns false for comparison
16:30 (def s1 {:a 1 :b 2})
16:30 (def s2 {:a 1 :b 2})
16:30 (= (first s1) (first s2)
16:30 (= (first s1) (second s2))
16:30 both returns flase
16:31 but you answered that is is not value checking MapEntry
16:31 rhickey: right, not yet
16:31 nsinghal_: (defn subset? [m1 m2]
16:31 (every? #(let [item %] (some #(= item %) (seq m1))) (seq m2)))
16:32 rhickey: I'm not happy with Map.Entry as a base - may switch map entries to pairs
16:32 nsinghal_: nested #() forms is bad style - too hard to read
16:32 hoeck_: rhickey: and the '<>' sharp brackets? are they used for reading map entrys?
16:33 rhickey: no - there is no read syntax for map entries
16:33 yet
16:33 nsinghal_: somehow it is fun to right hard code in Clojure but I will stay away from thius
16:33 thx
16:34 rhickey: as I said, I think I'd rather switch to pairs than elevate map entries to first-class status
16:35 nsinghal_: that will be nice, map entries sound like part of a map while you can have list, sequence etc for pairs
16:35 rhickey: yeah, they aren;t more useful than [k v]
16:36 nsinghal_: thx
16:36 hoeck_: i was just puzzled by the output of (first {:a 1}) being <:a 1>
16:37 Chouser: Just today I wanted to use map to process both parts of a map entry.
16:37 rhickey: You can do destructuring of map entries already using [k v]
16:38 Chouser: ah, that's cool.
16:38 oh! I can use that...
16:39 ah, very nice.
16:41 hoeck_: destructuring in let and fn is really nice
16:41 rhickey: I still have to add it to loop
16:43 hoeck_: but i found out, while using clojure i am sticking more to the functional paradigms of lisp
16:44 Chouser: those immutable data strcutres are keeping you honest, aren't they.
16:44 rhickey: you pretty much have to
16:44 :)
16:44 hoeck_: as opposed to common or emacs lisp where i loved (and love) the loop and iterate macros
16:44 rhickey: loop in Clojure is completely functional
16:45 Chouser: using scala broke me of needing looping structures. It's recursion or (map/reduce/filter) for me.
16:46 rhickey: Isn't Scala less functional than Clojure?
16:47 Chouser: eh. Scala allows some less functional code, but it too provides mainly immutable data, and fully supports tail recursion, map/reduce/filter, and for-comprehension.
16:47 you can use while loops and Java mutable containers if you really want to.
16:48 rhickey: but Scala itself also has mutable variables and members, not just in the Java interop, right?
16:49 Chouser: yeah, you can declare a "var" instead of a "val", but that seems roughly like "def" instead of "let".
16:50 Not sure about class data members -- didn't do much with that, but I think it's essentially the same-- pick an immutable "val" or a mutable "var".
16:50 rhickey: I don't think so - given a Scala object can you know that it is safe to treat it as a value, i.s. that it is immutable?
16:51 If anywhere in the member chain there's a var, you can't
16:51 Chouser: Right, I'm not sure if that info is carried in the type system or not. I think probably not.
16:52 rhickey: mutable data scares me much more than lack of a 'type system"
16:52 Chouser: I haven't written anything big in Scala (or Clojure, for that matter) to become familiar with the interaction of more complex types.
16:53 I'm still ambivalent about static types. I *think* what I want is optional static typing, but I'm not sure.
16:54 Scala requires types, and I often found myself fighting to correctly declare what I new to be functionally correct code, or distorting my design to make up for static typing (or my lack of understanding of its type system).
16:54 s/new/knew/
16:58 what's the best way to test if x is empty, when x may be a map or a list of map entries?
16:58 rhickey: (seq x)
16:58 Chouser: (nil? (seq x)) works, but is it slow for a large x?
16:59 rhickey: no - seq is constant time for everything
16:59 Chouser: splendid, thank.
16:59 thanks.
17:00 rhickey: (when-not (seq x)... better than (when (nil? (seq x)) ...
17:01 Chouser: for performance or readability?
17:01 rhickey: readability, more idiomatic, the return value of seq is directly testable by if, that's an important idiom
17:02 Chouser: ok
17:02 I'm in a cond. I'll re-arrange...
17:02 rhickey: in a cond, ok
17:04 Chouser: I'm finding I like cond even when I could use if, just because I can mark the :else clause more clearly.
17:05 rhickey: interesting - pg took else out of cond and called it if in arc
17:05 Chouser: heh, yeha.
17:06 is there a common idiom for where to put terminal case in recursion? First, last, doesn't matter?
17:07 rhickey: I usually follow the positive test - if there's stuff to do, do it, (else) return
17:08 Chouser: ok
17:13 ericthorsen: when passing java objects to clojure do i need to wrap them in something?
17:13 rhickey: nope
17:13 ericthorsen: just checking
17:13 rhickey: primitives will get boxed when passing to invoke as Object
17:14 which is what Clojure expects to see
17:14 ericthorsen: just wanted to make sure clojureVarInJava.fn().invoke(new MyJava())
17:14 was all i needed
17:15 rhickey: just use clojureVarInJava.invoke(...), don't use fn()
20:08 rhickey__: proxies are up! - you can now derive from concrete classes dynamically
20:16 * Chouser tries it out
20:16 albino: Is a concrete class a class written and compile in java?
20:16 rhickey__: It's a class that's not an interface
20:17 but yes, it must be named and therefore from Java-land
20:18 for instance you could derive a proxy from javax.mail.Authenticator
20:19 and override getPasswordAuthentication()
20:22 Chouser: hm, sounds familier...
20:28 ha! just like that. worked perfectly first try.
20:28 rhickey__: great!
20:28 Chouser: thank you!
20:28 rhickey__: sure - it was the most frequently requested missing feature
20:28 Chouser: that code in proxy.clj's pretty scary.
20:29 rhickey__: Welcome to compiler writing
20:33 actually at ~200 lines of serious stuff, it's much more compact the kind of code that takes Compiler.java to 3500
20:40 albino: Is that an actual file Compiler.java?
20:41 rhickey__: yes, part of the Clojure source
20:41 albino: ahh, okay
20:41 I thought you were referencing jdk7 source code or something
20:42 rhickey__: no, just me in Java vs me in Clojure
20:43 albino: yeah
20:43 rhickey__: you pretty good with cL?
20:43 err CL
20:43 rhickey__: ok
20:44 It was my first Lisp love...
20:44 albino: rhickey__: have you thought about porting clojure to CL?
20:44 rhickey__: clojure started in CL
20:44 albino: oh cool
20:44 does that version still exist in some source control tool somwhere?
20:44 rhickey__: Originally it was CL that generated Java and C# source
20:45 Everything source-wise is on SF, all the design stuff is on my Macs
20:46 Clojure never targeted CL though
20:47 It has changed a bunch over the years, a lot of work preceded its release in October
20:48 Chouser: The first release was just in October?
20:48 rhickey__: yup
20:49 Chouser: How much have you written in Clojure, not counting parts of Clojure itself?
20:49 rhickey__: mostly Clojure
20:49 that's the bane of the compiler writer
20:50 Chouser: :-) yeah.
20:50 albino: rhickey__: so you've been working on it on your own for years, and just got around to releasing it recently?
20:50 rhickey__: I am very excited about using it for the rest of my work
20:51 Chouser: what is that other work?
20:51 If I may ask.
20:51 rhickey__: yes, worked for years to solve the Lisp+Java/.Net problem - see jFli, Foil, Lisplets etc
20:52 My other work is audio research, cochlear modeling, scheduling systems etc
20:52 Chouser: huh! ok.
20:53 pjb3: Is there a way to have one clojure script load another clojure script?
20:54 rhickey__: load-file
20:54 albino: wow, never heard of jFli before, looks cool
20:57 Chouser: neither \xA0 nor \u00A0 work in my string literal
20:57 So I guess I'll continue using (str (char 160))
21:27 pjb3: Is there something like load-path and require in clojure?
21:27 where load-path is all of the places clojure looks for files to load
21:27 and require loads them, making sure not to reload already loaded files
21:28 rhickey__: not yet, it has been suggested
21:29 pjb3: ok, it seems like that would be helpful for organizing larger projects, what do you think?
21:30 rhickey__: I think that loading and requiring are going to be separate
21:31 pjb3: what do you mean by that
21:32 rhickey__: that loading should not be a side-effect of requiring, requires can be analyzed to create a load system definition
21:38 pjb3: So would (require "foo") load foo.clj?
21:40 ericthor_: are you referring to parsing and finding all the refers for a set of files to determine a load order?
21:41 what about qualifier names? name-sapce/func-call
21:41 rhickey__: So would (require "foo") load foo.clj -> no
21:41 pjb3: then what does (require "foo") do ?
21:41 ericthor_: "requires can be analyzed to create a load system definition" ...how?
21:42 we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls
21:43 we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls
21:43 I'm ready to do it!
21:43 rhickey__: a program could be analyzed for refers and requires to determine the dependency graph and generate a loading plan
21:44 ericthor_: but it would need to analyze the use of qualified names as well...yes?
21:47 rhickey__: no - if you use qualified names without refer you will need a require
21:48 ericthor_: I cannot say n1/foo without a (require 'n1) ?
21:49 i know it works if n1/foo is loaded...is it not 'proper' clojure?
21:50 rhickey__: there is no such thing as require yet, we're just speculating, but the loading system will need it
21:51 ericthor_: that was my next question....
21:52 that would not be an unreasonable requirement IMHO and at least is something we can do and use now even if the requires is just used for a dependancy graph
21:52 i like it...it's simple