2010-12-05
| 00:09 | slyrus | is there a way to tell leiningen that my project has a dependency without specifying the particular version? e.g. clojure-1.2-or-later or swank-clojure-1.3.0 or later? |
| 00:19 | technomancy | slyrus: you can, but it's almost always a bad idea since you don't know what the future will hold. most projects that work with clojure 1.2 won't work with 1.3. |
| 00:20 | technomancy | anyway, it's in the tutorial. |
| 00:20 | slyrus | hrm... grumble grumble... OK, thanks! |
| 00:22 | slyrus | I didn't realize that the clojure 1.3 was going to be backwards-incompatible |
| 00:23 | slyrus | the old stable vs. evolving language double-edged sword thing... |
| 00:23 | brehaut | slyrus: just enough to hurt ;) |
| 00:23 | technomancy | in the case of swank-clojure it's probably safe |
| 00:23 | technomancy | since it won't break anything in production |
| 00:26 | slyrus | technomancy: I'm confused by your last two comments. What's probably safe? and what is "production"? |
| 00:27 | slyrus | are you saying that 1.2 and 1.3 are de facto incompatible or that some code for 1.2 will need some changes to work with 1.3 but that said code will then continue to work under 1.2? |
| 00:27 | slyrus | hrmm... I probably didn't want to use de facto there. but you get the idea. |
| 00:28 | slyrus | it would be nice if folks libraries could continue to be used for both 1.2 and 1.3, right? |
| 00:28 | technomancy | depending on a version of swank-clojure that doesn't exist yet is will probably not cause issues with projects that are in production (live, customer-facing, etc) because swank-clojure is a development tool |
| 00:29 | slyrus | what, you don't give customers access to the debugger? :) |
| 00:29 | technomancy | but I've seen changes in even bugfix point releases in ruby code that has caused actual data loss in production scenarios because our project pulled in the latest version, assuming it would be safe without much testing |
| 00:29 | technomancy | heh |
| 00:31 | technomancy | many projects that work with Clojure 1.2 will not work with 1.3, but most projects that work in 1.3 will work in 1.2 as long as they don't depend upon primitive support or cross-thread dynamic binding |
| 00:32 | slyrus | yes, this touches a nerve that bothers me about leiningen. You, rightly and justifiably, I'm sure, see it as a way of saying "you need these particular versions of these particular libraries" and providing the infrastructure to go and find those versions. I see it more as "hey, you're going to want some version of these libraries and surely you've already got your own versions of them lying... |
| 00:32 | slyrus | ...around your system somewhere, so I'll let you figure out how to tell me where I should find them". |
| 00:34 | technomancy | non-repeatable builds are fine for experimentation but totally incompatible with responsible deployment |
| 00:37 | pdk` | is 1.3 in RC phase |
| 00:41 | technomancy | what you describe might be nice to have in some circumstances, but repeatable builds are a necessity, so naturally that's where most people are focusing |
| 00:41 | slyrus | technomancy: in my mind, not having the source for all of the relevant pieces -- and the ability to build thos pieces myself -- is incompatible with responsible development |
| 00:41 | technomancy | are there any Clojure projects that deploy to clojars without source in their jars? |
| 00:42 | technomancy | I'm not aware of any |
| 00:42 | slyrus | I'd rather have my sources in a local git tree than a random jar from some jar repo |
| 00:42 | slyrus | but, I suppose that's a good point |
| 00:43 | technomancy | as long as slime can M-. to it, it's good enough for me |
| 00:43 | slyrus | hrm... not so great for tracking any local changes one might make to it -- not to mention rebuilding a world that contains those changes! |
| 00:44 | technomancy | sure; making local changes is what checkout dependencies are for |
| 00:44 | technomancy | but that's an opt-in special case |
| 00:44 | slyrus | I see that as the base case, I guess |
| 00:45 | slyrus | perhaps I should have been at the conj where y'all could have disabused my of silly holdover common-lispisms over a beer or two |
| 00:46 | technomancy | I actually wrote a precursor to Leiningen that would support git checkouts |
| 00:46 | brehaut | technomancy: any reason it didnt carry over? |
| 00:46 | technomancy | https://github.com/technomancy/corkscrew/blob/master/src/cork/screw/deps/git.clj |
| 00:46 | technomancy | brehaut: I guess the main thing is you just couldn't make any assumptions about how the dependent project was structured |
| 00:47 | slyrus | technomancy: but checking things out with git isn't the problem. it's developing one's libraries/programs in that environment that seems to be more difficult than it should be. |
| 00:47 | brehaut | technomancy: makes sense |
| 00:47 | technomancy | brehaut: does the presence of build.xml imply "ant" is enough to get a working jar? if so, what is the jar named?, etc |
| 00:48 | brehaut | technomancy: sounds like a winding garden path of suffering |
| 00:48 | technomancy | brehaut: and you have to support mvn repos anyway, since some java projects are going to be a pain to track down source for, not perform tagging correctly, not be mirrored well, etc. |
| 00:49 | technomancy | who wants to have CVS installed locally just so they can use javamail? |
| 00:49 | slyrus | technomancy: here's another disconnect between you and me. You see the end result of the build process as a jar (that can be repeatably built). I see it as a running clojure instance with the good bits in it. |
| 00:49 | slyrus | technomancy: I have no interest in those crappy java projects |
| 00:50 | technomancy | javamail is actually a really solid library |
| 00:50 | technomancy | I wouldn't have a job using Clojure if it weren't for it |
| 00:50 | slyrus | ok, fine, but the point is I want the version control and the dependency management to be separated |
| 00:51 | technomancy | slyrus: you can do a lot to customize the classpath with leiningen plugins |
| 00:51 | technomancy | if you've got some ideas to experiment with, I think it should be doable |
| 00:51 | technomancy | actually most jars on clojars have git-related metadata in them |
| 00:52 | technomancy | so it wouldn't be hard to write a task that says "for all my dependencies that provide repository metadata, check them out and put them on the classpath" |
| 00:52 | technomancy | https://github.com/technomancy/leiningen/blob/master/pom.xml#L13 |
| 00:53 | technomancy | well I am going to head off |
| 00:54 | technomancy | if you have questions about how such a thing would work, hit up the lein mailing list |
| 00:54 | slyrus | ok, thanks for your thoughts |
| 00:54 | technomancy | cheers |
| 00:55 | slyrus | indeed. first beer's on me next conj. |
| 02:11 | rata_ | I know this is a weird question, but what is the cheapest sequence constructor? |
| 02:11 | rata_ | I need to (compare ...) two sequences, but (keys ...) returns a seq that's not Comparable |
| 02:12 | rata_ | should I vec it? or list* it? |
| 03:20 | mister_roboto | when you're running some clojure app "in production", like a compojure web app or something, is it usual practice to leave a REPL running? |
| 05:58 | fliebel | morning |
| 06:01 | fliebel | I figured there are at least 2 couchdb projects for Clojure. Which one do you recommend? clojure-couchdb appears on top at google, but clutch seems to have a Clojure view server. |
| 06:22 | fliebel | Okay Clutch wins. Though I wonder how it works. Especially how it handles the revision when updating. |
| 06:26 | DubFish | Anyone willing & able to help troubleshoot a Mac 10.5 MacPorts setup? |
| 06:32 | DubFish | Here's what I get: |
| 06:32 | DubFish | % sudo port -R -u -c install clojure clojure-contrib leiningen |
| 06:33 | DubFish | 5% lein help install 101205Su111826 |
| 06:33 | DubFish | That's not a task. Use "lein help" to list all tasks. |
| 06:33 | DubFish | Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil (jar.clj:17) |
| 06:33 | DubFish | at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2911) |
| 06:33 | DubFish | I'm hoping this is a well-known issue... |
| 06:34 | DubFish | Mac OS X 10.5.8 on a 2006 MacBook Pro (dual-core Intel) |
| 06:34 | DubFish | Java 1.6.0_22 |
| 06:35 | DubFish | MacPorts Clojure 1.2 |
| 06:41 | DubFish | % lein self-install 101205Su113513 |
| 06:41 | DubFish | That's not a task. Use "lein help" to list all tasks. |
| 06:41 | DubFish | (please ignore right-hand prompt date strings) |
| 06:49 | ismarc | so, from your errors, it looks like lein is installed |
| 07:29 | fliebel | DubFish: lein is on macports? |
| 07:51 | fliebel | Hey, isn't there a nice interface I can implement for atom? atom is "final public class Atom extends ARef" so the final means I can't even subclass it, right? |
| 07:58 | fliebel | Hrm, so I can't subclass it, and I can't implement the interface, because there is none. But I have a case I think fits the atom model perfectly, but isn't a data structure. |
| 08:00 | raek | fliebel: you can make your own type that behaves exactly as an atom by implementing ARef |
| 08:01 | raek | hrm, swap! and friends are limited to clojure.lang.Atom.... |
| 08:02 | fliebel | right |
| 08:02 | raek | fliebel: I'm curious... what are you working on? |
| 08:02 | fliebel | raek: Nothing, but looking at couchdb, it seems to be a prefect fit. |
| 08:03 | fliebel | raek: Normally updating a document involves a revision, which works exactly like compare-and-set!, if the _rev doesn't match, it fails. |
| 08:04 | raek | interesting |
| 08:04 | fliebel | So I think it would be easier to get deref to return the value and swap! and compare-and-set! to do the usual spin loop on updating the document. |
| 08:06 | fliebel | raek: Interesting, but impossible with the current implementation of atom. |
| 08:07 | fliebel | I'd have to bring my own swap! IDeref exist though, so @ would work. |
| 08:07 | raek | maybe you should mention this to rhicket |
| 08:07 | raek | *rhickey |
| 08:08 | fliebel | raek: Do you think atom and friends could get a shiny new interface if I asked him? |
| 08:08 | raek | after all, there is a very strong semantic match |
| 08:08 | nickik | sombody know ruby? whats not= in ruby? |
| 08:09 | raek | I don't know. but it could be interesting to hear why there isn't interfaces for these things |
| 08:09 | fliebel | nickik: !=? |
| 08:09 | fliebel | raek: Atom is marked final, so maybe he doesn;t want people to toy with it? |
| 08:09 | raek | well, all the concrete classes in clojure is final |
| 08:10 | raek | but wherever there is a concrete class, there is usually an interface as well |
| 08:10 | raek | e.g. IPersistentVector and PersistentVector |
| 08:10 | fliebel | raek: Why is that? (and what is the best way to reach rhickey?) |
| 08:10 | fliebel | (the final part) |
| 08:11 | nickik | @fliebel: thanks |
| 08:11 | aligole | hi guys |
| 08:12 | raek | I think there are some issues with subclassing (maybe thread safety?), as clojure as stayed away from it when deftype, defrecord and defprotocol was introduced |
| 08:12 | raek | but I don't remeber the details |
| 08:12 | fliebel | okay |
| 08:14 | raek | I guess you could post to the mail list (or even the dev mail list, if you have signed the CA), or just hang around and hask him here |
| 08:14 | fliebel | No CA, but I'll wait for him to make his appearance here. |
| 08:15 | raek | having interfaces for the other reference types might be another story |
| 08:15 | fliebel | Why? |
| 08:15 | clojurebot | http://clojure.org/rationale |
| 08:15 | raek | since they have much more intricate semantics |
| 08:16 | raek | it might be hard to find something that has exactly the same semantics as a ref, for instance |
| 08:17 | fliebel | raek: So it's because they're hard to get right? |
| 08:17 | raek | that is my guess |
| 08:17 | raek | this is just speculations |
| 08:18 | fliebel | But say there is a perfect use case for ref just around the corner, it wouldn't hurt to be able to implement it, right? |
| 08:18 | aligole | Can anyone point me to some sample code or tutorials for some one with Python/C# background? |
| 08:21 | raek | fliebel: refs are entangled with the STM, so there might not be a clear cut interface in that case (this is my guess) |
| 08:22 | fliebel | raek: That would make sense… I think… I'll look at the ref impl |
| 08:22 | raek | atoms are more simple, as they only involve the atom object itself |
| 08:24 | malky42 | do you guys know how to defstruct with default values. For example, if I do (defstruct test :arg1 :arg2) how I get arg1 to have a default value of 1? |
| 08:25 | fliebel | malky42: My guess is using a :or keyword, but I am surely wrong. |
| 08:26 | raek | fliebel: defstruct not destruct... :-) |
| 08:26 | fliebel | raek: Yea, that's why I'm wrong :( Nyway, I think he ought to use records, tight? |
| 08:27 | raek | malky42: you can store a "default struct" in a var and merge that with a map that the user supplies |
| 08:27 | malky42 | raek: okay, I think I play with that. |
| 08:27 | malky42 | raek: one thing, do records now supersede structs? |
| 08:28 | raek | (defn make-thing [t] (merge default-thing t)) |
| 08:28 | raek | malky42: records do what structs did, but with even less space |
| 08:29 | raek | but yes, redords makes them a bit obsolete |
| 08:29 | mduerksen | raek, malky42: you actually have to do a merge-with, otherwise it won't work |
| 08:30 | raek | ,(doc merge) |
| 08:30 | fliebel | raek: Can you do destructering in a record? |
| 08:30 | clojurebot | "([& maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping from the latter (left-to-right) will be the mapping in the r... |
| 08:30 | mduerksen | as a struct always has an entry for every key, which can be nil |
| 08:30 | malky42 | raek: I haven't really looked at records. I think I'll have to read that chapter before playing with the merge/merge-with. That's a good idea to include defaults -- i hadn't thought of that. |
| 08:30 | raek | fliebel: records are maps. |
| 08:30 | fliebel | raek: yes, yes… wait… hrm... |
| 08:32 | raek | mduerksen: why would one have to use merge-with rather than merge? |
| 08:32 | mduerksen | raek, malky42: the problem with merge is that is is a difference if the key is not present or if the value for the key is nil, which is the case in structs |
| 08:32 | mduerksen | ,(merge {:a 1} {:a nil}) |
| 08:32 | clojurebot | {:a nil} |
| 08:33 | mduerksen | ,(merge-with #(if %2 %2 %1) {:a 1} {:a nil}) |
| 08:33 | clojurebot | {:a 1} |
| 08:33 | raek | my assumption was that the left map was a struct object with all its slots filled |
| 08:34 | raek | and the right map an ordinary map used to override the defaults |
| 08:34 | fliebel | hrm, no destructuring at all in records: #:user.blah{:& 1, :c 2} |
| 08:34 | mduerksen | the problem is, that a struct always has its slots filled, but some could have nil value |
| 08:34 | clojurebot | not a problem, the average bid for it on getacoder is $821.00 |
| 08:35 | raek | fliebel: ah, you mean in the fields vector? no. |
| 08:35 | fliebel | (is it me, or has clojurebot learnt a lot of new interruptions?) |
| 08:36 | raek | mduerksen: ok, now I see what you meant. if the 't' argument in my function is a struct, then you need to use merge-with. |
| 08:36 | raek | fliebel: the fields become java class fields |
| 08:37 | raek | so you can't have a dynamic number of fields |
| 08:37 | fliebel | I see |
| 08:38 | mduerksen | raek: yes. i ran into that issue just yesterday. the merge-with solution was all i could come up with. maybe there is something more elegant? |
| 08:43 | killy971 | Hello. I was looking for some help on "(case ...)" statement generation with macros. I have a "factorial" function and would like to generate "(case 1 1 2 2 3 6 4 24 ...)" until a given value. |
| 08:51 | raek | (defmacro factorial-prime [n] `(case ~@(mapcat (juxt identity factorial) (range 0 (inc n)))))) |
| 08:52 | raek | wait |
| 08:55 | killy971 | ~@ is used to inline a list? |
| 08:55 | clojurebot | @ is splicing unquote |
| 08:56 | raek | (defmacro factorial-cases [x n] `(case ~x ~@(mapcat (juxt identity factorial) (range n)) (factorial ~x))) |
| 08:56 | raek | (defn factorial2 [x] (factorial-cases x 5)) |
| 08:57 | raek | ,(let [xs [1 2 3]] `(foo a ~x b)) |
| 08:57 | clojurebot | java.lang.Exception: Unable to resolve symbol: x in this context |
| 08:57 | raek | ,(let [xs [1 2 3]] `(foo a ~xs b)) |
| 08:57 | clojurebot | (sandbox/foo sandbox/a [1 2 3] sandbox/b) |
| 08:57 | aligole | Hey guys! if you have a something like (defrecord Brain [neuron glia]) and you have (defrecord Neuron [id x y]) when you are "instantiating" a new brain is there a way to validate the parameter being passed is a valid Neuron! |
| 08:57 | raek | ,(let [xs [1 2 3]] `(foo a ~@xs b)) |
| 08:57 | clojurebot | (sandbox/foo sandbox/a 1 2 3 sandbox/b) |
| 08:57 | killy971 | ok, I see, thanks. trying the macro |
| 08:58 | raek | killy971: yes, it buts the elements in the list, rather than the whole thing as one element |
| 08:59 | raek | ,(let [x 'x, n 5] `(case ~x ~@(mapcat (juxt identity factorial) (range n))) |
| 08:59 | clojurebot | EOF while reading |
| 08:59 | raek | ,(let [x 'x, n 5] `(case ~x ~@(mapcat (juxt identity factorial) (range n)))) |
| 08:59 | clojurebot | java.lang.Exception: Unable to resolve symbol: factorial in this context |
| 09:00 | killy971 | ,(def factorial [n] (if (zero? n) 1 (reduce * n (range 2 n)))) |
| 09:00 | clojurebot | DENIED |
| 09:01 | raek | ,(let [x 'x, n 5, factorial #(reduce * (range 1 (inc %)))] `(case ~x ~@(mapcat (juxt identity factorial) (range n))) (factorial ~x)) |
| 09:01 | clojurebot | java.lang.IllegalStateException: Var clojure.core/unquote is unbound. |
| 09:03 | raek | aligole: a very common solution is to not force the users to call the Neuron constructor themselves, but provide a function like (defn make-neuron [...] ...) that can do validation, etc |
| 09:04 | raek | with this approach, you can change the number of fields (as well as the ordering), without having to rewrite all code that makes instances |
| 09:05 | raek | user=> (let [x 'x, n 5] `(case ~x ~@(mapcat (juxt identity factorial) (range n)) (factorial ~x))) |
| 09:05 | raek | (clojure.core/case x 0 1 1 1 2 2 3 6 4 24 (user/factorial x)) |
| 09:05 | raek | killy971: ^ |
| 09:05 | killy971 | yes? |
| 09:05 | killy971 | looks perfect! |
| 09:06 | killy971 | thank you very much |
| 09:08 | aligole | raek: thanks, I am still in non-clojure/lisp way of thinking, |
| 09:18 | aligole | raek: if I don't care about concurrency, can I just ignore about all the immutability and just use everything as I used to do in other languages?! |
| 09:19 | raek | no :) |
| 09:19 | raek | the data structures in clojure are immutable |
| 09:20 | raek | they are defined that way, so you can't change it |
| 09:21 | Raynes | You could always just use Java collections, but that would be kind of silly. |
| 09:21 | nickik | @aligole you could but it would be really ugly code because you had to use refrencetypes everywhere. |
| 09:21 | Raynes | s/kind of/extremely/ |
| 09:21 | sexpbot | <Raynes> You could always just use Java collections, but that would be extremely silly. |
| 09:21 | aligole | :) I mean, can I think like they are not! and use set! and go ahead? or let me put it like this, programming is all about changing the value og variables if I try to keep the variables constant how I could solve the problem! |
| 09:21 | raek | aligole: clojure is a functional programming language. that means that much (most?) of your code takes some values and calculates new new values (without changing the old ones) |
| 09:23 | raek | there are of course thing that can change, but those are separated from the datastructures themselves |
| 09:23 | nickik | aligole, sure you could but why would you learn clojure in the first platz. If you want that common lisp or python would be a better fit. |
| 09:23 | nickik | *platz place |
| 09:24 | nickik | i used the german word :) |
| 09:24 | raek | I think clojure is a great language even if you don't use the concurrency bits |
| 09:25 | aligole | I know that and I have very limited functional programming experience (a couple of arc functions!) but can you guys point me to some code that solves a regular problem in clojure? I am not objecting I just want to learn the new way of thinking! |
| 09:26 | nickik | @not using concurrency and doing everything non-FP is not the same. You can do FP without concurrency |
| 09:27 | nickik | @aligole, define regular problem :) |
| 09:27 | Raynes | nickik: You know, IRC isn't twitter. :p |
| 09:27 | raek | aligole: what programming languages are you accustomed to? |
| 09:28 | Raynes | nickik: Just prefixing a message with someone's nick name is enough to make their clients beep or taskbar icon flash or something similar. You don't need the @. |
| 09:29 | aligole | Like I want to read some data from disk visualize them for the user and let the user manipulate them and save them back to disk! |
| 09:29 | nickik | I know that now but I only learnd that and I do it atomaticly |
| 09:30 | raek | there are different kinds of side-effects. one could be file IO, updating the UI etc. the other kind is changing data structures. Clojure is only picky about the second one... |
| 09:31 | aligole | nickik: now that I expressed the problem it seems clear that it could be done in a functional way, but I am too used to having global variables that I need to practice to the new ways! |
| 09:31 | raek | aligole: Clojure as a family of "reference types" that let you have things that change over time (e.g. things that the user can modify) |
| 09:31 | raek | one of them is the atom |
| 09:32 | nickik | agree, in this case an atom would could hold the changes |
| 09:33 | raek | the reference types are updated by giving them a function |
| 09:33 | raek | the function takes the old value (plus any extra args) and returns the new value |
| 09:34 | nickik | read in the file and convert it to a clojure data (line-seq) then save that in an atom and provide a sean API to change that data and when you are finished convert the atom back to a file |
| 09:34 | nickik | *sean sane |
| 09:35 | raek | aligole: this is a gold mine of clojure videos: http://alexott.net/en/clojure/video.html |
| 09:36 | raek | I especially recommend http://vimeo.com/10896148 and http://vimeo.com/8672404 |
| 09:36 | nickik | @Raynes I'm trying to get someone to learn clojure and you last blogpost almost threw him over the cliff. :) |
| 09:37 | nickik | damn, did it again :) |
| 09:37 | aligole | that is cool! I need to actually try it to learn it. |
| 09:37 | aligole | thanks guy |
| 09:37 | Raynes | nickik: Hehe. I'm going to assume "threw him over the cliff" is a good thing in this case. :< |
| 09:37 | Raynes | :>* |
| 09:39 | nickik | Raynes, it is if the cliff is indefinitely high |
| 09:39 | Raynes | :p |
| 09:42 | nickik | aligole, look at http://clojure.blip.tv/posts?view=archive&nsfw=dc for you the Clojure for Java Programmers videos would be best. (java meaning not lisp or FP) |
| 09:42 | Raynes | nickik: You're talking about the build tool introductory post, right? |
| 09:43 | Raynes | My last post was about sexpbot. |
| 09:43 | nickik | the one about sexpbot |
| 09:43 | Raynes | Oh. He likes sexpbot? :o |
| 09:43 | nickik | he wanted to write one anyway |
| 09:43 | clojurebot | I don't understand. |
| 09:46 | Raynes | sexpbot is my favorite project just because I have gotten at least three people into Clojure just by giving them sexpbot as a project to contribute to and write plugins for. |
| 09:46 | nickik | I showed him your post and he twitter me back that that would almost be sufficiently cool to start learning clojure |
| 09:47 | Raynes | It's very low-barrier-to-entry stuff, and they get to see it in action and use their plugins in a tool they use everyday as it is. |
| 09:48 | nickik | Il be sure to tell him that |
| 09:49 | fliebel | Raynes: I can vouch for that. Though started Clojure before sexpbot even existed, I ping everyone I have the slightest reason to :) |
| 09:49 | Raynes | fliebel: :p |
| 09:49 | Raynes | fliebel: You'll be happy to know that several people in unrelated channels find that little tidbit of functionality neat as well. |
| 09:53 | fliebel | I seem to have a tendency to write incredibly useful stuff that takes very few lines. Only problem being that I don't dare asking €300 for this kind of things. (seriously, a friend told me about a twitter tool that's being sold for that price that would be a one liner to make) |
| 09:53 | nickik | We do people need tools for twitter? |
| 09:54 | nickik | I mean wtf browse read write something if you want. What tooling is required? |
| 09:54 | fliebel | nickik: Marketeers need them. To spam people and to follow hash tags and manage things... |
| 09:55 | nickik | ok, valid point |
| 09:55 | fliebel | nickik: The tool in question monitored a Dutch hash tags for questions + a subject, and mailed you the questions, so you could make a good impression to people with related problems without scanning twitter manually. |
| 09:57 | p_l|home | nickik: trend tracking, use of twitter as automated information transport (with bots twittering and bots receiving), things like that |
| 10:06 | fliebel | https://github.com/pepijndevos/Twemail Would be lovely to have that in Clojure. Twisted is rather painfull. |
| 10:11 | jamesnvc | Hello |
| 10:11 | edw | In SLIME, I never get local vars in the backtrace. Is there a way to get them to show up? |
| 10:12 | jamesnvc | Question: What does "Pop without matching push" mean in the context of agents & atoms? |
| 10:13 | nickik | not sure but the idea in FP is that you cant have mutable data so you can not use the usal pop and push that cange the stack. |
| 10:14 | Bahman | Hi all! |
| 10:14 | jamesnvc | Hrm...I think it may be due to me somewhat-abusing agents |
| 10:15 | nickik | We us peek (top) to look at the first thing and pop to return the rest of the stack without changing the stack |
| 10:15 | nickik | don't just build a normal stack with ref-types |
| 10:16 | nickik | i had that same question to and im not sure how to think about stacks atm |
| 10:17 | jamesnvc | I don't have any explicit stacks here |
| 10:17 | jamesnvc | Although I think I might be doing something wrong |
| 10:18 | jamesnvc | I basically have a bunch of agents wandering around a grid, when the encounter another agent, one of them "kills" the other by sending it a "die" message |
| 10:18 | jamesnvc | The "pop w/o push" happens when it receives the die message |
| 10:19 | nickik | mhh |
| 10:19 | jamesnvc | (related: In order to have the agents repeatedly get called so they wander, I put a watch on each agent, which re-sends the move message. Not sure if that's idiomatic…) |
| 10:21 | nickik | why is not every element of your grid a ref? Then you could build some functions like move. |
| 10:22 | jamesnvc | I actually do have that, but I want the agents to maintain their own state |
| 10:22 | jamesnvc | (this is a proof-of-concept for something bigger, that will require each agent to carry around it's own position, &c) |
| 10:23 | nickik | so you have a map or a record in the agent |
| 10:23 | jamesnvc | Correct |
| 10:24 | jamesnvc | This is the nub of it: https://gist.github.com/729167 |
| 10:24 | nickik | i don't see the use of agents because you could change the state of the record everytime you do a move |
| 10:25 | __name__ | hi |
| 10:25 | jamesnvc | I'm using agents because I want to ultimately have potentially hundreds of independent units moving and doing their own thing |
| 10:26 | nickik | hallo |
| 10:26 | __name__ | Am I mistaken that there's no lambda in Clojure? |
| 10:26 | jamesnvc | __name__: lambda = fn |
| 10:26 | nickik | the lambda is justed named fn because that easyer for most people |
| 10:26 | __name__ | Ah. |
| 10:26 | __name__ | Fair enough :) |
| 10:28 | nickik | jamesnvc, I not sure i can help you because my lack experience |
| 10:29 | __name__ | Thank you a lot, jamesnvc and nickik. |
| 10:29 | nickik | but i can point you to a programme that is somewhat simular |
| 10:29 | nickik | http://clojure.googlegroups.com/web/ants.clj?gda=QaGDPzoAAAC_UdR48ERSha0tJ0UgPmyf3cnWebOqkFTyQwG7RLaV5e9OU0NQiFWgQuhmPR7veGf97daDQaep90o7AOpSKHW0 |
| 10:29 | jamesnvc | nickik: EXcellent, thanks a lot! |
| 10:32 | __name__ | Is there anything comparable to zip? (zip '(1 2 3) '(4 5 6)) => ((1 2) (2 3) (3 4)) |
| 10:33 | nickik | (doc zipmap) |
| 10:33 | clojurebot | "([keys vals]); Returns a map with the keys mapped to the corresponding vals." |
| 10:33 | nickik | &(zipmap [1 2 3] ["1" "2" "3"]) |
| 10:33 | sexpbot | ⟹ {3 "3", 2 "2", 1 "1"} |
| 10:34 | __name__ | wait, that's not the same thing. |
| 10:34 | nickik | i see |
| 10:34 | nickik | that if you want a map |
| 10:34 | nickik | &(partition 2 (concat [1 2 3] [4 5 6])) |
| 10:34 | sexpbot | ⟹ ((1 2) (3 4) (5 6)) |
| 10:35 | nickik | maybe there is something better but im not sure |
| 10:35 | nickik | in cases like this maps are normaly better |
| 10:41 | lyonscf | hey guys. :) |
| 10:41 | nickik | hallo |
| 10:41 | cky | nickik: But, like, maps aren't order-preserving, as your example showed. |
| 10:41 | cky | nickik: Real zip is. :-P |
| 10:42 | nickik | (doc orderd-map) |
| 10:42 | clojurebot | Pardon? |
| 10:42 | cky | nickik: How do you make zipmap generate one of those? |
| 10:42 | nickik | (doc sorted-map) |
| 10:42 | clojurebot | "([& keyvals]); keyval => key val Returns a new sorted map with supplied mappings." |
| 10:42 | __name__ | &(map (fn [x y] (x y)) '(1 2 3) '(2 3 4)) |
| 10:42 | sexpbot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 10:43 | __name__ | &(map (fn [x y] (list x y)) '(1 2 3) '(2 3 4)) |
| 10:43 | sexpbot | ⟹ ((1 2) (2 3) (3 4)) |
| 10:43 | __name__ | Now just for an arbitrary length of arguments. |
| 10:43 | cky | __name__: :-D |
| 10:43 | cky | You just want SRFI 1-style zip, dontcha. :-P |
| 10:44 | __name__ | SRFI? |
| 10:44 | __name__ | I want Python style zip and zip_longest :) |
| 10:44 | cky | __name__: It's a Scheme thing. http://srfi.schemers.org/srfi-1/srfi-1.html |
| 10:45 | __name__ | cky: I am pretty new to Lisp, so please all bear with me :) |
| 10:45 | cky | All the SRFI 1 functions that take multiple lists use the shortest list as the length to process. That way, you can pass in circular lists for all but one, for example. |
| 10:46 | nickik | you have to write it yourself (its easy enougth) or use a sorted-map |
| 10:46 | __name__ | cky: Yeah I want that and zip for the longest with padding :) |
| 10:46 | cky | nickik: :-P |
| 10:46 | mduerksen | ,(doc partition-all) |
| 10:46 | clojurebot | "([n coll] [n step coll]); Returns a lazy sequence of lists like partition, but may include partitions with fewer than n items at the end." |
| 10:47 | nickik | &(apply sorted-map [[1 2 3] [4 5 6]]) |
| 10:47 | sexpbot | ⟹ {[1 2 3] [4 5 6]} |
| 10:47 | nickik | mmh |
| 10:48 | nickik | &(sorted-map [1 2 3] [4 5 6]) |
| 10:48 | sexpbot | ⟹ {[1 2 3] [4 5 6]} |
| 10:49 | lyonscf | Hey guys, I have a question about clj-time |
| 10:50 | lyonscf | It says use (now) to get a current date-time |
| 10:50 | lyonscf | in the docs |
| 10:50 | nickik | &((fn [& coll] (partition (count coll) (concat coll) )) '(1 2 3) '(4 5 6) '(7 8 9)) |
| 10:50 | sexpbot | ⟹ (((1 2 3) (4 5 6) (7 8 9))) |
| 10:50 | lyonscf | and that fails when I make the call |
| 10:50 | lyonscf | for example |
| 10:50 | lyonscf | (def cur-date (date-time now)) |
| 10:51 | lyonscf | doesn't work |
| 10:51 | lyonscf | any ideas what's going wrong? |
| 10:51 | nickik | &((fn [& coll] (partition (count coll) (apply concat coll) )) '(1 2 3) '(4 5 6) '(7 8 9)) |
| 10:51 | sexpbot | ⟹ ((1 2 3) (4 5 6) (7 8 9)) |
| 10:51 | nickik | lyonscf, have you included it? |
| 10:52 | lyonscf | nickik: yea |
| 10:52 | lyonscf | I think i figured it out |
| 10:52 | lyonscf | I shouldn't be doing (date-time now) |
| 10:52 | lyonscf | and only (now) |
| 10:52 | lyonscf | and that will return the current date-time |
| 10:53 | lyonscf | yup, that's it |
| 10:53 | lyonscf | thanks anyway. :) |
| 12:00 | kzar | init-clojure.el seems to enable paredit-mode for the REPL in Emacs, I don't mind but then how do you enter a new line without evaluation? (It forces parenthesis to match so every time I press Enter the REPL thinks my statement is finished) |
| 12:07 | stuartsierra | try C-j |
| 12:07 | kzar | stuartsierra: Oh sweet thanks |
| 12:08 | __name__ | &(map (fn [& rest] rest) '(1 2 3) '(2 3 4) '(4 5 6)) |
| 12:08 | sexpbot | ⟹ ((1 2 4) (2 3 5) (3 4 6)) |
| 12:08 | __name__ | \o/ |
| 12:09 | raek | __name__: you can use the 'list' function too |
| 12:28 | rata_ | hi |
| 12:28 | kzar | hey |
| 12:32 | cky | &(map list '(1 2 3) '(4 5 6) '(7 8 9)) |
| 12:32 | sexpbot | ⟹ ((1 4 7) (2 5 8) (3 6 9)) |
| 12:33 | cky | &(map list '(1 2 3) '(4 5 6) '(7 8 9 10)) |
| 12:33 | sexpbot | ⟹ ((1 4 7) (2 5 8) (3 6 9)) |
| 12:33 | cky | &(map list '(1 2 3 42) '(4 5 6) '(7 8 9 10)) |
| 12:33 | sexpbot | ⟹ ((1 4 7) (2 5 8) (3 6 9)) |
| 13:09 | __name__ | raek: Thanks |
| 14:20 | thruspa | Hi, may I ask a totally newbie question? |
| 14:22 | raek | sure... go ahead! |
| 14:27 | wyrg | Just a question. |
| 14:27 | wyrg | I type in clojure "Math/Pi" and it fails with "Unable to find static field". |
| 14:28 | raek | wyrg: all the letters in PI should be capital... |
| 14:28 | wyrg | Oh, thanks. |
| 14:28 | raek | &Math/PI |
| 14:28 | sexpbot | ⟹ 3.141592653589793 |
| 14:28 | wyrg | The problem really is with: |
| 14:29 | wyrg | java.awt.GraphicsEnvironment/getLocalGraphicsEnvironment |
| 14:29 | wyrg | same error. |
| 14:29 | lyonscf | Hey guys, does anyone have any experience with webmine? |
| 14:29 | wyrg | &java.awt.GraphicsEnvironment/getLocalGraphicsEnvironment |
| 14:29 | sexpbot | java.lang.Exception: Unable to find static field: getLocalGraphicsEnvironment in class java.awt.GraphicsEnvironment |
| 14:29 | lyonscf | clj-sys/webmine that is. :) |
| 14:30 | raek | wyrg: do you have parens around it? |
| 14:30 | wyrg | I will try... |
| 14:30 | raek | &(java.awt.GraphicsEnvironment/getLocalGraphicsEnvironment) |
| 14:30 | sexpbot | ⟹ #<HeadlessGraphicsEnvironment sun.java2d.HeadlessGraphicsEnvironment@4f7dc0> |
| 14:31 | raek | since it's a method, you need to call it |
| 14:31 | wyrg | I see. |
| 14:31 | wyrg | Thank you very much! |
| 14:31 | wyrg | I'm just starting with LISP. |
| 14:31 | raek | np |
| 14:34 | p_l|home | wyrg: please avoid using the name LISP (with all caps). It refers to language that probably was used before you were born :P |
| 14:34 | Raynes | Haha. |
| 14:34 | Raynes | I've always wondered why people still write that word in all caps. |
| 14:35 | p_l|home | Raynes: bad College courses |
| 14:35 | Raynes | AFAIK, even McCarthy doesn't anymore. |
| 14:35 | p_l|home | and FUD on the net |
| 14:35 | p_l|home | Raynes: McCarthy asked everyone not to name their languages just "lisp", no matter what case :) |
| 14:36 | wyrg | Thank you. As I said I'm new to clojure, so I think I will absorb the nuances little by little :-) |
| 14:37 | Raynes | But it's so much easier to shove them down your throat and be done with it! ;p |
| 14:38 | Raynes | That explains the vocalness about not using writing Lisp in all caps. |
| 14:39 | p_l|home | Raynes: well, Clojure has the difference in name, Common Lisp gets all the wackos attracted to "LISP" -_-; |
| 14:39 | Raynes | technomancy: ping |
| 14:40 | Raynes | fliebel: Make ping case insensitive and take an optional period at the end so that I can make use of it while still looking like a grammar Nazi. |
| 14:47 | p_l|home | Raynes: better, make it into a command language capable of looking like english sentences |
| 14:47 | p_l|home | (both easier and harder than it sounds) |
| 14:59 | rata_ | chouser: what would be a good comparator fn for counted-sorted-sets to store maps? how is the comparator fn used there? |
| 15:11 | firepoet | Hey all.. Java interop question... |
| 15:13 | firepoet | I have a function: (defn -editCardWithAction [this user board-id card-id actions] |
| 15:13 | firepoet | (let [action-blocks (.split actions ";")] |
| 15:13 | firepoet | (do |
| 15:13 | firepoet | (.info logger (str "edit card with: " (alength action-blocks))) |
| 15:13 | firepoet | (map #(.info logger (str "perform card action: " %)) action-blocks)))) |
| 15:14 | firepoet | And when I run it in a repl this way, I get: com.pegby.service.clj.boardUpdate=> (-editCardWithAction nil "test" "test" 123 "first: something; second: else; third: stuff") |
| 15:14 | firepoet | 0 [main] INFO com.pegby.service.clj.boardUpdate - edit card with: 3 |
| 15:14 | firepoet | 7 [main] INFO com.pegby.service.clj.boardUpdate - perform card action: first: something |
| 15:14 | firepoet | 7 [main] INFO com.pegby.service.clj.boardUpdate - perform card action: second: else |
| 15:14 | firepoet | 7 [main] INFO com.pegby.service.clj.boardUpdate - perform card action: third: stuff |
| 15:14 | firepoet | (nil nil nil) |
| 15:14 | rata_ | firepoet: use gist.github.com |
| 15:15 | firepoet | Oh sorry. |
| 15:18 | firepoet | So the gist is: https://gist.github.com/729428 |
| 15:18 | firepoet | :-) |
| 15:18 | raek | firepoet: also, you should use doseq (or something similar) instead of map if you only care about the side-effects of the function |
| 15:18 | firepoet | Ah |
| 15:18 | raek | firepoet: what was the question? :-) |
| 15:18 | firepoet | There was a time when I cared about the result as well. |
| 15:19 | firepoet | At least for testing, since some of the functions actually return stuff I care about. |
| 15:19 | firepoet | So the question is why it doesn't seem to be calling the map function at all.. |
| 15:19 | firepoet | But only when I compile the clojure code and run it as a Java class. |
| 15:19 | firepoet | Works great on the REPL. |
| 15:20 | raek | fliebel: that is because the repl will print, and therefore force, every element of the sequence map returns |
| 15:21 | raek | the function will only be ivoked when elements are forced |
| 15:21 | firepoet | Ohh. |
| 15:21 | _ato | if you care about the return value and also want to force the lazyseq: wrap the map call in (doall ...) |
| 15:22 | firepoet | Lazy sequences to the rescue! |
| 15:22 | firepoet | Great..lemme test.. |
| 15:24 | firepoet | So is doall supposed to throw an NPE if the result is a seq of nils? |
| 15:25 | firepoet | (you can tell I'm a java programmer trying to learn clojure.. hehe) |
| 15:26 | LauJensen | Morning all :) |
| 15:26 | firepoet | _ato: I tried your suggestion, and it got further, but is now throwing a NullPointerException |
| 15:27 | lyonscf | What's the best way to debug clojure? Can anyone point me in the right direction? :) |
| 15:27 | lyonscf | I'm using emacs and swank-clojure |
| 15:29 | fliebel | Raynes: Another regex change? Sure. Want a commit, or can I tell you right away how to change the regex? |
| 15:29 | fliebel | raek: Was that message for me? |
| 15:30 | fliebel | rhickey: ping |
| 15:32 | rata_ | lyonscf: I use swank-clojure to debug |
| 15:32 | rata_ | just write (swank.core/break) where you want to know the value of locals |
| 15:32 | lyonscf | ah |
| 15:32 | firepoet | Great.. I worked through those issues and am now on to a new one. Thanks for your help! |
| 15:32 | lyonscf | awesome |
| 15:32 | lyonscf | have any useful links? |
| 15:33 | rata_ | lyonscf: http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml |
| 15:34 | firepoet | New question: Is there anything special I have to to do to make the resolve function find things properly when I'm compiling to a Java class? I'm finding that (resolve (symbol str)) works great in the REPL, but not when compiled. |
| 15:35 | firepoet | (as in, it returns nil when compiled) |
| 15:35 | lyonscf | rata_: thanks. :) |
| 15:37 | fliebel | Raynes: The regex already works for a dot at the end, or a question- or exclamation mark even. You could do [pP]ing though if you want to be able to look like a grammar nazi. I guess you don't want to support PiNg in that case. |
| 15:41 | rata_ | is it guaranteed that (= (seq m1) (seq m2)) if (= m1 m2), where m1 and m2 are hash-maps? |
| 15:42 | firepoet | So my new question: https://gist.github.com/729449 |
| 15:48 | rata_ | why sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run() takes so much time when I profile a clojure app with visualvm? |
| 15:51 | __name__ | Is there a map that runs until the longest item is exhausted, supplying a default argument for the ones that are already exhausted? |
| 15:51 | rata_ | so many questions I have |
| 15:52 | rata_ | __name__: you can (concat s (repeat default-argument)) your shorter seqs |
| 15:52 | kevinjq | hello everyone. wondering why protocol cannot be used in `derive`. e.g., (defprotocol bar (method1 [])) then (derive bar ::quux), i got error msg: java.lang.AssertionError: Assert failed: (or (class? tag) (and (instance? clojure.lang.Named tag) (namespace tag))) (NO_SOURCE_FILE:0) |
| 15:52 | hiredman | ,(map vector (concat [:a :b] (cycle [:default])) (range 10)) |
| 15:52 | clojurebot | ([:a 0] [:b 1] [:default 2] [:default 3] [:default 4] [:default 5] [:default 6] [:default 7] [:default 8] [:default 9]) |
| 15:52 | __name__ | Then I will need to know the length of the longest. |
| 15:53 | rata_ | __name__: no, you just need to know which one is the longest |
| 15:53 | hiredman | kevinjq: just like the exception says, not a class of a named thing |
| 15:53 | __name__ | Fair enough, rata_ |
| 15:54 | hiredman | __name__: do you see my map? |
| 15:54 | __name__ | hiredman: Yes. |
| 15:54 | kevinjq | hiredman, yes, i know, but i'm wondering why clojure doesn't let protocol be an acceptable arg in derive? |
| 15:55 | __name__ | hiredman: But then I need to know the longest. Still, thanks! |
| 15:55 | hiredman | kevinjq: why would they be? |
| 15:56 | kevinjq | hiredman, protocol, as clojure doc says, is similar to java interfaces. if you return java interfaces when you call (ancestors some-type), then why shouldn't interfaces allowable in (derive ...)? |
| 15:57 | hiredman | kevinjq: similar is not the same, that still doesn't seem to be a compelling reason |
| 15:58 | kevinjq | hiredman: well, actually, protocol is implemented under the hood as a java interface... the compelling reason is, when you call (ancestor (type []), it returns all the superclasses as well as interfaces that a persistent vector implements |
| 15:59 | kevinjq | why should protocol be different? |
| 15:59 | hiredman | kevinjq: just because X can be optimized as Y it does not mean that X has the same semantics as Y |
| 16:01 | kevinjq | that's not reasoning |
| 16:01 | firepoet | *sigh* guess I hit an un-solveable one. |
| 16:01 | hiredman | it is |
| 16:01 | hiredman | you are saying "protocols can be optimized as interfaces for some cases, so they should behave the same as interfaces" |
| 16:02 | rlb | chouser: wrt managining sub-commands and pipelines, could it make sense (for now) to just require you to provide a "context" -- i.e. something like (exec context "find" "/" ...). The scope of "context" would restrict the related process(es) resource lifetime(s). |
| 16:03 | raek | fliebel: 21:30 < fliebel> raek: Was that message for me? <-- which one? |
| 16:03 | kevinjq | hiredman, the main reason i wanted to use protocol in derive, is that i want to use it for multimethods. e.g., i have protocol foobar, and i have a record (which implements Map), then i want the dispatch simply be (derive foobar ::my-type), (derive java.util.Map ::my-type) and in (defmulti mymethod class) (defmethod mymethod ::my-type [] "blah blah") |
| 16:03 | rlb | So you might have something like (with-process-context context ... set-up-and-use-commands-here) |
| 16:04 | hiredman | kevinjq: protocols don't create is-a relationships, so using them for type dispatch is not a good idea |
| 16:04 | hiredman | protocols are not interfaces |
| 16:04 | firepoet | Ha! Figured it out. Java object methods aren't invoked in the same namespace as the other functions declared therein. Craziness. |
| 16:04 | kevinjq | hiredman, what do you suggest in this case? |
| 16:05 | firepoet | ns-resolve to the rescue |
| 16:06 | raek | firepoet: do you need to construct the symbol from a string? |
| 16:06 | hiredman | kevinjq: *shrug* |
| 16:06 | firepoet | Yeah. |
| 16:06 | kevinjq | hiredman, you keep saying protocol isn't interface, then do you mind sharing your vision of what protocol really is? |
| 16:07 | firepoet | raek: I figured it out. Replaced resolve with ns-resolve and all was well. |
| 16:07 | firepoet | raek: the function name is derived from something a user sends in an email |
| 16:08 | hiredman | kevinjq: there are a number of videos on the web |
| 16:08 | vIkSiT | lo all |
| 16:08 | kevinjq | lol |
| 16:08 | hiredman | there is the protocol page on clojure.org |
| 16:08 | vIkSiT | whats the best method to have a function running as a background thread (for instance, a file tailer)? |
| 16:09 | raek | you can use future or future-call to start off something in another thread |
| 16:09 | vIkSiT | ah future-call. |
| 16:09 | vIkSiT | great, thanks |
| 16:09 | vIkSiT | let me experiment |
| 16:09 | kevinjq | hiredman, i read it. the reason for protocols are to provide abstraction/contracts, which is exactly what java interfaces are for |
| 16:10 | hiredman | kevinjq: again, just because two thigns are aimed at solving the same problem is does not mean they are the same |
| 16:11 | hiredman | you obvisouly read up the point where you saw the word interface and said "oh, right, it's and interface" then tuned out |
| 16:12 | kevinjq | hiredman, i read the whole thing, thank you very much ... i keep asking what's your interpretation of clojure protocol and you keep pointing me to other resources |
| 16:13 | hiredman | kevinjq: because in my opinion those other resources explain it better than I can, and if you don't get it from there I don't see how you can be made to understand |
| 16:14 | hiredman | ~google stuart halloway expression problem |
| 16:14 | clojurebot | First, out of 516 results is: |
| 16:14 | clojurebot | Clojure 1.2 Protocols on Vimeo |
| 16:14 | clojurebot | http://vimeo.com/11236603 |
| 16:15 | hiredman | chouser actually has a video on infoq where he discusses protocols vs. multimethods |
| 16:17 | kevinjq | hiredman, thanks anyway |
| 16:17 | vIkSiT | raek, hmm, couple of questions about futures and threads if you've got a minute |
| 16:18 | vIkSiT | this is the function i'm using to tail a file: http://paste.lisp.org/display/117361 |
| 16:18 | vIkSiT | because of the Thread/sleep and recur, whenever I use this function in somehting like (doseq [line (tail-seq filename)] ... ) |
| 16:19 | vIkSiT | even with a future-call, the REPL basically gets taken over by this function and its output |
| 16:19 | vIkSiT | would i have to use an agent to perhaps run this in the background? |
| 16:21 | vIkSiT | (or anyone else have an idea about this issue?) |
| 16:22 | __name__ | Does Clojure have the concept of iterators and if so, could you link me to resources about it? |
| 16:23 | hiredman | sequences are a functional interation cosntruct |
| 16:24 | __name__ | So I have laziness instead of iterators? |
| 16:24 | vIkSiT | hmm, so a different question. lets say i've got a function that generates random numbers and prints them. |
| 16:24 | vIkSiT | a future would only run this function once - as opposed to keep it running in the background? |
| 16:25 | hiredman | __name__: not all sequences are lazy |
| 16:27 | jamesnvc | Hello |
| 16:28 | jamesnvc | Question: Is there any reason why *agent* is suddenly turning nil, ina function that is only ever called by being sent to an agent? |
| 16:30 | hiredman | jamesnvc: sounds like you just switch to clojure 1.3 |
| 16:31 | jamesnvc | Yup |
| 16:31 | jamesnvc | 1.3 has issues with that? |
| 16:31 | hiredman | the binding propagation stuff screws up *agent*, there should be a issue in jira for it |
| 16:32 | stuartsierra | it's fixed on master |
| 16:32 | jamesnvc | Alright |
| 16:32 | jamesnvc | Um, if I'm using leiningen, is there any easy way to get that on master? |
| 16:32 | jamesnvc | 1.3.0-SNAPSHOT? |
| 16:33 | hiredman | jamesnvc: you have to wait for a snapshot build of master +/- a day |
| 16:33 | bmh | Is anyone else having trouble with clojars? |
| 16:33 | jamesnvc | hiredman: Thanks |
| 16:34 | bmh | (looks like the problem is on my end) |
| 16:36 | Raynes | In that case, no. |
| 16:38 | rata_ | does anybody know why sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run() takes so much time when I profile a clojure app with visualvm? |
| 16:40 | raek | vIkSiT: you have to do the looping manually. future and future-call only evaluate the body / calls the function once |
| 16:40 | vIkSiT | raek, hmm. so basically a Thread/sleep and recur within the function? |
| 16:41 | raek | yes |
| 16:41 | vIkSiT | raek, I see. so would you recommend an agent for something like this, given their watch/error handling capabilities? |
| 16:41 | stuartsierra | Lazytest.next https://github.com/stuartsierra/lazytest/tree/next |
| 16:42 | raek | vIkSiT: if you have a state you want to serialize access to, I'd go for agents |
| 16:42 | vIkSiT | or, what are the best practices for the creation of a long running background thread? |
| 16:42 | vIkSiT | raek, ah |
| 16:44 | raek | 'future' just starts a new thread and gives you a handle to it, which can be used to get the last expression of the future body / the result of the function, check if it has finished, etc |
| 16:45 | chjames | help |
| 16:45 | raek | vIkSiT: when you doseq over that lazy sequence, you don't return until you have processed the *whole* sequence |
| 16:45 | raek | but putting the doseq call in a separate thread should not block the repl thread |
| 16:47 | vIkSiT | raek, aah. I understand the issue here. however, I'm not sure how to modify it in a way that will read one line and return that line then? |
| 16:47 | raek | vIkSiT: futures also have error handling capabilities |
| 16:48 | raek | deref/@ will throw the exception (wrapped) that the body threw |
| 16:48 | vIkSiT | ah I see |
| 16:49 | vIkSiT | (or the return value, I take it) |
| 16:49 | raek | what is the problem you are solving? |
| 16:49 | raek | what do you want to do in a separate thread? |
| 16:49 | vIkSiT | raek, i've got a file i want to tail in the background |
| 16:50 | vIkSiT | that i want to keep running unless i explicitly want to stop it |
| 16:50 | vIkSiT | for each new line in the file, i'd like to process it in some way |
| 16:50 | raek | one way could be to doseq over the lines in another thread |
| 16:51 | vIkSiT | hmm |
| 16:51 | vIkSiT | perhaps wrap tail-seq into another thread? |
| 16:51 | raek | stepping through the sequence might block, but that would be ok if it happens in a background thrad |
| 16:51 | raek | then what should the thread that waits for the next thing do? |
| 16:52 | vIkSiT | raek, id like it to call another function with the new line as a param.. (def myfn [newline] (process-line newline) (.. do more stuff ..)) |
| 16:52 | raek | you could also consider using java.util.concurrent.LinkedBlockingQueue to build your app in a producer-consumer way |
| 16:53 | vIkSiT | raek, i'm using the lamina project's channels to do that |
| 16:53 | raek | (future (doseq [line (tail-seq ...)] (process-line line))) ? |
| 16:54 | raek | lazy sequences are "pull driven" |
| 16:54 | vIkSiT | hmm |
| 16:54 | jamesnvc | Stupid question, but how do I get the 1.3.0 master in leiningen? 1.3.0-master-SNAPSHOT? |
| 16:55 | vIkSiT | ah |
| 16:56 | vIkSiT | raek, that seems to work! now to see how to stop that :) |
| 16:56 | stuartsierra | jamesnvc: it's mis-versioned now as 1.3.0-alpha3-SNAPSHOT I think |
| 16:56 | jamesnvc | stuartsierra: Cool, thanks |
| 16:57 | vIkSiT | raek, for instance, i get this : http://paste.lisp.org/display/117361#1 |
| 16:57 | vIkSiT | in the background, things work fine. but i'm guessing i can't stop the future unless i'd wrapped the doseq in a function and called (future-cancel myfn) |
| 17:00 | vIkSiT | raek, hmm this is the weird part. |
| 17:00 | vIkSiT | if i wrap that in (defn myfn [] ...) and then (future-call (myfn filename)) |
| 17:00 | raek | vIkSiT: you need some way of telling it to stop. future-cancel will interrupt the thread, which will abort an ongoing sleep call, causing it to throw an InterruptedException |
| 17:00 | vIkSiT | the REPL thread still bocks on it. |
| 17:00 | raek | blocks on the future call? |
| 17:00 | vIkSiT | pasting.. |
| 17:01 | vIkSiT | raek, http://paste.lisp.org/display/117361#2 |
| 17:02 | raek | vIkSiT: replace future-call with future |
| 17:03 | raek | future-call takes a function. you try to give it the result of invoiking tailfn |
| 17:03 | raek | (future <body>) is just sugar for (future-call (fn [] <body>)) |
| 17:05 | vIkSiT | interesting. if i put a (future (..)) within the function body |
| 17:05 | vIkSiT | it works as expected |
| 17:05 | vIkSiT | perhaps there's a difference in the way future and future-call work |
| 17:05 | vIkSiT | oh i see. |
| 17:10 | rata_ | does anybody know why sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run() takes so much time when I profile a clojure app with visualvm? |
| 17:21 | rata_ | is there a number for infinity in clojure? |
| 17:22 | fliebel | rata_: No ##(/ 1 0) |
| 17:22 | sexpbot | java.lang.ArithmeticException: Divide by zero |
| 17:22 | bmh | rata_: Double has NEGATIVE_INFINITY and POSITIVE_INFINITY |
| 17:22 | rata_ | thanks =) |
| 17:23 | fliebel | bmh: What's inside it? |
| 17:23 | bmh | fliebel: 0x7ff0000000000000L http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#NEGATIVE_INFINITY |
| 17:23 | bmh | and 0xfff0000000000000L |
| 17:33 | __name__ | Comments and constructive criticism appreciated: http://bpaste.net/show/12026/ |
| 18:40 | cky | &(map (fn [op] (op Double/POSITIVE_INFINITY Double/NEGATIVE_INFINITY) `(,+ ,/)) |
| 18:40 | sexpbot | java.lang.Exception: EOF while reading |
| 18:40 | cky | &(map (fn [op] (op Double/POSITIVE_INFINITY Double/NEGATIVE_INFINITY)) `(,+ ,/)) |
| 18:40 | sexpbot | ⟹ (-Infinity -Infinity) |
| 18:41 | cky | ...I must be doing something wrong. |
| 18:41 | cky | &(+ Double/POSITIVE_INFINITY Double/NEGATIVE_INFINITY) |
| 18:41 | sexpbot | ⟹ NaN |
| 18:41 | cky | &(/ Double/POSITIVE_INFINITY Double/NEGATIVE_INFINITY) |
| 18:41 | sexpbot | ⟹ NaN |
| 18:41 | cky | There, that's better. :-D |
| 18:41 | cky | &`(,+ ,/) |
| 18:41 | sexpbot | ⟹ (clojure.core/+ clojure.core//) |
| 18:42 | cky | &(map (fn [op] (op 2 5)) `(,+ ,/)) |
| 18:42 | sexpbot | ⟹ (5 5) |
| 18:42 | tonyl | why the commas |
| 18:42 | cky | tonyl: They're unquotes. |
| 18:43 | cky | `(+ /) is the same as '(+ /): two symbols in a list. |
| 18:43 | tonyl | oh, I thought it was only whitespace and ~ was to unquote |
| 18:43 | cky | `(,+ ,/) is a list with two function objects. |
| 18:43 | cky | Hmm, maybe you're right. |
| 18:43 | cky | `(~+ ~/) |
| 18:43 | cky | &`(~+ ~/) |
| 18:43 | sexpbot | ⟹ (#<core$_PLUS_ clojure.core$_PLUS_@1ba24d5> #<core$_SLASH_ clojure.core$_SLASH_@b48593>) |
| 18:43 | cky | Ah, much better. |
| 18:44 | cky | tonyl: Thanks. :-) |
| 18:44 | cky | &(map (fn [op] (op Double/POSITIVE_INFINITY Double/NEGATIVE_INFINITY)) `(~+ ~/)) |
| 18:44 | sexpbot | ⟹ (NaN NaN) |
| 18:44 | cky | \o/ |
| 18:44 | tonyl | np |
| 18:44 | cky | (Old Lisp habits have a way of sticking around. :-P) |
| 18:45 | tonyl | what does the comma mean in old lisp? I am new to lisp |
| 18:45 | cky | tonyl: In traditional Lisp, comma is unquote. |
| 18:45 | tonyl | oh |
| 18:46 | cky | Let's try one more thing.... |
| 18:46 | cky | &`(1 2 ~@(map - '(1 2 3)) 3 4 5) |
| 18:46 | sexpbot | ⟹ (1 2 -1 -2 -3 3 4 5) |
| 18:46 | cky | \o/ |
| 18:47 | cky | tonyl: In traditional Lisp, ,@ is "unquote-splicing". Glad to see that ~@ works the same way here. |
| 18:48 | tonyl | yeah, i wasn't aware of the change in lisps, did ~ meant something else in other lisps? |
| 18:49 | cky | I don't think ~ has any special meaning in other Lisps. At least, not in Scheme. |
| 18:49 | rata_ | lets inside a fn are compiled as ns$fn-name$fn_xxx? |
| 18:49 | hiredman | rata_: no |
| 18:49 | tonyl | cky: a little more info if you want http://clojure.org/reader |
| 18:50 | cky | Thanks! Hopefully the info will stick this time. :-) |
| 18:51 | rata_ | *ns$fn-name$fn__xxx? |
| 18:51 | rata_ | or are fors compiled as ns$fn-name$fn__xxx? |
| 18:52 | cky | tonyl: O_o Wow, apparently viewing that page on w3m (a least on Ubuntu 9.10) causes a segmentation fault. |
| 18:54 | tonyl | wow, let me try it |
| 18:54 | rata_ | how are lets compiled? |
| 18:55 | tonyl | cky: it worked in my machine (ubuntu 10.10) but it took a couple of mins |
| 18:55 | cky | I searched for "unquote" (which found the first instance successfully). Pressing "n" to find the next instance caused the segfault. |
| 18:56 | cky | It doesn't happen every time, but I've managed to replicate it 3 times. |
| 18:56 | tonyl | oh weird |
| 18:56 | cky | ...yeah. I must try upgrading to 10.10 and see where I get. |
| 19:25 | DietCokeIsMyBloo | can someone clarify the difference between the rem and mod operators |
| 19:28 | tonyl | I think the only difference that mod truncates toward negative infinity |
| 19:30 | DietCokeIsMyBloo | i saw that, but i don't know what that means |
| 19:32 | tonyl | mod uses rem and checks for the result and if it is zero or the multiplication of the 2 numbers passed to it is positive it would return the value |
| 19:32 | tonyl | $source mod |
| 19:32 | sexpbot | mod is http://is.gd/igoOF |
| 19:34 | DietCokeIsMyBloo | ok. |
| 19:34 | DietCokeIsMyBloo | i think i got it |
| 19:34 | DietCokeIsMyBloo | danke :) |
| 20:18 | DietCokeIsMyBloo | got another question |
| 20:19 | DietCokeIsMyBloo | it's a recursion qustion |
| 20:19 | DietCokeIsMyBloo | what's happening in line 3 |
| 20:19 | DietCokeIsMyBloo | http://codepad.org/QQRU8Gqp |
| 20:20 | DietCokeIsMyBloo | is that way you go from a fxn with a single variable to 2? or is there some annonymous function stuff going on? |
| 20:46 | tomoj | DietCokeIsMyBloo: basically, it's defining a default value for the acc parameter |
| 20:46 | tomoj | when you call factorial-2 with one arg, it's n |
| 20:46 | tomoj | then it calls itself with 1 and your n |
| 20:47 | tomoj | so you can either call factorial-2 passing in acc and n (the two-arg version), or if you just pass n, acc will be 1 |
| 20:47 | DietCokeIsMyBloo | i get that part.. like what's it doing.. do i need to worry about the how thogh? |
| 20:47 | tomoj | the how is simple, it just calls itself |
| 20:48 | tomoj | the function is called factorial-2 |
| 20:48 | tomoj | on line three you see just a function call to factorial-2, passing in 1 and n as args |
| 20:48 | DietCokeIsMyBloo | so on line 7- when it recurs, what happens? |
| 20:48 | tomoj | the one-arg version of the function is just calling the two-arg version of the function |
| 20:49 | tomoj | then, the two-arg recurs to itself |
| 20:49 | tomoj | say you pass in acc 1 and n 3 |
| 20:49 | DietCokeIsMyBloo | it seems wierd though- you're defining a fxn with one param, then saying turn into 2 param.... do stuff, and recur with the 2 param |
| 20:50 | DietCokeIsMyBloo | at which point, it calls the fxn which takes 1 arg |
| 20:50 | tomoj | 3 isn't equal to 1, so it recurs, calling itself with (* 3 1) = 3 and (dec 3) = 2 |
| 20:50 | tomoj | now 2 isn't equal to 1, so it recurs again, calling itself with (* 2 3) = 6 and (dec 2) = 1 |
| 20:50 | tomoj | now 1 is equal to 1, so it returns 6, 3! |
| 20:51 | tomoj | the one-arg version calls by name because you can't recur from a one-arg to a two-arg |
| 20:51 | tomoj | if you recur, you have to use the same number of arguments as the version you're defining (the two-arg in the example) |
| 20:52 | tomoj | DietCokeIsMyBloo: what languages do you already know? |
| 20:52 | tomoj | java, c++, ruby, python, anything like that? |
| 20:53 | DietCokeIsMyBloo | java and c |
| 20:53 | DietCokeIsMyBloo | i know recursion |
| 20:53 | tomoj | ok, so say you were doing this in java, how would you do it? |
| 20:53 | tomoj | int acc = 1; |
| 20:53 | tomoj | then acc *= i; in a loop? |
| 20:54 | DietCokeIsMyBloo | well, i'd do 2 functions( defn factorial-2 [n] factorial-helper [n 1] ) |
| 20:54 | DietCokeIsMyBloo | and then have factorial helper do the rest |
| 20:54 | DietCokeIsMyBloo | oh sorry- you said java |
| 20:54 | tomoj | well, yeah, that would work too |
| 20:54 | tomoj | the thing is, you don't want to defn factorial-helper really |
| 20:54 | tomoj | because that's not something anyone will probably call |
| 20:54 | DietCokeIsMyBloo | why's that? |
| 20:55 | tomoj | I don't think you want to define a two-arg version of factorial, either, really |
| 20:55 | DietCokeIsMyBloo | agreed |
| 20:55 | tomoj | no one will use it |
| 20:55 | DietCokeIsMyBloo | so, one more time |
| 20:55 | tomoj | the fact that we're threading an accumulator through arguments is an internal detail |
| 20:55 | DietCokeIsMyBloo | fact-2 takes 1 arg n initially |
| 20:56 | DietCokeIsMyBloo | changes it into a 2 arg fxn |
| 20:56 | DietCokeIsMyBloo | does stuff, recurs |
| 20:56 | DietCokeIsMyBloo | with the new accumulator and dec'd n |
| 20:57 | DietCokeIsMyBloo | and then..n it goes to line 1, tries line2- fails goes to line 3, and doesn't do anything, then hops to line 4? |
| 20:57 | DietCokeIsMyBloo | i'm missing something there... |
| 20:58 | DietCokeIsMyBloo | how the fxn knows it can take 2 args... |
| 20:58 | lucian | DietCokeIsMyBloo: you don't need 2 args |
| 20:59 | tomoj | when you call the function, you either pass in one arg or two args |
| 21:00 | tomoj | the appropriate version in the defn is used |
| 21:00 | lucian | DietCokeIsMyBloo: if you get the chance, read "The Little Schemer" |
| 21:00 | DietCokeIsMyBloo | is that what line 4 means? |
| 21:00 | lucian | it's great for learning recursion |
| 21:01 | tomoj | when you recur with two args, it doesn't need to try line 2 or line 3, it just calls the two arg version because you passed in two args |
| 21:01 | DietCokeIsMyBloo | sorry- let me be more specific- does line 4 mean, that it can take 2 args? |
| 21:01 | tomoj | yeah |
| 21:01 | tomoj | you can either define a single arity like this: (defn foo [x y] ...) |
| 21:01 | tomoj | or multiple arities like this: (defn foo ([x] ..) ([x y] ..) ([x y z] ..)) |
| 21:02 | DietCokeIsMyBloo | ahh |
| 21:02 | DietCokeIsMyBloo | this was where the confustion was.... |
| 21:02 | DietCokeIsMyBloo | tomoj- you're a superstar! |
| 21:02 | DietCokeIsMyBloo | yes, that's what you are my friend! |
| 21:02 | tomoj | anonymous fns can do it too |
| 21:03 | DietCokeIsMyBloo | oh |
| 21:03 | DietCokeIsMyBloo | let me try an annon fxn instead for this |
| 21:03 | DietCokeIsMyBloo | brb |
| 21:04 | tomoj | ,((fn fact ([n] (fact 1 n)) ([a n] (if (= n 1) a (recur (* n a) (dec n))))) 20) |
| 21:04 | clojurebot | 2432902008176640000 |
| 21:04 | tomoj | but really the two-arg version should be hidden I'd think |
| 21:04 | lucian | and if you're curious you can do this with one arg, but it's no longer constant space |
| 21:05 | tomoj | meaning it might overflow the stack? |
| 21:05 | DietCokeIsMyBloo | got it |
| 21:05 | lucian | tomoj: the recur version is tail recursive |
| 21:05 | tomoj | right |
| 21:05 | tomoj | your one-arg version isn't? |
| 21:06 | lucian | nope, all call stacks exist |
| 21:06 | lucian | &(defn fac [n] (if (= n 1) 1 (* n (fac (- n 1))))) |
| 21:06 | sexpbot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 21:06 | lucian | meh |
| 21:06 | tomoj | oh, right |
| 21:06 | lucian | &((fn fac [n] (if (= n 1) 1 (* n (fac (- n 1))))) 10) |
| 21:06 | sexpbot | ⟹ 3628800 |
| 21:06 | tomoj | wonder what types fact should use |
| 21:10 | tomoj | interesting: (loop [acc (bigint 1) n (int n)] ...) with (* n acc) in the recur gives auto-growing results |
| 21:10 | tomoj | integer, long, or BigInteger, whichever is big enough for the answer |
| 21:10 | tomoj | I would've thought that if you started with bigint it would always be a BigInteger |
| 21:11 | lucian | since they're immutable, stuff like this is easy |
| 21:12 | lucian | stuff like this = promoting/demoting ints |
| 21:12 | cky | lucian: Does Clojure actually have tail calls? http://clojure.org/functional_programming suggests it doesn't. |
| 21:13 | lucian | cky: afaik it uses recur for the same results |
| 21:14 | cky | Ah. :-) |
| 21:14 | tomoj | it just won't automatically recognize tail calls |
| 21:15 | cky | Darn. I was gonna read up on recur, but, my browser crashed again. :-P |
| 21:15 | tomoj | you must use recur and you must do it in tail position |
| 21:15 | cky | tomoj: *nods* |
| 21:15 | lucian | i think it's quite nice and explicit |
| 21:15 | lucian | even if clojure had tail calls, i'd still use recur |
| 21:17 | cky | Okay, so, this is a complete n00b question, but, is it possible to recur to the non-innermost loop/fn? |
| 21:31 | DietCokeIsMyBloo | can you help me with filter? |
| 21:31 | DietCokeIsMyBloo | if i have a list of numbers, and i want to filter out the odds what would it be? |
| 21:32 | DietCokeIsMyBloo | (filter (predicate) lst) |
| 21:32 | DietCokeIsMyBloo | but the predicate is what i don't know... |
| 21:32 | DietCokeIsMyBloo | (fn[x] (odd? x) true) is not right.... |
| 21:33 | DietCokeIsMyBloo | i just need to get rid of the true |
| 21:33 | DietCokeIsMyBloo | but i don't get why |
| 21:34 | DietCokeIsMyBloo | so, the result WOULD be, (filter (fn[x] (odd? x) ) lst).... but why? |
| 21:34 | headlessClown | it's not just (filter odd? lst)? |
| 21:35 | DietCokeIsMyBloo | i didn't try that one |
| 21:35 | DietCokeIsMyBloo | but don't you need a true false condition for the predicate? |
| 21:35 | DietCokeIsMyBloo | or is that the way filter works... |
| 21:35 | tonyl | odd? is a fn that returns true or false |
| 21:35 | DietCokeIsMyBloo | right |
| 21:35 | headlessClown | it's all baked in |
| 21:35 | tonyl | usually fns endind in ? do that |
| 21:35 | DietCokeIsMyBloo | ok |
| 21:36 | DietCokeIsMyBloo | so to use filter- apply a fxn that returns true or false. that function is applied to EVERy element of the list and those elements passing the predicate are returned? |
| 21:37 | cky | &(odd? Double/POSITIVE_INFINITY) |
| 21:37 | sexpbot | java.lang.ArithmeticException: bit operation on non integer type: class java.lang.Double |
| 21:37 | tonyl | diateCokeIsMyBloo: yea |
| 21:37 | cky | Well, that makes it pretty obvious how odd? is implemented. :-P |
| 21:38 | tonyl | $source odd? |
| 21:38 | sexpbot | odd? is http://is.gd/igDKd |
| 21:38 | cky | tonyl: Does tab completion not work on your IRC client? |
| 21:38 | tonyl | I don't know. I am pretty new to IRC, I am using XChat |
| 21:39 | cky | Ah, I think if you type "di<TAB>" (where <TAB> is your tab key), it should complete the rest. |
| 21:39 | tonyl | oh snap, it does. thanks |
| 21:39 | cky | \o/ |
| 21:39 | DietCokeIsMyBloo | maybe i need a break for a bit :) |
| 21:40 | DietCokeIsMyBloo | thanks guys |
| 21:40 | cky | And yeah, even? and odd? are implemented the way I thought it was (given the error message :-P). |
| 21:40 | tonyl | using bit-and |
| 21:43 | cky | Yep. |
| 22:15 | brehaut | xcthulhu: fhtagn |
| 22:15 | xcthulhu | Indeed |
| 22:16 | xcthulhu | This is hardly a #clojure question, but what are good channels for embedded system development? |
| 22:16 | xcthulhu | Although I'm holding out that clojure will harken the second coming of the lisp-machine... |
| 22:21 | xcthulhu | No bites... alas... |
| 22:24 | cky | My 2 cents on the "second coming of the Lisp Machine" business: I think x64 is the dominant platform these days. There is no getting away from that. But, you can design an OS, that runs well under virtualisation, that is fully managed and based on Clojure. |
| 22:25 | cky | Your OS also needs to support loading .class files, or at least some format the Java class libraries can be compiled into. |
| 22:25 | trytotrace | hi. I have a question about tracing. anyone here has done it the lisp way on clojure? |
| 22:25 | cky | The topic of writing fully-managed Lisp-based OSs is a not-infrequent topic in #scheme. |
| 22:25 | cky | xcthulhu: ^^--- |
| 22:27 | trytotrace | is it possible to shadow a function during runtime for tracing? |
| 22:32 | jweiss | i'm trying to write automated tests in clojure. I'd like to not have to write separate human-readable procedures. Should I made my tests more data-like, and transform it into a more readable form for humans? or should I just make my programs readable to begin with by using a lot of macro syntactic sugar? |
| 22:33 | jweiss | so far i've been using macros, but i keep hearing the stern warnings in my head to only use them when necessary, and I'm not sure it's necessary this time |
| 22:35 | cky | jweiss: My 2 cents (as a Scheme programmer, not a Clojure one): you can use macros for syntactic sugar, but, if there's a way to make a procedure for doing so that's just as clear, then that's preferable. |
| 22:35 | Derander | as a ruby programmer: damn performance, pour on the sugar! |
| 22:36 | cky | Derander: Hahahaha. |
| 22:36 | jweiss | yeah I am not particularly concerned with perf either, since my app under test is completely separate. my code spends a lot of time just waiting on the app. |
| 22:37 | cky | jweiss: Indeed. Really, either approach is fine. Just truck along with what you have. |
| 22:37 | jweiss | cky: by human readable, i mean, readable by non programmers |
| 22:37 | cky | jweiss: Of course. |
| 22:38 | cky | jweiss: In my day job, we program in Ruby, and care a lot about making code easy to read (I think the buzzword these days is "DSL"). So I totally understand. |
| 22:40 | jweiss | cky: yeah it not a problem that i'm sure i can solve. i just know it seems really stupid to me to write an english procedure as the official "test" and then automate it and have the two "definitions" drift apart over time |
| 22:41 | jweiss | if there's just going to be a canonical definition of the test it should be the code |
| 22:43 | Derander | jweiss: you'll care about performance after your cucumber/rspec tests take 45 seconds to run :- |
| 22:43 | Derander | :-) |
| 22:43 | jweiss | hah i wish |
| 22:43 | jweiss | we have selenium tests that take 12 hours |
| 22:43 | Derander | oh yeah, I'm just talking about two basic scenarios |
| 22:43 | jweiss | not a single test mind you, hundreds of them |
| 22:44 | Derander | asdf. <3 ruby, but it's painfully slow sometimes. |
| 22:44 | jweiss | i'm not a big fan of cucumber's style of testing |
| 22:44 | Derander | at least it's really obvious when you have an inefficient algorithm in ruby... |
| 22:44 | Derander | jweiss: I am for some things |
| 22:44 | jweiss | too much dependency on regex |
| 22:45 | Derander | I have some of the people at my place of employment almost trained to write them for me |
| 22:45 | Derander | so the help desk people can write my specs |
| 22:45 | hippiehunter | is it possible to destructure into params for a function? |
| 22:45 | jweiss | hippiehunter: i'm pretty sure that works the same way |
| 22:45 | xcthulhu | jweiss, Does clojure have a fast regex, like google's re2? |
| 22:46 | xcthulhu | I seem to recall that google's re2 was linear time (rather than exp like ordinary implementations) |
| 22:46 | jweiss | xcthulhu: i don't know |
| 22:46 | jweiss | my problem with cucumber's use of regex has nothing ot do with performance |
| 22:47 | jweiss | it's just that if you change your english spec, you have to dig up your regex and fix that |
| 22:47 | jweiss | even if there's no real change in behavior |
| 22:47 | Derander | trade-offs must be made |
| 22:47 | jweiss | yup |
| 22:47 | jweiss | it's good at what it does |
| 22:47 | jweiss | it's just not a good fit for me |
| 22:48 | Derander | https://github.com/cavalle/steak <-- this is a cucumber alternative |
| 22:48 | Derander | less english but more code |
| 22:48 | Derander | s/but// |
| 22:48 | sexpbot | <Derander> less english more code |
| 22:48 | hippiehunter | :jweiss im having a hard time translating my knowledge of destructuring into let and named parameters into passing parameters to a function im calling. Do you know of any examples i can look at? |
| 22:50 | jweiss | hippiehunter: hm i take that back |
| 22:50 | jweiss | i guess you can't destructure in the param list of a fn definition |
| 22:50 | jweiss | ,(defn [ [x y] ] (+ x y)) |
| 22:50 | clojurebot | java.lang.IllegalArgumentException: Parameter declaration + should be a vector |
| 22:52 | hiredman | jweiss: you are missing something there |
| 22:52 | jweiss | oh yea |
| 22:52 | jweiss | ,(defn foo [ [x y] ] (+ x y)) |
| 22:52 | clojurebot | DENIED |
| 22:52 | jweiss | doh |
| 22:52 | tonyl | &((fn [[x y]] (str x "." y) [4 5]) |
| 22:52 | sexpbot | java.lang.Exception: EOF while reading |
| 22:52 | tonyl | &((fn [[x y]] (str x "." y)) [4 5]) |
| 22:52 | sexpbot | ⟹ "4.5" |
| 22:52 | jweiss | ok i take it back again hippiehunter - it does work |
| 22:53 | jweiss | (defn foo [ [x y] ] (+ x y)) |
| 22:53 | jweiss | (foo [1 3]) |
| 22:53 | jweiss | 4 |
| 22:53 | cky | &((fn [(x y)] (+ x y)) '(4 5)) |
| 22:53 | sexpbot | java.lang.Exception: Unsupported binding form: (x y) |
| 22:53 | cky | &((fn [(x . y)] (+ x y)) '(4 . 5)) |
| 22:53 | sexpbot | java.lang.Exception: Unsupported binding form: (x . y) |
| 22:53 | tonyl | &((fn [[x y]] (+ x y)) [4 5]) |
| 22:53 | sexpbot | ⟹ 9 |
| 22:53 | hippiehunter | does food need to be defined in terms of [[x y]] or is there a way without the nested vector? |
| 22:53 | cky | tonyl: I'm trying to see if one can get away from vectors. |
| 22:53 | hippiehunter | err foo |
| 22:54 | tonyl | no, i think only maps and vectors |
| 22:54 | cky | Oh well. |
| 22:54 | cky | It seems in Clojure vectors are much more first-class than they are in other Lisp dialects. |
| 22:54 | jweiss | hippiehunter: it works the same way as with let |
| 22:55 | jweiss | except you aren't assigning a value until you call the function |
| 22:55 | cky | In other Lisp dialects I've seen, vectors are very much second-class, to be used only for specific cases. |
| 22:55 | cky | (Not second-class in the sense of "first class functions", but, just, its use is not particularly encouraged, not to the same degree as lists.) |
| 22:55 | hippiehunter | right but the called method needs to be aware of this |
| 22:56 | hippiehunter | i was hoping to turn a map into the parameters for an arbitrary function |
| 22:57 | Derander | you can do it with a map |
| 22:57 | hippiehunter | I suppose in my case (constructor) i can just make a plain one, then assoc it in |
| 22:58 | tonyl | you can destructure maps |
| 22:59 | Derander | ,(defn foo [{a :a b :b}] (+ a b)) |
| 22:59 | clojurebot | DENIED |
| 22:59 | Derander | ,((fn [{a :a b :b}] (+ a b)) {:a 1 :b 2} ) |
| 22:59 | tonyl | &((fn [{x :x y :y}] (+ x y)) {:x 5 :y 9}) |
| 22:59 | clojurebot | 3 |
| 22:59 | sexpbot | ⟹ 14 |
| 22:59 | Derander | haha |
| 23:00 | Derander | good timing |
| 23:00 | tonyl | haha yeah |
| 23:00 | tonyl | took me a while to test it first :P |
| 23:01 | tonyl | Derander: how do you use :keys for destructuring? I can never remember |
| 23:01 | Derander | no clue |
| 23:01 | tonyl | mm |
| 23:02 | tonyl | found it ##((fn [{:keys [x y]}] (+ x y)) {:x 5 :y 9}) |
| 23:02 | sexpbot | ⟹ 14 |
| 23:02 | Derander | ah |
| 23:03 | Derander | interesting |
| 23:03 | brehaut | there are equivalents for strings and maybe symbols(?) too |
| 23:04 | brehaut | :strs and :syms |
| 23:04 | tonyl | brehaut: how do you use those? |
| 23:05 | brehaut | ,(let [{:strs [a b]} {"a" 1 "b" 3 "c" 3}] (+ a b)) |
| 23:05 | clojurebot | 4 |
| 23:05 | brehaut | ,(let [{:syms [a b]} {'a 1 'b 3 'c 3}] (+ a b)) |
| 23:05 | clojurebot | 4 |
| 23:06 | brehaut | syms is probably more useful in a macro than normal code? |
| 23:06 | tonyl | ooh great to know |
| 23:06 | hippiehunter | holy crap thats awsome, that makes dealing with json so much better |
| 23:06 | brehaut | http://clojure.org/special_forms |
| 23:06 | brehaut | its all in there |
| 23:07 | brehaut | yup, destructuring + multimethods = super json powers |
| 23:10 | cky | brehaut: Oh, hey, on a different topic, I notice that you're from NZ as well...do you know talios (in person, I mean)? Just trying to see how small of a world this is. |
| 23:11 | brehaut | not in person |
| 23:11 | cky | Ah, okay. |
| 23:11 | brehaut | we live about 2 hours drive apart |
| 23:11 | cky | ...is that 2 hours from Auckland, or 2 hours from Napier? :-P |
| 23:11 | brehaut | two hours from auckland |
| 23:11 | brehaut | actually, its possible both :P |
| 23:12 | cky | (Napier is talios's hometown, IIRC, hence my question. :-P) |
| 23:12 | brehaut | ah, 3.45 hours |
| 23:12 | cky | Hehehehe. |
| 23:12 | brehaut | im in hamilton |
| 23:12 | brehaut | bustling metropolis of cows |
| 23:12 | cky | Nice. We (the social circle that I know talios from) have people who live in Hamilton, too. |
| 23:13 | brehaut | oh true |
| 23:13 | cky | But, yeah, some shade of small world. :-) |
| 23:13 | brehaut | yeah :) |
| 23:14 | brehaut | its frighteningly likely that there might be someone incommon :P |
| 23:14 | cky | That wouldn't surprise me in the slightest. |
| 23:14 | cky | Heh, I consider Hamilton to be 1.15 hours from Auckland, but that's more a sign of the speed I drive at more than anything else. :-P |
| 23:14 | brehaut | hah |
| 23:15 | brehaut | wherer are you from? |
| 23:15 | cky | Well, I'm an Aucklander, but, I don't actually currently live in New Zealand. |
| 23:15 | brehaut | oh right |
| 23:15 | cky | In fact, in terms of small world, I live in the same city as Relevance. :-P |
| 23:15 | brehaut | hah |
| 23:16 | cky | (Not by intention---I've only heard about Relevance some time after I've lived in Durham.) |
| 23:24 | cky | So, since I'm new to the channel and all, what's the difference between sexpbot and clojurebot? :-) |
| 23:24 | brehaut | maintainer and various additional magic mostly? |
| 23:25 | cky | Okay, so, does it matter which one I pick on? |
| 23:25 | brehaut | i dont think so? |
| 23:25 | brehaut | https://github.com/raynes/sexpbot |
| 23:25 | cky | Okie dokie. :-) |
| 23:26 | cky | I ask because in #scheme, there are multiple bots, each running a different Scheme implementation. But, I can't really imagine there currently being more than one Clojure implementation (unless someone is running Clojure CLR in one of the bots :-P), so. |
| 23:27 | pdk | clojure had a .net version at least early on |
| 23:27 | pdk | it's probably still maintained but second fiddle to the java one |
| 23:27 | cky | pdk: It's still there. |
| 23:27 | hiredman | I have a clojure interpreter (written in clojure) I've been thinking about switching clojurebot too for better sandboxing |
| 23:27 | cky | Nice. |
| 23:27 | pdk | scheme implementations it seems have crap cross compatibility |
| 23:27 | p_l|home | "crap" is a superlative |
| 23:28 | p_l|home | a positive one, in this case :> |
| 23:28 | cky | p_l|home: ...it is? |
| 23:28 | pdk | oh you |
| 23:28 | cky | pdk: It's true, if you want to write sizeable Scheme programs, you basically have to write for a certain implementation and stick with it. |
| 23:29 | cky | Porting between implementations is, well, not free of work. |
| 23:29 | p_l|home | the SRFIs don't cover enough... then you have the fact that SRFI coverage differs among implementations |
| 23:29 | cky | p_l|home: ...and that the syntax for loading SRFIs are not portable, either. |
| 23:29 | p_l|home | especially which ones are implemented by code shipped with them |
| 23:29 | p_l|home | cky: true |
| 23:30 | hiredman | that is my concern with switching clojurebot over to the interpreter, it wouldn't really be "clojure" it would be sort of kind of like clojure |
| 23:30 | p_l|home | Racket avoids the whole issue by renaming itself and differentiating from Scheme family |
| 23:30 | cky | Indeed, Racket is...its own language. |
| 23:32 | pdk | how do clojure and abcl usually compare for speed now |
| 23:32 | p_l|home | pdk: hard to compare, IMHO |
| 23:32 | pdk | well are there some rules of thumb |
| 23:32 | p_l|home | ABCL when running compiled has definitely respectable performance, and might have less GCing than Clojure |
| 23:33 | p_l|home | the big slow point of ABCL got fixed few years ago, but still floats in information available on internet |
| 23:34 | p_l|home | recently hashtables got fixed (switchover from ABCL own code to JVM native) |
| 23:44 | pdk | what was the achilles heel with abcl for so long that you're referring to |
| 23:44 | pdk | is it just the hashtable implementation or |
| 23:46 | p_l|home | pdk: it had some issues in CLOS speed |
| 23:47 | p_l|home | it still shows up in the material on the net, but has been actually fixed for quite long time |
| 23:47 | pdk | does working with cl structs still perform well |
| 23:48 | pdk | could always roll it paul graham style and go "YEAH WELL FORGET YOU CLOS I NEVER NEEDED YOU ANYWAY" |
| 23:48 | p_l|home | pdk: now it doesn't matter, both structs and classes work fasst |
| 23:48 | pdk | gotta look into that stuff again |
| 23:48 | p_l|home | pdk: some people claim that he never learned CLOS :P |
| 23:48 | pdk | so i could do something interesting with graham's lisp book besides reading it again |
| 23:49 | p_l|home | pdk: which book? |
| 23:49 | pdk | it always struck me like the guys coming from c to c++ who went back because they said structs were good enough |
| 23:49 | pdk | ansi common lisp |
| 23:49 | p_l|home | afaik people don't really recommend that book |
| 23:50 | p_l|home | Graham has some style bloopers, at least compared to "lingua franca" of CL style |
| 23:51 | cky | p_l|home: On CL boks, what's your take on Practical Common Lisp? |
| 23:51 | p_l|home | cky: wonderful :) |
| 23:51 | cky | p_l|home: I'm trying to decide how high or low to put it on my reading list. :-) |
| 23:51 | cky | Good, I'll bump it right to near the top. |
| 23:51 | p_l|home | or, to quote Xach, “dead sexy” |
| 23:51 | cky | (Programming Clojure is currenty at top. I think PCL can be #2, at the mo.) |
| 23:54 | p_l|home | cky: PCL is good enough to give someone a fast start into CL, Gentle Introduction to Symbolic Computation is IMHO useful for all lisps, especially the early chapters (and both are available for free on the net) |
| 23:54 | DietCokeIsMyBloo | i have a beginner's question about using iterate |
| 23:54 | pdk | i should go back and finish pcl |
| 23:54 | DietCokeIsMyBloo | the question is: write an expression using iterate to return a list of squares of numbers btw 5 and 15 |
| 23:55 | pdk | where do you find the symbolic computation one |
| 23:55 | cky | p_l|home: Thanks for that, I'll add that to my list too. |
| 23:55 | pdk | is this for some sort of assignment or can you use something instead of iterate |
| 23:55 | DietCokeIsMyBloo | I have it written but was wondering if there is a cleaner way |
| 23:55 | DietCokeIsMyBloo | http://codepad.org/2gAKOmaO |
| 23:55 | DietCokeIsMyBloo | gotta use iterate |
| 23:55 | cky | Hahahahahaha. |
| 23:56 | pdk | if you're going to use iterate that way looks fine to me |
| 23:56 | DietCokeIsMyBloo | is there a "better" or cleaner way? |
| 23:56 | p_l|home | pdk: gentle: "Common Lisp: A Gentle Introduction to Symbolic Computation" is a smoother introduction to lisp programming. http://www.cs.cmu.edu/~dst/LispBook/ |
| 23:56 | pdk | though for dinky 1-argument lambdas i'd prefer to say #(* % %) instead of (fn [x] (* x x)) |
| 23:57 | DietCokeIsMyBloo | can i do it without using map? |
| 23:57 | p_l|home | cky: FYI - recently released Land of Lisp, while concentrating on CL, also has a chapter on clojure afaik |
| 23:57 | pdk | i wouldn't think to use iterate for it off the bat first thing but if you want iterate in there i think you've hit on a fairly idiomatic way to do it |
| 23:57 | cky | p_l|home: Wow, that's quite the tour of Lisp languages...wonder if it covers Arc too. :-P |
| 23:57 | pdk | land of lisp is the games coding one right |
| 23:57 | DietCokeIsMyBloo | ok :) |
| 23:57 | DietCokeIsMyBloo | thanks pdk!!! |
| 23:58 | cky | pdk: I think so, yes. |
| 23:58 | p_l|home | cky: it does in one chapter :P |
| 23:58 | pdk | i was thinking of that on kindle store but i wondered if it'd be too much like those java 101 books that teach you to use swing without knowing what an if statement even is |
| 23:58 | cky | pdk: It came #23 in sales on the O'Reilly ebook Cyber Monday sale. :-P |
| 23:58 | pdk | does it still yknow try to teach you lisp for real |
| 23:58 | Derander | it was available from o'reilly for like $10 during their 60% off ebooks |
| 23:58 | cky | Derander: Jinx! |
| 23:58 | pdk | oh snap is the sale already over |
| 23:58 | Derander | cky: :-) |
| 23:58 | Derander | pdk: yeah |
| 23:58 | Derander | pdk: it's my understanding that it does |
| 23:58 | p_l|home | pdk: it's quite good, I haven't read the whole thing yet, waiting to obtain it through official channels :) |
| 23:58 | Derander | I haven't started it though |
| 23:59 | pdk | is that code for "i pirated the kindle version" |
| 23:59 | p_l|home | pdk: if you know _why's poignant guide to ruby, it's done in similar wayu |
| 23:59 | p_l|home | *way |
| 23:59 | cky | I didn't know about the book until after the sale (though I bought 11 books from O'Reilly during it), so, I guess I'll get it when the next sale comes 'round. |
| 23:59 | p_l|home | pdk: No, not the kindle version, Kindle sucks at formatting :P |
| 23:59 | pdk | i've only heard of why's guide |
| 23:59 | pdk | i bought elementary standard ml off kindle store cause for some dopey reason |