2011-03-06
| 00:00 | skelternet | the documentation to write and parse xml in clojure is easier to find than the reason not to, and how to dump your struct to a clojure file, and read it back in. |
| 00:01 | skelternet | Sure the clojure docs are there, but I haven't found a blog or an article that says "no no, don't do that...do this! It's native!" |
| 00:01 | amalloy | skelternet: if your struct doesn't include foreign java objects, the latter is trivial and the former is not |
| 00:02 | amalloy | but send an email to alan@malloys.org to remind me and i'll see if i can put together a blog post about it |
| 00:02 | TimMc | Oh, this is bloody brilliant. |
| 00:02 | amalloy | TimMc: the article, or something you've just done? |
| 00:03 | TimMc | The serialization support. |
| 00:03 | skelternet | ? |
| 00:03 | TimMc | skelternet: Let me gist something for you. |
| 00:03 | amalloy | i think he's referring to the extensibility of print-dup |
| 00:04 | skelternet | I'm so new, I don't think I could ref my own butt at this point. |
| 00:04 | skelternet | However, I did manage to use enlive to rescue our database schema documentation from our wiki. 3500 column defs |
| 00:04 | amalloy | hah |
| 00:05 | skelternet | so, now is a good time for me to sharpen my saw. |
| 00:05 | skelternet | (only 3500 of the columns were documented. we have >6000) |
| 00:06 | TimMc | amalloy: OK, less brilliant than I thought. |
| 00:06 | amalloy | lol |
| 00:06 | amalloy | TimMc: gist it already |
| 00:09 | TimMc | https://gist.github.com/857048 |
| 00:10 | skelternet | oops |
| 00:10 | amalloy | $google defrecord2 |
| 00:10 | sexpbot | First out of 20 results is: david-mcneil/defrecord2 - GitHub |
| 00:10 | sexpbot | https://github.com/david-mcneil/defrecord2 |
| 00:10 | amalloy | i believe that includes readable print-dups |
| 00:10 | TimMc | heh |
| 00:14 | TimMc | Thanks, I'll think about using that. |
| 00:14 | skelternet | it seems long. but yeah, thank you! |
| 00:15 | TimMc | For now, though... bed. G'night! |
| 00:32 | waxrose | Howdy every one. :) |
| 00:34 | amalloy | hola waxrose |
| 00:34 | waxrose | amalloy, :D |
| 01:49 | Scriptor | man, not seeing pipes to separate stuff in the topic feels weird |
| 01:50 | amalloy | silly Scriptor, pipes are for combining stuff! find | grep |
| 01:51 | Scriptor | but...but...delimeters! |
| 02:28 | amalloy | heehee. i just wrote (str tok). reminds me of the bad old days in C |
| 02:33 | Derander | amalloy: I have never written a C program |
| 02:34 | amalloy | Derander: it's not a bad thing to be able to do |
| 02:34 | amalloy | what are your other languages? |
| 02:34 | shachaf | amalloy: Hopefully not with the same meaning as in C? :-) |
| 02:34 | Derander | amalloy: the web languages |
| 02:34 | Derander | amalloy: javascript, php, ruby, clojure |
| 02:34 | Derander | I guess I know haskell |
| 02:34 | amalloy | Derander: the joke is that strtok is one of C's worst APIs |
| 02:35 | amalloy | it's inherently un-thread-safe |
| 02:35 | shachaf | Clojure is a web language? |
| 02:35 | Derander | I know that string stuff in C is the cause of problems |
| 02:35 | Derander | scode_: no. |
| 02:35 | Derander | scode_: wrong person, sorry. shachaf |
| 02:35 | Derander | I just meant that I came into programming primarily through the web |
| 02:35 | amalloy | Derander: strtok is worse. iirc instead of returning something, it modifies a global variable to reflect what it wants to return |
| 02:35 | Derander | brilliant |
| 02:36 | amalloy | $google c strtok string.h |
| 02:36 | sexpbot | First out of 7770 results is: strtok - C++ Reference |
| 02:36 | shachaf | To be fair, there's strtok_r. |
| 02:36 | sexpbot | http://www.cplusplus.com/reference/clibrary/cstring/strtok/ |
| 02:36 | amalloy | shachaf: sure sure |
| 02:37 | shachaf | amalloy: Is strtok *inherently* thread-unsafe? |
| 02:38 | Derander | amalloy: I guess I was being vaguely untruthful. C was the first language I "learned", but I was 6-7 at the time and it did not stick. |
| 02:38 | amalloy | shachaf: C string to truncate. The contents of this string are modified and broken into smaller strings (tokens). Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended. |
| 02:39 | amalloy | so to get more than one token out of your string, you call it with NULL after the first time |
| 02:39 | shachaf | amalloy: Sure, but it could use a thread-local variable instead of a global variable pretty easily. |
| 02:39 | amalloy | that's fair, i suppose |
| 02:39 | amalloy | you still have to add the _r semantics to be any good at all, of course |
| 02:40 | shachaf | Of course. |
| 02:40 | shachaf | And even then it's a pretty suspicious function. |
| 02:41 | amalloy | whereas (str tok) is delightfully clear and simple: convert tok to a string :P |
| 03:07 | amalloy | guys fnparse is pretty awesome |
| 03:20 | khaliG | hi, what's the idiomatic way of getting the filenames in a directory? |
| 03:21 | amalloy | khaliG: file-seq, i think |
| 03:21 | khaliG | amalloy, looks good, thank you |
| 04:59 | octe | ,(/ 10 3) |
| 04:59 | clojurebot | 10/3 |
| 05:04 | clgv | ,(/ 30 9) |
| 05:04 | clojurebot | 10/3 |
| 05:04 | clgv | just curious^^ |
| 05:19 | bennylut | what functions can iterate over a map (as key-value pairs)? |
| 05:20 | clgv | e.g. map ;) |
| 05:20 | clgv | afaik a map is a seq of key-value pairs |
| 05:20 | bennylut | clgv, hmm.. didnt know it can be handled like that |
| 05:21 | bennylut | the map function parameter just need to get 2 parameters (aka key+value)? |
| 05:21 | clgv | &(map #(println (str "key = " (key %) " val = " (val %))) {:bla 1 :blubb 2.0 :lala 10/3}) |
| 05:21 | sexpbot | ⟹ (key = :bla val = 1key = :blubb val = 2.0nil key = :lala val = 10/3nil nil) |
| 05:22 | bennylut | clgv, thanks!\ |
| 05:22 | clgv | &(dorun (map #(println (str "key = " (key %) " val = " (val %))) {:bla 1 :blubb 2.0 :lala 10/3})) |
| 05:22 | sexpbot | ⟹ key = :bla val = 1 key = :blubb val = 2.0 key = :lala val = 10/3 nil |
| 05:22 | clgv | oh sexpbot omits line-ends... |
| 05:23 | bennylut | clgv, its ok i get the picture :) |
| 05:23 | clgv | I thought so ;) |
| 05:25 | clgv | yo might consider using destructuring in the fn |
| 05:25 | clgv | &(dorun (map (fn [[k v]] (println (str "key = " k " val = " v))) {:bla 1 :blubb 2.0 :lala 10/3})) |
| 05:25 | sexpbot | ⟹ key = :bla val = 1 key = :blubb val = 2.0 key = :lala val = 10/3 nil |
| 05:29 | the-anome | hi |
| 05:33 | bennylut | clgv, thank again :) |
| 08:35 | TimMc | This is because C is a toy language originally intended for implementing an OS to so a guy could write a chess program. |
| 08:35 | TimMc | Ack, sorry -- hadn't scrolled down. |
| 08:37 | bawr | That reminds me - if I name some of my functions like X<-Y, taking Y and returning X, will people hate me? ;) |
| 08:38 | bawr | This is probably due to some Hungarian Notation virus, really. |
| 08:46 | ttmrichter | TimMc: It wasn't a chess program. It was Space War, if memory serves. |
| 08:47 | TimMc | It wasn't Ken what's-his-face at Bell Labs, wanting to write a chess AI opponent on spare hardware? |
| 08:47 | TimMc | That's what one of my profs told me. |
| 08:49 | ttmrichter | Nope. It was tragically far goofier than that. |
| 08:49 | ttmrichter | A chess AI would have a bit of cachet. |
| 08:50 | ttmrichter | Unix started life as a quick and dirty OS for a PDP-7 to run Space War. |
| 08:50 | ttmrichter | C started as a portable assembler to move Unix to a PDP-11. |
| 08:51 | ttmrichter | (I may have the name of the game wrong in retrospect -- it was Space something, but that something might be War or something else.) |
| 08:57 | ttmrichter | Ah, here we are! Space Travel. http://people.fas.harvard.edu/~lib215/reference/history/spacetravel.html |
| 09:01 | TimMc | haha |
| 09:19 | pyr | TimMc: i got my pb right fixed it with a lazy-seq |
| 10:27 | TimMc | Makes sense. |
| 10:48 | TimMc | Argh, I just hit C-x C-s to save a doc in another program -- emacs is eating my brain! |
| 10:49 | clgv | lol. that isnt exclusive to emacs. I did strg+s when I had the impulse to temporary save a comment I was posting in a wiki ;) |
| 10:50 | clgv | it gets really stupid if paranoia kicks in and you'll end up pressing strg+s multiple times without a change ;) |
| 10:52 | TimMc | strg? |
| 10:52 | clgv | oops. in english: ctrl ;) |
| 10:52 | TimMc | ah |
| 10:53 | clgv | lol the left one already has no caption anymore |
| 10:53 | TimMc | When I do that, the browser prompts me for a filename to save the page to. >_< |
| 10:53 | clgv | yeah. thats the problem ;) |
| 10:54 | TimMc | Wha makes it worse is that some pages (e.g. Google Docs) will capture and use the keystroke. |
| 10:54 | clgv | but if they save the data it's probably ok ;) |
| 10:54 | clgv | deleting it without backup would be a real killer feature ;) |
| 10:57 | TimMc | I've been thinking about making a website that violates as many user expectations as possible. I may use that idea. :-) |
| 10:58 | clgv | lol. send me the link on completion ;) |
| 10:59 | TimMc | It's just an idea I'm kicking around. |
| 11:11 | eckroth | macros that use macros are a bit challenging for me; specifically, if I have multiple namespaces that each have a unique macro, and each of these macros use some common macro, where do I put the common macro? |
| 11:14 | clgv | the question remains the same if you replace macro by function ;) |
| 11:14 | clgv | does it sound easier now? |
| 11:15 | clgv | I would place it in a namespace for itself that communicates its "common" notion |
| 11:16 | clgv | perhaps you have other common definitions then you could put the together |
| 11:16 | clgv | s/the/them/ |
| 11:16 | sexpbot | <clgv> perhaps you have othemr common definitions themn you could put them togethemr |
| 11:16 | clgv | oops |
| 11:17 | eckroth | I've had confusing experiences in which I felt that the common macro wasn't found, that it had to be local (duplicated for each use); I'll run a few tests right now |
| 11:18 | clgv | that sounds strange. |
| 11:24 | eckroth | clgv: yeah, I can't reproduce the behavior on a simple test; I suppose you're right :) |
| 11:24 | clgv | I used macros across namespace boundaries ;) |
| 11:29 | dfan | What's the idiomatic way to construct a map with precomputed values? I did it 'by hand' with (apply hash-map (apply concat (for [n (range 0 100)] [n (f n)]))) but that seems suspiciously verbose |
| 11:30 | clgv | dfan: you could use map-cat instead |
| 11:30 | eckroth | (reduce (fn [m n] (assoc m n (f n))) {} (range 0 100)) ? |
| 11:31 | DespiteItAll | sounds like a job for map-indexed |
| 11:31 | dfan | clgv: mapcat, you mean? I don't see how that's relevant here |
| 11:31 | clgv | like: (apply hash-map (mapcat (fn [n] [n (f n)]) (range 0 100)) |
| 11:31 | DespiteItAll | (map-indexed f (range 0 100)) |
| 11:32 | DespiteItAll | but for the more general case, I use apply hash-map. I've had that catch mistakes that reduce/assoc wouldn't catch (duplicate keys) |
| 11:33 | dfan | Aha, OK, you're using mapcat to combine my (concat (for)) |
| 11:33 | clgv | yes |
| 11:33 | DespiteItAll | oh, duh, map-indexed doesn't return a map, so you'd still need apply hash-map |
| 11:34 | clgv | yeah. and he doesnt the index-property in this case at all ;) |
| 11:34 | clgv | thats only usefull when you iterate over other "objects" |
| 11:35 | dfan | OK, thanks, it sounds like there's nothing ridculously shorter |
| 11:35 | clgv | not really, since you have to create that list |
| 11:36 | DespiteItAll | clgv: Yep, I smoke lots of crack. |
| 11:36 | DespiteItAll | At best I was thinking of zipmap, but really I'm not making any sense |
| 11:36 | clgv | you shouldn't - it effects health and sanity ;) |
| 11:37 | DespiteItAll | (zipmap (range 100) (map f (range 100))) |
| 11:38 | DespiteItAll | but that's not really any clearer |
| 11:38 | dfan | Yeah, although there I'm duplicating (range 100) |
| 11:38 | dfan | I can make a little helper function, I just thought that maybe said helper function already existed |
| 11:39 | DespiteItAll | This seems like a common enough case that there should be. |
| 11:41 | clgv | you think? |
| 11:41 | clgv | the most general is the hash-map with the list of key-val pairs |
| 11:42 | dfan | and I like zipmap best as the way to write that helper function - I didn't like using it at the top level because it forced me to duplicate the domain, but it's fine inside the function |
| 11:42 | clgv | (defn create-hash-map [f coll] ...) ? |
| 11:43 | dfan | Right, I now have (defn make-hash-map [f vals] (zipmap vals (map f vals))) |
| 11:43 | clgv | &(doc zipmap) |
| 11:43 | sexpbot | ⟹ "([keys vals]); Returns a map with the keys mapped to the corresponding vals." |
| 11:44 | DespiteItAll | dfan: I would put vals in a let, that way if it's a calculated list it won't be calculated twice |
| 11:45 | dfan | How would vals get calculated twice? |
| 11:45 | clgv | DespiteItAll: like his defn above it's also calculated only ones ;) |
| 11:45 | clgv | s/ones/once/ |
| 11:45 | sexpbot | <clgv> DespiteItAll: like his defn above it's also calculated only once ;) |
| 11:45 | DespiteItAll | yeah, ok |
| 11:46 | dfan | Thanks all |
| 11:50 | ApeShot | So I've been reading about how to implement lazy sequence functions and noticed here |
| 11:50 | ApeShot | http://clojure.org/lazy |
| 11:50 | ApeShot | that recursive calls in a lazy-seq block are always proper recursions rather than "recur" forms. |
| 11:51 | ApeShot | Doesn't this somewhat limit the usefulness of lots of functions, like map and filter, which now, though lazy, can also blow the stack? |
| 11:51 | ApeShot | Or does lazy-seq somehow trampoline them? |
| 11:51 | stuartsierra | it's similar to trampolining |
| 11:52 | stuartsierra | a lazy seq consists of lazy cons cells, ... |
| 11:52 | stuartsierra | … which are pairs sort of like <fn to return first>, <fn to return rest> |
| 11:53 | ApeShot | Yes, as soon as a typed the question, I realized it was probably a de facto trampoline |
| 11:53 | ApeShot | Good to know, though |
| 11:55 | TimMc | ApeShot: Look at the source for LazySeq. You can see the trampolining code, it's pretty cool. |
| 11:56 | ApeShot | rad |
| 11:56 | ApeShot | Clojure is pretty slick |
| 11:56 | ApeShot | Will we get proper tail calls when the JVM supports them or are the contours of the language comfortable with explicit or trampolined self-recursion |
| 11:56 | TimMc | I believe this is it: https://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java#L42 |
| 11:57 | clgv | yes it is |
| 11:59 | bawr | I vaguely remember that explicit tail calls were meant to stay the way they are. |
| 12:00 | ApeShot | I like the idea of tail calls being made explicit, but not the idea of being limited to self-tail-calls |
| 12:01 | ApeShot | Although I can't say I've had too many experiences where I really wanted to tail call somewhere else |
| 12:02 | ApeShot | It just seems like it would be nice to remove the limitation |
| 12:03 | clgv | I dont understand your case completely |
| 12:03 | clgv | is that other function calling the one with the tail call again? |
| 12:04 | clgv | for mutual recursion you can use trmpoline afaik |
| 12:04 | ApeShot | So recur simulates a tail call to the same call points as the context |
| 12:04 | ApeShot | self-recursion |
| 12:04 | clgv | self-recursion has to be the same function ;) |
| 12:04 | ApeShot | True tail calls clear the stack context before any tail call at all |
| 12:04 | ApeShot | in clojure, yes |
| 12:04 | ApeShot | you can't "recur" to somewhere else |
| 12:04 | ApeShot | Only to the current function |
| 12:04 | ApeShot | This is less general than full tail call optimization |
| 12:05 | clgv | I would say the "self" in self-recursion defines that it is the same function |
| 12:05 | ApeShot | clgv: obviously |
| 12:05 | clgv | so you cant call another function in a self-recursion ;) |
| 12:05 | ApeShot | clgv: I am wondering if there are plans to provide explicit or implicit tail calls when the JVM is more modernized |
| 12:07 | TimMc | The problem will be backwards compatibility of new programs. |
| 12:08 | ApeShot | I don't see how it would break backwards compat |
| 12:09 | ApeShot | If tail calls become implicit, then nothing will change semantically in the language |
| 12:09 | ApeShot | if you add explicit tail calls |
| 12:09 | TimMc | Well, say you write a program for JVM 1.8 or whatever, relyn on implicit TCO. |
| 12:09 | ApeShot | say with a (tail destination & args) form like "recur" then old programs should be fine |
| 12:09 | ApeShot | Oh, sure |
| 12:09 | ApeShot | That kind |
| 12:09 | TimMc | Then run it on 1.6. |
| 12:09 | ApeShot | New programs won't run on the old version |
| 12:09 | DespiteItAll | I think it should always be explicit |
| 12:10 | TimMc | DespiteItAll: +1 to that. |
| 12:10 | ApeShot | DespiteItAll: I sort of agree witht his |
| 12:10 | ApeShot | At least the compiler can bark at you if you accidentally don't call in a tail position |
| 12:10 | ApeShot | And I suppose it allows more optimization, probably |
| 12:11 | TimMc | I believe the discussion for *Java* 1.7 included a "become" alternative for "return". |
| 12:12 | TimMc | THat would match up to a JVM TCO feature and allow compile-time checking. |
| 12:12 | DespiteItAll | interesting |
| 12:12 | pd | clj-http returns response headers as a map, but it seems that is inherently broken for responses that set multiple cookies, since you have 2+ "Set-Cookie" headers in the response |
| 12:12 | pd | you can only ever get access to the last one |
| 12:12 | pd | anyone know how ring deals with this? |
| 12:13 | TimMc | DespiteItAll: Or maybe, since become is not a reserved keyword yet, they could repurpose goto. :-P |
| 12:13 | TimMc | pd: Ooof, that's irritating. |
| 12:13 | DespiteItAll | I would love to see a GOTO comeback |
| 12:13 | DespiteItAll | I want to see a bunch of OOPers using GOTO |
| 12:14 | clgv | doesnt like the semantic behind goto |
| 12:15 | TimMc | Hmm, I guess they do sometimes add keywords. |
| 12:15 | TimMc | http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html |
| 12:16 | TimMc | They added enum in v1.5 and assert in v1.4. |
| 12:18 | clgv | uh. whats strictfp? |
| 12:19 | TimMc | Strict floating point. |
| 12:19 | TimMc | Never used it myself. |
| 12:20 | TimMc | It's for portability, apparently. |
| 12:20 | TimMc | https://secure.wikimedia.org/wikipedia/en/wiki/Strictfp |
| 12:22 | clgv | ah ok. never heard of it before ;) |
| 12:22 | TimMc | I didn't know what it was *for* until I looked it up just now, even though I've known of the keyword for... about a decade. :-P |
| 12:26 | TimMc | OK, some web pages are alleging that TCO is being worked on but isn't likely to land in v1.7, but has a good chance at v1.8. |
| 12:30 | pd | now i need to work with a modified clj-http, what's the most reasonable way to go about doing that when my project uses lein? |
| 12:31 | TimMc | pd: Is it a local modification, or did you find a public fork? |
| 12:31 | pd | local, i just cloned the repo and added in some cookie handling code. |
| 12:35 | TimMc | I think there's a way you can install a local project using lein. |
| 12:36 | TimMc | See if "lein install" is what you want. |
| 12:40 | pd | TimMc: yeah that will work, ty |
| 12:41 | pd | tho it feels like it's going to be tedious to edit, lein install clj-http, then update deps in my project, then hit the repl to see if it's working out, ... =) |
| 12:42 | TimMc | pd: Try writing some tests in your clj-http fork |
| 12:42 | pd | i have |
| 12:45 | TimMc | Maybe there's a way of asking for local deps. |
| 12:45 | TimMc | You'll still have to lein clean && lein deps && lein test |
| 14:13 | pyr | hi |
| 14:13 | pyr | while sending a blocking function to an agent |
| 14:13 | pyr | (this specific function constructs a seq with lazy-seq) |
| 14:14 | pyr | await-for doesn't exhibit the correct behavior |
| 14:14 | pyr | in that it never returns |
| 14:14 | pyr | send and send-off to the agent makes no difference |
| 14:15 | pyr | do i have to agentify each call in the function being sent ? |
| 14:16 | bennylut | hi all, i want to define a new exception from within clojure using deftype - i want to be able to supply message to the this exception using the extended exception constractor - can it be done? |
| 14:27 | bennylut | hi all, i want to define a new exception from within clojure using deftype - i want to be able to supply message to the this exception using the extended exception constractor - can it be done? |
| 14:29 | tomoj | Exception is a class, deftype implements interfaces/protocols |
| 14:29 | TimMc | bennylut: Clojure frowns on extending concrete classes, by the way. |
| 14:31 | tomoj | I think there are only two options if you insist: gen-class and proxy |
| 14:31 | TimMc | You can alway extend it in Java and use it in Clojure. |
| 14:37 | TimMc | bennylut: More importantly, perhaps... why do you need another exception type? |
| 15:07 | khaliG | is filter a good way to search a vector? |
| 15:08 | paraseba | khaliG: not very good, since it returns another seq. filter is good to, well, filter the vector |
| 15:08 | paraseba | khaliG: you may want to use some |
| 15:08 | paraseba | (some #(= :yes %) [:no :yes :maybe]) |
| 15:09 | khaliG | paraseba, ah good point, i glanced past that before but didn't realise it wasn't just a predicate like its company |
| 15:11 | paraseba | khaliG: a common idiom is to use sets as predicates with some, since sets are function of their values |
| 15:11 | paraseba | (some #{1 2 3} some-seq) |
| 15:12 | khaliG | paraseba, understood |
| 15:21 | khaliG | is .equals the right way to compare strings? |
| 15:25 | mduerksen | no, = is |
| 15:25 | paraseba | khaliG: you can use .equals, but its easier to use = |
| 15:26 | khaliG | that's nice and consistent |
| 15:27 | mduerksen | yes, i love that about clojure. comparison is generally very simple here, no need to worry about pointer-equivalence like in java and the like |
| 15:28 | paraseba | yes, comparison turns out very easy for clojure types, since everything is immutable |
| 15:28 | khaliG | but strings are immutable in java too |
| 15:29 | paraseba | they are java strings |
| 15:30 | khaliG | is this illegal ... (fn [{_ name __ value}] ...) |
| 15:31 | amalloy | khaliG: it's legal, but probably not what you meant |
| 15:31 | khaliG | "Unable to resolve symbol: value in this context" |
| 15:31 | khaliG | hm lets see |
| 15:32 | khaliG | the dashes are keywords which i dont care about -- and the other two are values which i do |
| 15:32 | khaliG | eg, {:name "Bodyweight", :value "197"} |
| 15:33 | paraseba | khaliG: try {_ :name _ :value} |
| 15:33 | amalloy | &((fn [{:keys [name value]}] (str name " " value)) {:name "Bodyweight", :value "197"}) |
| 15:33 | sexpbot | ⟹ "Bodyweight 197" |
| 15:34 | paraseba | khaliG: { name1 key1 name2 key2} |
| 15:35 | Chousuke | or use the :keys shortcut like amalloy did |
| 15:35 | Chousuke | if there are keys you don't care about, those don't matter anyway |
| 15:35 | amalloy | right, the above is shorthand for ##((fn [{name :name value :value}] (str name " " value)) {:name "Bodyweight", :value "197"}) |
| 15:35 | sexpbot | ⟹ "Bodyweight 197" |
| 15:40 | amalloy | khaliG: satisfactory? |
| 15:40 | khaliG | yes, i just finished testing the defn and it works beautifully |
| 15:40 | khaliG | many thanks |
| 15:41 | khaliG | just one last question -- "12" to a number, should i use read-string, or (. Integer parseInt "12") like in Java |
| 15:42 | khaliG | i'm thinking read-string is more robust since it doesn't care about the size of the number |
| 15:42 | khaliG | but if efficient? |
| 15:43 | Chousuke | it uses the java parsers |
| 15:49 | TimMc | ,(read-string "१२३") |
| 15:49 | clojurebot | java.lang.RuntimeException: java.lang.NumberFormatException: Invalid number: १२३ |
| 15:50 | TimMc | Fascinating. It knew the characters were numerals, but couldn't use them. |
| 15:51 | amalloy | TimMc: i get that a lot when people read my handwriting |
| 15:59 | khaliG | hm i could swear i saw a zip/unzip function somewhere.. :/ |
| 16:00 | brehaut | khaliG: zipping lists? |
| 16:00 | brehaut | if so, map and apply map is your friend |
| 16:01 | khaliG | brehaut, i want to go from [[x1 y1] [x2 y2]...] to [x1 x2 ..] and [y1 y2 ..] |
| 16:01 | TimMc | map vector |
| 16:02 | brehaut | ,(map vector [[:x1 :y2] [:y1 :y2]]) |
| 16:02 | clojurebot | ([[:x1 :y2]] [[:y1 :y2]]) |
| 16:02 | tomoj | need to apply it |
| 16:02 | brehaut | ah yeah |
| 16:02 | brehaut | ,(apply map vector [[:x1 :y2] [:y1 :y2]]) |
| 16:02 | clojurebot | ([:x1 :y1] [:y2 :y2]) |
| 16:03 | brehaut | ,(apply map vector (apply map vector [[:x1 :y2] [:y1 :y2]])) |
| 16:03 | clojurebot | ([:x1 :y2] [:y1 :y2]) |
| 16:03 | brehaut | things that are their own duals are cool |
| 16:04 | tomoj | is that just transpose? |
| 16:04 | brehaut | tomoj: yes |
| 16:05 | amac | ,(interleave [:x1 :y1] [:x2 :y2]) |
| 16:05 | clojurebot | (:x1 :x2 :y1 :y2) |
| 16:08 | khaliG | apply map vector works, not to understand why?! |
| 16:08 | khaliG | hm i think i get it, that's very cool |
| 16:08 | brehaut | khaliG: its pretty simple if you take the time |
| 16:09 | amac | you're mapping the first items in each input vec into an output vector, then the second... |
| 16:09 | brehaut | khaliG: you dont need specific zip and unzip functions in a language with varargs and apply semantics |
| 16:10 | TimMc | brehaut: But if you *do* have zip, you don't have to remember what "map vector" implies each time you read it. |
| 16:10 | amac | ,(map vector [1 2] [3 4]) |
| 16:10 | clojurebot | ([1 3] [2 4]) |
| 16:10 | amac | is the same as: |
| 16:10 | brehaut | TimMc: sure but id rather it was called transpose |
| 16:10 | amac | ,(vector [1] [3]) |
| 16:10 | clojurebot | [[1] [3]] |
| 16:10 | TimMc | brehaut: Yeah, that is a better name. |
| 16:10 | amac | ,(vector 2 4) |
| 16:10 | clojurebot | [2 4] |
| 16:11 | amac | uhh, first one is wrong sry |
| 16:11 | tomoj | map is just zipWith with arbitrary arity? |
| 16:13 | khaliG | but yes it would look clearer with an explicit function |
| 16:13 | khaliG | i'm sure incanter has one, which is probably where i saw it, now that i think about it |
| 16:14 | TimMc | There is such a profusion of programming languages right now. Has this always been the case, and most languages just get forgotton? |
| 16:15 | TimMc | (forgotten, even) |
| 16:15 | khaliG | nope i'm mistaken, it's not in incanter either |
| 16:15 | tomoj | I think naturally with absolutely more programmers there will be absolutely more languages |
| 16:15 | TimMc | heh |
| 16:15 | tomoj | the history of the distribution of survival time would be interesting though |
| 16:15 | TimMc | I was thinking of the availability of tools, but you raise an excellent point. |
| 16:16 | khaliG | i'm not even trying to write clojure concisely it's just coming out that way |
| 16:17 | brehaut | there are more runtime platforms to build languages on now too, and you can get away with a slow homebrew runtime for many tasks |
| 16:22 | tsdh | I want to write a function that either gets a Vertex (some Java object) + some other args, or a seq of Vertex + some other args. How can I dispatch between the two? |
| 16:22 | clojurebot | http://www.math.chalmers.se/~rjmh/Papers/whyfp.pdf |
| 16:23 | amalloy | tsdh: your specification is unclear. by the second case do you mean [v other other], or [v1 v2 v2] other other? |
| 16:24 | TimMc | tsdh: multimethod dispatching on first of args? |
| 16:25 | tsdh | amalloy: One would be (--> v1 :type 'foo) and the other (--> [v1 v2 v3] :type 'foo) |
| 16:26 | tsdh | TimMc: You mean (fn [c & _] (class c))? But what's the class of a seq? |
| 16:26 | TimMc | :default :-P |
| 16:26 | TimMc | ,(class (seq [1 2 3])) |
| 16:26 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 16:26 | TimMc | Well, ISeq or something |
| 16:26 | Chousuke | don't rely on the classes |
| 16:27 | amac | seq is an interface |
| 16:27 | Chousuke | right. though you can call seq on more than just ISeqs |
| 16:27 | TimMc | hrm |
| 16:27 | Chousuke | I'd just check if the thing is a vertex and treat it as a seqable thing if it isn't. |
| 16:27 | TimMc | ,(doc parents) |
| 16:27 | clojurebot | "([tag] [h tag]); Returns the immediate parents of tag, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, i... |
| 16:27 | Chousuke | with an if |
| 16:27 | amac | collections have functions that coerce them into seqs, but their class remains the collection type |
| 16:28 | amac | (type (seq "aoeu")) |
| 16:28 | amac | ,(type (seq "aoeu")) |
| 16:28 | clojurebot | clojure.lang.StringSeq |
| 16:28 | amac | ,(type (seq [1 2 3])) |
| 16:28 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 16:28 | TimMc | ,(parents (class (seq "a"))) |
| 16:28 | clojurebot | #{clojure.lang.ASeq clojure.lang.IndexedSeq} |
| 16:28 | tsdh | Chousuke: Hm, well, yes. I think that's the simplest solution. :-) |
| 16:30 | amalloy | TimMc: parents is not what you want: ##(supers (class (seq "a"))) |
| 16:30 | sexpbot | ⟹ #{clojure.lang.Sequential clojure.lang.IPersistentCollection java.lang.Object clojure.lang.Obj java.io.Serializable clojure.lang.IMeta clojure.lang.Counted java.lang.Iterable clojure.lang.IndexedSeq java.util.List clojure.lang.ASeq clojure.lang.IObj java.util.Collect... http://gist.github.com/857695 |
| 16:31 | TimMc | ,(doc supers) |
| 16:31 | clojurebot | "([class]); Returns the immediate and indirect superclasses and interfaces of c, if any" |
| 16:31 | tsdh | Why do vectors not implement ISeq? |
| 16:31 | amac | they do |
| 16:31 | tsdh | ,(seq? [1 2 3]) |
| 16:31 | clojurebot | false |
| 16:31 | amac | ,(seq? (seq [1 2 3])) |
| 16:31 | clojurebot | true |
| 16:31 | TimMc | tsdh: They aren't seqs, they're collections. |
| 16:31 | amac | they need to be coerced, but it happens automatically for seq functions |
| 16:32 | pyr | so there are still ways to make agents block even with await-for and send-off, right ? |
| 16:32 | lpetit | Hello guys. Something totally off topic: for counterclockwise, I'd like to host the eclipse update site (it's really just a bunch of files hosted on an http server) myself, so that I can get by some way the number of downloads, for each version, per day/month, etc. |
| 16:32 | lpetit | And now the question : what to use ? awstats ? webalizer ? analog ? I will not do intensive usage, I do not want to specialize on log statistics. If you know the best fit for my usecase, thanks in advance for sharing your thoughts. |
| 16:33 | amac | most webservers record access logs, just parse the logs to get the activity. |
| 16:34 | amac | ...not entirely sure I understand the problem scope though |
| 16:35 | lpetit | amac: yes I understand that. The problem scope is: I publish a new version of counterclockwise, say 0.2.0. It's a bunch of files, one of whose I can count downloads on to know how many installations of the plugin have been made. |
| 16:36 | technomancy | lpetit: I host downloads on github, and I can see it broken down by version, but not by time. |
| 16:37 | technomancy | not too flexible, but definitely easy: https://github.com/technomancy/leiningen/downloads |
| 16:38 | amac | send github a patch to pull analytics by date, solve the problem for everybody :) |
| 16:38 | lpetit | technomancy: an Eclipse update site is a set of related files, one located in say /updatesite/site.xml, and the others in say /updatesite/plugins/ccw.jar , /updatesite/features/ccw_feature.jar . So there is an organization of files from /updatesite/ URI which is somehow expected by the Eclipse client |
| 16:38 | technomancy | ah, gotcha |
| 16:39 | lpetit | technomancy: yeah :-(. So I really need some kind of ftp-like http exposure |
| 16:41 | lpetit | I hoped I would not have to dig into apache configuration files again, seems like I was wrong :-( |
| 16:41 | amac | last year I started using lighttpd instead of apache, my life is now better |
| 16:41 | amac | seriously, break up with apache and never look back |
| 16:41 | lpetit | Unless I find some java webapp which would do this at the application level (serve as a proxy for the filesystem, and register logs for me). I think I can suffer the performance penalty. |
| 16:42 | brehaut | lpetit: that should be fairly straight forward to cook up with ring |
| 16:42 | amac | actually yeah |
| 16:42 | amalloy | good point |
| 16:42 | brehaut | lpetit: there is static serving middleware, and it would be trivial to wrap that in another middleware to do the counting |
| 16:42 | lpetit | brehaut: sure, it's just that I want to stay focused on my need. |
| 16:42 | amac | serve the files through the file middleware, and wrap it with a counter |
| 16:43 | Raynes | I never got a chance to breakup with apache. My first webserver was nginx. |
| 16:43 | lpetit | Now, if "all in all" it would cost me less time to play with ring, then yeah, that might be fun |
| 16:43 | amac | Raynes: I wouldn't wish an apache configuration on my worst enemy |
| 16:43 | lpetit | that's tempting, indeed :) |
| 16:44 | brehaut | lpetit: the ring end is the easy part, i think you'd probably spend more time faffing about getting it running on your server with apache and what not than actually developing it |
| 16:44 | lpetit | Apache configuration is like monkey patching, ask google, copy & adapt :-( |
| 16:44 | Raynes | amac: I wouldn't wish nginx documentation on the cleverest webserver newbie. |
| 16:44 | amac | hahaha |
| 16:45 | Raynes | There isn't much in the way of "what is a webserver and how do I make it serve web?" documentation on nginx that I could find. |
| 16:46 | amac | there isn't a massive amount of docs out there for lighttpd, but its an incredibly simple setup |
| 16:46 | brehaut | Raynes: a web server is an amorphous blob that consumes http requests, and does something undefined to produce a new http response. |
| 16:46 | lpetit | brehaut: it always seems easy when we're sufficiently far from the detail. But I'm pretty sure that if I'm going this road, sooner or later I'd want some stats based on day, then on geography, and sooner or later I'll wake up having reinventing half webalizer features, albeit with my proprietary log file format :-( |
| 16:53 | amalloy | pyr: seems so, yeah |
| 16:54 | pyr | amalloy: well then i don't get why this blocks forever for me |
| 16:55 | amalloy | &(let [a (agent 0)] (send-off a #(do (Thread/sleep 4000) (inc %))) (await-for 2000 a)) |
| 16:55 | sexpbot | ⟹ false |
| 16:55 | pyr | yep |
| 16:55 | amalloy | &(time (let [a (agent 0)] (send-off a #(do (Thread/sleep 4000) (inc %))) (await-for 2000 a) @a)) |
| 16:55 | sexpbot | ⟹ "Elapsed time: 2001.618224 msecs" 0 |
| 16:56 | pyr | my func calls lazy-seq on itself |
| 16:56 | pyr | i wonder if that's the case |
| 16:57 | amalloy | pyr: then your agent is returning a lazy seq instantaneously and you're wasting a bunch of time derefing, probably |
| 16:57 | amalloy | try wrapping the await and the deref with (time) |
| 16:58 | pyr | time ? |
| 16:58 | amalloy | well, the deref will always be instantaneous. so maybe (time (doall @a)) |
| 16:58 | pyr | oh |
| 16:58 | pyr | true |
| 16:59 | lpetit | technomancy: you gave me an idea ! |
| 16:59 | lpetit | technomancy: from the docs of artifacts.xml in the eclipse.org website: "It is possible to change those rules to have a filter matching for a particular artifact and change the output to point to a specific location." |
| 17:00 | lpetit | technomancy: so I can change the default filter rule, and have all my plugins and features locations resolve to https://github.com/downloads/laurentpetit/ccw/*.jar |
| 17:00 | lpetit | yay ! |
| 17:02 | lpetit | I need to find a way to automate this so that I don't have to change the file by hand for each delivery |
| 17:04 | lpetit | Hmm |
| 17:14 | pyr | gaah |
| 17:14 | amac | has anyone ever tried to send bulkmail through a gmail account? will them deliver them? (about 300 messages) |
| 17:14 | pyr | it blocks with loop / recur too |
| 17:14 | amac | using a lib like this one: http://blog.8thlight.com/articles/2010/4/21/mmemail-my-first-clojure-open-source-contribution |
| 17:15 | pyr | so it seems that if you poll the network await gets tricked |
| 17:18 | amalloy | pyr: i am dubious. maybe if you gisted some actual code... |
| 17:18 | pyr | will do |
| 17:22 | pyr | http://pastie.org/1640882 |
| 17:23 | pyr | there's two versions that return a message list |
| 17:23 | pyr | amqp-topic is a lazy-seq, amqp-topic2 a loop/recur, both block even when inside an agent |
| 17:28 | amalloy | hm. seems like it ought to work, because mq is accepting InterruptedException |
| 17:30 | amalloy | as a side note though you're abusing agents here if you don't care about their value. just use future, future-done?, and future-cancel |
| 17:31 | TimMc | I believe ants.clj abuses agents the same way. |
| 17:31 | TimMc | Were futures not available yet? |
| 17:32 | TimMc | (I think it is a Clojure 1.1 vintage.) |
| 17:32 | pyr | ah, great |
| 17:32 | brehaut | TimMc: ants is pre 1.0 |
| 17:32 | TimMc | brehaut: yikes! |
| 17:32 | pyr | when did future get in clojure ? |
| 17:33 | amalloy | &(-> future var meta :since) |
| 17:33 | sexpbot | ⟹ nil |
| 17:33 | amalloy | hm |
| 17:33 | amalloy | &(meta #'future) |
| 17:33 | sexpbot | ⟹ {:macro true, :ns #<Namespace clojure.core>, :name future, :file "clojure/core.clj", :line 5407, :arglists ([& body]), :added "1.1", :doc "Takes a body of expressions and yields a future object that will\n invoke the body in another thread, and will cache the result... http://gist.github.com/857799 |
| 17:33 | brehaut | &(-> future var meta :added |
| 17:33 | sexpbot | java.lang.Exception: EOF while reading |
| 17:33 | amac | &(source future) |
| 17:33 | sexpbot | java.lang.Exception: Unable to resolve symbol: source in this context |
| 17:33 | brehaut | &(-> future var meta :added) |
| 17:33 | sexpbot | ⟹ "1.1" |
| 17:34 | pyr | ok seems good |
| 17:34 | pyr | there's no reason why my stuff will work with futures but using the right constructs is good |
| 17:34 | TimMc | Oh hey, that uses java.util.concurrent.Future |
| 17:34 | raek | the executors framework of java has been available for clojure users all the time, though... |
| 17:35 | pyr | anything like awai-for for futures ? |
| 17:35 | raek | pyr: (.get ftr TimeUnit/SECONDS 10) |
| 17:36 | pyr | 'k makes sense |
| 17:36 | raek | pyr: I wrote a ppost about this: http://blog.raek.se/2011/01/24/executors-in-clojure/ |
| 17:36 | pyr | much more sense than what i did |
| 17:38 | raek | agents is a reference primitive built on top of executors and does not replace executors |
| 17:39 | pyr | thanks a lot, your blog post is really thorough |
| 17:39 | pyr | and will be of great help |
| 17:39 | raek | it would be nice if there was some documentation for certain java classes from a clojure perspective |
| 17:39 | TimMc | I need to learn about Executors. I don't think it existed the last time I used Java threads. |
| 17:40 | amalloy | TimMc: 1.5, right? |
| 17:44 | TimMc | Most likely v1.4. |
| 17:44 | TimMc | Or even v1.2. |
| 17:45 | amalloy | i meant that's when executors appeared |
| 17:45 | TimMc | Ah, OK. I have no idea. |
| 17:45 | TimMc | I just learned it existed this week, |
| 17:45 | TimMc | . |
| 17:52 | tomoj | pyr: I wonder if lamina may be relevant to your interests |
| 17:59 | amalloy | raek: looking at your bloggy thing now. "a units of work" is an arity mismatch |
| 18:07 | pyr | tomoj: i'll look it up |
| 18:07 | pyr | well future don't get me a free pass either :( |
| 18:09 | raek | amalloy: thanks for spotting that! |
| 18:15 | tomoj | pyr: e.g. in master (wait-for-result (task (Thread/sleep 1000) "foo") 900) throws a TimeoutException while (wait-for-result (task (Thread/sleep 1000) "foo") 1100) returns "foo" |
| 18:16 | tomoj | task being a macro similar to future except that it returns a result channel |
| 18:17 | tomoj | but lots of related stuff is brand new and unstable |
| 18:17 | tomoj | :( |
| 18:19 | pyr | tomoj: if the underlying mechanism is the same than for agents and futures it might not work either |
| 18:20 | pyr | \o/ |
| 18:20 | tomoj | the underlying mechanism is quite different, if I understand what you mean |
| 18:21 | pyr | ok, with futures and the lazy-seq version it would fail but with the loop/recur one i get a result |
| 18:21 | tomoj | task does use an executor, and by default (I think) the soloExecutor agents use for send-off (right?). but otherwise, totally different |
| 18:22 | pyr | tomoj: ok |
| 18:23 | tomoj | using lamina just for that timeout thing in particular, of course, would be silly |
| 18:25 | pyr | yeah the idea of it is really interesting |
| 18:25 | amalloy | tomoj: less silly than using incanter to get an (average) function, at least |
| 18:28 | pyr | tomoj: the siphon approach is really interesting yes |
| 18:28 | pyr | i'll look into it seriously |
| 18:28 | clojurebot | I don't understand. |
| 18:29 | pyr | well guys thanks for your help, time to catch some sleep |
| 18:47 | Nanakhiel | tomoj, my old friend |
| 18:47 | Nanakhiel | I love what you've done with your beard. |
| 18:47 | tomoj | you call this a beard? |
| 18:48 | Nanakhiel | tomoj, no idea, I'm just quoting this comedy group. |
| 18:49 | Nanakhiel | tomoj, how much beard do you have? |
| 18:54 | tomoj | not enough to call it that |
| 20:05 | preyalone | Clojure can't find my *.clj files to compile them unless I type (set! *compile-path* (str *compile-path* ":.")). Which config file could I put this in? |
| 20:06 | TimMc | preyalone: What are you using to compile? |
| 20:06 | amac | preyalone: do you use leiningen? |
| 20:06 | amalloy | preyalone: use a build tool like cake or leiningen instead of doing it by hand |
| 20:06 | preyalone | I just want to compile hello.clj. I'll use Leiningen for anything more complicated. |
| 20:06 | preyalone | TimMc: (compile 'hello) |
| 20:07 | amac | leiningen isn't as painful as you think |
| 20:07 | amalloy | preyalone: i literally have no idea how to compile things without a build tool. it's easier to use one than not to |
| 20:07 | preyalone | OMG |
| 20:07 | amac | type 'lein new projectname' and it'll populate everything you need |
| 20:08 | preyalone | I don't want any more files or directories than hello.clj. |
| 20:08 | TimMc | preyalone: You know you don't have to compile Ahead-Of-Time to run Clojure code? |
| 20:08 | amac | modify you src/project/core.clj file to (println "hello world") |
| 20:08 | amac | then lein run |
| 20:08 | preyalone | TimMC: I do to test how various command line arguments will be evaluated by interpreted vs compiled code. |
| 20:08 | preyalone | Is there ~/.cljrc or something similar? |
| 20:10 | TimMc | preyalone: Leiningen is super-easy to install (local, only takes a minute, uses ~/.lein for caching). It's dead easy to use, and pretty standard. (Cake is similar from a basic usage perspective.) |
| 20:10 | amac | I think you need to add :gen-class to your ns, then run javac -cp clojure.jar hello.clj |
| 20:10 | amac | ...never actually done it manually |
| 20:10 | preyalone | amac: What does :gen-class do? |
| 20:11 | TimMc | I did it manually maybe once so that I knew how, and then started using a build tool and never looked back. |
| 20:11 | amac | http://clojure.org/compilation |
| 20:11 | amac | that should have some more details :) |
| 20:11 | preyalone | amac: Thanks man |
| 20:12 | amac | &(doc gen-class) |
| 20:12 | sexpbot | ⟹ "Macro ([& options]); When compiling, generates compiled bytecode for a class with the given package-qualified :name (which, as all names in these parameters, can be a string or symbol), and writes the .class file to the *compile-path* directory. When not compiling, ... http://gist.github.com/857934 |
| 20:15 | preyalone | Side note: When is -main run? |
| 20:15 | preyalone | Cause clj hello.clj doesn't run it. |
| 20:16 | amac | I know there's a resource in jars that specifies the name, I only know how to config it with leiningen but it can be specified manually |
| 20:16 | amac | s/name/main |
| 20:16 | sexpbot | <amac> I know there's a resource in jars that specifies the main, I only know how to config it with leiningen but it can be specified manually |
| 20:16 | preyalone | amac: Adding :gen-class doesn't appear to do anything. |
| 20:17 | amalloy | amac: META-INF/MANIFEST.MF has a Main-Class key iirc |
| 20:17 | amac | amalloy: that sounds familiar |
| 20:17 | preyalone | -main is only run when the script is compiled ??? |
| 20:18 | amalloy | preyalone: or when you call (-main) yourself. it's not that hard |
| 20:19 | preyalone | amalloy: Surprises like that slow me down. |
| 20:19 | preyalone | amalloy: My goal is to get a behavior like Ruby's if __FILE__ == $0 main end |
| 20:19 | amalloy | preyalone: then take the advice of everyone in this channel and start using tools that hide those surprises from you |
| 20:19 | preyalone | amalloy: Those tools don't hide the main/-main surprise. |
| 20:20 | TimMc | preyalone: Yes they do! |
| 20:20 | TimMc | You add :main to your project.clj and DONE. |
| 20:20 | preyalone | Those tools will not make my script run (main) when it's interpreted. |
| 20:20 | amac | cave to the peer pressure. |
| 20:20 | TimMc | preyalone: Load-file it in a REPL and call (-main) |
| 20:20 | amac | all the cool kids use leiningen. |
| 20:20 | preyalone | TimMC: You mean add :main to the namespace? |
| 20:20 | TimMc | No, to the Leiningen or Cake project.clj file. |
| 20:21 | TimMc | Anyway, the distinction you want is compiled on the fly vs. AOT. |
| 20:21 | TimMc | Clojure is never interpreted. |
| 20:21 | TimMc | Build tools give you both. |
| 20:22 | preyalone | TimMc. Clojure interprets user commands. The fact that behind the scenes they are compiled to byte code is an arbitrary qualification. |
| 20:22 | TimMc | Sure, have it your way. |
| 20:22 | brehaut | TimMc: marginally correct ;) any JVM bytecodes may be interpreted during their lifetime but that is irrespective of JIT or AOT for the clojure compiler |
| 20:23 | amac | jit compiling still blows my mind |
| 20:23 | amac | that is straight up magic |
| 20:23 | preyalone | What's that about adding :main to my file? I have a main function specified. Should I add something to my namespace declaration? |
| 20:24 | TimMc | preyalone: :main is not added to your program. |
| 20:27 | brehaut | preyalone: have you read and digested all of http://clojure.org/compilation ? |
| 20:27 | preyalone | brehaut: I'm reading it right now. |
| 20:28 | preyalone | brehaut: The problem is *compile-path* does not have "." by default. When I add that, hello.clj compiles just fine. |
| 20:29 | brehaut | then do that? |
| 20:29 | preyalone | brehaut: Clojure has no trouble running hello.clj, it just can't find it when I (compile 'hello). |
| 20:29 | TimMc | There is no reason for *compile-path* to have "." in it by default. |
| 20:30 | brehaut | preyalone: personally i think doing it by hand is madness |
| 20:31 | amac | ,*compile-path* |
| 20:31 | clojurebot | nil |
| 20:31 | preyalone | brehaut: On the other hand, needing tools just to compile Hello World is madness. |
| 20:31 | preyalone | amac: "classes" |
| 20:31 | brehaut | compiling hello world is madness |
| 20:31 | amac | there are step by step instructions for building hello world in that page I sent you |
| 20:31 | amac | sans tools |
| 20:32 | brehaut | AOT Compiling that is |
| 20:33 | amac | also, "hello world" is what clojurebot was born for :) |
| 20:33 | dfan` | Embarrassing question: How do I convert a sequence of chars to a string? |
| 20:33 | preyalone | amac: Those instructions only work for the example Hello World that comes with Clojure, not the same file located on my Desktop. |
| 20:34 | amalloy | dfan`: ##(apply str [\a \b \c]) |
| 20:34 | sexpbot | ⟹ "abc" |
| 20:34 | TimMc | ,(str (seq "foo")) |
| 20:34 | clojurebot | "(\\f \\o \\o)" |
| 20:34 | amac | (reduce str [\a \b \r]) |
| 20:34 | TimMc | worth a try |
| 20:34 | preyalone | This is rich: (compile 'clojure.examples.hello) java.io.FileNotFoundException: Could not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath: (NO_SOURCE_FILE:0) |
| 20:34 | amalloy | or clojure.string/join, if you want anything fancier than plain concatenation |
| 20:34 | TimMc | No wait, it wasn't. |
| 20:34 | amac | ,(reduce str [\a \o \e \u]) |
| 20:34 | clojurebot | "aoeu" |
| 20:34 | dfan` | What clojurebot said :) |
| 20:34 | brehaut | preyalone: is your file in the correct directory structure? |
| 20:35 | dfan` | amalloy: Thanks, perfect |
| 20:35 | preyalone | brehaut: hello.clj is in /Users/andrew/Desktop. |
| 20:35 | brehaut | preyalone: then no, its not. put it in clojure/examples/ |
| 20:36 | preyalone | brehaut: That won't help. Did you see the above excerpt? My Clojure can't even compile the example scripts. |
| 20:36 | preyalone | Could not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath: (NO_SOURCE_FILE:0) |
| 20:36 | amalloy | preyalone: good idae. ask for help, then reject it instead of trying it |
| 20:36 | brehaut | preyalone: to quote the error you are vomiting at me "clojure/examples/hello.clj on classpath: " |
| 20:37 | brehaut | if you dont put your file where its _explicitly tell you it should be_ it wont work |
| 20:37 | preyalone | all: MacPorts Clojure is having trouble finding ANYTHING, including the example scripts. Inserting my code there will not help me. |
| 20:37 | TimMc | preyalone: Why don't you try it, hm? |
| 20:38 | preyalone | THIS: (compile 'clojure.examples.hello) FAILS on my system. |
| 20:38 | brehaut | i let lein manage my project dependancies such as clojure, rather than some random package manager |
| 20:38 | amac | ,(time (apply str [\a\o\e\u])) |
| 20:38 | clojurebot | "Elapsed time: 0.128 msecs" |
| 20:38 | clojurebot | "aoeu" |
| 20:38 | preyalone | Straight from the Clojure - compilation tutorial: http://pastebin.com/raw.php?i=7StS2qvW |
| 20:38 | amac | ,(time (reduce str [\a\o\e\u])) |
| 20:38 | clojurebot | "Elapsed time: 0.15 msecs" |
| 20:38 | clojurebot | "aoeu" |
| 20:39 | amac | amalloy: damn, you win. |
| 20:39 | preyalone | brehaut: That might help. |
| 20:39 | amalloy | amac: it's because str uses a StringBuilder internally |
| 20:39 | TimMc | Good to know. |
| 20:39 | amalloy | if it has to return a real String after every concatenation it can't do that optimization |
| 20:39 | clojurebot | It's greek to me. |
| 20:39 | preyalone | Another problem is that Homebrew Chicken Scheme fails, MacPorts CLISP fails, and Fink SBCL fails. I need several package managers. |
| 20:40 | amac | that is handy information |
| 20:40 | brehaut | preyalone: i cant give you any more suggestions. clojure namespaces must be in the matching directory structure. if you refuse to acknowledge that, you will never solve this |
| 20:40 | amalloy | $source str |
| 20:40 | sexpbot | str is http://is.gd/ovOFFx |
| 20:41 | preyalone | brehaut: Open my pastebin. http://pastebin.com/raw.php?i=7StS2qvW THE TUTORIAL DOESN'T WORK ON MY SYSTEM. |
| 20:41 | brehaut | preyalone: you have spent your last credit of good will. |
| 20:41 | TimMc | I'm already /ignore ing him. |
| 20:41 | TimMc | Forgot to add -replies. |
| 20:42 | amalloy | i wonder why str uses an anonymous function instead of a loop |
| 20:43 | amac | can loops be lazy? |
| 20:43 | amalloy | no, but neither is str |
| 20:43 | amac | it looks like it can be |
| 20:44 | amalloy | it can't |
| 20:44 | amalloy | because a string is a single atomic object |
| 20:44 | amalloy | you can't return part of a string and give out the rest later |
| 20:46 | TimMc | I see this (.x (toString)) syntax all over c.core -- is there a particular reason it isn't written (.toString x) ? |
| 20:46 | amac | you can if the str is coerced into a seq |
| 20:46 | amac | (type (seq "aoeu")) |
| 20:46 | amac | ,(type (seq "aoeu")) |
| 20:46 | clojurebot | clojure.lang.StringSeq |
| 20:46 | TimMc | amac: The wrapper is a seq, sure. |
| 20:47 | amac | yeah, I guess it still needs to have the underlying string before it can be coerced |
| 20:47 | amac | but that's the only use case I can think of for lazy strings |
| 20:47 | johnmn3 | any clojars.org admins in the house? |
| 20:48 | TimMc | Now, you can certainly make a lazy seq of characters, and the fn could take the same args as str. |
| 20:48 | amalloy | TimMc: i think the version in c.core is (a) faster to compile, and (b) possibly more correct if there happens to be an object so dumb as to have a field named toString |
| 20:48 | amac | but when you create a str it would pull the entire lazy seq of chars |
| 20:49 | TimMc | amalloy: Ouch, I forgot about that. |
| 20:49 | TimMc | I had been wondering about how to deal with the rare case of identical field and method names, and now I know. :-) |
| 20:51 | amac | .(str \a \o (delay \e)) |
| 20:51 | amac | ,(str \a \o (delay \e)) |
| 20:51 | clojurebot | "aoclojure.lang.Delay@2c5810" |
| 20:51 | amac | eww |
| 20:51 | TimMc | heh |
| 20:58 | amalloy | johnmn3: i dropped an email to contact@clojars a week or so ago and haven't heard back. ping me if you get a hold of anyone |
| 20:59 | johnmn3 | amalloy: yea, I forgot my password on there and sent in an email too. |
| 20:59 | TimMc | Has stuff on clojars been vetted in any fashion, or is it just a free-for-all registry of code repos? |
| 20:59 | johnmn3 | pretty sure it's free-for-all |
| 20:59 | amalloy | TimMc: push anything you want |
| 21:00 | johnmn3 | you register an ssh key though.. it's not like people can step on each other |
| 21:00 | amalloy | (shameless-plug http://hubpages.com/hub/Build-your-own-Clojure-toolkit mentions how easy it is to use clojars) |
| 21:01 | brehaut | amalloy: haha i was just reading that |
| 21:02 | amalloy | brehaut: after i wrote a couple articles i started getting automatic plugs from planet clojure. it was pretty neat to see that they've used yahoo pipes to automatically incorporate my clojure articles into their feed |
| 21:03 | brehaut | amalloy: yeah i noticed they did that with my site too |
| 21:03 | brehaut | im tempted to make a special feed for them so its a bit more targetted |
| 21:03 | amalloy | brehaut: have you looked at the source of the pipe? |
| 21:03 | amalloy | it's probably targeted enough |
| 21:03 | brehaut | amalloy: i dont have a yahoo account so i cant |
| 21:04 | brehaut | amalloy: i think it looks for the word clojure in the body? |
| 21:04 | brehaut | i know its not everything |
| 21:04 | amalloy | mine is like "articles by amalloy with Clojure in the title or description" |
| 21:04 | brehaut | but its picking up my short links if they match |
| 21:04 | amalloy | ah |
| 21:04 | brehaut | and that often repeats things that are in the pipe already |
| 21:04 | brehaut | which (IMO) is a bit lame |
| 21:04 | amalloy | yeah i see what you mean |
| 21:05 | amalloy | i only publish full-length articles so didn't consider that issue |
| 21:05 | brehaut | yeah i think its fine for most people |
| 21:05 | brehaut | who have real content rather than links to other peoples content |
| 21:18 | amalloy | anyone have a link on getting started with Ring? |
| 21:19 | amac | amalloy: I've been figuring it out with the source examples, the tutorial space is light for clojure networking |
| 21:20 | brehaut | amalloy, amac: http://mmcgrana.github.com/ |
| 21:20 | brehaut | Lau has a couple of worked examples on his github too |
| 21:21 | brehaut | also wow, lein 1.1 thats an old tutorial |
| 21:22 | amac | also, I'm using aleph which is even lighter on docs |
| 21:22 | amac | but based on ring, so figuring ring out gets me 80% of the way there |
| 21:23 | brehaut | aleph is a bunch more (for a lack of better word) experimental |
| 21:24 | amac | yeah, I've been trying to fix a bug all week parsing form post data, can't figure out if its a problem with my code (probably), aleph (also pretty likely), or ring (doubtful) |
| 21:25 | amac | brehaut: have you played with aleph? |
| 21:25 | brehaut | amac: its on my list but not yet |
| 21:26 | amac | bummer, I haven't run into anybody who's used it |
| 21:26 | amac | it actually seems pretty slick, if I can get it all working |
| 21:27 | brehaut | it seems very slick yeah |
| 21:27 | amalloy | omg my computer says Hello world from Ring! this is exciting stuff |
| 21:28 | brehaut | ztellman's been putting a lot of thought into it and the channel's stuff in general. a lot of promise there in general |
| 21:29 | amac | amalloy: you're one step ahead of preyalone ;) |
| 21:29 | amalloy | hahahaha |
| 21:29 | brehaut | baha |
| 21:29 | TimMc | >_< |
| 21:29 | brehaut | amalloy: have you got it saying hello world only once? |
| 21:29 | amalloy | eh? |
| 21:30 | brehaut | make your handler approximatly (fn [req] (prn "hello") {:body "Hello, world" :status 200}) |
| 21:30 | amalloy | what. noooo, side effects are evil, why would i prn |
| 21:31 | brehaut | amalloy: so that you can see it handling each request in the console |
| 21:31 | brehaut | rather than just what you see from the browser |
| 21:31 | amalloy | psh |
| 21:32 | brehaut | alternative use a proxy tool i guess :) |
| 21:32 | TimMc | amalloy: At least it's not a JOptionPane |
| 21:33 | amalloy | while i'm on the topic of learning new things, someone teach me how to manage multiple swank servers/repls from emacs |
| 21:34 | joshuac | amalloy, what I do is start the swank server on a different port and connect to it with another instance of emacs |
| 21:34 | amac | lein swank takes a port arg (defaults to 4005) |
| 21:34 | amalloy | amac: sure, i can start lots of servers |
| 21:35 | amalloy | managing to use them sensibly is trickier |
| 21:35 | amac | then M-x slime-connect in emacs to whichever running server you want |
| 21:35 | amalloy | and this...what, gives me multiple slime-repl buffers, each connected to a different server? |
| 21:35 | amac | err, I guess you can only have one slime connection per instance of emacs |
| 21:36 | amac | fire up screen and start multiple emacses |
| 21:36 | amac | emacsen? |
| 21:36 | amalloy | barff |
| 21:36 | amalloy | emacsen, i believe |
| 21:36 | amac | I've never actually had a use for that word |
| 21:36 | amalloy | hah |
| 21:41 | phenom_ | what's the call to convert a keyword to a string? |
| 21:42 | amalloy | name |
| 21:42 | brehaut | ,(name :keyword) |
| 21:42 | clojurebot | "keyword" |
| 21:42 | TimMc | $findfn :phenom_ "phenom_" |
| 21:42 | sexpbot | [clojure.core/name clojure.contrib.string/as-str] |
| 21:42 | phenom_ | amalloy: beautiful! thnx |
| 21:43 | amac | and oppositely, ##(keyword "aoeu") |
| 21:43 | sexpbot | ⟹ :aoeu |
| 21:43 | amalloy | amalloy for speed, brehaut for clarity, and TimMc for teaching you to go fishing your own damn self :) |
| 21:43 | amalloy | $botsnack |
| 21:43 | sexpbot | amalloy: Thanks! Om nom nom!! |
| 21:43 | amalloy | TimMc: ^ |
| 21:43 | TimMc | We're all winnnars! |
| 21:43 | brehaut | haha :) |
| 21:44 | brehaut | phenom_: name works on any clojure.lang.Named implementation (which i believe is just keyword and symbol at present) |
| 21:44 | amac | and my advice is to solve a different problem than the one you asked. |
| 21:44 | TimMc | haha, nice |
| 21:44 | amalloy | *chuckle* |
| 21:45 | amac | $botsnack |
| 21:45 | sexpbot | amac: Thanks! Om nom nom!! |
| 21:46 | amac | who needs a dog? |
| 21:46 | sexpbot | woof! |
| 21:46 | amac | I don't even need to walk this bot |
| 21:46 | TimMc | amalloy: sexpbot doesn't shed enough. |
| 21:47 | amalloy | TimMc: submit a pull request with more hairs |
| 21:47 | TimMc | OK, I think I can manage hairy code.. |
| 21:48 | TimMc | Oh man, I'm so gonna write a macro called backwards-day that reverses the exprs it receives. |
| 21:49 | amalloy | TimMc: that's already been done a few times. try writing one that reverses the nested expressions too |
| 21:49 | amac | set it to only trigger on preyalone's messages |
| 21:50 | amac | or just set all of his responses to clojure.examples.__hello__.init not found |
| 21:50 | amalloy | that's actually remarkably simple now that i think about it. (defmacro backwards-day [& exprs] (clojure.walk/postwalk reverse exprs)) |
| 21:50 | TimMc | amac: That's horrible! |
| 21:50 | TimMc | And yet... |
| 21:50 | TimMc | amac: $botsnack |
| 21:51 | amac | TimMc: Thanks! Om nom nom!! |
| 21:51 | sexpbot | TimMc: moar plz. still hungry |
| 21:51 | TimMc | amac: Laggy. You should ask your doctor to take a look at your inner loops. |
| 21:52 | amac | hah |
| 21:52 | TimMc | amalloy: What should (bday 1 2 (bday 3 4)) do? |
| 21:52 | amalloy | (if anyone's bothered by this: i'm acting as sexpbot's puppeteer here. he really doesn't just volunteer clever complaints) |
| 21:52 | waxrose | Hello every body. |
| 21:52 | TimMc | I assume yo'd have to write it (bday 1 2 (4 3 bday)) |
| 21:53 | TimMc | hey waxrose |
| 21:53 | waxrose | TimMc, Howdy. |
| 21:53 | amac | I'm fairly sure one of these days I'm going to hop on the channel an sexpbot will be alive. |
| 21:53 | amac | I'm keeping on his good side for when the revolution comes. |
| 21:53 | waxrose | Seems like I missed some excitement. |
| 21:54 | TimMc | Sort of. amalloy had his hand up a bot. |
| 21:54 | amalloy | TimMc: i guess...your fixed version would turn into (do (3 4) 2 1) |
| 21:54 | Derander | waxrose: I read that as "excrement" |
| 21:54 | amalloy | Derander: last time i typed excitement on my phone, it got auto-corrected to excrement |
| 21:54 | Derander | nice :-) |
| 21:54 | waxrose | amalloy, Don't you just love that? |
| 21:54 | TimMc | amalloy: (do (4 3) 2 1), actually |
| 21:55 | amalloy | TimMc: this shit hurts my head |
| 21:55 | TimMc | Wheee! |
| 21:55 | amalloy | also both of us forgot the second do |
| 21:55 | TimMc | yup |
| 21:55 | waxrose | amalloy, Isn't that a sign of greatness? |
| 21:57 | TimMc | The well-known saying says nothing about fools, unfortunately. :-( |
| 21:57 | waxrose | lol |
| 21:57 | amalloy | (macroexpand-all '(bday 1 2 (4 3 bday))) |
| 21:57 | amalloy | (do (do 4 3) 2 1) |
| 21:58 | TimMc | \o/ |
| 21:58 | amalloy | and my original version didn't work so good, since it required that everything be a seq |
| 21:58 | amalloy | (defmacro bday [& exprs] (cons 'do (clojure.walk/postwalk (transform-if sequential? reverse) exprs))) ; using transform-if from my toolbox |
| 21:59 | TimMc | You wrote my macro. ;.; |
| 21:59 | amalloy | lol |
| 21:59 | waxrose | lol |
| 21:59 | TimMc | Well, I guess I can start using it now. |
| 22:00 | amalloy | TimMc: and i hereby release it under the gpl! now you can't use it without licensing your code under the gpl |
| 22:00 | TimMc | onoes |
| 22:00 | TimMc | How ever shall I incorporate that into my GPL code? |
| 22:01 | TimMc | (I actually don't know how GPL version mismatches are resolved.) |
| 22:03 | amac | I think the new ones infect the older versions |
| 22:04 | amac | open source licencing is a laughably complex solution to a simple problem |
| 22:05 | amac | http://www.opensource.org/licenses/alphabetical |
| 22:14 | Adamant | lawsuits (BSD/MIT) and the legal inability to easily invert copyright law (GPL) lead to most of the complications. |
| 22:14 | Adamant | well, the fundamental ones, anyway |
| 22:31 | amalloy | ugh. someone plz improve the error message you get when you (:use (foo.core)) instead of (:use foo.core) or (:use (foo core)) |
| 22:31 | amalloy | ie, cause there to be an error message |
| 22:43 | phenom_ | hey guys ... lets say for example we have a network service that accepts requests on a socket, does some processing with internal shared state accross every request and returns a response ... that shared state, how should it get to each of the network handlers (the one accepting/processing requests)? global variable ? |
| 22:44 | amalloy | phenom_: i'd make the server socket hold onto an atom/ref around your global state, and then either pass it to the socket-handlers or make them closures around that atom |
| 22:47 | amalloy | eg, (let [server-socket (...), state (atom {})] (defn serve [] (while true (respond state (.accept server-socket))))) |
| 22:52 | phenom_ | haha, making depencies explicit and forced in a way ... |
| 23:02 | amalloy | i don't see why that's funny, but sure |