2009-07-15
| 00:02 | grrrt | how can you test if a name is a function? I guess isa? or instance? wouldn't work here? |
| 00:04 | gnuvince | grrrt: fn? and ifn? come to mind |
| 00:04 | gnuvince | ,(fn? map) |
| 00:04 | clojurebot | true |
| 00:04 | grrrt | ahh doh! |
| 00:04 | grrrt | sigh, brain has left the office for the day :) |
| 00:04 | gnuvince | ,[(fn? {}) (ifn? {})] |
| 00:04 | clojurebot | [false true] |
| 00:04 | grrrt | cheers |
| 00:05 | gnuvince | np |
| 00:13 | arohner | does anyone have experience running a profiler on clojure code in OSX? |
| 00:13 | arohner | or linux. but eclipse's TPTP is not working for me |
| 02:29 | Jomyoot | Is there example of how to structure clojure into different source files? |
| 02:29 | Jomyoot | name spaces and etc? |
| 02:29 | Jomyoot | basically a simple project structure |
| 02:29 | Jomyoot | i so far have used clojure as glue code. so all in one file |
| 03:25 | ataggart | very loosely speaking, one clj file for a namespace |
| 04:54 | Jomyoot | should they use or require each other? |
| 05:05 | AWizzArd | depends on how you want to use them |
| 05:06 | AWizzArd | both are valid options |
| 05:06 | AWizzArd | I use 60% and require 40% |
| 05:39 | Jomyoot | is there a guilde or tutorial for this? |
| 05:50 | ataggart | with require you still need to use a namespace (or namespace aliias). with use you don't need to prefix everythign with a namespace |
| 05:50 | ataggart | it's style prefernce more than anything |
| 06:03 | Jomyoot_ | do i put deeper name spaces into deeper folders? |
| 06:04 | Jomyoot_ | or throw all files into same folder |
| 06:04 | Jomyoot_ | does java style folder/package mapping still work here? |
| 06:06 | jdz | the Java style hierarchical file/namespace relation remains |
| 06:06 | jdz | http://clojure.org/libs |
| 06:08 | Jomyoot_ | any idea when cascade will be available? |
| 06:09 | jdz | what's cascade? |
| 06:11 | Jomyoot_ | something tapestry guy said he would make |
| 06:11 | Jomyoot_ | for clojure |
| 06:11 | Jomyoot_ | that's all i know |
| 06:11 | Chousuke | Jomyoot_: you can also split a namespace into multiple files by having the "main" file use 'load to "include" other files |
| 06:11 | Jomyoot_ | i don't even know if tapestry is popular |
| 06:13 | Jomyoot_ | :use com.test.me.ns would that go look for the com/test/me/ns.clj file? assuming that it's all source file |
| 06:13 | Chousuke | yeah. |
| 06:14 | Chousuke | see (doc ns) and (doc require) at least. |
| 06:14 | Chousuke | the ns documentation is a bit scattered |
| 07:36 | Neun | hello, why does this not work: (eval (list #(%) "foo")) |
| 07:36 | Neun | why do I have to quote the function? |
| 07:38 | cemerick | Neun: is foo the function you're trying to invoke? |
| 07:39 | Neun | I tried this (map (comp eval list) list-of-functions list-of-elemts) |
| 07:40 | Neun | this works though: (map #(%1 %2) list-of-functions list-of-elements) |
| 07:40 | cemerick | eval is unnecessary unless you've got symbols, etc., as opposed to actual functions |
| 07:41 | cemerick | e.g.: |
| 07:41 | cemerick | ,(eval '(+ 5 6)) |
| 07:41 | clojurebot | DENIED |
| 07:41 | cemerick | bah |
| 07:41 | Neun | I see |
| 07:41 | cemerick | anyway, that would return 11, but clearly, you just want to invoke a fn directly: |
| 07:42 | cemerick | ,(+ 5 6) |
| 07:42 | clojurebot | 11 |
| 07:42 | jdz | Neun: would just plain (map apply list-of-functions list-of-elements) not work? |
| 07:42 | Neun | jdz: no, apply needs a vector of arguments |
| 07:43 | jdz | no, just a sequence |
| 07:43 | cemerick | Neun: not so: |
| 07:43 | jdz | well, not really |
| 07:43 | cemerick | ,(apply + (list 5 6)) |
| 07:43 | clojurebot | 11 |
| 07:43 | jdz | the last argument should be a sequnce |
| 07:43 | cemerick | right |
| 07:43 | cemerick | ,(apply + 14 (list 5 6)) |
| 07:43 | clojurebot | 25 |
| 07:44 | jdz | ,(apply + 42) |
| 07:44 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer |
| 07:47 | Jomyoot | can (def x (ref (hash-map)) bedefined using (let) as well? |
| 07:47 | jdz | let creates bindings in it's scope. when the scope is gone, so are the bindings. |
| 07:49 | cemerick | Jomyoot: you can certainly use let to perform some initial computation, and use the result as the value of the new def binding: (def x (let [foo ... bar ...] (ref {baz (some-fn foo bar)}))) |
| 07:59 | rottcodd | is there a way to call private functions in another namespace? |
| 07:59 | cemerick | rottcodd: (#'some.other.ns/fn-name ...) |
| 08:00 | cemerick | #'foo returns the var named by foo |
| 08:00 | Chousuke | and var just happens to delegate to its value if it appears in operator position :P |
| 08:01 | cemerick | I think that was a stroke of genius. Much nicer than other lisps where you really had to be conscious of that sort of thing. |
| 08:03 | rottcodd | cemerick: thanks |
| 08:10 | rhickey | did anyone ever do a reasonable with-captured-bindings macro? |
| 08:13 | cemerick | ach, I always get tripped up by the order of fns to comp |
| 08:14 | rhickey | (foo (bar (baz ... -> (comp foo bar baz) |
| 08:14 | rhickey | i.e. comp just removes some parens |
| 08:15 | cemerick | rhickey: yeah, I just happen to use -> more often, which applies in the reverse order |
| 08:15 | cemerick | comp is more consistent with mathematical notation, too, so this is really just a mental problem on my part |
| 08:15 | rhickey | I have to think twice sometimes too :) |
| 08:17 | rhickey | I really want to get a pipe macro in place, to further confuse things :), like -> but puts arg at end. We've discussed before, just need a name |
| 08:18 | rhickey | saw an F# presentation where they did everything with the :> operator, made people very comfortable |
| 08:18 | cemerick | heh. I have no idea what :> would mean. |
| 08:18 | rhickey | sorry, |> operator |
| 08:18 | cemerick | yeah, that doesn't ring any bells, either :-) |
| 08:19 | Chouser | $ means end-of-the-thing in regex and sh |
| 08:19 | rhickey | right, I'm not advocating |>, but it had the same concept as pipe, put arg at end, except you have to keep repeating it |
| 08:19 | cemerick | ah |
| 08:20 | rhickey | we haven't used $ or | yet, probably not worth it for this |
| 08:20 | rhickey | -<, <- |
| 08:20 | Chouser | ($-> coll (map foo) (filter bar)) |
| 08:20 | cemerick | well, I generally try to avoid shell scripting, so #(-> % .. .. ..) and comp are good enough for me :-) |
| 08:21 | rhickey | cemerick: really, you use -> and wouldn't use (pipe xs (map f) (filter p) (reduce op)) ? |
| 08:22 | Chouser | One of the first clojure macros I ever wrote was called >>_ |
| 08:22 | Chouser | (>>_ coll (map foo _) (filter bar _)) |
| 08:22 | rhickey | for pipe? |
| 08:23 | rhickey | funny I would have gone the other way << |
| 08:23 | rhickey | maybe not |
| 08:23 | Chouser | it's going the same way as -> |
| 08:23 | rhickey | well, it's generally useful, and should be standard |
| 08:24 | Chouser | yeah, I used >>_ once or twice early on, but being non-standard makes it tiring to communitcate with others |
| 08:24 | rhickey | Chouser: yes, in some sense (calls) but not others (args) |
| 08:24 | rhickey | Chouser: especially with a name like >>_ :) |
| 08:24 | cemerick | rhickey: Not sure I'd use it, at least until I'd had a chance to internalize it. -> is very intuitive for me, but so far, I'm feeling like I'd end up having to read the docs on pipe when I end up reading code later on. |
| 08:24 | Chouser | hmph |
| 08:25 | cemerick | Stuff like that changes fast, though. |
| 08:25 | Neun | jdz: maybe I could write (map apply seq-of-functions (map list (seq-of-values))) |
| 08:25 | wlr | what's wrong with calling it just, er, pipe? |
| 08:26 | cemerick | FWIW, I use -> most often for simple navigation of data structures (-> foo :key deref seq last), etc. |
| 08:26 | rhickey | wlr: nothing, except for the other meaning of pipe (data structure, IO channel) |
| 08:26 | rhickey | cemerick: that's its intended use for sure |
| 08:26 | jdz | Neun: that should work. |
| 08:27 | rhickey | wlr: one reason -> isn't called 'thread' |
| 08:27 | cemerick | honestly, I'd be very worried if I were regularly mapping and filtering my way through things. Linear time bounds aren't nearly good enough. :-) |
| 08:27 | jdz | Neun: despite the fact that i don't like how it looks :/ |
| 08:28 | Neun | jdz: yes, there should be something better/cleaner |
| 08:28 | rhickey | all of the seq fns are set up for pipe |
| 08:28 | wlr | rhickey: okay, competing concepts. thanks. |
| 08:29 | rhickey | anyway, we've got -<, <-, >>_, $-> - any others? |
| 08:29 | rhickey | ->> |
| 08:30 | jdz | => |
| 08:30 | Chouser | --> <-- |
| 08:30 | jdz | ==> |
| 08:30 | cemerick | <- is the most intuitive of them all, at least with respect to -> |
| 08:30 | jdz | ^.^ |
| 08:30 | jdz | but that's taken by meta |
| 08:30 | jdz | \m/ |
| 08:31 | jdz | >.> |
| 08:31 | rhickey | I think Clojure datalog lib is using <- ? |
| 08:32 | cemerick | shouldn't it be (some-fn-name (filter f) (map f2) coll), though? By that I mean, shouldn't the collection be the last arg to the fn if it's proceeding right to left? |
| 08:33 | Chouser | but it's not proceeding right to left |
| 08:33 | Chouser | that's why the left-pointing things may not be appropriate |
| 08:33 | cemerick | ah-ha -- that's what I get for reading a random group posting on "pipe" |
| 08:33 | Chouser | (map f2 (filter f coll)) |
| 08:34 | rhickey | it's kind of imperative, take xs, map it, filter it, reduce it ... |
| 08:35 | rhickey | In the F# demo it made people comfortable to see code that looked like "do this, do that", but was actually functional |
| 08:36 | rhickey | I'm now with Chouser that call order dominates the sense of order, not arg order |
| 08:36 | rhickey | so ->> or --> working best right now |
| 08:37 | Chouser | two > certainly stands out more than two - |
| 08:37 | Chouser | -=> |
| 08:37 | rhickey | yup |
| 08:37 | Chouser | ->* |
| 08:37 | rhickey | = and > makes one think numbers |
| 08:37 | Chouser | >- |
| 08:38 | Chouser | >>- |
| 08:38 | rhickey | Chouser: documenting the path to >>_, eh :) |
| 08:38 | Chouser | :-) |
| 08:38 | cemerick | multiple >'s make me think of bit-shifts |
| 08:39 | Chouser | >-- |
| 08:39 | rhickey | cemerick: me too, but ->> still seems like an arrow to me |
| 08:39 | Chouser | (>-- coll (filter x) (map y)) |
| 08:39 | rhickey | which is kind of nice in being able to call them the two arrow ops |
| 08:40 | rhickey | arrow threads and double arrow pipes |
| 08:40 | rhickey | through a series of calls |
| 08:42 | cemerick | of course, there's the inevitable clojure impl of haskell arrows :-P |
| 09:01 | weissj | is there a particular reason why there's no builtin function called != ? that just does (not (= a b)) |
| 09:02 | Chousuke | there's not= |
| 09:02 | cemerick | ,(doc not=) |
| 09:02 | clojurebot | "([x] [x y] [x y & more]); Same as (not (= obj1 obj2))" |
| 09:02 | weissj | ah |
| 09:02 | cemerick | hrm, odd irc latency |
| 09:02 | weissj | would never have thought to look for that. :) |
| 09:03 | Chousuke | ! carries the "side-effect!" meaning |
| 09:03 | weissj | Chousuke: even when the ! is at the beginning? |
| 09:03 | cemerick | I would have exempted it for !=, but oh well |
| 09:04 | cemerick | that's one of the advantages of having a BDFL (or similar), as opposed to cargo-cult design. |
| 09:06 | Jomyoot | do I have to both (require) and (refer) a namespace in another file? |
| 09:06 | jdz | or just use? |
| 09:06 | weissj | cemerick: what are bfdl and cargo-cult designs |
| 09:07 | cemerick | Jomyoot: yeah, just use use, or, require with an :as name: (require [some.ns.util :as util]), and then access some.ns.util's fns with util/fn-name |
| 09:08 | Chousuke | require needs its argument quoted though :) |
| 09:08 | Chousuke | or you can use the ns macro |
| 09:09 | Jomyoot | So (refer) without (require) does not work? |
| 09:09 | Chousuke | I've never used refer directly :/ |
| 09:10 | jdz | refer with require is called 'use', as far as i understand |
| 09:10 | cemerick | weissj: http://en.wikipedia.org/wiki/BDFL -- by cargo-cult, I meant a bikeshed-susceptible design process (http://bikeshed.com/) |
| 09:10 | jdz | and refer does work without require. see the documentation what refer does... |
| 09:11 | Jomyoot | I get java.lang.ClassNotFoundException: com.atcloud.build-tags-hash-map |
| 09:12 | Jomyoot | I have (ns com.atcloud |
| 09:12 | Jomyoot | (:use [clojure.contrib.sql])) |
| 09:12 | Jomyoot | and (defn build-tags-hash-map [db] in the other file |
| 09:12 | jdz | do you have a file com/atcloud/build_tags_hash_map.clj in your classpath? |
| 09:13 | Jomyoot | i am idiot |
| 09:13 | Jomyoot | i am supposed to use / |
| 09:13 | Jomyoot | rather than . i think |
| 09:15 | weissj | is it possible that a future version of clojure will allow you to have a function call earlier in the file than its definition? or is there something too inherent in the language that disallows this? |
| 09:15 | weissj | it's not a huge deal, but it tends to make a file harder to read (the higher level more 'important' stuff is at the bottom) |
| 09:16 | cemerick | weissj: I think rhickey has said that it's possible that forward declarations could eventually be handled automatically |
| 09:16 | weissj | cemerick: cool |
| 09:16 | cemerick | until then, you can use declare to create those (undefined) vars, and then define them later in the file |
| 09:17 | weissj | cemerick: functions too? |
| 09:17 | cemerick | especially functions |
| 09:17 | cemerick | IME, anyway |
| 09:17 | weissj | hm, i'm not sure if that makes things better or worse :) |
| 09:17 | cemerick | well, it lets you structure your code how you want, anyway |
| 09:18 | weissj | cemerick: yeah, but you still have declarations at the top |
| 09:18 | cemerick | it generally doesn't happen that much, at least to me |
| 09:18 | cemerick | *shrug* |
| 09:18 | weissj | oh i see you can declare them all at once? nice |
| 09:18 | weissj | ie (declare a b c d) |
| 09:19 | rhickey | cemerick: I don't know that I said that - it would be a change to the compilation model (from the equivalent of streaming the same commands into a repl), and would require the introduction of some notion of compilation unit, issues with macros etc |
| 09:19 | rottcodd | should I use *var* or var for variable names? |
| 09:19 | jdz | rottcodd: "variables" is a very stretched term |
| 09:20 | rhickey | rottcodd: *var* only if you intend to dynamically rebind them |
| 09:20 | cemerick | rhickey: it was a long time ago (probably two April's ago or so), when I had the same question as weissj. I wouldn't be surprised if things have changed since then that would make it less feasible. |
| 09:20 | cemerick | regardless, it's surely a lot of work for a very small gain, IMO |
| 09:20 | rhickey | cemerick: it is certainly possible, but a lot of work for a very minor feature IMO |
| 09:20 | rhickey | heh |
| 09:20 | Chouser | I find code easier to read when I know where to find definitions, that is "above here". Declaring things out of order doesn't seem like an improvment to me. |
| 09:22 | weissj | Chouser: yeah i don't think it's a big deal either, i am just used to java where i put all my private and protected methods at the bottom |
| 09:22 | rhickey | what old time Lispers really want is not whole-file resolution, but simply the ability to compile with unresolved names and get runtime errors |
| 09:22 | cemerick | old-time *common* lispers, of course. The current situation in clojure is exactly like the schemes I remember. |
| 09:23 | rhickey | cemerick: yes, CL |
| 09:24 | rhickey | there's the whole 'define your program in the debugger' thing |
| 09:24 | cemerick | rhickey: did you notice the type hinting that C. Nutter is adding to JRuby? |
| 09:24 | rhickey | cemerick: link? |
| 09:26 | cemerick | rhickey: http://twitter.com/headius/status/2639903017 http://twitter.com/headius/status/2640249841 http://twitter.com/headius/status/2640406401 |
| 09:28 | rhickey | cemerick: java with 'end' ? |
| 09:28 | cemerick | ouch :-) |
| 09:29 | rhickey | I've said the same thing as far as Clojure becoming Java with parens |
| 09:29 | rhickey | what's the point? |
| 09:29 | cemerick | either are surely better than Java -- if the hints are just there to keep the reflector away, then all's well |
| 09:31 | cemerick | rhickey: it's telling that, honestly, most devs don't need much more than Java -- so, giving them the opportunity to write java-ish things in one's language makes adoption *possible*, anyway. And not ensuring smooth interop along all possible axes makes widespread adoption simply impossible. |
| 09:31 | rhickey | cemerick: I'm not sure, vs a Java stub and a simple way to reach more involved logic in the preferred lang. The cost is bringin in all the Java cruft into your lang, protected etc |
| 09:34 | cemerick | rhickey: Oh, I agree wholeheartedly, but then, I'm not involved in building or using a language for the masses. |
| 09:34 | rhickey | Have you ever seen LinJ? |
| 09:34 | rhickey | seems to have disappeared, but it was a lisp that generated idiomatic Java |
| 09:35 | rhickey | was weighed down, IMO, by the need to support all Javaisms |
| 09:36 | cemerick | its page on cl-user.net has a pretty meager example, but yeah, I can definitely see how dragging all that cruft along would make a lot of things painful |
| 09:36 | weissj | if I have a java method i want to call that can either return a value or throw an exception, and i want to catch the exception, or store the return val in a variable, how do i do this? declare the var as nil first? |
| 09:36 | rhickey | after all, if a lang Y is to support all constructs of another lang X, is it not inherently going to be more complex than X? |
| 09:36 | cemerick | type-hinting is pretty painful as it is, but it's certainly necessary |
| 09:37 | Chousuke | weissj: wrap the java method call in a function |
| 09:37 | cemerick | (although I wonder if the JIT in JDK 7 with all of its reflection-inlining, etc would optimize a reflective call to a regular method invocation given enough heat) |
| 09:37 | Chouser | weissj: (let [foo (try (foo-fn) (catch Exception e "error-val"))] ...) |
| 09:38 | weissj | Chouser: i see thanks |
| 09:38 | Chouser | that is, the final value of the catch block is what 'try' returns on the exception case |
| 09:39 | weissj | Chouser: yeah in my case i'm later checking for nil, so i'll have the exception clause return nil. that'll do it! |
| 09:41 | Jomyoot | is lisp code supposed to be more managable? |
| 09:41 | Jomyoot | than JAVA? |
| 09:42 | Jomyoot | once you have lots of it? |
| 09:42 | rhickey | so, last call, I'm thinking about calling 'pipe' ->> |
| 09:43 | Chousuke | Jomyoot: that probably depends on how good you're at writing manageable lisp code :) |
| 09:44 | Chousuke | Jomyoot: But lisp has more powerful tools for abstraction than java IMO, so I'd say yes. |
| 09:45 | cemerick | If you know what you're doing, there's amazing power in a good lisp. If you're not a good programmer, then you'll be hopelessly lost. |
| 09:46 | cemerick | I'm a little of both, but I've aspirations. :-) |
| 09:51 | weissj | is there a builtin function to execute a command on the command line (perhaps via java's Runtime/Process/execute api) |
| 09:53 | Jomyoot | so using .java stuff does break immutablity |
| 09:53 | weissj | clojure.contrib.shell-out/sh - found it. doc search on execute found nothing, but 'exec' found this |
| 09:53 | Jomyoot | i can modify their state without dosync |
| 09:54 | yason | Hmmm, was there a byte stream as a lazy sequence akin to line-seq ? |
| 09:54 | cemerick | Jomyoot: you can break immutability in a variety of ways if you're really motivated and your data structures allow it. |
| 09:55 | Jomyoot | what's the point of dosync when it's so easy to break immutability when using java objects |
| 09:56 | Chousuke | the point is that when you do use the immutable data structures, it allows for easy concurrency |
| 09:56 | Chousuke | Clojure does not force immutability on you. It just gets harder and harder to keep your program working the more mutability you introduce |
| 09:57 | cemerick | it's pretty difficult to introduce mutability to begin with, if you stay within clojure. |
| 09:57 | Chousuke | mutability support is pretty much an interop thing. |
| 09:57 | Jomyoot | it is hard to write Clojure without using java interop though |
| 09:58 | cemerick | Jomyoot: a corollary would be, "what's the point of garbage collection and memory protection in Java if it's so easy to segfault when you call into native methods?" |
| 09:58 | yason | Jomyoot: depends. I don't know Java much so I tend to steer away from any Java interop automatically |
| 09:58 | Chousuke | Hmm, perhaps. |
| 09:58 | Jomyoot | i get your point |
| 09:58 | cemerick | Jomyoot: Depends on your domain. I touch java very rarely. |
| 09:58 | yason | Jomyoot: I just wrap the most essential java stuff to get my stuff running (file i/o or GUI stuff) and stay with Clojure then |
| 09:59 | Chousuke | proper use of java interop is to keep it isolate from pure, functional clojure logic :) |
| 09:59 | Chousuke | isolated* |
| 09:59 | yason | Chousuke: that's what I was trying to say, with too many copies of "stuff" :D |
| 10:00 | Chousuke | of course, some java stuff is "immutable" as well, like strings, and thus not a problem. |
| 10:01 | Chousuke | It seems that arrays are the worst troublemakers :/ |
| 10:35 | Jomyoot | Is emacs still pretty as IDE for Clojure? |
| 10:38 | weissj | anybody here known about ant tasks with lancet? (lancet/echo {:message "hi" :level "warning"}) gives java.lang.ClassCastException: Cannot cast java.lang.String to org.apache.tools.ant.taskdefs.Echo$EchoLevel |
| 10:39 | weissj | ant actually takes a string for :level, but here it seems to insist on an internal class called "EchoLevel" |
| 10:39 | shoover | Jomyoot: I'm not sure anyone has ever accused emacs of being pretty, for clojure or otherwise |
| 10:39 | shoover | useful, sure |
| 10:42 | Jomyoot | What is equivalence of simple hash in Ruby like this { :a => 1, :b => 2, :c => 3} is that HashMap in Clojure then? |
| 10:43 | Chouser | Jomyoot: {:a 1, :b 2, :c 3} is a map in Clojure |
| 10:44 | scgilardi | Jomyoot: and literal maps are hashmaps |
| 10:45 | Jomyoot | is 'a equivalence of :a in ruby? |
| 10:46 | arbscht | it's probably not wise to think in terms of direct equivalents |
| 10:46 | liebke | jomyoot, :a in ruby is equivalent to :a in Clojure |
| 11:00 | weissj | once i delete a function definition in a file, and load it into the repl, how do i remove the binding from the repl? |
| 11:01 | weissj | do i have to restart the repl? |
| 11:01 | weissj | (in other words i remove the function def 'myfunc' but the repl still sees it as defined and I don't want it to be) |
| 11:01 | Chousuke | you can either redefine the var to nil or something or use ns-unmap |
| 11:02 | Chousuke | it's pretty simple to write a function that "cleans out" a namespace |
| 11:04 | weissj | ok, i think i got that |
| 11:05 | weissj | what's wrong with (ns myns (use lancet (:as 'ant))) |
| 11:05 | weissj | java.lang.IllegalArgumentException: No value supplied for key: true (jonSuite.clj:1) |
| 11:06 | Chouser | (ns myns (:use [lancet :as ant])) |
| 11:06 | Chouser | except lancet probably needs to be longer |
| 11:07 | weissj | longer? |
| 11:07 | Chouser | should be the fully-qualified namespace name |
| 11:07 | Chouser | Halloway didn't call it just "lancet", did he? |
| 11:07 | scgilardi | and :as is more often associated with :require. with use, you're bringing all of lancet's names into the current namespace and then also allowing prefixing them with ant/ |
| 11:07 | Chouser | good point! |
| 11:08 | Chouser | (ns myns (:use [lancet :as ant :only []])) |
| 11:08 | weissj | wait, i just want to refer to functions in lancet with the name ant instead |
| 11:08 | weissj | not also bring in everything into my own ns |
| 11:08 | Chouser | right. |
| 11:08 | Chouser | so :only [] |
| 11:08 | weissj | ok |
| 11:09 | scgilardi | chouser's most recent example is how I would write that |
| 11:09 | Chouser | or you could use 'require' instead, but these days I don't usually recommend that |
| 11:09 | Chouser | I'm still hoping to see those two merged at some point |
| 11:09 | scgilardi | me too |
| 11:11 | cemerick | Chouser: you don't like require + :as? |
| 11:12 | Chouser | cemerick: it's fine until you decide there's one var you want to refer in |
| 11:12 | Chouser | so you had (:require [fully.foo :as foo]) |
| 11:12 | Chouser | and now you have to change it to (:use [fully.foo :as foo :only [bar]]) |
| 11:13 | weissj | Chouser: halloway did just call it 'lancet', btw |
| 11:13 | cemerick | so you prefer :use + :as + :only? |
| 11:14 | scgilardi | did we come up with any downsides to (:use fully.foo :as foo) implying :only [] unless explicitly overridden? |
| 11:14 | Chouser | cemerick: at least it's more consistent -- that way I don't end up with a block of :requires and a block of :uses and have to reorder things based on which ones need an :only |
| 11:15 | cemerick | yeah, that's a point |
| 11:15 | Chouser | scgilardi: breaking change is a downside |
| 11:15 | Chousuke | Chouser: couldn't you add a :refer after the require? |
| 11:15 | cemerick | scgilardi: as long as there is an escape hatch to get full use (a wildcard :only, essentially). I don't do that very often at all, but when I do, it's pretty necessary to retain sanity. |
| 11:16 | Chouser | Chousuke: is :refer supported by something? |
| 11:16 | scgilardi | cemerick: the escape hatch is :exclude [] |
| 11:16 | cemerick | ok :-) |
| 11:16 | Chousuke | (ns something (:require [foo.bar :as foo]) (:refer foo.bar :only [some stuff here])) |
| 11:16 | Chousuke | Chouser: the ns macro? |
| 11:16 | Chouser | Chousuke: ah. I guess that might work, though 'ns' doesn't document it. |
| 11:17 | Chouser | I'd rather have the namespace listed once anyway. |
| 11:17 | Chouser | Chousuke: is there something wrong with :use + :only ? |
| 11:17 | Chousuke | Chouser: not really. |
| 11:17 | Chousuke | I guess it's a matter of preference |
| 11:18 | scgilardi | chouser: I find it a little ugly (though I still use it). It's like explicitly passing nil as an argument to a function. It kinda feels like it would be nicer if you didn't have to. |
| 11:18 | Chousuke | I guess the combined effect of :as and :only is a bit confusing, too |
| 11:18 | Chouser | scgilardi: yes! |
| 11:19 | Chousuke | you wouldn't expect the entire namespace to be available through the :as alias either. |
| 11:19 | Chouser | scgilardi: I find it ugly, but less painful than mixing both :use and :require in random ways in the same ns form |
| 11:19 | Chousuke | I wonder if ns actually does support :refer |
| 11:19 | Chouser | Chousuke: good point. maybe :only is misnamed for :use. |
| 11:19 | Chousuke | (doc refer) ; refers to it though :P |
| 11:19 | clojurebot | "([ns-sym & filters]); refers to all public vars of ns, subject to filters. filters can include at most one each of: :exclude list-of-symbols :only list-of-symbols :rename map-of-fromsymbol-tosymbol For each public interned var in the namespace named by the symbol, adds a mapping from the name of the var to the var to the current namespace. Throws an exception if name is already mapped to something else in the current nam |
| 11:20 | Chousuke | damn, too lon |
| 11:20 | Chousuke | g |
| 11:20 | Chouser | Chousuke: ns macro currently just maps the keywords (like :use and :require) to core function names, and calls them. |
| 11:20 | scgilardi | chouser: exactly right. I think the combination of :use and :as as we have things now is just an attractive hazard. Better replaced by useful functionality. |
| 11:20 | Chousuke | oh wait. |
| 11:20 | Chousuke | refer actually refers to :use, not :refer |
| 11:21 | Chousuke | hmm... |
| 11:25 | Chouser | so the least-breaking way forward would be to introduce a new word and give it the semantics we now know we want |
| 11:25 | Chouser | and deprecate :use and :require |
| 11:25 | scgilardi | chouser: I think Rich also had a notion of "default aliases" at one point. Removing :require and replacing it with :use :as would tend to thwart that. |
| 11:26 | Chouser | but using up another word has drawbacks too |
| 11:26 | Chousuke | Chouser: :assimilate? :) |
| 11:26 | Chouser | scgilardi: hm... maybe. |
| 11:26 | Chouser | :demand |
| 11:26 | Chouser | :-P |
| 11:26 | scgilardi | :depend |
| 11:26 | Chouser | actually -- hm. :require doesn't do anything bad, it's just missing features. Maybe that's the way forward. |
| 11:27 | scgilardi | what's it missing? |
| 11:27 | Chouser | perhaps we could add :refer and support for default aliases to :require |
| 11:27 | Chouser | then deprecate :use |
| 11:33 | scgilardi | as a detail of the current implementation (:require [clojure.contrib.sql :use true]) is exactly equivalent to (:use clojure.contrib.sql). |
| 11:34 | cemerick | oh, poor Stuart :-) |
| 11:34 | Chouser | oh, does :only work with :require? |
| 11:35 | scgilardi | only when accompanied by ":use true" (but that could be changed pretty easily, I think) |
| 11:36 | Chouser | oh, I see. |
| 11:36 | scgilardi | sounds pretty nice... add support for the refer options to :require and have them imply :use true (effectively) |
| 11:37 | Chouser | probably still need something that means :exclude, or at least :exclude [] |
| 11:38 | Chouser | so as to enable our lazy brethren |
| 11:38 | Chouser | :refer-all-because-i-care-more-about-myself-than-my-readers |
| 11:39 | cemerick | Chouser: there *are* good reasons, aside from sloth |
| 11:39 | Chouser | cemerick: really? |
| 11:39 | Chouser | in cases where :as z or something wouldn't suffice? |
| 11:40 | cemerick | well, a throwaway :as name is just noise. |
| 11:40 | cemerick | I use use in conjunction with two namespaces that provide a pile of utility fns that we use throughout our codebase. |
| 11:42 | cemerick | e.g. stuff that, in our domain, we'd be perfectly happy if it happened to be defined in clojure.core (but obviously won't ever, and shouldn't be) |
| 11:44 | Chouser | hm |
| 11:44 | Chouser | ok, would you buy :refer :all ? |
| 11:45 | cemerick | what, (:require [foo.bar :refer :all])? |
| 11:45 | Chouser | yeah |
| 11:45 | cemerick | fine by me |
| 11:46 | cemerick | It's definitely a corner case, so I'm happy to accept a syntactic compromise in order to make everything else simpler. |
| 11:50 | scgilardi | :exclude is one of the refer options to support. We could add :refer :all as sugar for :exclude [], but we would already have the capability it provides. |
| 11:51 | scgilardi | the full list is :exclude, :only, and :rename |
| 11:52 | Chouser | but if :only is renamed to :refer (which I like very much) that raises the question of what :exclude and :rename should be called |
| 11:52 | Chouser | :refer-all-but for :exclude? |
| 11:53 | scgilardi | I think :only :exclude and :rename fit just as nicely with the word "require" as they do with the word "refer". Why rename :only to :refer? |
| 11:55 | Chouser | because require is a verb whose subject is the lib. "only" doesn't modify the lib, but something else, so it seems a poor fit to me. "refer" is a verb matching the core fn, so seems a natural choice. |
| 11:56 | duck1123 | I always mess up :exclude as :except |
| 11:58 | scgilardi | I see it as "require this collection of stuff" (which is the lib). The modifiers let us optionally tailor which pieces of the collection we also bring into the namespace. I do see your point though, we are pulling in the entire lib either way and these options are about how that impacts the current namespace. |
| 11:59 | Chouser | on the other hand I care so much less about the name than the functionality. :-) |
| 12:02 | scgilardi | with either the current or the new names, this would be an easy change to get right in the implementation and would strictly add capability to require that nobody is using currently. it would leave us free to deprecate :use. |
| 12:08 | weissj | if i want to create a java object, call a setter on that object, then return the object, do i need a var? |
| 12:10 | Chouser | nope |
| 12:10 | Chouser | not even a local, if you use 'doto' |
| 12:10 | Chouser | (doto (new JavaClass) (.setFoo 5)) |
| 12:13 | rhickey | Chouser, scgilardi: It would be nice if this new improved use/require thingy had a completely new name, and vastly simpler syntax and semantics than use/require currently do, i.e. if you pick a new name, even :uses, you get a clean slate for a simpler design |
| 12:13 | rhickey | I can never remember how to use use and require |
| 12:13 | Chousuke | heh. |
| 12:19 | scgilardi | I'm open to suggestions. Other than collapsing both use and require into one thing, I don't see obvious opportunities for vast simplification. |
| 12:20 | rhickey | scgilardi: doing less is an opportunity |
| 12:20 | rhickey | the use of the nested vector is tricky too |
| 12:22 | scgilardi | please explain re: doing less |
| 12:24 | rhickey | well, I haven't thought it through, but right now it is undeniably complex, so it begs the question what would be simpler? where is there redundancy? what is infrequently used? |
| 12:25 | rhickey | e.g. foo.bar.baz vs (foo.bar baz) seems like a feature but adds complexity |
| 12:26 | scgilardi | removing the opportunity to use prefix lists to extract out common prefixes would lead to simpler, but more redundant ns forms. |
| 12:27 | rhickey | scgilardi: I thought we'd go the other way |
| 12:28 | rhickey | having just :uses vs :require and :use is good in and of itself |
| 12:28 | rhickey | the nested structure is also tricky |
| 12:29 | rhickey | I can't design it right now, just encouraging a search for simplification |
| 12:29 | scgilardi | that sounds like a good direction. we could remove the vectors perhaps by recognizing symbols as distinct from keyword value pairs in the same way that clojure cond is simpler than CL cond. |
| 12:29 | scgilardi | ok, I'll give it some thought |
| 12:30 | Chouser | if we only allow (foo bar) instead of foo.bar, would it be acceptible to remove one nesting level? (:uses (foo bar :as fr baz :as fz)) ? |
| 12:30 | Chouser | eh |
| 12:30 | Chouser | nm, I don't like that |
| 12:31 | scgilardi | Along the lines of the "circular load" issue, I'm giving some thought to a design for removing the need for :reload and :reload-all by using the resource mod dates like the compiler does. |
| 12:31 | rhickey | scgilardi: sounds appealing |
| 12:32 | scgilardi | rhickey: I'll write up what I have and post it to the developer's list. |
| 12:32 | rhickey | scgilardi: thanks! |
| 12:33 | scgilardi | chouser: what if "fr baz :as fz" were on a separate line. That kind of construct is what I was talking about for removing the vectors above. |
| 12:34 | rhickey | commas are free too |
| 12:34 | rhickey | (:uses (foo bar :as fr, baz :as fz) |
| 12:35 | rhickey | ignored but useful still |
| 12:37 | rhickey | (:uses (foo bar {:as fr} baz {:as fz :refer bleh})) |
| 12:39 | rhickey | nice because adding options doesn't require restructuring |
| 12:39 | Chousuke | I don't see the point of "foo bar" instead of foo.bar |
| 12:39 | Chousuke | or is it importing two libraries? :/ |
| 12:39 | rhickey | right 2 |
| 12:40 | rhickey | share prefix |
| 12:40 | cemerick | where's the prefix, then? |
| 12:40 | scgilardi | For simplifying, I like them being inline better than collected in maps. Adding option wouldn't require restructuring in that case either. A keyword implies a subsequent value. |
| 12:40 | rhickey | cemerick: foo.bar and foo.baz |
| 12:40 | cemerick | ah. |
| 12:41 | rhickey | scgilardi: but a lot harder to parse, even with commas |
| 12:41 | rhickey | better with newlines |
| 12:41 | scgilardi | but compare: (:uses (foo [bar :as fr] [baz :as fz :refer bleh])) |
| 12:42 | rhickey | scgilardi: I really dislike that because the two names are at different nesting levels when no options |
| 12:42 | rhickey | (:uses (foo bar [baz :as fz :refer bleh])) |
| 12:43 | rhickey | ick^ |
| 12:43 | scgilardi | ok, I understand that |
| 12:44 | rhickey | saving typing is a non-objective here, we want clarity and somewhat guessable syntax |
| 12:45 | Chousuke | I like the map approach. |
| 12:46 | rhickey | maps might be a little easier on tools, they definitely are parsing this ns stuff right now, with a lot of hair-pulling |
| 12:48 | scgilardi | I don't mind maps. There is a tension between regularity and succinctness though. I trust we don't want to see empty maps when there are no options. |
| 12:48 | scgilardi | absolutely regular: (prefix name opts name opts name opts) |
| 12:49 | Chousuke | well, '(' prefix (lib-name option-map?)+ ')' would still be very simple |
| 12:50 | scgilardi | I agree. I think we should remove the limitation that lib-name can't have any dots in it. I'd like to be able to express (:uses (clojure.contrib sql sql.test)) without requiring two :uses clauses. |
| 12:51 | scgilardi | Also, if we do end up with :uses, we could also change to :imports and break the (perhaps) unfortunate one to one mapping between ns keywords and like-named functions. |
| 12:51 | scgilardi | ns being declarative in English as well as intent would be a plus I think |
| 12:55 | Chousuke | Why aren't dots allowed in lib names currently, anyway? |
| 12:55 | cemerick | rhickey: surely I don't have to point you towards AppleScript :-P |
| 12:55 | cemerick | besides, this isn't about naming at all, is it? |
| 12:55 | Chousuke | cemerick: what applescript does is called "taking it too far" |
| 12:55 | Chousuke | cemerick: it's still important :) |
| 12:56 | rhickey | cemerick: it's both, use vs uses is naming, the structural stuff is not |
| 13:39 | krl | anyone using clojure with sesame? |
| 13:40 | jackdempsey | no, but sounds delicious |
| 13:41 | duck11231 | I hadn't tried sesame, but i did some work with jena |
| 13:41 | duck11231 | until I abandoned it to go a different way |
| 13:41 | krl | i need a good rdf store without coding java. :) |
| 13:43 | duck11231 | I found that I liked Jena better as a RDF store when I was evaluating both |
| 13:43 | duck11231 | plus, jena worked better with Topbraid Composer. |
| 13:43 | weissj | can someone tell me what's wrong with this (trying to process xml): (clojure.contrib.zip-filter.xml/xml-> myxml :entry) |
| 13:43 | weissj | 1:48 jon-install=> java.lang.ClassNotFoundException: clojure.contrib.zip-filter.xml (repl-1:47) |
| 13:44 | weissj | i need slashes? |
| 13:44 | krl | duck11231: what was better with jena? |
| 13:44 | Chousuke | weissj: that looks fine |
| 13:45 | duck11231 | It's been so long since I looked at the two. I think I needed inferencing that sesame wouldn't give me right |
| 13:45 | duck11231 | plus Jena was easier for me to learn |
| 13:45 | weissj | Chousuke: do you know why i'm getting the ClassNotFoundException? isn't that code supposed to be in the contrib jar? |
| 13:45 | Chousuke | weissj: you probably need to require it |
| 13:46 | Chousuke | weissj: using the fully-qualified name to get to unimported stuff only works with java. |
| 13:46 | weissj | Chousuke: ah |
| 13:48 | weissj | Chousuke: (require 'clojure.contrib.zip-filter.xml) ? |
| 13:48 | Chousuke | yeah. |
| 13:48 | duck11231 | Chousuke: really? I could've sworn I've done something like that and it worked. (although it may have been required in a different ns) |
| 13:48 | weissj | (xml-> myxml :entry) |
| 13:48 | weissj | 1:54 jon-install=> java.lang.Exception: Unable to resolve symbol: xml-> in this context (repl-1:53) |
| 13:48 | Chousuke | weissj: require is not use. |
| 13:48 | Chousuke | weissj: after requiring, you can use the fully-qualified name :) |
| 13:49 | weissj | oh |
| 13:49 | Chousuke | alternatively, (require '[clojure.contrib... :as xml] |
| 13:49 | Chousuke | ) |
| 13:49 | Chousuke | and then (xml/xml-> ...) |
| 14:19 | weissj | ok, so i see how to parse xml with zip_filter/xml, but how do i edit the structure? ie, i found the element and want to replace it with something else |
| 14:20 | Chouser | weissj: use the functions in clojure.zip |
| 14:25 | weissj | Chouser: i see there's a zip/replace... but not sure how to use that. is there an example somewhere of finding something in xml and replacing with something else |
| 14:28 | Chouser | http://paste.lisp.org/display/71471 |
| 14:29 | weissj | Chouser: thanks! |
| 14:30 | Chouser | if you think you might ever need to change more than one item found by a filter (ie. changing every <b> tag or something), zip-filter is going to let you down |
| 14:31 | Chouser | in that case (and perhaps in every case) I'd recommend you look at enlive |
| 14:42 | weissj | Chouser: for my purposes right now, i'm doing one edit at a time. having trouble figuring out how to replace the value of an attribute tho |
| 14:48 | cemerick | am I right in thinking that there's no var I can bind to prevent the runaway printing of circular datastructures? |
| 14:49 | Chouser | *print-level* |
| 14:49 | Chouser | ,(doc *print-level*) |
| 14:49 | clojurebot | "; *print-level* controls how many levels deep the printer will print nested objects. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum level to print. Each argument to print is at level 0; if an argument is a collection, its items are at level 1; and so on. If an object is a collection and is at a level greater than or equal to the value bound to *print-l |
| 14:51 | cemerick | yeah, that I know about -- I was hoping to retain unlimited print-level and print IDs or something for recursively-referenced objects |
| 14:51 | Chouser | oh, you mean for IDerefs in particular |
| 14:51 | cemerick | yeah |
| 14:52 | cemerick | though it's a general problem for anyone writing a print-method or print-dup impl for, say, a regular Java class |
| 14:52 | Chouser | or even .toString |
| 14:52 | cemerick | yeah |
| 14:53 | Chouser | then even *print-level* doesn't help |
| 14:54 | cemerick | I guess I'm looking for something like #1={:foo #1#} |
| 14:54 | Chouser | oh. my. |
| 14:55 | Chouser | I guess that's not unreasonable. Does pprint do something like that? |
| 14:55 | cemerick | hrm, that's an idea |
| 14:55 | Chouser | ,(let [x (java.util.HashMap.) y (java.util.HashMap.)] (.put x :y y) (.put y :x x) (.toString x)) |
| 14:55 | clojurebot | java.lang.StackOverflowError |
| 14:57 | cemerick | nope, pprint doesn't help -- although it looks like the beginnings of an impl of that sort of thing is in pprint/dispatch |
| 14:59 | Chouser | hm, this shouldn't be hard |
| 14:59 | cemerick | no, one just needs to track the objects that have been visited so far |
| 15:00 | Chouser | IDerefs in particular |
| 15:00 | Chouser | ids are already printed |
| 15:01 | cemerick | yeah, that'd be the first target -- general support for any circular references in java objs would be a little trickier, though a general facility that any implementor of a print-method or print-dup method would be handy |
| 15:03 | Chouser | but the latter is impossible |
| 15:03 | Chouser | isn't it? that's what the java.util.HashMap example above shows |
| 15:04 | Chouser | print-method doesn't even get touched |
| 15:04 | cemerick | hrm |
| 15:05 | cemerick | there's a print-dup impl for java.util.Map, but not for print-method |
| 15:06 | Chouser | oh, overridding .toString. hm. |
| 15:07 | cemerick | so, I don't think it's reasonable to think all java classes could be covered, but standard collections seems reasonable, and whatever mechanism is used to track visited objects for IDerefs and standard collections could be reused for any other print-method impl |
| 15:07 | cemerick | Making this work with print-dup would require reader changes, of course. |
| 15:07 | cemerick | or, no, they wouldn't, nm |
| 15:08 | lisppaste8 | Chouser pasted "prevent infinite print recursion for IDeref" at http://paste.lisp.org/display/83647 |
| 15:13 | cemerick | Chouser: ech, I'm still on v1.0, no future? |
| 15:13 | cemerick | That looks about right, though |
| 15:15 | Chouser | oh, just take that part out |
| 15:16 | lisppaste8 | Chouser annotated #83647 "without 'future' support" at http://paste.lisp.org/display/83647#1 |
| 15:22 | cemerick | it works on a trivial example, but I'm still getting spews from real data. I'm trying to isolate the issue. |
| 15:23 | Chouser | hm... |
| 15:23 | Chouser | actually, binding anew at each level isn't quite what I had in mind originally |
| 15:26 | cemerick | hrm, actually, I think that might be a bug on my part |
| 15:26 | cemerick | (unsuprisingly) |
| 15:28 | ChrisPS | ... |
| 15:28 | Chouser | huh. no way to find out if a var has been bound thread-locally except to attempt a 'set!' and catch the exception if not? |
| 15:30 | cemerick | Chouser: Var.getThreadBinding, but it's package-private |
| 15:30 | Chouser | right |
| 15:34 | lisppaste8 | Chouser annotated #83647 "manual binding scope, without future" at http://paste.lisp.org/display/83647#2 |
| 16:05 | porpoise | I made some change to a file and did (use 'mycode.myfile) and it gave me the same error as before I fixed my file. How do I get it to reload the file with the changes? |
| 16:05 | porpoise | when I restarted clojure it worked fine |
| 16:06 | Chouser | (use :reload 'mycode.myfile) |
| 16:06 | porpoise | oh |
| 16:06 | porpoise | heh thanks |
| 16:06 | porpoise | maybe I should keep a noob journal and write a noob guide |
| 16:06 | porpoise | i'm asking enough dumb questions |
| 16:07 | Chouser | http://clojure-log.n01se.net/ is my noob guide |
| 16:07 | Chouser | a bit wordy, I suppose |
| 16:07 | porpoise | cool |
| 16:10 | technomancy | porpoise: it's easier if you have editor integration |
| 16:10 | porpoise | technomancy: I'm using slime and emacs |
| 16:10 | porpoise | is there a better integrated editor for clojure? |
| 16:11 | porpoise | I was doing C-c C-l before |
| 16:11 | technomancy | porpoise: if you've already got slime set up, just use C-c C-k |
| 16:11 | technomancy | or that |
| 16:11 | porpoise | C-c C-l didn't solve my problem but (reload ...) did |
| 16:11 | technomancy | did you do C-c C-l on the file that actually changed? |
| 16:12 | porpoise | technomancy: yes. and it prompted me whether to save and I said yes |
| 16:12 | porpoise | so I thought it was weird that it didn't actually reload |
| 16:12 | technomancy | that's really strange |
| 16:12 | porpoise | maybe my setup is screwed up |
| 16:13 | porpoise | does it work properly for you then? |
| 16:13 | technomancy | do you only have one slime instance running? |
| 16:13 | technomancy | yeah, I've never had that problem |
| 16:13 | porpoise | technomancy: I'll restart emacs to check |
| 16:13 | technomancy | if you can consistently reproduce it, please submit it as a bug to the clojure mailing list |
| 16:13 | technomancy | bonus points if you can narrow it down to a simple case |
| 16:15 | porpoise | maybe i'll try it on clojurebox on my windows machine as well |
| 16:15 | porpoise | what instructions should I use to setup slime and clojure? I used |
| 16:15 | porpoise | the Bill Clementson script |
| 16:15 | technomancy | clojurebot: slime? |
| 16:15 | clojurebot | slime is best configured using M-x clojure-install once you have clojure-mode installed. Please *don't* configure it manually unless you know what you're doing. |
| 16:16 | technomancy | hrm; I personally heartily recommend the instructions at http://technomancy.us/126 while fully admitting that I may be biased. |
| 16:16 | technomancy | Bill Clementson's stuff is pretty outdated. |
| 16:17 | Chouser | what's do you call the class in which a nested class is nested? |
| 16:17 | Chouser | not its parent class |
| 16:17 | Chouser | its "nestor class" |
| 16:17 | j-dot | outer class? |
| 16:17 | technomancy | container? |
| 16:17 | cemerick | outer class, usually |
| 16:17 | Chouser | ah, thanks |
| 16:17 | porpoise | the nest? |
| 16:18 | cemerick | is anyone aware of a NetBeans RCP wrapper for clojure (or the start of one)? |
| 16:19 | weissj | Chouser: any hints on how to replace an xml attribute value? (xml-> z zf/descendants :foo (attr :name)) |
| 16:19 | weissj | ("hi") |
| 16:19 | weissj | it just returns the value, not the whole attribute. if i try to replace it with "yo" like so: |
| 16:20 | weissj | (zip/replace rpl (parse-str "yo")) |
| 16:20 | weissj | 1:40 user=> org.xml.sax.SAXParseException: Content is not allowed in prolog. (repl-1:39) |
| 16:20 | Chousuke | tried with just "yo" instead of trying to parse it? |
| 16:20 | Chouser | Yeah, the attributes aren't children in xml-zip |
| 16:21 | hiredman | lisppaste8: url? |
| 16:21 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 16:21 | Chouser | you'll probably have to replace the whole element |
| 16:22 | weissj | Chouser: how can i replace the whole element, if i only know one attribute |
| 16:22 | Chouser | you'll have to not go down that far in your filter expr |
| 16:23 | weissj | Chouser: is there a way to select the element based on its attribute? |
| 16:23 | Chouser | yes |
| 16:24 | Chouser | you know the value you want, or just the existence of the attr? |
| 16:24 | weissj | Chouser: value |
| 16:24 | weissj | (xml-> z zf/descendants :foo [(attr= :name "hi")]) |
| 16:24 | Chouser | right |
| 16:24 | weissj | that seems to select a lot more than the element |
| 16:25 | lisppaste8 | hiredman pasted "get non-public field" at http://paste.lisp.org/display/83651 |
| 16:26 | hiredman | ugh |
| 16:26 | hiredman | missing a paren |
| 16:26 | Chousuke | I like the name :P |
| 16:26 | hiredman | :) |
| 16:27 | beutdeuce | question, how do you do if-else statements? |
| 16:27 | Chouser | weissj: it's a loc object |
| 16:27 | weissj | Chouser: oh ok.. let me see if that works |
| 16:28 | Chousuke | beutdeuce: (if condition then-expr else-expr) |
| 16:28 | Chousuke | beutdeuce: see also: cond, when, if-let, condp |
| 16:29 | beutdeuce | k |
| 16:29 | weissj | Chouser: so what do i give as the 2nd arg to zip/replace, if i'm replacing <foo name='hi'>1</foo> with <foo name='yo'>1</foo> ? i can't just use that string because that code won't know the rest of that element, ie, the "1" content. |
| 16:29 | Chouser | (def changed (let [e (xml1-> z zf/descendants :foo [(attr= :name "name1")])] (zip/replace e (assoc-in (zip/node e) [:attrs :name] "new-name")))) |
| 16:30 | Chouser | so beautiful and simple :-P |
| 16:30 | Chouser | why can't I annotate that paste? too old? |
| 16:30 | beutdeuce | why doesnt this work => http://clojure.pastebin.com/m478e6cc |
| 16:30 | weissj | Chouser: yeah i seem to be giving up a lot to get thread safety when i don't need it :) |
| 16:31 | Chouser | the APIs just need work |
| 16:31 | Chouser | I have faith |
| 16:31 | Chouser | :-) |
| 16:32 | Chousuke | beutdeuce: the then and else are not part of if syntax |
| 16:32 | beutdeuce | oh |
| 16:32 | beutdeuce | k |
| 16:32 | Chousuke | beutdeuce: also, you should not put the closing parens on their own lines |
| 16:33 | Chousuke | they'll feel lonely. |
| 16:33 | beutdeuce | now, it tells me too little arguments for if |
| 16:33 | technomancy | Chousuke: that's the best reason I've heard yet. =) |
| 16:33 | weissj | beutdeuce: you need two forms, a "then" and "else" form |
| 16:33 | weissj | if you're just doing an "if" with no "else", use when |
| 16:34 | beutdeuce | k |
| 16:34 | beutdeuce | argh, still too few arguments => http://clojure.pastebin.com/m6c8cfe87 |
| 16:35 | weissj | beutdeuce: there's no "then" or "else" - |
| 16:35 | beutdeuce | yes there is |
| 16:35 | weissj | there shouldn't be |
| 16:35 | weissj | example: |
| 16:35 | beutdeuce | oh |
| 16:35 | technomancy | also the "then" and "else" clauses need to be *inside* the last paren of the "if" clause |
| 16:36 | weissj | (if (= (+ 1 1) 2) (print "yep") (print "nope")) |
| 16:36 | beutdeuce | yeah, k , thnx |
| 16:36 | Chouser | ,(if (= (+ 1 1) 2) (print "yep") (print "nope")) |
| 16:36 | clojurebot | yep |
| 16:37 | beutdeuce | does clojure do null or nil ? |
| 16:37 | Chousuke | nil |
| 16:37 | Chousuke | which equals java's null |
| 16:37 | beutdeuce | k |
| 16:39 | Chousuke | technomancy: If you want more rational reasons, I guess it reduces visual noise because lisp code tends to nest a lot; or that generally every nesting level will only have only one expression |
| 16:39 | technomancy | Chousuke: yeah, but many people don't buy that right away |
| 16:40 | porpoise | technomancy: I'm not using the emacs starter kit because I already have an Emacs setup (based on the launchpad apt-source). It seems slime is not part of ELPA? Should I just install slime manually? |
| 16:40 | technomancy | porpoise: clojure-mode can handle that for you actually with M-x clojure-install |
| 16:41 | porpoise | oh |
| 16:42 | Chousuke | I set myself up a super-emacs (moved away from aquamacs to Cocoa emacs) using http://github.com/purcell/emacs.d/tree/master as a base :P |
| 16:42 | beutdeuce | after i get the right output, i am constantly getting a null pointer exception, why is that? => http://clojure.pastebin.com/m66074d66 |
| 16:43 | Chousuke | beutdeuce: you have parens around (println "true") |
| 16:43 | Chousuke | that means you're calling the return value of (println "true") |
| 16:43 | Chousuke | which is nil |
| 16:46 | arohner_ | is there a version of memoize out there that only memoizes the last N values? |
| 16:48 | Chousuke | hmm |
| 16:48 | Chousuke | Can't think of any, but it should be fairly easy to make one |
| 16:48 | arohner_ | yeah, I just wanted to make sure I wasn't duplicating effort |
| 16:48 | Chousuke | fetching the memoised value would have to be O(n) though |
| 16:49 | arohner_ | why? |
| 16:50 | arohner_ | even a naive version would probably be acceptable. I'm memoizing a fairly expensive function, and it doesn't need to store too many values ( < 1000) |
| 16:50 | Chousuke | well, you have to remove the old values at some point I guess. how are you going to know which values are old if you have just a map? |
| 16:50 | clojurebot | map is *LAZY* |
| 16:50 | Chouser | you'd definitely need more bookkeeping |
| 16:50 | arohner_ | yeah |
| 16:51 | arohner_ | the memoized function is run as part of a webpage, and the values can change over time, so unbounded memory growth is not acceptable |
| 16:54 | Chouser | you'd probably want lru, so a lookup causes an entry to be immune from deletion for a while |
| 16:54 | Chousuke | you could always do periodic "garbage collection" on the memoised map. |
| 16:55 | Chouser | if you had a map of args -> lookup-seq-num, that could be updated in constant time for each cache hit |
| 16:55 | Chousuke | yeah. then go through it every once in a while and remove entries from the actual memorised map that are too old |
| 16:55 | Chouser | but then on insert you'd have to O(1) walk that map looking for low-numbered values |
| 16:58 | porpoise | I just started using the clojure-install setup from ELPA. What's the correct way of adding my code directory to the search path, and add my java classpaths and native libraries? |
| 16:58 | porpoise | Previously I was directly editing slime's invocation of java |
| 16:59 | Chousuke | swank-clojure-extra-jar-paths or something? |
| 16:59 | Chousuke | it's in the customize group for swank-clojure |
| 17:01 | porpoise | thanks |
| 17:02 | lisppaste8 | hiredman annotated #83651 "wall-hack-method" at http://paste.lisp.org/display/83651#1 |
| 17:02 | technomancy | porpoise: it's actually generally easier if you extract all your dependencies in one place rather than adding jar files to your classpath one-by-one |
| 17:04 | beutdeuce | Chousuke: if i remove parens around println "True", it says if has too many args |
| 17:10 | technomancy | beutdeuce: remove just one pair of parens |
| 17:11 | beutdeuce | technomancy: still says too many args: |
| 17:11 | beutdeuce | (defn elem |
| 17:11 | beutdeuce | [x xs] |
| 17:11 | beutdeuce | (if (= x (first xs) ) |
| 17:11 | beutdeuce | print "True" |
| 17:11 | beutdeuce | (if (= (rest xs) nil) print "False" ((elem x (rest xs)))))) |
| 17:12 | technomancy | beutdeuce: you removed two levels of parens around print "True" |
| 17:13 | technomancy | also you didn't put it inside the if expression like I said |
| 17:13 | beutdeuce | could u please paste the right version, i'm a bit confused right now |
| 17:13 | technomancy | sure, but I think you might want to take a step back and try reading some more existing code before you proceed. |
| 17:15 | technomancy | here's the working version: http://clojure.pastebin.com/m1cbcfc5f |
| 17:17 | beutdeuce | i appreciate your help |
| 17:17 | technomancy | np; I hope you get things figured out |
| 17:17 | beutdeuce | say, is ther infix notation on clojure, like in haskell `` ? |
| 17:17 | Chousuke | no |
| 17:17 | hiredman | ugh |
| 17:17 | beutdeuce | k |
| 17:20 | Chousuke | beutdeuce: lisp has this concept of "forms". a single form evaluates to a single value. a form is either "atomic", or a composite form. '5', '"foo"', 'bar', ':bar' etc. are atomic forms. '(print "2+2=" (+ 2 2))' (a list) '["foo" 5]' (a vector) etc. are composite forms. composite forms. list composite forms are evaluated specially in that the first item in the list composite form |
| 17:20 | Chousuke | is considered an "operator" and the rest are the arguments; so, the list form evaluates to whatever that operator called with the arguments returns. |
| 17:20 | Chousuke | beutdeuce: further, there are macros and special forms which can "bend" the rules a bit. |
| 17:21 | mariorz | what should I use to parse a huge xml file without loading the whole thing to memory? |
| 17:22 | Chouser | mariorz: you can try clojure.contrib.lazy-xml |
| 17:22 | mariorz | Chouser: cool |
| 17:22 | Chouser | but it's pretty easy to accidentally bring in the whole thing |
| 17:23 | Chouser | I'd be interested to know how it works out for you. |
| 17:23 | mariorz | why accidentally? |
| 17:23 | Chousuke | beutdeuce: if is one example of a special form; but if you look at '(if (= 2 2) "yay" (print "nay"))', it is still the if operator, called with three arguments: the condition, the form that is evaluated and returned if the condition is true, and the form that is evaluated and returned when the condition is false. |
| 17:24 | Chouser | mariorz: if you have <doc><t1>...10GB of nested data...</t1><t2>foo</t2></doc> |
| 17:24 | Chouser | mariorz: ...and you ask for doc's second child, the whole thing gets parsed |
| 17:24 | beutdeuce | Chousuke: k |
| 17:25 | mariorz | Chouser: makes sense, ill let you know how it owrks out |
| 17:25 | Chousuke | beutdeuce: in this case, the second argument gets evaluated and returned, yielding the value "yay"; if the condition were instead false, the third argument would get evaluated, having the *side-effect* of printing "nay", in addition to yielding the value nil |
| 17:26 | beutdeuce | ah |
| 17:27 | Chousuke | beutdeuce: as if only takes three arguments, each of the result branches can only contain one form. |
| 17:28 | beutdeuce | makes sense |
| 17:28 | Chousuke | beutdeuce: sometimes, if you need to evaluate more forms (for side-effects), you can wrap them in a do form, which evaluates all its arguments in sequence. |
| 17:28 | beutdeuce | i see, like Haskell |
| 17:28 | beutdeuce | question, if i made a .clj file with my elem function defn'ed in it, is there a clojure function that loads it or imports it? |
| 17:29 | Chousuke | so (if true (do (print "1") (print "2")) (print "not true")) |
| 17:29 | beutdeuce | yeah |
| 17:30 | Chousuke | beutdeuce: usually, you want to declare a namespace at the top of your file |
| 17:30 | Chousuke | beutdeuce: but you can also use (load "foo") (no .clj) to just "include" a file |
| 17:31 | beutdeuce | Chousuke: cool thanks. i g2g for now. Thanks for all the help. and technomancy. |
| 17:47 | hiredman | I am always surprised when I see people who are obviously unfamiliar with clojure doing performance testing |
| 17:48 | hiredman | it seems to imply performance is the first thing people look at |
| 17:48 | hiredman | which is at odds with, well, me |
| 17:48 | Chouser | heh |
| 17:51 | mariorz | Chouser: so if I use parse-trim on the file the content wont be loaded to mem until I actually call it using :content, right? |
| 17:52 | Chouser | that's the idea |
| 17:53 | mariorz | cool |
| 17:56 | mariorz | i dont think its working |
| 17:56 | mariorz | just calling trim-space on the file makes me run out of heap space |
| 17:56 | mariorz | er parse-trim |
| 17:56 | Chouser | :-( |
| 17:57 | Chouser | what are you doing with the result of parse-trim? |
| 17:58 | mariorz | assigning it to a var |
| 17:58 | Chouser | bah. that ought to be safe. |
| 17:58 | mariorz | (def foo (parse-trim "bigfile)) |
| 17:59 | fsodomka | Chouser: logging at http://clojure-log.n01se.net/ doesn't work recently for me |
| 18:00 | Chouser | mariorz: try (parse-seq "bigfile" startparse-sax 1) |
| 18:02 | mariorz | Chouser: cool, i think that works |
| 18:03 | Chouser | mariorz: ok. without that it was going ahead in the background trying to parse the whole thing. |
| 18:03 | Chouser | So I essentially lied to you before. :-P sorry. |
| 18:03 | mariorz | hah np |
| 18:04 | Chouser | fsodomka: bleh. indeed. thanks. |
| 18:05 | Chouser | fsodomka: can't fix it tonight. I'll try to get to it soon. |
| 18:05 | Chouser | I've got the logs, but they're in the wrong format, so once its fixed the intervening days should show up |
| 18:05 | mariorz | Chouser: those this mean i could use parse-trim as well as long as i suply startparse-sax? |
| 18:06 | mariorz | s/those/does/ |
| 18:06 | fsodomka | Chouser: cool, looking forward to it |
| 18:06 | Chouser | no, it's the 1 that matters |
| 18:06 | fsodomka | Chouser: thanks! |
| 18:06 | Chouser | that tells the parsing thread how far ahead of the consumer it's allowed to get |
| 18:07 | mariorz | Chouser: ok, startparse-sax is the default aprser anyway? |
| 18:07 | Chouser | oh, yes -- (parse-trim "bigfile" startparse-sax 1) |
| 18:07 | Chouser | yes, startparse-sax is the default |
| 18:07 | mariorz | cool, thanks for the help! |
| 18:08 | Chouser | the pull-parser is better, but requires another jar: http://www.extreme.indiana.edu/xgws/xsoap/xpp/ |
| 18:09 | Chouser | huh. that's kinda weird. Looks like if you put that xpp jar in your classpath, (parse-trim "bigfile") may just do what you want |
| 18:10 | mariorz | why? |
| 18:11 | mariorz | it automatically sets a queue size? |
| 18:12 | mariorz | ah i see |
| 18:12 | mariorz | If no parser |
| 18:12 | mariorz | is specified and org.xmlpull.v1.XmlPullParser is in the classpath, |
| 18:12 | mariorz | this superior pull parser will be used." |
| 18:15 | westajay | is there a simpler api function for testing if all elements in a collection are true? |
| 18:15 | westajay | other than doing this |
| 18:15 | westajay | (every? (fn[x] x) [true true true]) |
| 18:16 | Chousuke | westajay: there's the "identity" function |
| 18:17 | scgilardi | (every? true? a-collection) (if you mean literally true and not just non-nil and non-false) |
| 18:18 | westajay | scgilardi: that works |
| 18:19 | westajay | thank you sir |
| 18:19 | scgilardi | westajay: you're welcome :) |
| 18:20 | Raynes- | ,(true? (true? (true? true))) |
| 18:20 | clojurebot | true |
| 18:20 | Raynes- | True! |
| 18:21 | scgilardi | Chousuke: you asked earlier about the prohibition on periods in lib names. Rich requested that around the time he integrated the use and require stuff into Clojure. As I recall, the rationale was to keep things as simple as possible. |
| 18:22 | scgilardi | [ the prohibition I'm talking about is that this is not currently accepted: (:use (clojure.contrib sql sql.test)) ] because sql.test contains a period. |
| 18:24 | scgilardi | Before it was simplified, one could use the prefix list concept nested arbitrarily deeply: (:use (clojure (contrib sql (sql test)))) |
| 18:24 | hiredman | clojurebot: CA? |
| 18:24 | clojurebot | CA is Contributor Agreement: http://clojure.org/contributing |
| 18:29 | Raynes- | I wish I had a printer, so I could print that. :( |
| 18:30 | Raynes- | I'd buy one, but hiredman took all my moneys. |
| 18:31 | hiredman | all the money you where going to get paid for NPEs |
| 18:31 | scgilardi | given his recent demise, at least that's one problem you won't have any more |
| 18:31 | scgilardi | hey! |
| 18:42 | Modius | Is clojure's "doall" a function or a macro? |
| 18:43 | hiredman | ,(meta #'doall) |
| 18:43 | clojurebot | {:ns #<Namespace clojure.core>, :name doall, :file "clojure/core.clj", :line 1780, :arglists ([coll] [n coll]), :doc "When lazy sequences are produced via functions that have side\n effects, any effects other than those needed to produce the first\n element in the seq do not occur until the seq is consumed. doall can\n be used to force any effects. Walks through the successive nexts of\n the seq, retains the head and retu |
| 18:43 | Modius | Does that mean it is a function? |
| 18:43 | hiredman | ,(meta #'defn) |
| 18:43 | clojurebot | {:macro true, :ns #<Namespace clojure.core>, :name defn, :file "clojure/core.clj", :line 189, :doc "Same as (def name (fn [params* ] exprs*)) or (def\n name (fn ([params* ] exprs*)+)) with any doc-string or attrs added\n to the var metadata", :arglists ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?])} |
| 18:43 | hiredman | yes |
| 18:44 | hiredman | if it is a macro there iwll be a :macro true |
| 18:46 | scgilardi | ,(doc doc) |
| 18:46 | clojurebot | "([name]); Prints documentation for a var or special form given its name" |
| 18:46 | scgilardi | clojurebot has a custom doc func? |
| 18:47 | hiredman | yes |
| 18:47 | hiredman | well, custom doc macro |
| 18:47 | scgilardi | right. is it to minimize lines of output or to solve some security problem? |
| 18:48 | hiredman | well, the way doc prints out stuff is not irc friendly |
| 18:48 | hiredman | the dashes, the spaces, etc |
| 18:49 | scgilardi | makes sense. clojure.core/doc also prints out "Macro" for macros. |
| 18:49 | hiredman | oh really |
| 18:49 | hiredman | how useful |
| 18:55 | beutdeuce | if i have a fun.clj file with (ns "lib") at the top, can i use (in-ns "lib") from Repl to load it? |
| 18:57 | hiredman | no |
| 18:57 | Raynes- | You could just load the file. |
| 18:57 | hiredman | namespace names are symbols |
| 18:57 | beutdeuce | how? |
| 18:57 | hiredman | not strings |
| 18:57 | hiredman | (ns lib) |
| 18:57 | hiredman | (in-ns lib) |
| 18:58 | hiredman | and in-ns does not load anything |
| 18:58 | hiredman | it jsut switches to another namespace |
| 18:58 | beutdeuce | how would i be able to load an external clj file? |
| 18:58 | hiredman | you can just one of the load functions or require or use |
| 18:58 | Raynes | beutdeuce: (load "path") |
| 18:58 | Raynes | hiredman: I win. |
| 18:59 | beutdeuce | doesnt work |
| 18:59 | beutdeuce | tells my no source file |
| 19:00 | Raynes | beutdeuce: It has to be on your classpath, by the way. |
| 19:00 | Raynes | I think. |
| 19:00 | beutdeuce | is there any alternative way? |
| 19:00 | Raynes | Require or use, but it still has to be on the classpath. |
| 19:01 | Raynes | Once again, I think. I never have to do stuff like this. I use Slime. |
| 19:01 | beutdeuce | hmm. whats that? |
| 19:02 | beutdeuce | works with clojure? |
| 19:03 | Raynes | It's what you specify when you start up the clojure REPL. java -cp <paths that you want on the classpath separated by :'s on *nix and ;'s on windows> -jar clojure.jar |
| 19:03 | Raynes | -cp adds whatever directories you specify to the classpath. |
| 19:03 | Raynes | For example: java -cp /home/rayne/clojure:/home/rayne/clojure2 -jar clojure.jar |
| 19:04 | Raynes | Anything in Clojure and Clojure 2 will be on the classpath. |
| 19:04 | Raynes | I don't know enough about the classpath to really /explain/ it, I just know how to use it. |
| 19:04 | Raynes | If anyone else can explain it better, feel free to step in. :) |
| 19:05 | beutdeuce | thats clear enough |
| 19:05 | beutdeuce | whats slime though? |
| 19:05 | Raynes | It's an Emacs mode for Lisp. |
| 19:05 | Raynes | Most people use it and clojure-mode+clojure-swank for their clojure editing needs. |
| 19:06 | technomancy | beutdeuce: there's an explanation/tutorial at http://technomancy.us/126 |
| 19:06 | Raynes | technomancy: Thank you. I was scared to death he was going to ask something more complex about Slime. :| |
| 19:07 | beutdeuce | :P |
| 19:09 | technomancy | hehe |
| 19:10 | lisppaste8 | mariorz pasted "untitled" at http://paste.lisp.org/display/83661 |
| 19:10 | mariorz | Chouser: still around? |
| 19:10 | beutdeuce | i'm on a mac and i have no idea what i set my inferior-lisp-system to, i dont even know where its located |
| 19:11 | technomancy | beutdeuce: if you read the article I linked to, you shouldn't have to configure that stuff by hand |
| 19:12 | beutdeuce | works with mac? |
| 19:23 | technomancy | beutdeuce: others have reported success |
| 19:23 | technomancy | can't test myself |
| 19:23 | beutdeuce | technomancy: nothing happens when i do M-x package-list-packages |
| 19:26 | technomancy | beutdeuce: you've triggered an obscure elpa bug I've been unable to reproduce. =\ |
| 19:26 | technomancy | try restarting Emacs; if that doesn't help, rm -rf the elpa directory inside your .emacs.d and try again |
| 19:26 | beutdeuce | emacs-starter-kit in currently in ~/.emacs.d/emacs-starter-kit |
| 19:26 | beutdeuce | it should work |
| 19:27 | Knekk | Sorry, I missed the top of the discussion. This is for setting Emacs for Clojure? |
| 19:28 | beutdeuce | Knekk: yeah, trying to get emacs-starter-kit to work |
| 19:28 | Knekk | beutdeuce: where can I download that? |
| 19:28 | beutdeuce | Knekk: http://technomancy.us/126 |
| 19:28 | technomancy | beutdeuce: emacs-starter-kit should actually be just ~/.emacs.d rather than nested inside it |
| 19:29 | beutdeuce | oh |
| 19:30 | beutdeuce | nice, seemed to work now |
| 19:30 | beutdeuce | woa, this is amazign |
| 19:36 | technomancy | yay =) |
| 19:45 | beutdeuce | i'm getting trouble loading slime after emacs restarts |
| 19:48 | technomancy | beutdeuce: does it work after you open a .clj file? |
| 19:48 | beutdeuce | i think i know a fix, instead of adding a call to "(eval-after-load 'clojure-mode '(clojure-slime-config))" to .emacs, i load it to init.el |
| 19:51 | beutdeuce | argh, didnt work |
| 19:51 | beutdeuce | its as if it doesnt recall slime after i restart emacs |
| 19:52 | technomancy | init.el is the equivalent of .emacs |
| 19:52 | beutdeuce | i put it there, but then it gave me an error |
| 19:53 | beutdeuce | when i take that line out, it works again, just not slime |
| 19:53 | technomancy | can you paste the error? |
| 19:54 | beutdeuce | it flashes quickly then emacs loads to default gnu screen |
| 19:55 | technomancy | right; if you switch to the *Messages* buffer you can see the error |
| 19:56 | beutdeuce | does it matter where i put: (eval-after-load 'clojure-mode '(clojure-slime-config)) ? |
| 19:56 | technomancy | if you're using the starter kit, put it in a file in .emacs.d named after your username + .el |
| 19:56 | technomancy | that way you won't get merge conflicts if you update to a newer version of the starter kit |
| 19:57 | beutdeuce | well, no error, but M-x slime doesnt work |
| 19:57 | beutdeuce | oh eait |
| 19:57 | beutdeuce | wrong dir |
| 19:57 | beutdeuce | h/o |
| 19:58 | beutdeuce | yeah |
| 19:58 | beutdeuce | still no slime |
| 19:58 | beutdeuce | do i have to load username.el manually? |
| 19:58 | beutdeuce | its in my .emacs.d/currently |
| 19:59 | technomancy | no, that happens for you |
| 20:00 | technomancy | try M-x slime after you've opened a .clj file |
| 20:00 | beutdeuce | (eval-after-load 'clojure-mode '(clojure-slime-config)) is whats in there, should i try to run that in emacs itself? |
| 20:00 | technomancy | no, you don't need to load it manually |
| 20:01 | beutdeuce | technomancy: yeah, it only works when i load a .clj file, is there a way to get it work without loading a clj file? |
| 20:02 | technomancy | beutdeuce: try just putting in (clojure-slime-config) instead of (eval-after-load [...]) |
| 20:02 | beutdeuce | makes sense, i'll try |
| 20:02 | technomancy | recent versions do this, but my packages haven't been uploaded to elpa yet. =\ |
| 20:04 | beutdeuce | yep now works, thanks for all your help! |
| 20:05 | technomancy | no problem |
| 20:12 | spaceman_stu | Hi guys - I'm trying to write a build.xml file and am getting an error saying the SAXParserFactoryImpl can't be found on the line I call an xml function from contrib. I've got the contrib jar included - any tips to getting it working? |
| 20:22 | gstamp | spaceman_stu: maybe you need to include the xerces library? |
| 20:25 | spaceman_stu | gstamp: That may well be it, but I don't understand why I wouldn't have had to deal with that before - it runs fine from slime. I'm guessing somethign with the classpath isn't right |
| 20:28 | hiredman | man, almost everything is a reader macro |
| 20:37 | skalnik | Anyone know of a good resource for Ruby programmers looking to play with Clojure? |
| 20:40 | ataggart | ,(if (Boolean. "false") :weird :ok) |
| 20:40 | clojurebot | :weird |
| 20:42 | Anniepoo | skalnik, I'm learning from Stuart Halloway, Programming Clojure, it's pretty good |
| 20:42 | skalnik | I'll look into it, thanks. |
| 20:42 | skalnik | Ah, pragprog. Must be good :) |
| 20:42 | Chousuke | ataggart: I think you're supposed to use Boolean/valueOf :) |
| 20:43 | ataggart | it's good, though it helps to know a bit of java |
| 20:43 | Anniepoo | it shares the usual pragmatic problem of being more boosterish than actually informative |
| 20:43 | ataggart | chousuke: I know, just testing it out as osmeone brought it up on reddit |
| 20:43 | Raynes | Anniepoo: It's pretty informative regardless. |
| 20:43 | Chousuke | Making your own Boolean instances is weird anyway :P |
| 20:44 | Anniepoo | yes, agree |
| 20:44 | Chousuke | I wonder why it's even supported |
| 20:44 | Raynes | It's more of a "pump you up and get you going tutorial!" than a endless pit of knowledge. |
| 20:44 | Raynes | But Clojure is a Lisp. There just really isn't all that much to talk about. The proof is in the kodak. |
| 20:45 | mariorz | does map make use of seperate threads? |
| 20:46 | Chousuke | no |
| 20:46 | Chousuke | there's pmap for parallel mapping. |
| 20:46 | mariorz | im having a weird error where calling map returns a transaction not in thread error |
| 20:47 | Chouser | map is lazy |
| 20:47 | mariorz | mapping a function to a persitnat list |
| 20:47 | mariorz | no, it is but im trying out with a normal list |
| 20:47 | Chouser | but what map returns is lazy regardless |
| 20:48 | Chouser | if map is called inside a dosync, but what it returns gets passed to outside the dosync, you're likely to have problems |
| 20:49 | Anniepoo | sorry Raynes, I got distracted by RL, yes, I'd agree with you. |
| 20:49 | Anniepoo | my complaint is only that at times I feel like, in common with all the PP series, it sacrifices |
| 20:50 | Anniepoo | clarity in elucidating some boring but vital part of the language for an 'ooh wow, isn't that cool' demo |
| 20:51 | Anniepoo | but that aside, it's a pretty clear intro to the language, esp. if you're not coming from another functional language |
| 20:54 | Raynes | I've never read a pragprog book. |
| 20:54 | Raynes | I generally stick to O'Riley books. |
| 20:54 | Anniepoo | I've read many, they all have this same problem. |
| 20:55 | Anniepoo | O'Riley used to be God, they seem to have let a lot of fluff in at some point |
| 20:56 | mariorz | Chouser: http://paste.lisp.org/display/83670 |
| 20:56 | mariorz | thats what i mean |
| 20:56 | Raynes | Real World Haskell is a good, comprehensive book. But it's amazing the amount of stuff they managed to screw up in it. |
| 20:56 | arohner_ | Raynes: what did they screw up in RWH? |
| 20:57 | arohner_ | I have the book, but I"m not a haskell expert and I didn't read it carefully |
| 20:57 | Raynes | arohner_: Various stuff, they contradicted themselves in some chapters, plenty of typos, they introduce things at the wrong time, some of the examples apparently don't even work correctly, and the coding style changes depending on whoever is writing the current chapter. |
| 20:58 | Raynes | But it still manages to be a very good read. |
| 20:58 | arohner_ | I got it mainly to read about what was different in haskell rather than a serious attempt to learn it |
| 20:59 | Raynes | arohner_: You could have just read it online, if that was the case. |
| 20:59 | Chouser | mariorz: yeah, try wrapping your (map ...) in a (doall ...) |
| 21:00 | mariorz | Chouser: coolness, i get it now |
| 21:00 | mariorz | i.e. what you meant with map returns lazy |
| 21:01 | Anniepoo | I've found one error in Halloway, and it's a trivial one |
| 21:02 | Anniepoo | You know, I'm also having to deal with building a big C# library today, and the difference is truly breathtaking |
| 21:02 | hiredman | Chouser: do you know of a no-op reader macro off hand? |
| 21:03 | Chouser | #_ |
| 21:03 | Chouser | or what do you mean by no-op? |
| 21:03 | Chouser | mariorz: right |
| 21:03 | hiredman | Chouser: dunno |
| 21:03 | hiredman | //no op macros return the reader |
| 21:04 | Chouser | ,[1 2 3 #_ 4 5 6] |
| 21:04 | clojurebot | [1 2 3 5 6] |
| 21:04 | hiredman | from LispReader |
| 21:05 | Chouser | hm -- a reader macro can use thre reader obj as a sentinel, looks like. |
| 21:06 | hiredman | hiredman.reader=> (eval (my-read)) |
| 21:06 | hiredman | (+ 1 2) |
| 21:06 | hiredman | 3 |
| 21:06 | clojurebot | 3 |
| 21:06 | Chouser | ah, a comment |
| 21:06 | Chouser | ; is a reader macro |
| 21:06 | hiredman | Chouser: I see |
| 21:07 | Chouser | CommentReader.invoke() walks to the end of the line, then returns the reader as a sentinel that no form has actually been produced yet |
| 21:08 | Chouser | looks like #_ may be the only other one. It reads the following form and likewise indicates nothing has been read yet |
| 21:08 | Chouser | ,(read-string "; foo") |
| 21:08 | clojurebot | java.lang.RuntimeException: java.lang.Exception: EOF while reading |
| 21:08 | Chouser | ,(read-string "; foo\n5") |
| 21:08 | clojurebot | 5 |
| 21:09 | mariorz | :( |
| 21:09 | mariorz | im still running out of heap space |
| 21:10 | Chouser | you can make your heap bigger when you launch java |
| 21:10 | mariorz | but it should not be loading the whole file to mem this way, right? |
| 21:11 | Chouser | you're walking all the way to the end of the xml file? |
| 21:11 | Chouser | or do you stop early? |
| 21:11 | mariorz | all the way |
| 21:11 | mariorz | http://paste.lisp.org/display/83670#1 |
| 21:11 | Chouser | hm... that may be the problem... |
| 21:12 | mariorz | how so? |
| 21:12 | Chouser | as in, the whole file is not loaded at the beginning, but it's probably all cached |
| 21:12 | Chouser | so if you don't bail early, it may all end up in memory after all... |
| 21:13 | mariorz | what do you mean bail early? |
| 21:13 | mariorz | like jsut parse the first x elements ? |
| 21:14 | Chouser | Right. The normal clojure.xml/parse parses the whole file before it even returns. |
| 21:15 | Chouser | but lazy-xml will parse only as much as you demand -- however if you demand all of it, it may all end up in memory after all |
| 21:15 | Chouser | hang on, gotta put a kid to bed. back in a few. |
| 21:15 | mariorz | k |
| 21:20 | mariorz | shouldnt the cache have a max size so this doesnt happen though? |
| 21:25 | Raynes | How cute. Chouser has minicoders. |
| 21:30 | mariorz | memory usage for the java process never seems to go up though |
| 21:30 | mariorz | just cpu |
| 21:30 | arohner_ | right, java has a limit on how much ram it will take |
| 21:30 | Chouser | mariorz: it's the regular lazy seq caching -- each cell caches it's own value, there's no global view. |
| 21:31 | mariorz | but that low? |
| 21:31 | mariorz | around 90mb |
| 21:31 | Chouser | the solution is to make sure that you release earlier head(s) of the seq(s) as you walk through. |
| 21:32 | mariorz | the seq returned by the map right? |
| 21:32 | mariorz | Chouser: how do i do that? |
| 21:32 | Chouser | but if you're walking through (:content node), the node map is hanging onto the head so it must all end up in memory |
| 21:32 | Raynes | Chouser: How many minicoders do you have? |
| 21:32 | Chouser | none coding yet. :-) |
| 21:33 | Raynes | :) |
| 21:34 | mariorz | so the seq to which i apply the doall is lazy, but as the doall evaluates each cell in the seq its value gets cached which is what eats up the heap, is that whats happening? |
| 21:34 | Chouser | yes |
| 21:35 | Chouser | and if it's not allowed to do any processing after you leave the with-tx block, then you have a bit of a problem. |
| 21:35 | Chouser | oh! |
| 21:35 | Chouser | are you throwing away the return value of the map? |
| 21:35 | mariorz | so what would be a way around that? :) |
| 21:35 | Chouser | save_node is about side-effects? |
| 21:36 | mariorz | well it stores the node value in a db |
| 21:36 | Chouser | right -- you don't care about the return value of save_node, right? |
| 21:36 | mariorz | nope |
| 21:37 | Chouser | ok, then you should use (dorun (map ...)) or better yet (doseq ...) inside your with-tx |
| 21:37 | Chouser | well, I should warn you that I'm not sure it's possible to get what you want without restructuring lazy-xml itself |
| 21:38 | Chouser | but it might be. And even if lazy-xml is doing the right thing, using (doall (map ...)) would thwart it. |
| 21:39 | mariorz | from the api docs it would seem doseq is what i want no? |
| 21:39 | Chouser | yes |
| 21:41 | mariorz | same error |
| 21:41 | Chouser | yes. |
| 21:42 | mariorz | but why? |
| 21:43 | Chouser | now, the next thing is that bigfile is a map which contains (nested in a ways) the head of the seq you're walking through |
| 21:44 | Chouser | after your doseq is done (if it didn't run out of heap), you can still go get the first item in seq. The fact that you can means it's been stored in exactly the way that you can't allow |
| 21:46 | mariorz | didnt really understand that |
| 21:47 | Chouser | ok, let's look at a simpler example |
| 21:47 | Chouser | (let [x (map #(str "A number: " %) (range 1e7))] (last x)) |
| 21:47 | Chouser | x is a very long lazy seq of strings. |
| 21:47 | Chouser | I say "is" but more accurate would of course be to say "promises to be" |
| 21:48 | mariorz | right |
| 21:48 | mariorz | becuae its lazy |
| 21:48 | Chouser | Right. Now, (last x) has to walk to the end of the seq and return the final item. |
| 21:48 | Chouser | as shown above, this will happen fairly quickly and return the result. |
| 21:48 | Chouser | ,(let [x (map #(str "A number: " %) (range 1e7))] (last x)) |
| 21:48 | clojurebot | Execution Timed Out |
| 21:48 | Chouser | hm, not so quickly. |
| 21:51 | Chouser | well, anyway, it should work in your repl, returning a string after a few seconds |
| 21:51 | mariorz | right |
| 21:51 | Chouser | it doesn't consume memory because nothing is able to get to the first element of x, so the JVM reclaims the memory used to cache those values |
| 21:51 | gko | Hello... How to check if an element is in a list? |
| 21:52 | Chouser | gko: perhaps a set would work better? |
| 21:52 | Chouser | mariorz: but one small change breaks it: |
| 21:53 | gko | Oh: ((set my-list) 1) |
| 21:53 | hiredman | grrr |
| 21:53 | Chouser | gko: sure, but that walks through the whole list to build that set before looking it up. Can you not use a set through your code instead of that list? |
| 21:54 | Chouser | (let [x (map #(str "A number: " %) (range 1e7))] [(first x) (last x)]) |
| 21:55 | gko | Chouser: it was just a general question... I have already been using sets because of this... |
| 21:55 | Chouser | mariorz: in this case, the head of the seq is retained (so that the literal [] vector can do what it needs to), so the JVM does not release memory, and it tries to hold the entire seq in memory |
| 21:56 | Chouser | gko: ah. |
| 21:56 | Chouser | ,(.contains '(a b c) 'b) |
| 21:56 | clojurebot | true |
| 21:57 | gko | (set 1 2 3) |
| 21:57 | mariorz | Chouser: ok, and this happens within lazy-xml becuase it maintains a pointer to the head of the document? |
| 21:57 | Chouser | mariorz: right. bigfile points to the whole document |
| 21:58 | ataggart | ~some |
| 21:58 | clojurebot | Hello, gnuvince |
| 21:58 | ataggart | (doc some) |
| 21:58 | clojurebot | "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll)" |
| 21:58 | Chouser | mariorz: I'm looking at lazy-xml's code to see if i can spot any head-retaining there, but I'm not sure... |
| 21:58 | Chouser | mariorz: so anyway, the next thing that is necessary (but perhaps not yet sufficient) is to not store bigfile globally. |
| 21:59 | ataggart | gko: use some |
| 21:59 | gko | ataggart: ? |
| 21:59 | ataggart | (doc some) |
| 21:59 | clojurebot | "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll)" |
| 21:59 | mariorz | Chouser: just something like (with-tx (doall (map save_node (:content (parse-trim "file.xml" startparse-sax 1))))) |
| 22:00 | mariorz | ? |
| 22:00 | mariorz | Chouser: using xpp would not help with this right? |
| 22:01 | Chouser | mariorz: try (with-tx (let [bigfile ...] (doseq [node (:content bigfile)] (save_node node)) ... |
| 22:01 | Chouser | mariorz: or what you had (but with dorun instead of doall) |
| 22:02 | Chouser | mariorz: this step is necessary anyway. it's possible yet that lazy-xml itself is hanging onto something, in which case the xpp code path may be better (or worse) ... not sure yet. |
| 22:02 | mariorz | doseq or dorun? |
| 22:02 | Chouser | I prefer doseq. It's your choice. |
| 22:02 | Chouser | both return nil which is the critical thing |
| 22:02 | mariorz | k |
| 22:03 | mariorz | thx again for the help, going for a bite and will mess aorund some more later |
| 22:03 | gko | ataggart: Oh OK... any reason why lists are not functions like maps or sets? |
| 22:04 | ataggart | in what sense? |
| 22:04 | Chouser | mariorz: ok |
| 22:04 | gko | (my-map key) => value |
| 22:04 | ataggart | gko: ah because sets and maps have O(1) access on their keys |
| 22:04 | ataggart | so they can act as functions |
| 22:05 | ataggart | contains? only works on keys, which lists dont have |
| 22:05 | gko | ataggart: right... |
| 22:05 | ataggart | (contains? [:a :b :c] 2) |
| 22:05 | ataggart | ,(contains? [:a :b :c] 2) |
| 22:05 | clojurebot | true |
| 22:06 | ataggart | if you want to spin through a list, you can do it with some |
| 22:06 | Chouser | ,(some #{'c} '(a b c)) |
| 22:06 | clojurebot | c |
| 22:07 | gko | why , in front of your samples? |
| 22:07 | ataggart | it tells clojurebot to execute it |
| 22:07 | ataggart | though it sometimes excutes code anyway |
| 22:08 | ataggart | it's feisty |
| 22:08 | gko | ,1 |
| 22:08 | clojurebot | 1 |
| 22:08 | gko | :) |
| 22:08 | gko | couldn't clojurebot puts the evaluated expression? |
| 22:09 | gko | that's nice |
| 22:11 | ataggart | ~botsnack |
| 22:11 | clojurebot | thanks; that was delicious. (nom nom nom) |
| 22:25 | hiredman | do clojure's tests include reader tests? |
| 22:30 | arohner_ | hiredman: some |
| 22:30 | arohner_ | there's a clojure.test-clojure.reader ns |
| 22:31 | arohner_ | it's hardly comprehensive |
| 22:31 | hiredman | well |
| 22:32 | hiredman | my wrapper around LispReader passes that, so it's time to start replacing bits and pieces |
| 22:32 | arohner_ | what are you working on? |
| 22:33 | hiredman | replacing Lispreader.java with clojure code |
| 22:34 | arohner_ | cool |
| 22:34 | hiredman | http://github.com/hiredman/reader/blob/afb9e6266358fc965c9572a1cafc57dc15908e42/hiredman/reader.clj |
| 22:50 | arohner_ | sigh. Why does java provide SimpleDateFormat, and then not provide constants for really common date formats, like RFC 822 and ISO8601? |
| 23:23 | durka421 | why doesn't clojure support java variadic methods (like PrintWriter/printf) without to-array? |
| 23:35 | arohner_ | durka42: java variadic methods are sugar for "normal" functions that take arrays |
| 23:35 | durka42 | i suppose there's no way for clojure to detect them without reflection |
| 23:35 | durka42 | or maybe even with the use of reflection |
| 23:36 | durka42 | i know they take arrays, hence my (slight) annoyance at having to play with to-array |
| 23:45 | durka42 | i had caps lock and couldn't figure out what the _hell_ vim was doing |
| 23:45 | slaney | heh |
| 23:45 | slaney | I have done that |
| 23:46 | slaney | more than once |
| 23:46 | slaney | adl |
| 23:46 | slaney | sadly |