2008-02-29
| 00:13 | Chouser | Well, that worked. Ugly as sin, but it worked. Bedtime. |
| 00:45 | ericthor | anyone having problems with meta data in the latest build? |
| 00:46 | ericthor | (def #^{:a "tag"} f 1) |
| 00:46 | ericthor | (meta f) |
| 00:46 | ericthor | yields nil |
| 05:45 | arbscht | is there a clever naming convention for clojure-relevant projects? |
| 05:50 | bgeron | something with a J in the middle maybe? |
| 05:50 | arbscht | j is worth 8 points in scrabble |
| 05:50 | arbscht | 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 | Chouser | 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 | Chouser | 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 | Chouser | 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 | Chouser | anyway, fun. |
| 15:28 | Chouser | :-) |
| 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 | Chouser | I've got these annoying char 160s I want to treat like whitespace. I think they're s or something. |
| 15:37 | Chouser | 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 | nsinghal_ | (defn subset? [m1 m2] |
| 15:54 | nsinghal_ | (= (select m1 (keys m2)) m2)) |
| 15:54 | nsinghal_ | I wanted this to work for any structure passed in, list, vector, maps |
| 15:54 | nsinghal_ | I tried converting it to the sequences and then do the comparison. |
| 15:54 | nsinghal_ | (defn subset? [m1 m2] |
| 15:54 | nsinghal_ | (let [s1 (seq m1) |
| 15:55 | nsinghal_ | s2 (seq m2)] |
| 15:55 | nsinghal_ | (every? #(let [item = %] (some #(= item %) s2)) s1))) |
| 15:55 | nsinghal_ | 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 | nsinghal_ | true |
| 16:09 | nsinghal_ | user=> (= (first s1) (first s2)) |
| 16:09 | nsinghal_ | false |
| 16:09 | nsinghal_ | user=> (first s1) |
| 16:09 | nsinghal_ | <:a 1> |
| 16:09 | nsinghal_ | user=> (first s2) |
| 16:09 | nsinghal_ | <:a 1> |
| 16:09 | nsinghal_ | user=> (= (first {:a 1}) (first {:a 1})) |
| 16:10 | nsinghal_ | true |
| 16:10 | nsinghal_ | When i am comparing (= (first s1) (first s2)) it returns false |
| 16:10 | nsinghal_ | (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 | nsinghal_ | this evaluates to true |
| 16:18 | nsinghal_ | (= (first (seq {:a 1 :b 2})) (first (seq {:a 1 :b 2}))) |
| 16:18 | nsinghal_ | this evaluates to false |
| 16:23 | Chouser | ok, I see. Pretty squirrley. |
| 16:23 | Chouser | true: (= (first {:a 1}) (first {:a 1})) |
| 16:23 | Chouser | false: (= (first {:a 1 :b 2}) (first {:a 1 :b 2})) |
| 16:28 | rhickey | map entries don't have value semantics (yet) |
| 16:29 | rhickey | 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 | nsinghal_ | (def s1 {:a 1 :b 2}) |
| 16:30 | nsinghal_ | (def s2 {:a 1 :b 2}) |
| 16:30 | nsinghal_ | (= (first s1) (first s2) |
| 16:30 | nsinghal_ | (= (first s1) (second s2)) |
| 16:30 | nsinghal_ | both returns flase |
| 16:31 | nsinghal_ | 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 | nsinghal_ | (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 | rhickey | 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 | rhickey | yet |
| 16:33 | nsinghal_ | somehow it is fun to right hard code in Clojure but I will stay away from thius |
| 16:33 | nsinghal_ | 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 | Chouser | oh! I can use that... |
| 16:39 | Chouser | 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 | rhickey | :) |
| 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 | Chouser | 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 | Chouser | 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 | rhickey | 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 | Chouser | I'm still ambivalent about static types. I *think* what I want is optional static typing, but I'm not sure. |
| 16:54 | Chouser | 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 | Chouser | s/new/knew/ |
| 16:58 | Chouser | 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 | Chouser | 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 | Chouser | 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 | Chouser | 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 | rhickey | which is what Clojure expects to see |
| 17:14 | ericthorsen | just wanted to make sure clojureVarInJava.fn().invoke(new MyJava()) |
| 17:14 | ericthorsen | 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 | 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 | rhickey__ | but yes, it must be named and therefore from Java-land |
| 20:18 | rhickey__ | for instance you could derive a proxy from javax.mail.Authenticator |
| 20:19 | rhickey__ | and override getPasswordAuthentication() |
| 20:22 | Chouser | hm, sounds familier... |
| 20:28 | Chouser | 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 | rhickey__ | 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 | albino | 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 | albino | rhickey__: you pretty good with cL? |
| 20:43 | albino | err CL |
| 20:43 | rhickey__ | ok |
| 20:44 | rhickey__ | 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 | albino | 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 | rhickey__ | Everything source-wise is on SF, all the design stuff is on my Macs |
| 20:46 | rhickey__ | Clojure never targeted CL though |
| 20:47 | rhickey__ | 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 | rhickey__ | 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 | Chouser | 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 | rhickey__ | 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 | Chouser | 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 | pjb3 | where load-path is all of the places clojure looks for files to load |
| 21:27 | pjb3 | 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 | ericthor_ | 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 | ericthor_ | we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls |
| 21:43 | ericthor_ | we were discussing this today and ran into the question on knowing about other namespaces not in the 'refers' calls |
| 21:43 | ericthor_ | 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 | ericthor_ | 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 | ericthor_ | 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 | ericthor_ | i like it...it's simple |