#clojure logs

2008-02-29

00:13ChouserWell, that worked. Ugly as sin, but it worked. Bedtime.
00:45ericthoranyone having problems with meta data in the latest build?
00:46ericthor(def #^{:a "tag"} f 1)
00:46ericthor(meta f)
00:46ericthoryields nil
05:45arbschtis there a clever naming convention for clojure-relevant projects?
05:50bgeronsomething with a J in the middle maybe?
05:50arbschtj is worth 8 points in scrabble
05:50arbschtthis is not easy to do
14:50Chouserclojure is just too much fun
15:05hoeck_what are you doing with clojure?
15:20ChouserScreen-scraping web pages to generate email notifications.
15:21ChouserBut 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:22ChouserOnce 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:23ChouserThat'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:28Chouseranyway, fun.
15:28Chouser:-)
15:29rhickey_almost finished with proxies, which will let you derive from a concrete/abstract class
15:29Chouserrhickey_: cool! I'll be happy to banish my few lines of Java.
15:31hoeck_are there situations in clojure where one will need this?
15:31Chouserneed to derive from an Java class?
15:31rhickey_it's forced by some library designs
15:31hoeck_yes
15:32rhickey_they fail to use interfaces
15:32ChouserI 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:34hoeck_oh, luckily, i never touched such a library where i need to subclass something
15:36Chouserheh, ew. Is there a better way to do this: (. mystr (replaceAll (str "[ " (char 160) "]+") " "))
15:37ChouserI've got these annoying char 160s I want to treat like whitespace. I think they're  s or something.
15:37ChouserAnyway, the regex \s doesn't match them.
15:54hoeck_chouser: you could use \u00A0 in the regex
15:54nsinghal_i want to see if m2 is subset of m1.
15:54nsinghal_(defn subset? [m1 m2]
15:54nsinghal_ (= (select m1 (keys m2)) m2))
15:54nsinghal_I wanted this to work for any structure passed in, list, vector, maps
15:54nsinghal_I tried converting it to the sequences and then do the comparison.
15:54nsinghal_(defn subset? [m1 m2]
15:54nsinghal_ (let [s1 (seq m1)
15:55nsinghal_ s2 (seq m2)]
15:55nsinghal_ (every? #(let [item = %] (some #(= item %) s2)) s1)))
15:55nsinghal_This function returns REPL:1749: Bad binding form, expected matched symbol expression pairs. What is wrong here?
15:55rhickey_item = % is bad syntax
15:56nsinghal_sorry let me try agina
15:56Chouserhoeck_: ok, that would be a bit better.
15:59arbscht\xA0 rather
16:09nsinghal_user=> (= {:a 1} {:a 1})
16:09nsinghal_true
16:09nsinghal_user=> (= (first s1) (first s2))
16:09nsinghal_false
16:09nsinghal_user=> (first s1)
16:09nsinghal_<:a 1>
16:09nsinghal_user=> (first s2)
16:09nsinghal_<:a 1>
16:09nsinghal_user=> (= (first {:a 1}) (first {:a 1}))
16:10nsinghal_true
16:10nsinghal_When i am comparing (= (first s1) (first s2)) it returns false
16:10nsinghal_(first s1) evaluates to <:a 1> and (first s2) evaluates to <:a 1>
16:17hoeck_nsinghal: i guess comparing "< >" is not implemented yet
16:17Chouserhow are you setting s1 and s2? I used two separate defs, and (= (first s1) (first s2)) returns true for me.
16:18hoeck_chouser: i used two literal maps, it returned false
16:18nsinghal_(= (first (seq {:a 1})) (first (seq {:a 1})))
16:18nsinghal_this evaluates to true
16:18nsinghal_(= (first (seq {:a 1 :b 2})) (first (seq {:a 1 :b 2})))
16:18nsinghal_this evaluates to false
16:23Chouserok, I see. Pretty squirrley.
16:23Chousertrue: (= (first {:a 1}) (first {:a 1}))
16:23Chouserfalse: (= (first {:a 1 :b 2}) (first {:a 1 :b 2}))
16:28rhickeymap entries don't have value semantics (yet)
16:29rhickeybut you should always be careful with (first amap), unless it's a sorted map
16:30Chousercareful in what way?
16:30nsinghal_when we convert map to seq each seqeuence can have different order
16:30rhickeythere's no guaranteed order
16:30ChouserI'm not comparing map entries, but I'm using first and rest to iterate
16:30nsinghal_but if we cache the seqeunce and perform the match - still returns false for comparison
16:30nsinghal_(def s1 {:a 1 :b 2})
16:30nsinghal_(def s2 {:a 1 :b 2})
16:30nsinghal_(= (first s1) (first s2)
16:30nsinghal_(= (first s1) (second s2))
16:30nsinghal_both returns flase
16:31nsinghal_but you answered that is is not value checking MapEntry
16:31rhickeyright, not yet
16:31nsinghal_(defn subset? [m1 m2]
16:31nsinghal_ (every? #(let [item %] (some #(= item %) (seq m1))) (seq m2)))
16:32rhickeyI'm not happy with Map.Entry as a base - may switch map entries to pairs
16:32rhickeynsinghal_: nested #() forms is bad style - too hard to read
16:32hoeck_rhickey: and the '<>' sharp brackets? are they used for reading map entrys?
16:33rhickeyno - there is no read syntax for map entries
16:33rhickeyyet
16:33nsinghal_somehow it is fun to right hard code in Clojure but I will stay away from thius
16:33nsinghal_thx
16:34rhickeyas I said, I think I'd rather switch to pairs than elevate map entries to first-class status
16:35nsinghal_that will be nice, map entries sound like part of a map while you can have list, sequence etc for pairs
16:35rhickeyyeah, they aren;t more useful than [k v]
16:36nsinghal_thx
16:36hoeck_i was just puzzled by the output of (first {:a 1}) being <:a 1>
16:37ChouserJust today I wanted to use map to process both parts of a map entry.
16:37rhickeyYou can do destructuring of map entries already using [k v]
16:38Chouserah, that's cool.
16:38Chouseroh! I can use that...
16:39Chouserah, very nice.
16:41hoeck_destructuring in let and fn is really nice
16:41rhickeyI still have to add it to loop
16:43hoeck_but i found out, while using clojure i am sticking more to the functional paradigms of lisp
16:44Chouserthose immutable data strcutres are keeping you honest, aren't they.
16:44rhickeyyou pretty much have to
16:44rhickey:)
16:44hoeck_as opposed to common or emacs lisp where i loved (and love) the loop and iterate macros
16:44rhickeyloop in Clojure is completely functional
16:45Chouserusing scala broke me of needing looping structures. It's recursion or (map/reduce/filter) for me.
16:46rhickeyIsn't Scala less functional than Clojure?
16:47Chousereh. 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:47Chouseryou can use while loops and Java mutable containers if you really want to.
16:48rhickeybut Scala itself also has mutable variables and members, not just in the Java interop, right?
16:49Chouseryeah, you can declare a "var" instead of a "val", but that seems roughly like "def" instead of "let".
16:50ChouserNot 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:50rhickeyI 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:51rhickeyIf anywhere in the member chain there's a var, you can't
16:51ChouserRight, I'm not sure if that info is carried in the type system or not. I think probably not.
16:52rhickeymutable data scares me much more than lack of a 'type system"
16:52ChouserI haven't written anything big in Scala (or Clojure, for that matter) to become familiar with the interaction of more complex types.
16:53ChouserI'm still ambivalent about static types. I *think* what I want is optional static typing, but I'm not sure.
16:54ChouserScala 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:54Chousers/new/knew/
16:58Chouserwhat's the best way to test if x is empty, when x may be a map or a list of map entries?
16:58rhickey(seq x)
16:58Chouser(nil? (seq x)) works, but is it slow for a large x?
16:59rhickeyno - seq is constant time for everything
16:59Chousersplendid, thank.
16:59Chouserthanks.
17:00rhickey(when-not (seq x)... better than (when (nil? (seq x)) ...
17:01Chouserfor performance or readability?
17:01rhickeyreadability, more idiomatic, the return value of seq is directly testable by if, that's an important idiom
17:02Chouserok
17:02ChouserI'm in a cond. I'll re-arrange...
17:02rhickeyin a cond, ok
17:04ChouserI'm finding I like cond even when I could use if, just because I can mark the :else clause more clearly.
17:05rhickeyinteresting - pg took else out of cond and called it if in arc
17:05Chouserheh, yeha.
17:06Chouseris there a common idiom for where to put terminal case in recursion? First, last, doesn't matter?
17:07rhickeyI usually follow the positive test - if there's stuff to do, do it, (else) return
17:08Chouserok
17:13ericthorsenwhen passing java objects to clojure do i need to wrap them in something?
17:13rhickeynope
17:13ericthorsenjust checking
17:13rhickeyprimitives will get boxed when passing to invoke as Object
17:14rhickeywhich is what Clojure expects to see
17:14ericthorsenjust wanted to make sure clojureVarInJava.fn().invoke(new MyJava())
17:14ericthorsenwas all i needed
17:15rhickeyjust use clojureVarInJava.invoke(...), don't use fn()
20:08rhickey__proxies are up! - you can now derive from concrete classes dynamically
20:16albinoIs a concrete class a class written and compile in java?
20:16rhickey__It's a class that's not an interface
20:17rhickey__but yes, it must be named and therefore from Java-land
20:18rhickey__for instance you could derive a proxy from javax.mail.Authenticator
20:19rhickey__and override getPasswordAuthentication()
20:22Chouserhm, sounds familier...
20:28Chouserha! just like that. worked perfectly first try.
20:28rhickey__great!
20:28Chouserthank you!
20:28rhickey__sure - it was the most frequently requested missing feature
20:28Chouserthat code in proxy.clj's pretty scary.
20:29rhickey__Welcome to compiler writing
20:33rhickey__actually at ~200 lines of serious stuff, it's much more compact the kind of code that takes Compiler.java to 3500
20:40albinoIs that an actual file Compiler.java?
20:41rhickey__yes, part of the Clojure source
20:41albinoahh, okay
20:41albinoI thought you were referencing jdk7 source code or something
20:42rhickey__no, just me in Java vs me in Clojure
20:43albinoyeah
20:43albinorhickey__: you pretty good with cL?
20:43albinoerr CL
20:43rhickey__ok
20:44rhickey__It was my first Lisp love...
20:44albinorhickey__: have you thought about porting clojure to CL?
20:44rhickey__clojure started in CL
20:44albinooh cool
20:44albinodoes that version still exist in some source control tool somwhere?
20:44rhickey__Originally it was CL that generated Java and C# source
20:45rhickey__Everything source-wise is on SF, all the design stuff is on my Macs
20:46rhickey__Clojure never targeted CL though
20:47rhickey__It has changed a bunch over the years, a lot of work preceded its release in October
20:48ChouserThe first release was just in October?
20:48rhickey__yup
20:49ChouserHow much have you written in Clojure, not counting parts of Clojure itself?
20:49rhickey__mostly Clojure
20:49rhickey__that's the bane of the compiler writer
20:50Chouser:-) yeah.
20:50albinorhickey__: so you've been working on it on your own for years, and just got around to releasing it recently?
20:50rhickey__I am very excited about using it for the rest of my work
20:51Chouserwhat is that other work?
20:51ChouserIf I may ask.
20:51rhickey__yes, worked for years to solve the Lisp+Java/.Net problem - see jFli, Foil, Lisplets etc
20:52rhickey__My other work is audio research, cochlear modeling, scheduling systems etc
20:52Chouserhuh! ok.
20:53pjb3Is there a way to have one clojure script load another clojure script?
20:54rhickey__load-file
20:54albinowow, never heard of jFli before, looks cool
20:57Chouserneither \xA0 nor \u00A0 work in my string literal
20:57ChouserSo I guess I'll continue using (str (char 160))
21:27pjb3Is there something like load-path and require in clojure?
21:27pjb3where load-path is all of the places clojure looks for files to load
21:27pjb3and require loads them, making sure not to reload already loaded files
21:28rhickey__not yet, it has been suggested
21:29pjb3ok, it seems like that would be helpful for organizing larger projects, what do you think?
21:30rhickey__I think that loading and requiring are going to be separate
21:31pjb3what do you mean by that
21:32rhickey__that loading should not be a side-effect of requiring, requires can be analyzed to create a load system definition
21:38pjb3So would (require "foo") load foo.clj?
21:40ericthor_are you referring to parsing and finding all the refers for a set of files to determine a load order?
21:41ericthor_what about qualifier names? name-sapce/func-call
21:41rhickey__So would (require "foo") load foo.clj -> no
21:41pjb3then what does (require "foo") do ?
21:41ericthor_"requires can be analyzed to create a load system definition" ...how?
21:42ericthor_we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls
21:43ericthor_we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls
21:43ericthor_I'm ready to do it!
21:43rhickey__a program could be analyzed for refers and requires to determine the dependency graph and generate a loading plan
21:44ericthor_but it would need to analyze the use of qualified names as well...yes?
21:47rhickey__no - if you use qualified names without refer you will need a require
21:48ericthor_I cannot say n1/foo without a (require 'n1) ?
21:49ericthor_i know it works if n1/foo is loaded...is it not 'proper' clojure?
21:50rhickey__there is no such thing as require yet, we're just speculating, but the loading system will need it
21:51ericthor_that was my next question....
21:52ericthor_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:52ericthor_i like it...it's simple