2010-01-20
| 00:09 | replaca | new rule proposal: projects written in Clojure may not have the letter "j" in their names |
| 00:10 | technomancy | replaca: yes please! |
| 00:11 | technomancy | that cocoa bridge had a name that just made me cringe |
| 00:12 | defn` | i like the ji thing |
| 00:12 | defn` | like djirk |
| 00:15 | technomancy | personally I'm naming all my projects after literary characters from now on |
| 00:17 | alexyk | technomancy: how about I sing praises for leiningen every day for 5 days if you add host to lein swank in addition to port tmrw? :) |
| 00:17 | replaca | I think I'll go for the dullest possible names |
| 00:18 | replaca | starting with "autodoc" |
| 00:18 | technomancy | alexyk: you could spend the time you would potentially spend singing praises to write the code. =) |
| 00:18 | replaca | which would be pretty cool if it took out your appendix, but less so with the whole html generation thing |
| 00:18 | alexyk | technomancy: I don't know where to begin, macros scare me |
| 00:19 | alexyk | plus I don't know swank and where the host would need to be stuck/plucked from |
| 00:19 | alexyk | I'd rather stick to my core competency of singing and let you add it :) |
| 00:19 | technomancy | heh |
| 00:19 | defn` | my core competency is witchcraft |
| 00:20 | technomancy | alexyk: the swank server binds to more than just localhost for me |
| 00:20 | alexyk | defn: don't you have to be a witch to practice it? |
| 00:20 | technomancy | did you want to limit it to *just* localhost? |
| 00:20 | alexyk | technomancy: no, I don't see it binding to the external IP. Hmm. |
| 00:20 | alexyk | I actually wanted to have a host to explicitly tell it to bind there. |
| 00:20 | defn` | alexyk: i havent gotten that far yet |
| 00:21 | alexyk | defn: I never heard of male witches either |
| 00:21 | technomancy | alexyk: binding to 0.0.0.0 should work for all active interfaces |
| 00:21 | replaca | technomancy: is the sonian crew going to brave the tsunami and come to functional alcoholics tomorrow? |
| 00:22 | alexyk | technomancy: does it try to bind to 0.0.0.0 by default? |
| 00:22 | technomancy | replaca: that's the plan |
| 00:22 | technomancy | alexyk: seems to here |
| 00:22 | alexyk | hmm |
| 00:22 | replaca | technomancy: cool. looking forward to it. |
| 00:23 | replaca | it'll be fantastic not to be the only clojure guy there |
| 00:23 | technomancy | replaca: we should outnumber the scala guys this time. =) |
| 00:23 | technomancy | replaca: how many attend total normally? |
| 00:23 | replaca | technomancy: especially since we seem to be converting al3x |
| 00:23 | replaca | 30-40 |
| 00:23 | technomancy | wow! |
| 00:23 | technomancy | seafunc is 5-6 |
| 00:23 | alexyk | say I'm carrying around a tortured Java object. To mimic FP, I have defns like, (defn doGraph [graph] ... graph). Will it copy the graph, or, it being a Java object, pass references around? |
| 00:23 | replaca | we take our tech seriously by the bay :-) |
| 00:24 | replaca | does seafunc involve beer? |
| 00:24 | alexyk | replaca: it used to |
| 00:24 | technomancy | it varies. I'm sure that affects things. |
| 00:24 | replaca | that seems to be what brings them out |
| 00:24 | technomancy | also it only happens 4 or 5 times a year, which is lame |
| 00:25 | technomancy | alexyk: you've been? |
| 00:25 | alexyk | technomancy: yep |
| 00:25 | replaca | there used to be bayfp, too, which was more serious. But I don't think they've had one in a while |
| 00:25 | technomancy | alexyk: you in the area? |
| 00:25 | alexyk | a series of bearded and unbearded folks, the great FP ones, in University City or Capitol Hill... a couple years ago, alas. |
| 00:26 | wooby | anyone ever run across clojure jobs in the bay area? |
| 00:26 | technomancy | I'm thinking about having a Seattle Clojure meeting next month |
| 00:26 | technomancy | got 5 already interested |
| 00:26 | alexyk | I visit when giving a talk at MSFT once in a while |
| 00:27 | alexyk | or visiting my friends in the area |
| 00:27 | alexyk | technomancy: amazing, for clojure |
| 00:27 | alexyk | so what about accepting and returning a Java object in a defn, does it copy or hopefully not? |
| 00:28 | technomancy | it won't copy unless you explicitly do it |
| 00:28 | alexyk | good |
| 00:28 | replaca | technomancy: I think I may have had the honor of hosting the biggest pure clojure meetup ever |
| 00:28 | replaca | (to date that is) |
| 00:29 | replaca | when Rich came to SF and we had the bay area group meeting |
| 00:30 | technomancy | replaca: yeah, I made it for that one |
| 00:30 | technomancy | very exciting |
| 00:31 | joegg | technomancy: what you mean "explicity do it", regarding the copy? |
| 00:32 | joegg | As in (.clone foo)? Or am I missing something? |
| 00:32 | technomancy | joegg: that's what I meant, yeah |
| 00:32 | technomancy | there's no auto-immutablize |
| 00:32 | replaca | technomancy: I remember - a good crowd, but too much for the space |
| 00:32 | technomancy | standing room only |
| 00:32 | joegg | technomancy: Thanks, just wanted to make sure I hadn't missed something big. |
| 00:34 | alexyk | I'm running clojure under rlwrap and suddenly see rlwrap at 100% CPU all the time, and Java at 50-150% (8 cores). Is there a reason why rlwrap would hog CPU? |
| 00:40 | TheBusby | is there an easy way to rebind *in* to a file for testing in slime? |
| 01:42 | rikthevik_ | i want to write a pipeline function . it takes functions a, b, c and an initial value then calculated (c (b (a initial))) |
| 01:42 | rikthevik_ | thoughts? |
| 01:42 | rikthevik_ | i did it lisp-style using pop and peek, but it's not working great when the list of functions is a seq |
| 01:46 | TheBusby | rikthevik I think there is already something similiar, like ->> |
| 01:46 | TheBusby | or --> |
| 01:46 | TheBusby | one of the arrows I believe |
| 01:47 | TheBusby | good luck googling for it though... |
| 01:50 | TheBusby | ,(doc ->>) |
| 01:50 | clojurebot | "([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc." |
| 02:20 | konr` | What's the best way to represent a file? Is it a good idea to stick with Java's IO classes, or it's fine to create some convention for my function, like a PATH starting with @ denotes a file? |
| 02:25 | technomancy | konr`: I generally represent it as a string until I need to call file-related functions/methods on it |
| 02:26 | technomancy | konr`: c.c.java-utils/file is great for that; it will turn its argument into a file whether it's a string or already a file object |
| 03:19 | quizme | if you make something a ref, does that mean it's going to use another thread when possible? |
| 03:21 | technomancy | quizme: refs just have values; they don't represent computation |
| 03:21 | technomancy | maybe you're thinking of agents? |
| 03:21 | quizme | conversely, if you don't use a ref, atom, etc., does that mean it's NOT going to use another thread? |
| 03:21 | quizme | um |
| 03:21 | quizme | i dunno |
| 03:21 | quizme | just general confusion i think |
| 03:22 | quizme | i guess i'm wondering: what is it about clojure that makes it inherently more multi-CPU friendly? |
| 03:23 | defn` | it's functional |
| 03:23 | defn` | no side effects |
| 03:23 | quizme | and: are there any language constructs that let you control the threads.... (ok agents is one) |
| 03:23 | quizme | functional => all CPUs will be used? |
| 03:23 | defn` | agents, refs, atoms |
| 03:24 | defn` | quizme: no. http://en.wikipedia.org/wiki/Functional_programming |
| 03:24 | quizme | what does function programming have to do with multi-CPU friendliness? |
| 03:24 | defn` | functional as in, functions are first class |
| 03:24 | quizme | functional* |
| 03:25 | defn` | quizme: watch http://www.vimeo.com/8426709 |
| 03:25 | quizme | i'm just trying to make the connection between the language and being able to use all the CPUs |
| 03:25 | defn` | quizme: you're not going to do it by making wild guesses |
| 03:26 | defn` | it's false in the first place to say "use all the CPUs" |
| 03:26 | defn` | because A.. we're talking about cores, and B.. you can use all of the CPUs in any old language |
| 03:27 | defn` | cores |
| 03:27 | quizme | ok cores |
| 03:29 | defn` | quizme: what other languages have you worked with? |
| 03:30 | quizme | scheme, c, c++, java, ruby, php, as3, javascript |
| 03:30 | defn` | and you don't understand how functional programming solves many of the problems of concurrency? |
| 03:31 | quizme | no |
| 03:31 | defn` | have you written applications with locks in c? |
| 03:31 | quizme | no |
| 03:31 | quizme | no to both questions |
| 03:32 | defn` | what does functional programming mean to you? |
| 03:33 | quizme | function behavior only depends upon the arguments |
| 03:33 | defn` | which means...no side effects |
| 03:34 | quizme | yah |
| 03:34 | defn` | which makes concurrency easier |
| 03:34 | quizme | so what does that have to do with cores ? |
| 03:34 | defn` | in a non-functional style you have to be worried about what other objects any given function/method is touching |
| 03:36 | quizme | ok |
| 03:37 | defn` | quizme: do you see how that makes scaling cores easier? |
| 03:38 | quizme | if two cores are processing the same data at the same time, you know that the action of one function won't affect the behavior of another function? |
| 03:40 | defn` | let's call them threads |
| 03:41 | quizme | so |
| 03:41 | defn` | quizme: the software transactional memory is important here |
| 03:41 | quizme | if you want to increment x |
| 03:42 | quizme | like in Lau's vimeo link you gave me |
| 03:42 | defn` | mmhm |
| 03:42 | quizme | actually |
| 03:42 | quizme | it's better to use a lazy sequence instead of atoms and all that ? |
| 03:42 | defn` | they're for different things |
| 03:42 | quizme | cuz a lazy sequence is immutable |
| 03:42 | defn` | ,(doc atom) |
| 03:42 | clojurebot | "([x] [x & options]); Creates and returns an Atom with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the atom. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return |
| 03:42 | quizme | yes? no? |
| 03:43 | defn` | you need to read more before you will have a clear picture |
| 03:43 | defn` | atoms and lazy seqs aren't even close to related for the purposes of this discussion |
| 03:47 | quizme | let's say you didn't have any mutable data |
| 03:48 | quizme | how do you know if you program is going to use multiple cores or not? |
| 03:48 | quizme | just because your program is functional and processing immutable doesn't mean it's parallelizable. |
| 03:49 | quizme | immutable data i mean |
| 05:32 | lpetit | clojurebot: seen cgrand |
| 05:32 | clojurebot | cgrand was last seen quiting IRC, 274 minutes ago |
| 05:35 | esj | clojurebot you stalker |
| 05:39 | pao | clojurebot: (take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1))) |
| 05:39 | pao | hmmm |
| 05:39 | pao | why does this doesn't terminate? |
| 05:43 | pao | clojurebot: (first (filter zero? (concat (take 10 (repeat 1) [0] (repeat 1)))) |
| 05:43 | esj | i think because of the filter |
| 05:43 | pao | esj: missing parens |
| 05:44 | pao | clojurebot: (first (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1)))) |
| 05:44 | esj | it never gets a non-zero value |
| 05:44 | pao | esj: there a zero value |
| 05:44 | pao | *there is |
| 05:44 | pao | (first (filter zero? (concat (take 1000 (repeat 1)) [0] (repeat 1)))) |
| 05:44 | esj | after an infinite number of 1s, no ? |
| 05:44 | pao | clojurebot: (first (filter zero? (concat (take 1000 (repeat 1)) [0] (repeat 1)))) |
| 05:45 | pao | esj: no, after 10 1s |
| 05:45 | esj | hmm.... |
| 05:45 | pao | 1000 in this case |
| 05:45 | pao | esj: to you know how to query clojure version? |
| 05:45 | pao | it was a parenthesis problem, now on my machine it runs |
| 05:46 | esj | when the REPL starts it says |
| 05:46 | pao | esj: I was wondering about clojurebot's clojure version |
| 05:46 | esj | dunno :) |
| 05:46 | pao | esj: no prob :-) |
| 05:47 | pao | clojurebot: (take 10 (repeat 1)) |
| 05:47 | pao | clojurebot: > (+ 1 1) |
| 05:47 | pao | clojurebot: help |
| 05:47 | clojurebot | http://www.khanacademy.org/ |
| 05:48 | unfo- | not the khan i was expecting |
| 05:48 | pao | > (+ 1 1) |
| 05:48 | esj | you expecting designs for a nuke ? |
| 05:48 | unfo- | nope |
| 05:48 | pao | (+ 1 1) |
| 05:48 | clojurebot | 2 |
| 05:49 | pao | (take 10 (repeat 1)) |
| 05:49 | esj | hahahah, missing parens ! |
| 05:49 | pao | I guess it doesn't print seq... |
| 05:49 | pao | (first (take 10 (repeat 1))) |
| 05:49 | unfo- | esj, http://www.khaaan.com/ |
| 05:49 | esj | (take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1)))) |
| 05:49 | esj | ,(take 1 (filter zero? (concat (take 10 (repeat 1)) [0] (repeat 1)))) |
| 05:49 | clojurebot | (0) |
| 05:50 | pao | esj: what's the comma for? |
| 05:50 | esj | to ask clojurebot to execute the command :) |
| 05:50 | pao | esj: ah ok :-) |
| 05:50 | esj | np |
| 05:50 | pao | ,(take 10 (repeat 1)) |
| 05:50 | clojurebot | (1 1 1 1 1 1 1 1 1 1) |
| 05:50 | pao | nice :-) |
| 05:51 | esj | clojurebot is very friendly, for a stalker. |
| 05:51 | pao | esj: LOL |
| 06:03 | talios | Morning |
| 06:04 | AWizzArd | Hi tal |
| 06:05 | talios | mm been ages since I've fired up linkinus and lurked on IRC |
| 06:07 | Chousuke | ,*clojure-version* |
| 06:07 | clojurebot | {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "master"} |
| 06:07 | Chousuke | hmmh. |
| 06:25 | esj | now I know, thanks. |
| 06:47 | vu3rdd | given a sequence, is there a way to extract the elements from the first to last-but-one and the last? |
| 06:47 | vu3rdd | that is, first/rest but on a reversed list? |
| 06:47 | vu3rdd | (doc reverse) |
| 06:47 | clojurebot | "([coll]); Returns a seq of the items in coll in reverse order. Not lazy." |
| 06:48 | cypher23 | (doc butlast) |
| 06:49 | clojurebot | "([coll]); Return a seq of all but the last item in coll, in linear time" |
| 06:49 | cypher23 | (doc last) |
| 06:49 | clojurebot | "([coll]); Return the last item in coll, in linear time" |
| 06:49 | cypher23 | vu3rdd, ^ |
| 06:49 | vu3rdd | cypher23: thakns |
| 06:49 | vu3rdd | thanks |
| 07:26 | dabd | I don't see much use for the predicate empty? since (not (empty? is discouraged as it involves a double negation. So why not remove it and simply use (not (seq and (seq insted? |
| 07:33 | LauJensen | dabd, empty? for testing true/false, seq and not-empty for nil/coll |
| 07:56 | dabd | what is the alternative for the #^ reader macro? |
| 09:20 | kiuma | hello |
| 09:20 | kiuma | is there a library to print html code ? |
| 09:20 | chouser | kiuma: hi! |
| 09:20 | chouser | (println "<html></html>") ;-) |
| 09:20 | LauJensen | kiuma: Compojure is a good bet |
| 09:20 | kiuma | :/ |
| 09:21 | LauJensen | (html [:h1 "Hello Html"]) |
| 09:21 | chouser | kiuma: I guess it depends on what you're starting with. |
| 09:22 | chouser | If you have designer-created html that you want to adjust, I'd recommend enlive |
| 09:22 | kiuma | chouser, I created CLAW that is in common lisp |
| 09:23 | kiuma | a claw html renderer is similar to cl-html |
| 09:24 | kiuma | it transforms something like (div> (span> "foo")) to <div><span>foo</span></div> |
| 09:24 | kiuma | does already exist something similar in clojure ? |
| 09:25 | chouser | kiuma: ah. yeah, compojure has a lib for doing things roughly like that. something roughly like that has be written several times in clojure |
| 09:25 | cemerick | ouch |
| 09:25 | cemerick | kiuma: give enlive a try http://wiki.github.com/cgrand/enlive/ |
| 09:25 | kiuma | ok htx |
| 09:25 | chouser | usually the clojure ones use keywords and vectors, so something like [:div [:span "foo"]] |
| 09:28 | kiuma | chouser, so I only should implement a parser, right ? |
| 09:29 | cemerick | kiuma: are you aiming to create another templating library? |
| 09:29 | chouser | kiuma: an html parser? there are good ones available already. |
| 09:30 | kiuma | Id like something that is the most similar to html |
| 09:30 | dabd` | if the ^ read macro is deprecated in 1.1 what will substitute #^ ? |
| 09:30 | chouser | dabd`: eventually, yes. |
| 09:30 | cemerick | dabd`: I think with-meta will be required |
| 09:31 | chouser | oh, sorry, misunderstood. #^ has not been deprecated |
| 09:31 | cemerick | oh, I thought it was :-/ |
| 09:31 | cemerick | kiuma: it's worth using existing libs unless there's something compelling to build separately. |
| 09:31 | cemerick | some compelling reason, I mean |
| 09:32 | cgrand | kiuma: enlive is so similar to html that it's html ;-) |
| 09:32 | chouser | there's nothing else that will work in place of #^, though I guess ^ will eventually |
| 09:32 | dabd` | so only ^ will be deprecated |
| 09:32 | cemerick | cgrand: I've been trying to soft-pedal it ;-) |
| 09:32 | seths | kiuma: if you need to generate Javascript easily consider http://github.com/arohner/scriptjure/ |
| 09:32 | Hali_303 | hi! In Emacs/SLIME, when I try it the repl or do a compilation it hangs. how to find out what is the trouble? |
| 09:33 | cgrand | cemerick: I noticed your efforts :-) |
| 09:33 | seths | Hali_303: can you switch to the *inferior-lisp* buffer? |
| 09:33 | Hali_303 | seths, yes |
| 09:33 | seths | you should hopefully see something like |
| 09:33 | seths | user=> user=> Connection opened on local port 49318 |
| 09:33 | seths | #<ServerSocket ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=49318]> |
| 09:33 | kiuma | seths, javascript must be done in javascript |
| 09:33 | Hali_303 | seths: yes, that is there |
| 09:34 | kiuma | and not in html pages |
| 09:34 | dabd` | sorry to repeat the question but what is the use of the empty? predicate if (not (empty? is discouraged because of the double negation? Why not remove empty? and simply use (not (seq and (seq instead? |
| 09:34 | Hali_303 | seth: also, below that: user=> user=> WARNING: reader macro ^ is deprecated; use meta instead |
| 09:34 | Hali_303 | WARNING: reader macro ^ is deprecated; use meta instead ( |
| 09:34 | kiuma | this beacause it avoid compression in any other language |
| 09:34 | cemerick | dabd`: (not (empty?)) is discouraged? |
| 09:35 | seths | kiuma: sure, but Scriptjure is pretty slick: (js (alert "hello world")) => "alert(\"hello world\")" |
| 09:35 | chouser | dabd`: (not (seq x)) is less clear than (empty? x) |
| 09:35 | cemerick | cgrand: I'm *almost* to the point of knowing what I'm doing with enlive :-) It's quite pleasant. |
| 09:35 | seths | Hali_303: hmm, it sounds like swank is running then |
| 09:35 | dabd` | cemerick if you read the documentation it recommends avoiding (not (empty? and use the idiom (seq instead |
| 09:36 | Hali_303 | seths, when I type (+ 1 2) I can see that parentheses-matching is also working, but if I press enter after that, it hangs |
| 09:36 | cgrand | cemerick: I'm happy to hear that! |
| 09:36 | dabd` | chouser: but (seq x) is also less clear than (not (empty? x)). At least for me... |
| 09:36 | cemerick | dabd`: I'd say either is fine -- many people (myself included) like a 'literate' style, where the semantics of empty? are helpful |
| 09:36 | kiuma | seths, compression -> http://www.wingstech.it/claw/dojotoolkit/dojo/dojo.js |
| 09:36 | dabd` | cemerick: yes. I appreciate that too |
| 09:38 | seths | Hali_303: hrm. |
| 09:38 | chouser | mutliple negatives are more difficult to think about than simple positives. |
| 09:38 | cemerick | cgrand: the only thing I need to figure out is how to structure things properly. "normal" templating languages allow you to segment code pretty naturally based on one's layout -- that not being available means one has to figure out how to compose various transformations for each page, etc. |
| 09:38 | seths | Hali_303: how was swank-clojure installed? |
| 09:38 | fogus | chouser: That is not not not not true |
| 09:39 | ordnungswidrig | (def full (comp not empty?)) |
| 09:39 | cemerick | chouser: empty? is a predicate, and doesn't imply a negation. |
| 09:39 | dabd` | chouser: but when you use (not (empty? x)) the multiple negative is hidden in the implementation of empty? right?. For the user there is only one negation. |
| 09:39 | chouser | cemerick: right. so say (empty? x) instead of (not (seq x)) |
| 09:40 | chouser | cemerick: but also, say (seq x) instead of (not (empty? x)) |
| 09:40 | Hali_303 | seths: checked out into a directory as described here: http://riddell.us/tutorial/slime_swank/slime_swank.html |
| 09:41 | cemerick | chouser: the fact that empty? is implemented using a negation is an implementation detail, IMO, and shouldn't influence coding style *shrug* |
| 09:41 | ordnungswidrig | cemerick: hehe |
| 09:41 | chouser | sorry, let me amend my statement. *any* negation is harder to think about that simple positive statements |
| 09:41 | cemerick | consider an alternate universe where seq returns an ISeq instead of nil for empty, and provided an .isEmpty() method. |
| 09:42 | cemerick | even more to the point, what about if/when empty? becomes a protocol, totally divorced from seqs? |
| 09:42 | somnium` | (when-let [s (seq arg)] ...) seems more elegant than (when-let [s (not (empty? arg))] ...) |
| 09:42 | fogus | chouser: I !disagree |
| 09:43 | cemerick | heh |
| 09:43 | seths | Hali_303: another option is to use leiningen |
| 09:43 | cemerick | fogus: go away with your algolisms! :-P |
| 09:43 | fogus | cemerick: (not :)) |
| 09:43 | ordnungswidrig | offline... |
| 09:44 | Raynes | fogus. He disagrees. |
| 09:44 | seths | create a project, add [leiningen/lein-swank "1.0.0-SNAPSHOT"] to the :dev-dependencies |
| 09:44 | seths | and then run swank-clojure-project |
| 09:44 | seths | has been the smoothest process for me |
| 09:44 | Hali_303 | seths: ok, I'll look into that, thanks |
| 09:44 | seths | g/l |
| 09:50 | cgrand | cemerick: I've been experimenting with layout as middlewares. In such a setting the :body of the response is a map whose vals are html fragments. |
| 09:51 | seths | does anyone know if clojure-mode has been updated for deftype? |
| 09:51 | seths | when I'm defining a method inside a deftype, clojure-mode indents like I'm calling the function |
| 09:52 | seths | since there is no defn or similar keyword |
| 09:52 | AWizzArd | at least jochu’s repositories were not updated for months |
| 09:53 | cemerick | cgrand: I'm afraid I can't visualize that right off the bat. |
| 09:53 | cemerick | cgrand: I've been toying with identifying + looking up transformations based on element id's in the template/snippet. |
| 09:53 | Hali_303 | seths: it seems that slime was also installed as an ubuntu package and that did not like the one installed manually. working now, thanks! |
| 09:54 | seths | Hali_303: glad to hear it's working, not that I did anything really :-) |
| 10:09 | seths | ,(with-meta "foo" {:bar 'baz}) |
| 10:09 | clojurebot | java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IObj |
| 10:09 | seths | :-( |
| 10:09 | seths | I'm being idealistic I suppose |
| 10:10 | angerman | seths: there's nothing that keeps you from adding meta support to your own string type |
| 10:12 | cemerick | where do plans stand w.r.t. require? Typing [foobar :as foobar] all over the place is getting just a little old. :-) |
| 10:14 | fogus | ,(let [x (with-meta (lazy-seq (seq "foo")) {:bar 2})] [(class x) (meta x) (apply str x)]) ;; total hackery |
| 10:14 | clojurebot | [clojure.lang.LazySeq {:bar 2} "foo"] |
| 10:15 | seths | fogus: woah |
| 10:15 | seths | why wrap (seq) in a lazy-seq? |
| 10:16 | fogus | something to attach metadata to. But mostly just to be playful |
| 10:18 | seths | I noticed that deftype says it only works for interfaces, e.g. String is rejected, but Object works fine |
| 10:18 | seths | wonder why the special case? maybe since Object is the top of the Java food chain? |
| 10:19 | fogus | seths: For a string-like deftype, I would consider CharSequence |
| 10:19 | seths | hmm |
| 10:19 | chouser | that'll at least work with regex |
| 10:19 | chouser | iirc |
| 10:26 | seths | chouser: I think deftyping CharSequence would work with regex, but it would be painful |
| 10:27 | seths | have to expose all the methods that are invoked on CharSequence by the regex code |
| 10:30 | seths | anyways, just to wrap up the thought experiment with meta on a string |
| 10:30 | seths | this technically works but is really gross |
| 10:30 | seths | ,(deftype MyStringType [a-str] CharSequence (toString [] a-str)) |
| 10:30 | clojurebot | java.lang.Exception: Unable to resolve symbol: deftype in this context |
| 10:30 | seths | alas |
| 10:31 | seths | (str (with-meta (MyStringType "abc") {:foo 'bar})) |
| 10:31 | Chousuke | seths: I guess Object methods are overrideable because you're forced to derive from it in any case and not being able to override things would just be limiting |
| 10:36 | dabd | a very basic question: I thought the following would not work (let [a (ArrayList.)] (.add a "1") a) because the ArrayList would be immutable. Only Clojure data structures are immutable? If you create a Java data structure it is mutable? thx |
| 10:37 | Chousuke | dabd: the reference "a" is immutable, not the data structure itself |
| 10:37 | Chousuke | dabd: Clojure can't make Java's mutable things suddenly immutable :) |
| 10:38 | dabd | but if a was a ref to a Clojure map the map itself would be immutable (and also the ref)? |
| 10:39 | Chousuke | yes. |
| 10:39 | dabd | thx |
| 10:44 | angerman | I've created a pretty stupid ascii-progress chart i though I'd share: http://ideone.com/LU8RUJCD |
| 10:47 | dabd | (second [1 2]) |
| 10:48 | dabd | ,(second [1 2]) |
| 10:48 | clojurebot | 2 |
| 10:51 | seths | cemerick: what's the latest on the string interpolation code? |
| 10:51 | cemerick | seths: sitting right over here :-) I suppose I should open a ticket for adding it, but I haven't heard much in the way of demand. |
| 10:52 | seths | I'm getting a little tired of (str x y z) |
| 10:52 | seths | wouldn't mind using it, not sure if there is any licensing on it yet? |
| 10:53 | tolstoy | seths: You mean something like Groovy's "some ${nice} interpolation?" |
| 10:53 | seths | tolstoy: exactly |
| 10:53 | seths | http://muckandbrass.com/web/display/~cemerick/2009/12/04/String+Interpolation+in+Clojure |
| 10:54 | cemerick | seths: feel free to use it. Wouldn't have posted it otherwise. |
| 10:54 | seths | great, thanks |
| 10:54 | joegg | Is there a single function that will build an infinite sequence from a single item, or should I just "(cycle (list 4))"? Basically, I'm looking for "constantly" except for sequences. |
| 10:55 | angerman | joegg: repeatedly |
| 10:56 | Chousuke | repeatedly is for functions |
| 10:56 | Chousuke | repeat is for items |
| 10:56 | tolstoy | seths: I kinda with that was in contrib. ;) |
| 10:57 | joegg | I guess you can clean it up a bit with (cycle [4]) instead of calling list. |
| 10:57 | Chousuke | ,(take 5 (repeat 4)) |
| 10:57 | clojurebot | (4 4 4 4 4) |
| 10:58 | joegg | Chousuke: That looks perfect. |
| 10:58 | Chousuke | it's optional :) |
| 10:58 | angerman | has it always been optional? |
| 10:58 | Chousuke | I don't think so. |
| 10:58 | angerman | hmm. so maybe my memory is just too old :) |
| 10:59 | Chousuke | there were two functions at some point |
| 10:59 | Chousuke | but then someone realised that repeat is enough :P |
| 10:59 | joegg | Okay, so: (constantly 4) will build a function that always returns 4, (repeat 4) builds an infinite sequence of 4, and (repeatedly somefn) will build a lazysequence based on the results of calling some function. Let's not even get into iterate. :) |
| 11:00 | joegg | And if I said something wrong there, please do correct me. |
| 11:00 | Chousuke | you're correct. |
| 11:01 | seths | tolstoy: cemerick is the author |
| 11:01 | Chousuke | iterate is not that difficult either. it just keeps calling the function on its return value |
| 11:01 | seths | I agree with you, would be nice to have around |
| 11:01 | joegg | Amazing. The only thing that worries me about clojure so far is that I'm bet I'm doing a lot of stuff like (cycle [4]) because I haven't yet internalized (for instance, (repeat 4). |
| 11:02 | cemerick | I guess that makes four 'seconds' on the notion of adding it to contrib. I suppose I'll have to open that ticket now. :-) |
| 11:02 | Chousuke | ,(take 5 (iterate / 9)) |
| 11:02 | clojurebot | (9 1/9 9 1/9 9) |
| 11:02 | Chousuke | :P |
| 11:03 | tolstoy | cemerick: Do you think there's room in it for adding formatter type things? Like ~0,2{num} for zero padding, or some such thing? Or would that be too much. |
| 11:03 | tolstoy | cemerick: I'm thinking that if you need more than simple interpolation, format works, but, I don't know, would be kinda cool for that once in a long while use case. |
| 11:04 | cemerick | tolstoy: yeah, there's lots of room for stuff like that. I haven't thought about it at all, though. |
| 11:04 | Chousuke | tolstoy: for that you probably want to take a look at cl-format in clojure.contrib |
| 11:04 | seths | cemerick: whatever you do, don't make it as painful as formatting std::cout is in c++ |
| 11:04 | cemerick | I suppose I would like to reuse what java's Format provides. |
| 11:04 | tolstoy | cemerick: The danger is it becomes yet another embedded DSL. (like cl-format.... ) |
| 11:05 | cemerick | yeah, I definitely would stay away from anything approaching CL's FORMAT. |
| 11:05 | cemerick | java.text.Format is just fine. Beyond that, go write a function, please. |
| 11:05 | tolstoy | Yes, String.format works for me. |
| 11:06 | tolstoy | But, I'd find it useful for logging. (log/info (<< "some ~{value} and another ~{thing}")) |
| 11:06 | tolstoy | But then I'm a "printf" debugger type. ;) |
| 11:06 | seths | tolstoy: there's a FaceBook fan page for that |
| 11:06 | seths | printf debugging |
| 11:06 | cemerick | I use << for logging all the time :-) |
| 11:08 | tolstoy | seths: debuggering? I'm not even going to try and picture that. |
| 11:09 | seths | lol |
| 11:09 | cemerick | oh, yeah, -?>> would be helpful |
| 11:09 | tolstoy | cemerick: maybe (log/info<< "the ~{a}'s have it") |
| 11:09 | seths | you could have special macros for logging |
| 11:10 | seths | like this for really bad errors (>_< "inconceivable!") |
| 11:10 | tolstoy | the smilification of logging, eh? |
| 11:10 | tolstoy | (; "it worked!") |
| 11:11 | seths | tolstoy: I see what you did there |
| 11:11 | tolstoy | (-( "error!")) |
| 11:17 | wooby | seths: LOL |
| 11:17 | wooby | (8-o "oh no!") |
| 11:20 | chouser | ,'(T_T "Oh dear") |
| 11:20 | clojurebot | (T_T "Oh dear") |
| 11:20 | chouser | ,'(x_x "failed completely") |
| 11:20 | clojurebot | (x_x "failed completely") |
| 11:20 | somnium` | http://www.lrde.epita.fr/~didier/software/smilisp.php << maybe there's something to this |
| 11:21 | the-kenny | Implementing smilisp is a bit hard because it isn't possible to define your own reader-macros in cloure code |
| 11:21 | tolstoy | And now we know why. |
| 11:26 | tolstoy | Can you use deftype/reify to, say, create a custom exception class in clojure? Dynamically? |
| 11:27 | Chousuke | hmm. |
| 11:27 | Chousuke | aren't they limited to interfaces? |
| 11:27 | tolstoy | That's what I was thinking (from what I read). |
| 11:27 | AWizzArd | Well, then there is still (proxy ...) |
| 11:28 | tolstoy | But that's not named, is it? You can't (catch CustomException ...), right? |
| 11:28 | stuartsierra | proxy won't create a named class that you can use in a try/catch |
| 11:28 | chouser | but you can't really rely on the name of the class ... right, whatever everyone is saying. |
| 11:29 | stuartsierra | If you want named classes, you must compile ahead-of-time. |
| 11:30 | tolstoy | I sometimes have a use case (web requests which in turn call other remote services), where I'd like to create an exception that has several attributes. I can throw it, and at the top I can just catch the exception, formulate an error response, and return. |
| 11:30 | chouser | defprotocol now creates named interfaces without AOT |
| 11:30 | chouser | tolstoy: look at clojure.contrib.condition |
| 11:31 | tolstoy | chouser: Ah, hm. I bet that's exactly what I need. |
| 11:34 | LauJensen | Is there something nice in contrib for downloading binary files? |
| 11:34 | tolstoy | Downloading from the web? http-agent works. |
| 11:34 | the-kenny | clojure-http-client should support this |
| 11:35 | LauJensen | k thx |
| 11:36 | angerman | Does anyone know how to figure out the iowait statistics on os x? |
| 11:39 | CalJunior | ,(defstruct foo :bar) |
| 11:39 | clojurebot | DENIED |
| 11:39 | CalJunior | (defstruct foo :bar) |
| 11:39 | CalJunior | (def map1 (struct foo nil) |
| 11:40 | CalJunior | (assoc map1 :bar 1) |
| 11:40 | CalJunior | returns {:bar 1} |
| 11:40 | CalJunior | however if I call map1 |
| 11:40 | CalJunior | it returns {:bar nil} |
| 11:41 | the-kenny | CalJunior: Clojure is a functional language with immutable data structures |
| 11:41 | CalJunior | Yes I know it's immutability. |
| 11:41 | fliebel | The assoc did not actually change anything... |
| 11:41 | fliebel | It only returned the changed struct |
| 11:41 | CalJunior | How do I get it to return {:bar 1} |
| 11:41 | CalJunior | ? |
| 11:42 | ohpauleez | use an atom or a ref |
| 11:42 | the-kenny | CalJunior: try a ref or atom |
| 11:42 | fliebel | Why would you need that? |
| 11:42 | ohpauleez | fliebel's answer is the one to go with |
| 11:42 | ohpauleez | you really should ONLY do that if you have to |
| 11:42 | CalJunior | I only need to do it once at program start-up. |
| 11:43 | chouser | then why not (def map1 (struct foo 1)) ? |
| 11:43 | ohpauleez | maybe you just need to define one (def ...) that you need. |
| 11:43 | the-kenny | alter-var-root is propably what you want.. or (def) it with the right value |
| 11:43 | CalJunior | I need to map 'identities' to their place in a vector. |
| 11:44 | CalJunior | rather their index in vector. |
| 11:45 | the-kenny | ,(hash-map (zipmap [:foo :bar :baz] (iterate inc 0)) |
| 11:45 | clojurebot | EOF while reading |
| 11:45 | the-kenny | ,(hash-map (zipmap [:foo :bar :baz] (iterate inc 0))) |
| 11:45 | clojurebot | java.lang.IllegalArgumentException: No value supplied for key: {:baz 2, :bar 1, :foo 0} |
| 11:46 | the-kenny | (zipmap [:foo :bar :baz] (iterate inc 0)) |
| 11:46 | the-kenny | ,(zipmap [:foo :bar :baz] (iterate inc 0)) |
| 11:46 | clojurebot | {:baz 2, :bar 1, :foo 0} |
| 11:48 | the-kenny | uhh switch the arguments of zipmap |
| 11:49 | CalJunior | thanks the-kenny, but I'll try the atom idea first. |
| 11:49 | the-kenny | CalJunior: An atom slow compared to a simple "def" |
| 11:50 | the-kenny | too much overhead |
| 11:50 | CalJunior | speed is not a issue in this case |
| 11:50 | the-kenny | It also isn't the "Clojure Way" ;) |
| 11:50 | CalJunior | I thought atoms were quite zippy though. |
| 11:51 | chouser | using an atom except to coordinate multiple threads is best avoided. |
| 11:51 | hiredman | the-kenny: what would you know about it? |
| 11:51 | hiredman | alter-var-root is certainly not to be recommended |
| 11:52 | the-kenny | hiredman: I think that isn't a good problem for an atom. It looks like he doesn't really need mutable state here, as he only wants to do something while initializing the program |
| 11:52 | CalJunior | I timed the atom on a vector at 0.025 ms. |
| 11:52 | chouser | CalJunior: if you could more completely describe your input and desired output, we can probably give better advice. |
| 11:53 | the-kenny | hiredman: I'm absolutely not the haskell type (wtf, please, no state anywhere), but I think it should be avoided where it doesn't needs to be |
| 11:54 | CalJunior | chouser: I def a maps of values for a number of symbols. |
| 11:54 | CalJunior | most of these values a fixed and don't change ever. |
| 11:55 | chouser | it seems unlikely to me that any reference type needs to be updated. |
| 11:55 | CalJunior | however, one of them is set at the start-up of the program (daily). |
| 11:55 | chouser | CalJunior: "maps of values" still doesn't tell me much. Perhaps an example? |
| 11:55 | the-kenny | CalJunior: So you want to update a value later in the program? |
| 11:55 | CalJunior | yes. |
| 11:55 | the-kenny | Oh sorry |
| 11:56 | the-kenny | I misunderstand you.. an atom is the best way for this, of course. |
| 11:56 | the-kenny | Maybe a ref, if there needs to be some coordination etc. while setting from different threads |
| 11:56 | hiredman | CalJunior: is there a reason you can't just do (def map’ {:a 1 :b 2 :c (init-stuff-here)}) |
| 11:58 | CalJunior | I think the atom is the obvious solution. So I'll let it rest. |
| 11:59 | CalJunior | chouser: love the book. as you can tell: I need it. |
| 11:59 | jcromartie | Would it make sense to use an agent with a nil value to handle saving data to disk? |
| 11:59 | jcromartie | I |
| 11:59 | DeusExPikachu | what is a fixnum and what is its purpose? |
| 12:00 | jcromartie | Or should the agent represent the data being saved? |
| 12:00 | Chousuke | jcromartie: I think it's okay to have a "serializing agent" |
| 12:00 | chouser | jcromartie: nil is probably fine. I've sometimes put the filehandle in there, but you have to be careful to always return it from your action functions |
| 12:00 | Chousuke | so that you can just do (send someagent write-to-disk whatever) |
| 12:01 | chouser | CalJunior: glad you like it. |
| 12:01 | chouser | CalJunior: thanks from fogus as well. :-) |
| 12:02 | chouser | DeusExPikachu: I think that usually refers to an efficient way to store numbers that know their own type, that's not supported by the JVM yet. |
| 12:02 | CalJunior | fogus: love your book too :-) |
| 12:03 | hiredman | if have the agent hold the data to be saved you can use a watch to write |
| 12:03 | jcromartie | hiredman: that's a good idea |
| 12:03 | Chousuke | hiredman: hmm, what if the data changes while the watcher is writing it? |
| 12:03 | jcromartie | so I send things like conj or assoc or dissoc |
| 12:03 | jcromartie | but the writes have to be in order |
| 12:04 | hiredman | ,(doc add-watch) |
| 12:04 | clojurebot | "([reference key fn]); Experimental. Adds a watch function to an agent/atom/var/ref reference. The watch fn must be a fn of 4 args: a key, the reference, its old-state, its new-state. Whenever the reference's state might have been changed, any registered watches will have their functions called. The watch fn will be called synchronously, on the agent's thread if an agent, before any pending sends if agent or ref. Note tha |
| 12:04 | chouser | "The watch fn will be called synchronously" |
| 12:04 | jcromartie | ok |
| 12:04 | jcromartie | great! |
| 12:05 | jcromartie | now... is this so "experimental" that I shouldn't use it for production code? |
| 12:05 | jcromartie | otherwise I can just use a serializing agent |
| 12:05 | jcromartie | and call it a day |
| 12:05 | jcromartie | send-off would do the trick |
| 12:05 | chouser | jcromartie: that usually has more to do with the chances of the api changing than the code breaking. |
| 12:06 | jcromartie | I see |
| 12:07 | DeusExPikachu | chouser, thanks, now the jvm talk makes sense |
| 12:09 | chouser | DeusExPikachu: sure. the details are interesting too, if you're into that kind of thing. |
| 12:10 | DeusExPikachu | chouser, I'm watching "Fast Bytecodes for Funny Languages" and Cliff is talking about why clojure is close speed to java, and what it needs to do to close the gap |
| 12:10 | chouser | ah, yep. fixnums would be great for clojure. |
| 12:10 | chouser | meanwhile, rhickey's doing what he can to work around the problem. :-) |
| 12:19 | DeusExPikachu | chouser, I dont' know if you've watched the talk, but do you know if Escape Analysis is typically performed at the JIT level, or the clojure compiler level? |
| 12:20 | chouser | The Clojure compiler doesn't do much optimization at all. Post-1.1 it's now doing some fine-grained locals clearing, but any escape analysis is being done by the JVM. |
| 12:21 | chouser | Hm, I guess Clojure's also now doing some clever things with method caching at call sites, and some explicit (macro-style) inlining. |
| 12:22 | hiredman | that would be for deftype and protocols? |
| 12:23 | chouser | hiredman: yes, where (:foo bar) can be as fast as a direct field lookup, like a type-hinted (.foo bar) |
| 12:23 | chouser | I think that's the only place the call-site caching is done, but I may have forgotten something. |
| 12:24 | hiredman | do protocol fn call sites do some caching? |
| 12:24 | chouser | hm, perhaps that too. I haven't tried to read the implementation for any of that yet. |
| 12:27 | seths | cemerick: hey, email me if you are unhappy with http://bitbucket.org/seths/pokerepl/src/39b5efb4e905/src/com/muckandbrass/interpolate.clj |
| 12:33 | tayssir | Hi! I'm trying to search for the reasoning why add-classpath's deprecated... any pointers? (To get add-classpath's dynamicity, am I supposed to unzip the .jar into my classpath or something?) |
| 12:37 | hiredman | add-classpath was only ever supposed to be used in a very limited set of circumstances, since the visibility (scope) of classes loaded that way cannot be guaranteed |
| 12:38 | tmountain | is there a way to write this with the arrow operator? (get (get x "foo") "bar") |
| 12:38 | tmountain | or some better way to write it? |
| 12:38 | hiredman | it's deprecated generally because people were unable to keep themselves from using it only for experimental repl sessions |
| 12:38 | hiredman | (-> x (get "foo") (get "bar")) |
| 12:39 | tmountain | thanks hiredman |
| 12:39 | hiredman | the real solution appears to be a custom classloader as the system classloader durring developement |
| 12:40 | hiredman | but this has yet to be codified |
| 12:40 | hiredman | (honestly it's a fairly simple bit of code, so it should be) |
| 12:40 | Chousuke | isn't there a get-in as well? |
| 12:41 | hiredman | (doc get-in) |
| 12:41 | clojurebot | "([m ks]); returns the value in a nested associative structure, where ks is a sequence of keys" |
| 12:41 | hiredman | Yes |
| 12:41 | tmountain | ahh, that's what I was looking for |
| 12:41 | tmountain | I was browsing clojure categorized... I see it's under structs rather than maps on there |
| 12:42 | tayssir | hiredman: Ah, cool, thanks. |
| 12:45 | lypanov | gen-in is cute |
| 12:46 | Chousuke | update-in and assoc-in are also neat :) |
| 12:46 | Norrit | hi, I am looking for some kind of "flat" operation, is there something available? |
| 12:46 | Chousuke | Norrit: flatten? clojure.contrib.seq-utils |
| 12:46 | Norrit | ah .. thx :-) |
| 12:47 | Chousuke | contrib contains a lot of stuff |
| 12:47 | konr` | is it safe to assume that a randomly generated string does not occur in a file? |
| 12:48 | the-kenny | ,(doc gen-in) |
| 12:48 | clojurebot | It's greek to me. |
| 12:48 | the-kenny | Oh, get-in? |
| 12:48 | Chousuke | konr`: depends how good your PRNG is :P |
| 12:49 | Chousuke | also on the length of the string :) |
| 12:49 | hiredman | konr`: no |
| 12:49 | hiredman | a file is random collection of strings |
| 12:49 | Chousuke | mmh |
| 12:49 | Chousuke | most often not random |
| 12:50 | Chousuke | but still, nothing would prevent anyone from looking up one of your randomly generated strings and putting it in a file. |
| 12:50 | lypanov | the-kenny: aye, sorry. fingers are tired :D |
| 12:50 | hiredman | Chousuke: unless you know the contents of the file, it is random |
| 12:50 | the-kenny | lypanov: I was just asking because I never heard of gen-in |
| 12:51 | lypanov | maybe i should invent it |
| 12:51 | Chousuke | konr`: What are you you trying to accomplish? |
| 12:51 | hiredman | but unless you have actually checked to see if a random string exists in a file, it is not safe to assume it isn't in the file |
| 12:51 | lypanov | man this parleys thing uses a ton of cpu.. wonder where the vids are |
| 12:51 | Chousuke | hiredman: the contents of the system files on my hard disk are definitely not random, though I don't know it :) |
| 12:52 | Chousuke | I guess the issue here is about probability |
| 12:52 | Chousuke | I mean, it's not safe to assume that a hash does not collide with anything in the future |
| 12:53 | Chousuke | by your logic. |
| 12:53 | konr` | Chousuke: I want to generate a Boundary string to a multipart POST request, and I'm a little confused. In Drakma's source code, the string is random, but here: http://www.ietf.org/rfc/rfc2388.txt it says that the string should not appear on the content |
| 12:53 | konr` | Chousuke: drakma, the CL equivalent |
| 12:53 | Chousuke | konr`: generate a UUID or something |
| 12:53 | Chousuke | konr`: those are designed not to collide with each other :P |
| 12:54 | Chousuke | or you could hash the content that you're separating |
| 12:54 | Chousuke | then use /hash/ |
| 12:54 | Chousuke | or whatever |
| 12:56 | Chousuke | It's rather unlikely that any good hash function would generate output A from content that contains A :P |
| 13:05 | ohpauleez | konr`: you want to use HtmlUnit and interop + enlive |
| 13:05 | ohpauleez | that's what I've been doing |
| 13:09 | konr` | ohpauleez: "GUI-Less browser for Java programs" - hmmm, I didn't knew about this one |
| 13:09 | konr` | I'm going to try it out, thanks guys! |
| 13:10 | ohpauleez | totally welcome, I've been working on ripping parts of htmlunit out, and wrapping it a more functional way |
| 13:11 | hiredman | htmlunit is pretty nice |
| 13:11 | ohpauleez | agreed |
| 13:12 | the-kenny | http://kvardek-du.kerno.org/2010/01/how-common-lisp-programmer-views-users.html Clojure is Picard as a Borg :/ |
| 13:14 | wilig | technomancy: did you have a chance to look at clojure/repl? I tried the simple approach but didn't get far. |
| 13:15 | vu3rdd | I am trying to write an insertion sort routine. |
| 13:15 | vu3rdd | as a first step, I created an insert routine, which takes an integer and a sorted sequence as parameters. |
| 13:16 | vu3rdd | it works except when the number to be inserted in greater than all the elements in the list. |
| 13:16 | vu3rdd | The code is here: can someone help find the problem? |
| 13:16 | vu3rdd | http://paste.lisp.org/+2099 |
| 13:17 | cemerick | Good for a laugh, if folks haven't seen it yet: http://kvardek-du.kerno.org/2010/01/how-common-lisp-programmer-views-users.html |
| 13:17 | hiredman | vu3rdd: first (seq key) is most likely not what you want |
| 13:18 | hiredman | for the empty case |
| 13:18 | hiredman | (seq [key]) or (list key) |
| 13:19 | hiredman | infact |
| 13:19 | vu3rdd | ok |
| 13:19 | hiredman | that might be the actually problem, since it is the base case |
| 13:19 | hiredman | so do that and try again |
| 13:20 | vu3rdd | hiredman: thanks. yes indeed. |
| 13:20 | vu3rdd | I was struggling with it for a long time today! :-( |
| 13:21 | hiredman | seq is not like list or vector |
| 13:21 | hiredman | seq returns a seq on a collection, it doesn't create a collection |
| 13:22 | vu3rdd | ok. |
| 13:22 | vu3rdd | so, any collection can be converted to sequences and can be thought of as a logical representation of any collection? is that a fair statement? |
| 13:25 | tmountain | anyone know any existing libs for downloading binary data using something like InputStream and OutputStream? |
| 13:26 | Chousuke | vu3rdd: seqs are logical views to a collection, yes. |
| 13:27 | vu3rdd | Chousuke: thanks |
| 13:28 | Chousuke | vu3rdd: seqs are also persistent, ie. once you have realised (accessed) a part of a seq, that part is immutable. this means weird things can happen if you make a seq on a mutable array and then modify the array afterwards |
| 13:30 | vu3rdd | Chousuke: thanks. But aren't vectors, maps and lists also persistent? I guess by Arrays, you mean the Java Arrays? |
| 13:30 | Chousuke | yes |
| 13:31 | Chousuke | ,(let [a (into-array [1 2 3 4 5]) s (seq a)] (println (first s) ".") (aset a 0 42) (println (first s) ".") (println (aget a 0) ".")))) |
| 13:31 | clojurebot | 1 . 42 . 42 . |
| 13:31 | Chousuke | hmm. |
| 13:32 | Chousuke | I guess not cached in that case :/ |
| 13:32 | chouser | I think lazy seqs cache, not all seqs. |
| 13:32 | vu3rdd | ok |
| 13:32 | Chousuke | chouser: might be. |
| 13:33 | Chousuke | ,(let [a (into-array [1 2 3 4 5]) s (doall (seq a))] (println (first s) ".") (aset a 0 42) (println (first s) ".") (println (aget a 0) ".")))) |
| 13:33 | clojurebot | 1 . 42 . 42 . |
| 13:45 | hiredman | … |
| 13:46 | jkdufair | Anyone played with Alice? I see it's Java. Might be fun to bolt clojure on top of it somehow. |
| 13:46 | LauJensen | Guys - I had a thought earlier. Previously when there's been a challenge like prime-finding, Lucas-Lehmann, Hamming numbers etc, I've joyfully used lazy-seqs to get the data I want. Now with chunked-seqs do I still dare? I imagine that with Mersenne Primes for instance the computations run for 8+ hours once you get beyond the 10.th number or so, so wont a seq representation effecually be impossible because the CPU will burn out trying to get the |
| 13:47 | chouser | LauJensen: you may need to be careful, yes. But many seqs are still not chunked. |
| 13:47 | LauJensen | many? |
| 13:47 | chouser | many |
| 13:47 | hiredman | anything using range is chunked |
| 13:48 | LauJensen | hehe |
| 13:48 | chouser | anything you build manually using lazy-seq and cons is not chunked |
| 13:48 | LauJensen | Aah ok |
| 13:48 | LauJensen | Thats good news |
| 13:48 | chouser | anything using iterate is not chunked. |
| 13:48 | LauJensen | Preferably it would just be made explicit somehow if you want chunks or lazy seeing they're 2 different things |
| 13:49 | chouser | any of the seq library functions that consumes a non-chunked seq, produces a non-chunked seq. |
| 13:49 | Chousuke | it is kind of explicit right now. |
| 13:49 | Chousuke | there's just no function to convert from a chunked seq to a non-chunked one |
| 13:49 | chouser | we could use a seq1 fn. Not sure why we don't have one yet. |
| 13:49 | LauJensen | You dont me literally seq1 ? |
| 13:50 | Chousuke | seq1 is not a bad name. :) |
| 13:50 | chouser | yes, a seq1 that accepts a collection (or chunked seq) and returns a guaranteed non-chunked seq |
| 13:50 | rhickey | http://paste.lisp.org/display/90536 |
| 13:50 | Chousuke | I wonder if you can guarantee that for nested chunked seqs though? :/ |
| 13:50 | rhickey | just a rough draft |
| 13:51 | chouser | iterate, for example, could potentially be faster producing a chunked seq, but if there were code written relying on it being non-chunked, that could be considered a breaking change. :-/ |
| 13:52 | chouser | if we had an idiomatic seq1, then seq-returning things in generally could be considered potentially chunked, and code that *needed* non-chunked would explicitly use seq1 |
| 13:53 | hiredman | bleh |
| 13:54 | chouser | considering how little complaints we've heard about chunked seqs, I would imagine use of seq1 would be pretty rare. |
| 13:54 | Chousuke | I think it would serve as documentation too |
| 13:54 | chouser | yes |
| 13:55 | hiredman | bleh |
| 13:55 | Chousuke | hiredman: do you have a better solution? |
| 13:55 | chouser | hiredman: do you have an alternative you'd like to propose? :-) |
| 13:55 | chouser | heh |
| 13:55 | Chousuke | or should we call seq1 "bleh"? |
| 13:56 | hiredman | I like it when map, filter, etc were lazy |
| 13:56 | hiredman | liked |
| 13:56 | chouser | you would prefer to not have chunked seqs at all? |
| 13:56 | technomancy | wilig: not yet unfortunately |
| 13:57 | hiredman | I have to run catch a bus, but I would prefere explicit chunking to explicit seq-1 |
| 13:57 | Chousuke | the non-chunkedness will propagate though won't it? |
| 13:57 | technomancy | wilig: I ordered a nexus one and have been distracted by the android emulator. =) |
| 13:59 | Chousuke | so if you have (map ... (filter ... (map expensive-op (generate-chunked-seq)))) then you should be able to make the whole thing non-chunked by just wrapping the map operation in seq1 |
| 13:59 | chouser | the inner map, yes |
| 14:00 | chouser | well |
| 14:00 | chouser | no |
| 14:00 | chouser | (seq1 (generate-chunked-seq)) |
| 14:00 | chouser | ,(first (map prn (range 10))) |
| 14:00 | clojurebot | 0 1 2 3 4 5 6 7 8 9 |
| 14:01 | Chousuke | hiredman: I think having seq1 as the non-default op makes sense, because otherwise you'd need a lot of ceremony just to get the performance benefits. |
| 14:02 | Chousuke | hiredman: and in the vast majority of cases it makes no difference whether a seq is chunked or not |
| 14:02 | Chousuke | except that the chunked seq is faster, of course |
| 14:04 | Chousuke | but I guess if chunked seqs ever turn out to have been a *really* bad idea, the whole mechanism can just be removed :/ |
| 14:08 | hiredman | well, the bus drove away while I was running along side it yelling and pounding on the side of the bus trying to get the driver's attention |
| 14:08 | chouser | :-( |
| 14:08 | chouser | wait -- is that a metaphore for chunked seqs? |
| 14:08 | hiredman | could be |
| 14:09 | Chousuke | heh |
| 14:09 | Chousuke | you just need to make a convincing enough case against chunked seqs |
| 14:10 | hiredman | I like lazy seqs |
| 14:10 | Chousuke | yes, and chunked seqs are still lazy. |
| 14:10 | Chousuke | only less lazy than before. |
| 14:10 | wilig | technomancy: excellent. enjoy. I'm tempted to finally succumb to the smart phone itch. It's not the price of the phone that gets me, it's the recurring costs. |
| 14:10 | hiredman | yes, and less is less |
| 14:10 | Chousuke | and if (when) seq1 is introduced, you have an explicit way of getting back to the old semantics |
| 14:11 | Chousuke | so what is there not to like? |
| 14:11 | Chousuke | that you might need to wrap some seqs in seq1 sometimes? :/ |
| 14:13 | hiredman | chunked sequences basically go back on http://groups.google.com/group/clojure/browse_thread/thread/88d9fdb5bcad36a , so nil punning is gone for nothing |
| 14:14 | lisppaste8 | fogus pasted "seq1 -- for my version of clojure" at http://paste.lisp.org/display/93650 |
| 14:15 | Chousuke | hiredman: except seq1 rectifies that too |
| 14:16 | LauJensen | I prefer the speed that the chunks come with, so thats a good default, but it does change the way you can think about seqs a little bit |
| 14:16 | Chousuke | hiredman: and lazy sequences are still there. chunked sequences are just another, less lazy type of seq :P |
| 14:16 | rhickey | hiredman: no, they don't, as a chunked seq does nothing until something is asked for. When asked, it does more. And given some seq1-style source for seqs, it will be exactly as before |
| 14:17 | rhickey | hiredman: but you haven't proposed an alternative. Explicit chunks, linke chunk-map, chunk-filter etc? 2 versions of everything? |
| 14:18 | rhickey | once a seq is single, existing fns will process one-at-a-time |
| 14:19 | rhickey | or a (chunked-seq x) to start the chunked chain? |
| 14:19 | technomancy | wilig: yeah, with Google voice being able to fall back to wifi for calls means 95% of my voice usage will be free |
| 14:20 | rhickey | just saying bleh doesn't move the dialogue forward, and people want the perf benefits. As is now obvious, people aren't suffering much from the theoretical problem |
| 14:21 | slava | it just occurred to me that inserting usage of transients is something the compiler could do, at least in simple cases |
| 14:22 | Chousuke | slava: possibly, but that would be complicated |
| 14:22 | slava | also, what happened to 'persistent data structures are fast enough for everything' :-) |
| 14:22 | Chousuke | slava: even for simple cases :) |
| 14:22 | stuartsierra | slava: the core functions, like "into", already do. |
| 14:22 | Chousuke | slava: was that ever claimed? |
| 14:23 | technomancy | "everything" is a tricky term. =) |
| 14:24 | Chousuke | Clojure is developed kind of incrementally. |
| 14:25 | Chousuke | transients are just one new tool in the box :P |
| 14:25 | technomancy | slava: nobody wants to work on the compiler right now since it's going away with self-hosting around the corner. but it's certainly an interesting idea. |
| 14:25 | angerman | technomancy: is that look and feel issue going into lein soon? |
| 14:25 | technomancy | angerman: are you getting it on the latest version? or is it just a problem with the release? |
| 14:26 | angerman | technomancy: using the latest release, lein pulles on self-install (from yesterday) |
| 14:26 | technomancy | angerman: oh, I thought that had been fixed |
| 14:26 | technomancy | angerman: unfortunately it only manifests on OS X, so all I can do is accept patches |
| 14:27 | slava | transients are an interesting optimization. its not safe if you have multi-shot continuations |
| 14:27 | angerman | yes, I had it hand compiled for me. but then lein from the checkout was screweing with the classpath too much, so i cleared all of lein I had and pulled the version from the net. |
| 14:28 | Chousuke | I somehow doubt that Clojure will ever gain features that break transients (might deprecate some usage patterns) but amusingly enough it should be easy to remove them, too. |
| 14:29 | Chousuke | just make persistent! and transient no-ops and maps the ! ops to regular assoc etc. :P |
| 14:32 | angerman | technomancy: lein swank still crashes. Let's see if i find the patch that fixed it for me the last time |
| 14:32 | patrkris | hey... i'm looking for a quote that says something along the lines of "object-oriented design patterns were made to solve the deficiencies of OOP" |
| 14:32 | patrkris | for some reason, I think it might have been rhickey who said it |
| 14:33 | patrkris | or maybe he was quoting someone else |
| 14:40 | angerman | technomancy: I'm sure it was this patch: http://github.com/swannodette/leiningen/commit/9d79d631a9faa870a9347992f50a4312170fdf97 |
| 14:41 | wooby | angerman: is the OS X bug mentioned in the commit msg the OS X java runtime stuff not being on classpath? |
| 14:42 | angerman | wooby: that might be the case. It only happens with lein swank though |
| 14:42 | technomancy | angerman: right, that slows every execution down for everyone |
| 14:42 | technomancy | everyone else shouldn't have to be affected by a workaround for an OS X bug |
| 14:42 | angerman | technomancy: hmm ok, didn't know it caused slow down |
| 14:45 | Raynes | http://www.reddit.com/r/programming/comments/artiq/clojure_11_12_and_beyond_what_is_clojure_in/c0j3c8e :> |
| 14:46 | wooby | maybe lein swank could just sniff if OS X and include JavaRuntime.jar in -extra-classpath if necessary |
| 14:46 | wooby | i'll take a stab at it |
| 14:51 | angerman | wooby: (defn osx? [] (= (System/getProperty "os.name") "Mac OS X")) |
| 14:51 | angerman | wooby: if that helps :D |
| 14:51 | wooby | angerman: there 'tis :) |
| 14:52 | Raynes | ,(System/getProperty "os.name") |
| 14:52 | clojurebot | java.security.AccessControlException: access denied (java.util.PropertyPermission os.name read) |
| 14:52 | Raynes | :< |
| 14:52 | jasapp_ | I was about to try the samething |
| 15:07 | ts00000 | so, is technomancy's clojure-http-client the canonical way to do REST-type stuff these days? |
| 15:08 | ts00000 | e.g. http post. |
| 15:10 | the-kenny | Okay.. how do I merge two (or more) lists: (f [1 3] [2 4]) -> [1 2 3 4] |
| 15:10 | somnium` | concat |
| 15:10 | chouser | those are vectors |
| 15:10 | chouser | you want to keep them in order? |
| 15:10 | chouser | sorted order, I mean? |
| 15:11 | the-kenny | chouser: Yes |
| 15:11 | chouser | and you promise the input seqs are already in order? |
| 15:12 | the-kenny | I get one from a [& foo |
| 15:12 | the-kenny | ] function argument |
| 15:12 | chouser | if they're not already sorted, I don't think you can do better than (sort (concat c1 c2)) |
| 15:13 | wooby | interleave would work, at least in that case |
| 15:14 | the-kenny | I think I'll stick to (seq (zipmap ...)), the order of the interleaved pairs isn't very important, just that they're pairs |
| 15:15 | chouser | I don't see how that's at all similar, but if you've got something that works, then great. |
| 15:17 | the-kenny | chouser: (fun ['foo 'bar] [:foo :bar]) should return either [foo :foo bar :bar] or [bar :bar foo :foo |
| 15:17 | the-kenny | +] |
| 15:23 | ohpauleez | the-kenny: that's different from the orginal goal, in that case, zipping is what you want to do |
| 15:27 | chouser | ,(interleave ['foo 'bar] [:foo :bar]) ; ? |
| 15:27 | clojurebot | (foo :foo bar :bar) |
| 15:28 | chouser | zipmap returns a map collection, not a vector or sequence. |
| 15:28 | ohpauleez | right |
| 15:29 | ohpauleez | and I suppose if you really wanted a vector, just toss a into [] in front of the interleave |
| 15:29 | chouser | yes, or 'vec' :-) |
| 15:29 | ohpauleez | that would work too :) |
| 15:38 | CalJunior | I have: (def foo { :bar ( atom { } ) } ) |
| 15:38 | CalJunior | how do I swap the atom? |
| 15:39 | CalJunior | for example to 1 |
| 15:39 | chouser | (update-in foo [:bar] swap! assoc :a 1) |
| 15:39 | chouser | hm. |
| 15:39 | chouser | no |
| 15:40 | CalJunior | returns {:a 1} |
| 15:40 | CalJunior | I would like it to return 1 |
| 15:40 | chouser | (swap! (:bar foo) assoc :a 1) |
| 15:44 | CalJunior | chouser: thanks |
| 15:45 | CalJunior | I guess I have to change the atom from a map to a vector to just get 1 |
| 15:45 | chouser | an atom can hold a single number instead of a collection if you'd like |
| 15:46 | CalJunior | that's what I would like |
| 15:46 | chouser | ,(let [a (atom nil)] (reset! a 1) a) |
| 15:46 | clojurebot | #<Atom@192caa9: 1> |
| 15:48 | chouser | I continue to doubt that an atom is the best solution for you |
| 15:49 | CalJunior | I know what you mean. |
| 15:49 | CalJunior | (atom nil) was the key for me here. |
| 15:49 | CalJunior | works |
| 15:50 | CalJunior | I'll try to find a different solution later. |
| 15:53 | wilig | technomancy: New version of swank-clojure pushed to github. This one proxies LineNumberingPushbackReader. It's a small step on the path toward clojure.main/repl |
| 16:07 | ts00000 | there is no deliberate slowdown |
| 16:08 | ts00000 | wrong chan |
| 16:13 | ts00000 | doesn't swank-clojure-project autoload everything in ~/project/lib? |
| 16:13 | ts00000 | in terms of classpath? |
| 16:23 | stuartsierra | Hey Maven fans (& not). I'm working on a Maven-based build for contrib. |
| 16:25 | lpetit | cool |
| 16:26 | stuartsierra | It's SO much simpler than the Ant build. |
| 16:27 | chouser | why's that? |
| 16:28 | stuartsierra | No test script needed, far fewer exclusions needed when compiling, no need to manually define how to find/compile .clj sources, ... |
| 16:30 | stuartsierra | Basically, all the complexity of the Ant script is moved to the Maven plugin. |
| 16:30 | chouser | ah |
| 16:31 | stuartsierra | And the plugin is published in the central repository, so we don't need to distribute it. |
| 16:34 | stuartsierra | Check it out: http://github.com/richhickey/clojure-contrib/tree/maven |
| 16:37 | stuartsierra | No need to specify where to find clojure.jar on the command line... |
| 16:38 | zakwilson | I just set up a new machine with a new install of swank-clojure and an old .emacs file. It's saying java.lang.NoClassDefFoundError: clojure/main |
| 16:39 | zakwilson | and swank-clojure-jar-path is set to a real working clojure.jar |
| 16:39 | lpetit | stuart, are you a new convert, or did you know/use maven for a long time ? |
| 16:40 | stuartsierra | lpetit: I've been advocating Maven for Clojure projects for a while now. I wrote several blog articles on the subject. |
| 16:40 | lpetit | ok, was just wondering :-) |
| 16:41 | stuartsierra | http://stuartsierra.com/tag/maven |
| 16:41 | lpetit | I'm currently starting a project with GWT. Was wondering whether I would use ant or maven for it, just today :-). But I would really have loved being able to work with clojure full stack with GWT :-( |
| 16:42 | chouser | I think Clojure is less compatible with GWT than it is with C++ libs |
| 16:43 | jcromartie | ouch |
| 16:43 | stuartsierra | GWT is a Java source compiler, not much to be done about that. |
| 16:43 | chouser | *and* GWT can't compile Clojure's java sources |
| 16:43 | chouser | or couldn't last I tried, anyway. |
| 16:43 | lpetit | guessed so :'( |
| 16:44 | chouser | the only hope would be after cinc to write a java-source backend specifically designed to stay compatible with GWT requirements. |
| 16:46 | lpetit | yes. Some guys also reused the java->js compilation mechanism to extend it to their own classes. Depends on the size of the stuff to do, as always (e.g. a guy created QWT, qooxdoo widget toolkit, based on the google's compiler, AFAIK) |
| 16:51 | ts00000 | this is really bizarre |
| 16:51 | ts00000 | swank-clojure-project isn't adding my ~/project/lib to classpath |
| 17:06 | heow | Just fired up the latest NetBeans and Enclojure, getting an NPE when creating a new project. is this a known problem? |
| 17:11 | heow | Anybody use the [theoricicly user-friendly] NetBeans? |
| 17:13 | lpetit | I've just read interesting things about zippers, and will tend to become a zipper fan very quickly. So ... before I over abuse the tool, what are the limitations of zippers I don't see right now ? Where should they be avoided, for instance ? If not theoretically, at least given the current implementation in clojure.zip ... |
| 17:14 | technomancy | ts00000: it should add all the jars in $PROJECT_ROOT/lib to the classpath |
| 17:14 | dabd | how the see the value of classpath from a project REPL in netbeans 6.8? |
| 17:14 | chouser | zippers are pretty amazing, but they're not amazingly fast, and the way I used them in zip-filter turned out to be unexpectedly limiting. |
| 17:14 | stuartsierra | Simplifying contrib build with Maven: http://groups.google.com/group/clojure-dev/browse_thread/thread/cd807a1e5d7ce77d |
| 17:17 | lpetit | I thing I'll use them with the parsetree of the code of paredit.clj, to go to the node corresponding to the caret, and then from it find the parent, the previous siblings, etc. A limited number of operations, mostly navigational |
| 17:17 | heow | dabd: Oh hey, yeah the REPL's sig changed in 1.1. Bet that's it, thanks! |
| 17:19 | lpetit | But I'm currently "reinventing the wheel" in the parser code. I browse the code from first to last char, creating events as I go: entering a () , entering spaces, quitting spaces, entering an atom, quitting an atom, etc. So I keep a stack of the parents, and when I quit node, I "close" the node with the info I've gathered on it so far, peek the parent from the stack, update it with the... |
| 17:19 | lpetit | ..."closed" node by adding it as last child, and replace the parent on the stack. |
| 17:20 | dabd | heow: I'm still running clojure 1.0 with netbeans (because I cannot get 1.1 to work with the latest enclojure). I'm puzzled by this. It thought starting a proj REPL would take care of setting the classpath correctly |
| 17:20 | lpetit | So, basically, I guess I've reinvented a specialized version of a zipper with a limited subset of operations on it, and without the need to maintain an "after focus point context", just a "before focus point" context |
| 17:21 | lpetit | But I'm pretty sure my solution is efficient since I can see no superfluous (no non-essential) task in it. |
| 17:22 | jasapp_ | say I've got my.ns.foo, and my.ns.bar, which have similar functions, but are different internally |
| 17:22 | lpetit | But the question remains : will I also use zippers for the construction phase, or will I suffer a penalty I can't afford ? |
| 17:22 | jasapp_ | and I want my other code to be able to switch back and forth between them, interface-like |
| 17:22 | jasapp_ | what's the best way to do that? |
| 17:22 | ts00000 | technomancy: if it's not, where should I start to debug? |
| 17:22 | lpetit | chouser: what do you thing about it ? (and please don't tell me it will be in chapter xX of joc :-) ) |
| 17:23 | chouser | lpetit: hehe |
| 17:23 | ts00000 | technomancy: if it's in ~/.swank-clojure it's fine, if it's in the lib directory it doesn't work |
| 17:23 | chouser | lpetit: I'm afraid I don't grasp your whole context sufficiently to say. You're talking about parsing a stream of bytes into some kind of tree? |
| 17:23 | ts00000 | chouser: is there a way I can play with require without redeclaring my entire ns? I tried (require 'clojure.contrib.zip-filter) which works, but I can't seem to access any of the xml-> things |
| 17:24 | technomancy | ts00000: check the elisp value of swank-clojure-classpath with C-h v |
| 17:24 | ts00000 | technomancy: I did that, it's not there |
| 17:24 | ts00000 | technomancy: but it's definitely in my lib directory |
| 17:25 | stuartsierra | ts00000: require does not 'refer' symbols into the current namespace |
| 17:25 | ts00000 | stuartsierra: but shouldn't I be able to do (clojure.contrib.zip-filter/func ...) ? |
| 17:25 | technomancy | ts00000: I've never heard of that failing on a project that's laid out according to the directions in the swank-clojure-readme |
| 17:25 | stuartsierra | ts000000: yes, you should |
| 17:25 | stuartsierra | In that case the problem is somewhere else. |
| 17:26 | ts00000 | technomancy: http://pastie.org/787307 |
| 17:26 | lpetit | chouser: I'm the 100tiest guy to rewrite a clojure source code parser manually. For my purpose I'm just interested in a parsetree of the clojure code, and for the moment not interested in anything else than structural nodes (parens, square brackets, round brackets, strings, regexps, comments) and just 3 kinds of atoms: literal chars, spaces and the rest |
| 17:26 | ts00000 | technomancy: did I miss something? |
| 17:27 | lpetit | chouser: this should give you ideas of the size and depth of my tree. clojure/core.clj is used for tests, since I see it representing an upper limit :-) |
| 17:27 | technomancy | ts00000: when you do M-x swank-clojure-project, you input the directory containing lib/ ? |
| 17:27 | ts00000 | technomancy: yessir |
| 17:27 | chouser | lpetit: I think zippers will only be useful to you if you produce a tree of some kind from the parsing, and then keep it in memory while using the zipper api to navigate it. |
| 17:28 | lpetit | chouser: so too heavy for massive edit operations ? |
| 17:28 | chouser | lpetit: if I understood your description correctly, you're currently not holding the whole thing in memory, just keeping a stack representing your nested context? |
| 17:28 | ts00000 | technomancy: SLIME 20091016, emacs 23.1.91.1, osx |
| 17:29 | technomancy | ts00000: is that slime from elpa? |
| 17:29 | ts00000 | technomancy: yes |
| 17:29 | chouser | lpetit: you'll have to determine that yourself, I'm just saying it has to be in memory, at least ... well ... hm. |
| 17:30 | lpetit | chouser: well, the core function is just interested in navigating the code beginning-to-end, keeping a stack of the parents of the current node, and call hof arguments that do whatever they want in the process (they are called for each character, and given the current stack, offset, line, column context) |
| 17:30 | chouser | lpetit: this is for paredit-like functionality? |
| 17:30 | lpetit | i'm currently implementing a version of the hof arg which will write the complete parsetree |
| 17:31 | lpetit | for other simpler cases, i'll implement less heavy hof args to just peek what I want on the fly |
| 17:31 | lpetit | chouser: did I forget to mention that i also reinvented SAX in the process ? :-) |
| 17:31 | chouser | hm... |
| 17:31 | ts00000 | technomancy: also, I seem to have to declare the (require 'clojure.http.resourcefully :as resourcefully) inside a namespace - is that normal, I assume so |
| 17:31 | technomancy | ts00000: what do you get evaling this elisp? http://p.hagelb.org/classpath.html |
| 17:31 | lpetit | chouser: yes, it's my "paredit.clj" project |
| 17:31 | chouser | lpetit: you didn't use that word, but I guessed so. |
| 17:31 | chouser | lpetit: SAX, I mean. |
| 17:32 | technomancy | ts00000: that's fine for resourcefully, though it's better to keep it inside the ns form with (:require [clojure.http.resourcefully :as resourcefully]) |
| 17:32 | chouser | lpetit: so do you know where the cursor is and what kind of operation the user's trying to do? |
| 17:33 | ts00000 | technomancy: i'm saying I can't seem to declare it outside the ns, e.g. in a repl. also, evaling your lisp gave the right classpath results, but for some reason it's like your function doesn't get called when I do swank-clojure-project |
| 17:33 | ts00000 | if I just call it directly that doesn't show up in the classpath var |
| 17:33 | lpetit | chouser: sure. it's easy to go to the right node from the offset of the cursor by elimination, given that I currently store the offset and length of each node. I have no doubt concerning the navigational part : I'll user zippers. It's the creational part where I was pondering the overhead of using zippers. |
| 17:34 | technomancy | ts00000: you could (setq swank-clojure-classpath [the code I pasted]) for now and use M-x slime instead of swank-clojure-project |
| 17:34 | chouser | lpetit: oh, once you've built a whole tree, making a zipper of it is very fast |
| 17:34 | ts00000 | technomancy: yeah, I can edit the classpath manually so i'm not too concerned, just surprised it didn't work is all |
| 17:34 | jcromartie | a little bit off-topic, but what color-theme are you using in Emacs? |
| 17:34 | technomancy | but I can't reproduce your problem, so not much else I can do |
| 17:35 | technomancy | jcromartie: that would be zenburn |
| 17:35 | technomancy | it's not a built-in theme |
| 17:35 | ts00000 | technomancy: is there a way to trace what's being done when I swank-clojure-project? |
| 17:35 | technomancy | ts00000: you could add calls to message in the function |
| 17:36 | technomancy | the output goes to the *Messages* buffer |
| 17:36 | technomancy | given the correct project root, the classpath seems to be calculated correctly |
| 17:36 | lpetit | chouser: FYI, I'm writing paredit.clj in an IDE agnostic way, purely clojure of course (and as idiomatic as I'm capable of, given that I've just sacrificed modularity over premature optimization in the main loop), and not just a port of paredit, but will be tailored for clojure (will know literal sets so that when selecting them you also have the leading sharp in the selection, etc.) |
| 17:36 | jcromartie | I have tried light-on-dark themes and it doesn't work well with OS X's LCD font smoothing. Light-on-dark ends up making the text heavier. |
| 17:38 | ts00000 | technomancy: using trace-function, the path seems to be set correctly, but even when I fully qualify the path, the classpath only shows what's in ~/.swank-clojure |
| 17:38 | chouser | lpetit: I wonder if it would be faster and more robust in the face of incomplete code files to start at the cursor and word backwards/forwards just as much as needed to complete the user's operation |
| 17:38 | ts00000 | technomancy: in fact, if ~/.swank-clojure is empty, nothing on the classpath at all. |
| 17:38 | ts00000 | weird. |
| 17:38 | technomancy | ts00000: oh, I realized it's done a little differently now. the swank-clojure-classpath elisp var is only modified inside a let binding |
| 17:39 | technomancy | so once the repl session is launched, it goes back to its root binding |
| 17:39 | technomancy | so try messaging it right before the call to (slime) at the end |
| 17:40 | joegg | Is there any plan to make the various clojure launcher scripts a part of clojure generally, or is it up to individuals and package maintainers to keep rewriting them? (I ask because I just found what I think is a bug in the macports clj script.) |
| 17:40 | technomancy | joegg: sooner the better, but I don't know of any concrete efforts to do so unfortunately =\ |
| 17:41 | ts00000 | technomancy: what, just (message "%s" swank-clojure-classpath) or something? |
| 17:41 | lpetit | chouser: I've considered this possibility, and rejected it, for two reasons : I wanted to please myself by writing a parser manually, which I had never made before, and I hope that Christophe will quickly release a workable version of parsley, which, with its incremental parsing feature, will be unbeatable |
| 17:42 | technomancy | sure |
| 17:42 | chouser | lpetit: ok. so building a tree that can be used by a zipper should cost essentially no more than building a tree. |
| 17:42 | chouser | lpetit: or are you asking about using the zipper api to build the tree itself? |
| 17:43 | lpetit | chouser: yes, asking about the added overhead of using the zipper api for building the tree (edit and al) too |
| 17:46 | chouser | lpetit: I think building using insert-left, insert-child, replace, etc. will only be a small constant factor slower than building a plain persistent tree |
| 17:47 | ts00000 | technomancy: I have something interesting to report. inside your function, everything is declared normally |
| 17:47 | ts00000 | technomancy: it's almost as if the classpath gets reset after slime |
| 17:47 | chouser | lpetit: so, not an unreasonable thing to try, I think. |
| 17:47 | ts00000 | technomancy: path is correctly specified, and your code is correctly expanded |
| 17:47 | lpetit | chouser: ok, so worth considering a zipper as my state, will avoid me some boiler plate code. Will try this , thanks! |
| 17:48 | chouser | lpetit: sure, good luck. |
| 17:48 | chouser | hm. (seq-zip (read foo)) |
| 17:49 | technomancy | ts00000: yes, since the classpath is set inside a let form, the changes are localized to that function call |
| 17:49 | technomancy | but since elisp doesn't have lexical scope but dynamic only, the call to slime sees the new value. |
| 17:50 | joegg | technomancy: What would a standardized clj script require? Pretty much just writing one and asking someone to pull from a branch? Or, if you know, what has prevented this from already being done? This seems like something I could roll up my sleeves and do. |
| 17:50 | joegg | Unless there's massive problems that I'm just too ignorant to see. :) |
| 17:50 | ts00000 | technomancy: ok, I see what you're saying, so how do I fix it so the command is useful again :-) |
| 17:51 | ts00000 | technomancy: let me rephrase that |
| 17:51 | technomancy | joegg: I think rich just hasn't made it a priority because he assumes everyone's going to get set up with Emacs or Netbeans or whatever. |
| 17:51 | ts00000 | technomancy: I know how to fix it on my side, but how can I fix it so that rather than setting this manually on a per-project basis, it's dynamically set within swank-clojure-project and passed correctly |
| 17:52 | technomancy | ts00000: well because of the way dynamic binding works, it *does* get passed correctly from swank-clojure-project's let binding into the call to slime |
| 17:53 | ts00000 | oh, I see what you're saying |
| 17:53 | ts00000 | you're saying slime does see the right classpath |
| 17:53 | ts00000 | but it's cleared after i've entered slime |
| 17:53 | ts00000 | so that when I look at the variable it's wrong |
| 17:53 | technomancy | yes, when you inspect it, you're outside of the let |
| 17:54 | technomancy | which is a different scope from what slime was seeing |
| 17:54 | ts00000 | ah, I got it |
| 17:54 | ts00000 | well, this is the problem though |
| 17:54 | ts00000 | the reason I investigated this in the first place was because I couldn't load clojure.http.client |
| 17:54 | technomancy | ts00000: did you add the jar after launching the session? |
| 17:54 | ts00000 | no |
| 17:54 | ts00000 | :) |
| 17:54 | ts00000 | but let me see if it works now |
| 17:55 | ts00000 | wow, how fantastically convenient |
| 17:55 | ts00000 | it's there |
| 17:55 | ts00000 | :-) |
| 17:56 | ts00000 | technomancy: now, you were saying that I should be able to require resourcefully inside a repl, with the :as but without the namespace, although of course the namespacing is the preferred way to do it, right? |
| 17:57 | ts00000 | but the syntax for that doesn't seem to be (require 'clojure.http.resourcefully :as resourcefully) - what is the right syntax? |
| 17:57 | technomancy | try wrapping everything after "require" in [] |
| 17:58 | ts00000 | well, if I do it with the ', it says unable to resolve symbol resourcefully in this context, if I do it without the ', it can't find the class |
| 17:59 | technomancy | ts00000: should be: (ns eveloci.core (:require [clojure.http.resourcefully :as resourcefully])) |
| 17:59 | technomancy | ns is a macro, so you don't need to quote anything |
| 18:00 | ts00000 | if I want to do it without changing the namespace, can that be done? |
| 18:00 | ts00000 | like I just want to mess around with it in the repl. |
| 18:00 | technomancy | right, if you want to do it in the repl, you'll also need to quote the final resourcefully |
| 18:00 | ts00000 | ah, ok |
| 18:00 | ts00000 | that's what I was missing |
| 18:00 | technomancy | otherwise it treats it as a variable and tries to look up the value |
| 18:00 | ts00000 | thanks so much :) |
| 18:00 | technomancy | but you want the symbol itself |
| 18:00 | technomancy | np |
| 18:00 | hiredman | uh |
| 18:00 | jcromartie | what is this all about? http://gist.github.com/282385 |
| 18:00 | jcromartie | [B ? |
| 18:00 | hiredman | you were missing the whole vector |
| 18:01 | hiredman | ,(class (make-array Byte/TYPE 1)) |
| 18:01 | clojurebot | [B |
| 18:01 | lpetit | chouser: yes, but has no story to handle incorrect input, and no story to handle comments, literal metadata, etc. |
| 18:01 | hiredman | jcromartie: you need to call .getBytes on the string |
| 18:01 | jcromartie | hmm |
| 18:02 | jcromartie | public static byte[] decodeBase64(String base64String) |
| 18:02 | jcromartie | so what's the problem, the return value? |
| 18:02 | hiredman | jcromartie: no idea |
| 18:02 | jcromartie | .getBytes works, by the way... I'm just confused as to why the String method doesn't |
| 18:02 | hiredman | the string method wasn't being called |
| 18:03 | jcromartie | yeah |
| 18:03 | hiredman | possibly you have an old version of the library without it |
| 18:03 | hiredman | what library is that? |
| 18:03 | jcromartie | Apache Commons Codec |
| 18:03 | ts00000 | ah: and so when I try to access (clojure.contrib.zip-filter), I also have to use the symbol to get at the functions |
| 18:03 | ts00000 | ('clojure.contrib.zip-filter/xml-) |
| 18:03 | ts00000 | right? |
| 18:04 | hiredman | ,(import 'org.apache.commons.codec.binary.Base64 |
| 18:04 | clojurebot | EOF while reading |
| 18:05 | hiredman | ,(import 'org.apache.commons.codec.binary.Base64) |
| 18:05 | clojurebot | java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64 |
| 18:05 | hiredman | bah |
| 18:05 | hiredman | ,(doc show) |
| 18:05 | clojurebot | "clojure.contrib.repl-utils/show;[[x] [x selector]]; With one arg prints all static and instance members of x or (class x). Each member is listed with a number which can be given as 'selector' to return the member object -- the REPL will print more details for that member. The selector also may be a string or regex, in which case only members whose names match 'selector' as a case-insensitive regex will be printed. Finall |
| 18:08 | jcromartie | ooh |
| 18:08 | jcromartie | that's awesome |
| 18:12 | technomancy | jcromartie: that's nothing... in slime use C-c S-i to pull up the inspector |
| 18:12 | technomancy | it's hyperlinked |
| 18:12 | alexyk | how do I access a static field of a class? |
| 18:13 | alexyk | Java's |
| 18:15 | ts00000 | is there any way to get at private documentation from the repl? |
| 18:18 | joegg | alexyk: (BigDecimal/ZERO) |
| 18:19 | joegg | Is that what you mean? |
| 18:19 | alexyk | joegg: yeah... for some reason I get an error, Unable to find static field, on a class which must have it |
| 18:20 | alexyk | how can I use reflection to see what's inside a class in repl? |
| 18:20 | alexyk | it's a public static final int BLAH = 8 |
| 18:29 | joegg | ,(sequence (.getFields (class ""))) |
| 18:29 | clojurebot | (#<Field public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER>) |
| 18:29 | joegg | alexky: That might help, I guess. |
| 18:29 | joegg | Oops, sorry for typoing your handle. |
| 18:30 | joegg | You can also just use the name of the class: |
| 18:30 | joegg | ,(sequence (.getFields BigInteger)) |
| 18:30 | clojurebot | (#<Field public static final java.math.BigInteger java.math.BigInteger.ZERO> #<Field public static final java.math.BigInteger java.math.BigInteger.ONE> #<Field public static final java.math.BigInteger java.math.BigInteger.TEN>) |
| 18:30 | joegg | Is that helping? |
| 18:31 | joegg | Also, if someone knows a better way, please correct me, as I'm just a beginner. |
| 18:32 | alexyk | will try, thx! |
| 18:35 | dabd | I'm trying to pass java HashMap to a clojure function and I get the following error: java.lang.ClassCastException: java.util.HashMap cannot be cast to clojure.lang.IPersistentCollection |
| 18:36 | dabd | what type of Map should I pass to the Clojure function? |
| 18:36 | arohner | dabd: try a PersistentMap |
| 18:36 | dabd | arohner: thx |
| 18:36 | arohner | hrm, that might have been bad advice |
| 18:37 | arohner | can you paste what you're trying to do? |
| 18:39 | dabd | arohner I'm trying this invoke(PersistentHashMap.create(map)); |
| 18:39 | dabd | and map is a Java HashMap |
| 18:39 | arohner | invoke? are you calling from java? |
| 18:39 | dabd | the invoked Clojure function excepts a Clojure Map |
| 18:39 | dabd | yes I am calling from Java |
| 18:40 | dabd | I am implementing a Web Service that uses Java API for RESTful WS and unfortunately since it relies on Java annotations I have to write some Java code, so I need to invoke Clojure from Java |
| 18:41 | arohner | I know (into {} (seq map)) will work. Looking for a better way now |
| 18:42 | jcromartie | dabd: invoke takes a function, PersistentHashMap.create(map) returns a new PersistentHashMap |
| 18:42 | jcromartie | invoke takes IFn |
| 18:42 | jcromartie | so your map is being cast to an IFn and called |
| 18:43 | jcromartie | the equivalent clojure would be ((map m)) |
| 18:43 | hiredman | jcromartie: un |
| 18:43 | hiredman | invoke is a method on a fn |
| 18:43 | jcromartie | dur |
| 18:43 | hiredman | it may or may not take a function |
| 18:43 | jcromartie | sorry |
| 18:44 | arohner | dabd: I think the java equivalent of (into {} (seq your-map)) is your best bet |
| 18:45 | dabd | arohner: I think that Java equivalent might be PersistentHashMap.create(map) where map is a Java HashMap |
| 18:45 | arohner | oh yeah, I missed that |
| 18:45 | arohner | yeah, that looks better |
| 18:47 | arohner | can you paste the whole of your invoke() line? |
| 18:47 | dabd | invoke seems to accept a number of Java Objects which are the arguments to pass to the Clojure function |
| 18:47 | hiredman | correct |
| 18:47 | dabd | arohner: Object result = groupbytf.invoke(PersistentHashMap.create(map)); |
| 18:47 | dabd | where groupbytf is a clojure.lang.Var |
| 18:47 | hiredman | ~def c.l.PersistentHashMap |
| 18:48 | hiredman | and you still get the exception? |
| 18:49 | dabd | no I'm past that. Now I have to debug the next error :-) thx |
| 18:55 | raz__ | Does anyone know if the clojure compiler can be used to generate the AST or some other representation of clojure source code? I know there are classes like DefExpr or AssignmentExpr and so on but it looks like the compiler just keeps those to itself and does not expose the AST. I'd like to build a toy refactoring tool and a model of the source code would be very useful |
| 19:00 | lypanov | chouser: (and the other author) man joy of f'n rules. |
| 19:01 | ctdean | You could use a tool like jad to decompile the .class file that clojure generates |
| 19:02 | lypanov | ctdean: i've heard that thats not a great way of trying to use gwt to go from clojure to js |
| 19:02 | lypanov | various complications mean it sounds like its easiest to take the ast and translate directly |
| 19:03 | ctdean | lypanov: sounds like you know more about this than me already :) |
| 19:04 | ctdean | I used jad when I was working on one of the Scheme to jvm compilers. It was a useful debugging tool, but that's all I ever used it for |
| 19:06 | fiatmoney | (println "hello clojurebot") |
| 19:06 | raz__ | try with a comma before it |
| 19:06 | raz__ | ,(println "like this?") |
| 19:07 | clojurebot | like this? |
| 19:07 | fiatmoney | ,(println "hello clojurebot") |
| 19:07 | clojurebot | hello clojurebot |
| 19:07 | fiatmoney | ah, cool, thanks |
| 19:07 | raz__ | guess it pays of to read #clojure logs instead of learning for exams |
| 19:07 | raz__ | off* |
| 19:07 | lypanov | hehe |
| 19:21 | raz__ | lypanov: there seems to be a parser in the 'La Clojure' Intellij plugin. Check the parser namespace. It uses the apache 2 license. The repository is here: git://git.jetbrains.org/idea/clojure-plugin.git |
| 20:05 | arohner | Raz_: why do you need a separate AST than (read)'ing source? |
| 20:06 | chouser | Raynes: you can indeed get at the analysis tree, which has richer semantic information than just what 'read' returns |
| 20:07 | chouser | sorry, that was for Raz_ |
| 20:07 | chouser | oh. actually, raz__, but he's gone |
| 20:07 | Raynes | chouser: It's okay. I understand. You love my name so much, you can't help but say it every chance you get. <3 |
| 20:17 | ts00000 | chouser: do you have any idea what 'Unable to resolve symbol: text in this context' might mean while using zip-filter? |
| 20:17 | ts00000 | I have some xml with an attr of name, could it be getting hung up on that? |
| 20:32 | chouser | ts00000: it probably means you're using the symbol 'text' someplace where it isn't defined |
| 20:32 | chouser | zip-filter.xml defines a fn named text I believe. are you :use'ing it? |
| 20:38 | ts00000 | chouser: i figured out where I went wrong by directly qualifying it; but now if I have some random xml def'd that has a foo attr with a value of bar, and I try to xml-> thexmlvar :foo, the repl tells me a string can't be cast to an iobj |
| 21:08 | ts00000 | i'm really close to figuring this out. I have a function that returns a map (it comes from http.client). i'm trying to parse it but I think xml/parse isn't accepting the map because an illegalargumentexception is thrown. how do I get it into something parseable? |
| 21:09 | hiredman | … |
| 21:09 | hiredman | have you read the docstring on xml/parse? |
| 21:09 | hiredman | does it say anything that would lead you to believe it takes a map? |
| 21:11 | ts00000 | obviously not, but when I try to feed it a string, it does something I don't expect. |
| 21:11 | ts00000 | like (xml/parse (str (:body-seq testfunc))) |
| 21:11 | hiredman | ,(doc clojure.xml/parse) |
| 21:11 | clojurebot | "([s] [s startparse]); Parses and loads the source s, which can be a File, InputStream or String naming a URI. Returns a tree of the xml/element struct-map, which has the keys :tag, :attrs, and :content. and accessor fns tag, attrs, and content. Other parsers can be supplied by passing startparse, a fn taking a source and a ContentHandler and returning a parser" |
| 21:11 | hiredman | "or String naming a URI" |
| 21:12 | ts00000 | ok, so can I somehow smash my already-retrieved stuff into an inputstream? |
| 21:12 | hiredman | .getBytes and java.io.ByteArrayInputstream |
| 21:14 | ctdean | ,(doc with-in-str) |
| 21:14 | clojurebot | "([s & body]); Evaluates body in a context in which *in* is bound to a fresh StringReader initialized with the string s." |
| 21:17 | Raynes | ts00000: (ByteArrayInputStream. (.getBytes stuff "UTF-8")) |
| 21:20 | hiredman | #/. is like window 11, so escape+number key doesn't find it |
| 21:20 | hiredman | erp, mischan |
| 21:24 | ts00000 | i've got to be making this out to be far more complex than it should be :/ |
| 21:27 | ts00000 | in my map, the body of the returned xml is a sequence |
| 21:31 | dabd | is anyone able to inspect/watch values when debugging Clojure code with netbeans? |
| 21:41 | alexyk | how do you translate this into clojure: collection.find( query ).skip( 1000 ).limit( 100 ).toArray() |
| 21:41 | alexyk | is it what .. are for? |
| 21:42 | chouser | sure. or -> |
| 21:42 | hiredman | (-> collection filter drop take) |
| 21:42 | chouser | (-> collection (.find query) (.skip 1000) (.limit 100) .toArray) |
| 21:43 | alexyk | and what .. would look like? |
| 21:43 | chouser | (.. collection (find query) (skip 1000) (limit 100) toArray) |
| 21:43 | alexyk | hard to tell what's nicer |
| 21:43 | chouser | that is, it suddenly becomes less clear if find is a method or a fn, and samke with skip and limit |
| 21:44 | chouser | and you can no longer include regular clojure fns in the pipeline. |
| 21:45 | alexyk | oh, I need further trickery: if skip or limit parameters are nil, the whole skip or limit call must be avoided. How can I account for it? |
| 21:45 | chouser | you want to just return nil then instead of doing the rest of the chain? |
| 21:46 | alexyk | no -- find is always done; skip or limit should be simply skpped over if their arg is nil |
| 21:46 | cemerick | dabd: inspect, yes -- you can't set clojure watches though, AFAIK |
| 21:46 | alexyk | teh final toArray is also always done |
| 21:47 | chouser | if their arg is nil instead of 1000? |
| 21:47 | alexyk | yep |
| 21:48 | alexyk | is it a use case for a macro? |
| 21:50 | chouser | (-> c (.find q) (#(if n (.skip % n) %)) ...) |
| 21:50 | chouser | ick |
| 21:50 | dabd | cemerick: say u have a breakpoint on a Clojure line. How do you inspect a value? |
| 21:50 | alexyk | yackety-yack |
| 21:50 | alexyk | or yuckety-yuck |
| 21:51 | cemerick | dabd: open the 'variables' tab and dig around |
| 21:52 | alexyk | never wrote a macro; but perhaps one can be used for (#(if n (~method % n) %)) ? |
| 21:52 | dabd | cemerick: thx |
| 21:53 | cemerick | dabd: np -- FYI, make sure you have a tostring column in your variables table -- that should print out nicely-formatted representations of standard data structures, etc. |
| 21:55 | dabd | cemerick: thx for the tip! |
| 21:55 | alexyk | chouser: makes sense? what would the macro look like? |
| 21:56 | chouser | hm.. yes, a macro might work there. |
| 22:02 | alexyk | I'd appreciate a sample macro as an example |
| 22:03 | alexyk | would be a starting point! |
| 22:04 | chouser | well, the recipe is: first write the output by hand |
| 22:07 | alexyk | ok |
| 22:07 | ts00000 | any ideas where i'm going wrong? http://pastie.org/787642 |
| 22:08 | alexyk | chouser: to that's essentially (method coll n) or nil |
| 22:09 | ts00000 | testfunc returns something like {:body-seq ("<?xml version='1.0' encoding='UTF-8'?>" "<name>xxx</name>")} |
| 22:09 | ts00000 | but I can't seem to get at the text of <name> |
| 22:10 | chouser | alexyk: (let [a nil] (-> 5 ((fn [x] (if a (+ x a) x))))) |
| 22:10 | alexyk | chouser: something like this? (defmacro methornil [coll method n] `(#(if ~n (~method ~coll ~n) ~coll))) |
| 22:10 | alexyk | I |
| 22:10 | alexyk | ' |
| 22:10 | alexyk | ve made it up |
| 22:11 | alexyk | so it doesn't work yet :) |
| 22:12 | chouser | I don't think you can use #() in a macro expansion |
| 22:13 | somnium` | maybe smthing like (defmacro ?#&! [arg pred f] `(if ~pred (~f ~arg) ~arg)) |
| 22:13 | somnium` | every time I use clojure.walk I seem to write something similar |
| 22:14 | chouser | we're skipping a step. The next step is an example usage. |
| 22:14 | somnium` | my bad :) |
| 22:14 | chouser | :-) |
| 22:14 | chouser | (let [a nil] (-. |
| 22:15 | chouser | (let [a nil] (-> 5 (foo + a))) perhaps? |
| 22:17 | chouser | so, (defmacro foo [fnname & args] ...) right? |
| 22:17 | alexyk | yep |
| 22:18 | alexyk | which will then expand to the icky (#(if...)) thing |
| 22:20 | chouser | hm.. actually, looking at that example usage, I don't think it needs to be a macro at all |
| 22:22 | alexyk | I want this form: (-> [1 2 3] (methornil take 2)) |
| 22:22 | alexyk | if 2 is not nil, take is applied to [1 2 3], otherwise the original is returned |
| 22:22 | alexyk | methornil is "method or nil" |
| 22:22 | alexyk | a patented medication against macrophobia |
| 22:23 | chouser | (defn foo [x f a] (if a (f x a) x)) |
| 22:24 | alexyk | so no need for macros at all |
| 22:24 | chouser | :-) |
| 22:24 | chouser | sorry |
| 22:24 | alexyk | pity |
| 22:24 | alexyk | methornil expired |
| 22:24 | chouser | (let [a nil] (-> 5 (foo + a)) ;=> 5 |
| 22:24 | chouser | (let [a 9] (-> 5 (foo + a))) ;=> 14 |
| 22:25 | alexyk | indeed |
| 22:25 | alexyk | I'll call it methornil anyways :) |
| 22:25 | chouser | sure |
| 22:26 | alexyk | I stylistically prefer ->> to ->, is there any logic here to pick ->? |
| 22:26 | alexyk | I can reorder methornil's arg order |
| 22:26 | chouser | heh. yep. |
| 22:26 | chouser | oops. I'm not writing. |
| 22:27 | alexyk | ? |
| 22:27 | chouser | the book |
| 22:27 | alexyk | ah |
| 22:28 | somnium` | alexyk: how about <-??-> |
| 22:28 | alexyk | what's that? |
| 22:28 | somnium` | (its shorter than methornil) |
| 22:28 | alexyk | but it's not medicinal-sounding |
| 22:28 | alexyk | somnium`: I've tried to pick up mongo-specifics in the separate chat, so you see that? |
| 22:32 | ts00000 | wow, how counterintuitive, finally got it to work |
| 22:33 | ts00000 | what a pain in the royal ass :/ |
| 22:37 | ts00000 | chouser: now I have one that should be very easy to answer: why doesn't the root tag need to be declared when you're accessing an attribute with zip-filter.xml? I can't even get at the root tag |
| 22:37 | defn | Ask your Dr. of Computer Science if Methoril is right for you. |
| 22:38 | chouser | there's always one root, so you can just skip it |
| 22:38 | ts00000 | what if there are attrs on the root I want to get at? |
| 22:38 | ts00000 | e.g. <s3-api version="2"> ....body.... </s3-api> |
| 22:38 | chouser | oooh! hmph! |
| 22:38 | ts00000 | this is one of the things that has been confusing me all night and just had the eureka moment |
| 22:39 | ts00000 | by removing the root element all of a sudden all my blanks actually had data |
| 22:39 | ts00000 | :) |
| 22:44 | ts00000 | Error Message %ADJ-5-PARENT: Midchain parent maintenance for [chars] - [chars] |
| 22:44 | ts00000 | Explanation A midchain adjacency failed to stack onto an output chain because a loop was detected. Traffic through the adjacency will be dropped until the adjacency is restacked. This condition is typically transient and is resolved by the control plane that drives the stacking. For example, if an IP tunnel destination resolves through the tunnel transiently this message will appear. The situation would be resolved either by learning the tunnel destination t |
| 22:44 | ts00000 | sorry :/ |
| 22:44 | chouser | ts00000: oh, you can still pull attrs from the root element |
| 22:44 | ts00000 | ts00000: how? |
| 22:44 | chouser | when you put a tag like :foo, it descends a level an looks for a tag there. |
| 22:46 | ts00000 | chouser: in my case, i'm trying (xml-> blah :s3-api (attr :version)) - wrong way? |
| 22:46 | ts00000 | s3-api is the root of the tree |
| 22:47 | chouser | just drop the :s3-api |
| 22:47 | chouser | you're already at the root of the tree |
| 22:47 | ts00000 | ah! |
| 22:48 | ts00000 | I got it now |
| 22:48 | ts00000 | perfect |
| 22:49 | ts00000 | thanks so much for being patient |
| 22:49 | ts00000 | i think it does rescan and walk it after the timers are done |
| 22:49 | alexyk | ,(letfn [(methornil [x f a] (if a (f x a) x))] (methornil [1 2 3] take 2)) |
| 22:49 | clojurebot | java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number |
| 22:50 | chouser | sure. I actually find zip-filter fragile to use as well. I'm not sure how to fix it though. :-/ |
| 22:50 | alexyk | why error? |
| 22:50 | ts00000 | i don't think it needs to be fixed |
| 22:50 | ts00000 | it's just the most rapid way to prototype what I want to do, when what I should be doing is going deeper with just parsing out the tree itself |
| 22:51 | ts00000 | if I were to offer only one suggestion as a complete newbie coming to clojure, i'd say that in the absence of more error messages, there needs to be a more obvious way to trace and figure out why things are going wrong. the repl is great but it is unforgiving. |
| 22:51 | chouser | yeah, zip-filter just give you nils, and you're left flailing around |
| 22:51 | ts00000 | let me rephrase that; slime+repl is great but unforgiving |
| 22:51 | alexyk | ts00000: I saved a defn into a file, load-file it, boom -- printStackStrace prints the actual file:line, not no-source-file:0 :) |
| 22:51 | ts00000 | yes, there is a lot of flailing around in clojure I have noticed, it lets you do things that are not otherwise correct |
| 22:52 | hiredman | tree-map + filter works pretty well |
| 22:52 | ts00000 | alexyk: the no-source-file:0 is actually helpful to me when determining what's going on int he repl versus the file |
| 22:52 | alexyk | ts00000: unless you pasted 25 lines |
| 22:52 | chouser | alexyk: your args to 'take' are backwards |
| 22:52 | ts00000 | alexyk: but look at it this way, as a newcomer, your choices of IDEs are limited, and none of them are particularly helpful, and a great many newcomers are left choosing emacs, which is even more of an issue |
| 22:52 | ts00000 | alexyk: good point |
| 22:52 | alexyk | chouser: doh |
| 22:53 | alexyk | ts00000: newbies should stay away from IDEs |
| 22:53 | alexyk | wasting time on Emacs unless you know it or some GUIs is silly... raw text editor and repl and forge ahead! |
| 22:53 | ts00000 | yes, but developing without one, especially for someone new, is difficult :-) |
| 22:53 | alexyk | my take at least |
| 22:53 | hiredman | http://github.com/hiredman/clojurebot/blob/master/src/hiredman/clojurebot/clojars.clj <-- clojurebot scraping for the recently on clojars notices |
| 22:55 | alexyk | hiredman: how about capturing outcries "clojars search is broken" and forwarding it to the clojars-ers? :) |
| 22:56 | hiredman | *shrug* |
| 22:57 | alexyk | chouser: is there a "flip" adatper on things like take? |
| 22:57 | alexyk | adapter |
| 22:58 | alexyk | so I'd have only one methornil and call it with (flip take) or something |
| 22:58 | chouser | #(foo %2 %1)) |
| 22:59 | alexyk | ah |
| 23:00 | chouser | ,(-> [a 5] (let a)) |
| 23:00 | clojurebot | 5 |
| 23:01 | arohner | chouser: that's a little crazy |
| 23:03 | alexyk | what's (let a) ? |
| 23:03 | arohner | alexyk: (let a) doesn't work, but the macro turns that into (let [a 5] a) |
| 23:05 | alexyk | don't show it to the scala people :) |
| 23:06 | arohner | yeah |
| 23:06 | arohner | ,(macroexpand '(-> [a 5] (let a)) |
| 23:06 | clojurebot | EOF while reading |
| 23:07 | arohner | (macroexpand '(-> [a 5] (let a))) |
| 23:07 | arohner | ,(macroexpand '(-> [a 5] (let a))) |
| 23:07 | clojurebot | (let* [a 5] a) |
| 23:07 | chouser | ,((->> (+ a b) (fn [a b])) 4 5) |
| 23:07 | clojurebot | 9 |
| 23:08 | arohner | ok now you're scaring me |
| 23:08 | arohner | ,(macroexpand '((->> (+ a b) (fn [a b])) 4 5)) |
| 23:08 | clojurebot | ((->> (+ a b) (fn [a b])) 4 5) |
| 23:08 | chouser | ,(->> (inc a) (let [a 5])) |
| 23:08 | clojurebot | 6 |
| 23:09 | chouser | actually, it would be better to show this to nobody at all. |
| 23:09 | chouser | ,(->> a (+ 5) (let [a 5])) |
| 23:09 | clojurebot | 10 |
| 23:10 | joegg | ,(->> "Ooh, me too!" (println)) |
| 23:10 | clojurebot | Ooh, me too! |
| 23:10 | joegg | YAY! |
| 23:10 | chouser | if there's only one thing, you don't even need parens |
| 23:11 | joegg | Ah, because of the "makes it a list" part... |
| 23:11 | joegg | Sweet. |
| 23:12 | arohner | I need a random arrow. Takes your form and stick the first argument in a random place in the list... |
| 23:13 | arohner | wraps it in try catches, and tries again, until you make a form that doesn't throw an exception |
| 23:13 | alexyk | arohner: or even into a random orifice of the programmer |
| 23:14 | alexyk | "an arrow of doom" |
| 23:14 | ts00000 | where is the ->> better explained/documented? |
| 23:14 | ts00000 | i've looked at the doc string and in programming clojure but that doesn't cover that very well |
| 23:15 | chouser | do not look at the examples I was just giving. |
| 23:15 | alexyk | chouser: too late |
| 23:15 | chouser | they're a horrible abuse |
| 23:15 | ts00000 | <- eyes covered |
| 23:15 | chouser | I apologize for even mentioning them |
| 23:15 | ts00000 | i'm just curious, want to learn more |
| 23:15 | chouser | and then tweeting |
| 23:15 | chouser | ,(->> (range 30) (filter even?) (drop 10)) |
| 23:16 | clojurebot | (20 22 24 26 28) |
| 23:16 | chouser | that's a better example |
| 23:16 | chouser | each form is inserted as the final argument of the next form |
| 23:16 | chouser | so the above is the same as (->> (filter even? (range 30)) (drop 10)) |
| 23:16 | alexyk | every time a crooked ->> is used, a frog dies in the Amazon |
| 23:16 | chouser | which is the same as (drop 10 (filter even? (range 30))) |
| 23:17 | ts00000 | why would you want to use that as opposed to the (drop 10 ...) ? |
| 23:17 | chouser | this will be explored in detail in chapter 7 |
| 23:17 | chouser | :-) |
| 23:17 | ts00000 | of your new book? |
| 23:18 | ts00000 | joy of closure meap? |
| 23:18 | chouser | ts00000: it allows you to read it left-to-right, instead of inside-out. Can also help reduce nesting levels. Mostly a matter of taste. |
| 23:18 | chouser | ts00000: yep. http://joyofclojure.com/ |
| 23:18 | ts00000 | it's on the list for this weekend actually :) |
| 23:19 | chouser | except the TOC there will be revised next time the MEAP is updated |
| 23:19 | chouser | the version that's available now is undergoing major surgery by fogus's deft hand |
| 23:20 | alexyk | since clojure is lisp-2, function literals mean themselves, right? so I could call (methornil coll take 2). Now what if instead of take it's (methornil obj .method n) -- can I still invoke with literal method name .method? |
| 23:20 | arohner | clojure is not a lisp-2 |
| 23:20 | alexyk | lisp-1 I meant |
| 23:20 | alexyk | my understanding of the first part of my own utterance is infirm |
| 23:20 | alexyk | that's the gist I gathered from the past here :) |
| 23:21 | arohner | lisp-1 means that variables and functions live in the same namespace |
| 23:21 | arohner | in lisp-2s, you can have a variable foo, and a function foo, and they don't step on each other |
| 23:21 | alexyk | right; does it affect the fact that you can supply a function as a parameter by just writing its name? |
| 23:21 | arohner | yes |
| 23:22 | alexyk | ok, that's solved. Now about .method? |
| 23:22 | chouser | .foo is not a function |
| 23:22 | chouser | unfortunately |
| 23:22 | alexyk | arrgh |
| 23:22 | chouser | it's a special form |
| 23:22 | alexyk | methornil's just become obsolete |
| 23:22 | chouser | but this is actually a good thing! |
| 23:22 | chouser | because now you have an excuse to write methornil as a macro |
| 23:23 | arohner | you're wanting to pass a java method around to clojure functions? |
| 23:23 | alexyk | yep |
| 23:23 | alexyk | chouser: yay! let's do it |
| 23:23 | alexyk | back to the macros |
| 23:24 | alexyk | so I need to write a macro methornil, equivalent to the defn: (defn methornil [x f a] (if a (f x a) x)), which takes java methods as f |
| 23:25 | chouser | (defmacro methornil [x f a] `(if ~a (~f ~x ~a) ~x)) |
| 23:25 | chouser | except that expands a and x twice each, which could potentially cause problems |
| 23:26 | alexyk | chouser: is there like a macro val which stores the single expansion for reuse? |
| 23:26 | arohner | alexyk: your friend 'let' will do that |
| 23:26 | chouser | you just have your macro expand to something like (let [x-val x] ...) |
| 23:27 | arohner | (defmacro methodornil [x f a] `(let [a# ~a x# ~x] (if a# (~f x# a#) x#)) |
| 23:27 | alexyk | right |
| 23:27 | alexyk | what's a# and x#? |
| 23:28 | alexyk | ah, just single expansions |
| 23:28 | alexyk | chouser: so how would you summarize why exactly we need macro for both methods and functions? :) |
| 23:28 | alexyk | before you go... |
| 23:28 | arohner | nobody's ever told me I'm capable at clojure before |
| 23:29 | arohner | alexyk: you need a macro before java methods are not first class functions |
| 23:29 | alexyk | arohner: using # is a sign of maturity, also thwarts perl and ruby and python people into stupefaction :) |
| 23:29 | arohner | (.foo obj) is a special form; you use the macro to produce those |
| 23:30 | alexyk | right |
| 23:30 | alexyk | somnium`: perl people turn off like androids upon seeing # |
| 23:30 | alexyk | and skip to the next line |
| 23:32 | alexyk | ok, finally a case for macros. somnium`, consider this: I switched to clojure 'cause congomongo is better at mongo than scala for data; now it has lead me to learn macros. What else is in store? |
| 23:33 | alexyk | the next application of congomongo is general relativity probably |
| 23:34 | somnium` | alexyk: once you get comfortable with macros, you may find any non-lisp to feel unpleasantly lacking in expressiveness |
| 23:35 | somnium` | that, or general relativity I guess |
| 23:36 | joegg | alexky: one of the main things that macros allow you to do is to create new first class syntax, which I think you're already picking up on. |
| 23:36 | joegg | Darn, again, typo'd your name. |
| 23:36 | alexyk | np) |
| 23:36 | joegg | Anyway, (if...) is a macro that just calls (cond...), more or less. |
| 23:37 | joegg | (Also, I'm a beginner, so if I end up saying something wrong, anyone can feel free to correct me please.) |
| 23:37 | somnium` | ,(macroexpand '(cond true :foo)) |
| 23:37 | clojurebot | (if true :foo (clojure.core/cond)) |
| 23:37 | alexyk | how can you check what's a macro? |
| 23:37 | joegg | Now, one thing that I've always wanted in javascript/java/etc is a while/else. |
| 23:37 | arohner | alexyk: the metadata of the var |
| 23:37 | arohner | ,(meta (var cond)) |
| 23:37 | clojurebot | {:macro true, :ns #<Namespace clojure.core>, :name cond, :file "clojure/core.clj", :line 400, :arglists ([& clauses]), :doc "Takes a set of test/expr pairs. It evaluates each test one at a\n time. If a test returns logical true, cond evaluates and returns\n the value of the corresponding expr and doesn't evaluate any of the\n other tests or exprs. (cond) returns nil."} |
| 23:37 | tomoj | it tells you in (doc cond) too |
| 23:38 | joegg | while(foo) { } else { }, where the else is executed only if the while was never executed. |
| 23:38 | arohner | oh, right |
| 23:38 | joegg | In javascript, I couldn't have that, unless I wanted to write my own implementation. |
| 23:38 | tomoj | macro? would have to be a macro, eh? |
| 23:38 | joegg | Or, fake it, horribly, using functions. |
| 23:38 | joegg | In clojure, *I can create while/else using macros.* |
| 23:39 | joegg | And it has the same (total lack of) syntax as everything else, it's not some second class thing. |
| 23:39 | defn | hi all |
| 23:40 | defn | ls |
| 23:40 | joegg | alexyk: Does that make sense? (also, just found out I can tab-complete nicks.) |
| 23:42 | alexyk | yeah |
| 23:43 | alexyk | defn: we just decided macro is a better nick |
| 23:50 | joegg | Ooh, while-else, implemented (crappily): |
| 23:50 | joegg | (defmacro while-else [test body else] `(if ~test (while ~test ~body) ~else))) |
| 23:51 | joegg | Can anyone tell me if I've done something wrong on that? |
| 23:51 | joegg | It appears to work fine here, but I would love to know if there's something I could do differently or better. |