2010-02-04
| 00:13 | itistoday | ok, still working on converting that function, at least i have a couple lines of clojure code now that the api's back up |
| 00:13 | itistoday | how to fix this: http://paste.pocoo.org/show/173729/ |
| 00:14 | itistoday | err, rather, this: http://paste.pocoo.org/show/173730/ |
| 00:19 | somnium | itistoday: that style of closing parens is rather frowned upon |
| 00:20 | itistoday | i'm sorry, but to me it makes the code readable |
| 00:21 | itistoday | call it a habit from years of C-type languages |
| 00:21 | itistoday | it lets me know where one block ends and another begins |
| 00:21 | itistoday | err.. expression |
| 00:22 | somnium | itistoday: well, its likely to draw repeated comments |
| 00:23 | itistoday | somnium: i hold my tongue when i see people piling on their parenthesis at the end even though I feel just as you feel about my coding style |
| 00:24 | somnium | itistoday: thats what the indentation is for :) |
| 00:25 | itistoday | somnium: ok, if it will help you help me: http://paste.pocoo.org/show/173732/ |
| 00:25 | somnium | itistoday: anyway, I would recommend reading about syntax-quote and experimenting with macroexpand-1 |
| 00:25 | tomoj | I guess I don't need to say "just use a decent editor for lisp" eh |
| 00:26 | tomoj | well, certainly not since the issue to which that's a response didn't actually come up-readability is different than editability |
| 00:27 | somnium | itistoday: http://mumble.net/~campbell/scheme/style.txt :) |
| 00:27 | tomoj | I guess the standard response about readability is "you'll get used to it"? :( |
| 00:28 | somnium | "Rationale: The parentheses grow lonely if their closing brackets are all kept separated and segregated." |
| 00:28 | hiredman | the rationale is the people in the irc channels you ask for help on like it that way |
| 00:29 | hiredman | :P |
| 00:29 | tomoj | for me it would take more tabbing to reindent the lonely parens if I change something |
| 00:29 | itistoday | *sigh*... |
| 00:29 | itistoday | ok... poor lonely parenthesis, excellent rational |
| 00:29 | itistoday | i'll tell that to my poor lonely braces |
| 00:30 | itistoday | but i already broke in, gave in to conformity and your unreadable style: http://paste.pocoo.org/show/173732/ |
| 00:31 | itistoday | and it still won't run :-p |
| 00:32 | hiredman | itistoday: why? |
| 00:32 | itistoday | java.lang.Exception: Can't let qualified name: user/col-syms (NO_SOURCE_FILE:32) |
| 00:33 | hiredman | itistoday: no, why are you doing this? |
| 00:33 | itistoday | oh, i'm trying to see if it's possible to write this neat newlisp function in clojure |
| 00:33 | hiredman | that is a macro, not a function |
| 00:33 | hiredman | and I would hardly call it neat |
| 00:33 | itistoday | *this neat newlisp macro |
| 00:34 | itistoday | that's not it |
| 00:34 | itistoday | i'm building up to the newlisp one |
| 00:34 | hiredman | why? |
| 00:34 | itistoday | like i said |
| 00:34 | itistoday | the newlisp macro is awesome |
| 00:34 | DeusExPikachu | I was connected to swank with emacs via slime-connect and then I got disconnected because the internet died. Unlike when I have a graceful disconnect via slime-disconnect, I can not reconnect. Is this a bug in swank? is there anything I can do to reestablish a connection to the remote swank server? |
| 00:34 | hiredman | itistoday: I doubt that |
| 00:34 | itistoday | (for-query-with-db db "SELECT name FROM people" (println NAME)) |
| 00:34 | itistoday | see |
| 00:34 | itistoday | that's awesome |
| 00:35 | hiredman | how? |
| 00:35 | itistoday | hiredman: how is mona lisa awesome? |
| 00:35 | somnium | itistoday: it vaguely reminds me of php :P |
| 00:35 | itistoday | php can't do that |
| 00:35 | itistoday | and i'm wondering whether clojure can |
| 00:35 | itistoday | i assume it can |
| 00:35 | somnium | its good at mixing templating code with db access though |
| 00:36 | itistoday | yes, that's what i want it for |
| 00:36 | somnium | itistoday: it definitely can |
| 00:36 | hiredman | that is hardly different from what you would get from using contribs sql stuff |
| 00:36 | itistoday | hiredman: that's great |
| 00:36 | itistoday | somnium: how? |
| 00:36 | hiredman | except with the sql stuff you get a result seq, and you don't shadow names |
| 00:37 | itistoday | hiredman: it's not shadowing names either |
| 00:37 | hiredman | it is |
| 00:37 | itistoday | no, really, it's not |
| 00:37 | hiredman | well, shadowing is not the right word |
| 00:37 | itistoday | it's only shadowing NAME in the body |
| 00:37 | itistoday | "shadowing" indeed |
| 00:37 | hiredman | randomly introducing |
| 00:37 | itistoday | and NAME isn't bound to anything |
| 00:37 | itistoday | yes |
| 00:37 | itistoday | actually no,and it's not random |
| 00:37 | itistoday | *it's not random |
| 00:38 | itistoday | it's really cool |
| 00:38 | itistoday | very succinct |
| 00:38 | hiredman | clojureql does that, and was recently called out in a blogpost somewhere for doing so |
| 00:38 | itistoday | clean is the word |
| 00:38 | hiredman | it's not cool |
| 00:38 | itistoday | hiredman: you're not cool |
| 00:38 | hiredman | queries as strings are not cool |
| 00:39 | itistoday | look, you don't find it cool, i do |
| 00:39 | itistoday | it's a matter of personal preference |
| 00:39 | hiredman | itistoday: I'm not cool, I'm tired of your bellyaching about newlisp and passive agressive attempts to goad people into helping you by compare clojure and newlisp |
| 00:39 | hoeck | itistoday: don't worry too much about hiredman, what you want is possible in clojure |
| 00:40 | itistoday | hoeck: thanks, and i don't doubt that, but my clojure skillz are nonexistent at this point |
| 00:40 | hoeck | itistoday: in clojure.contrib.macro-utils, there is a symbol-macrolet macro |
| 00:41 | somnium | it can be done without symbol macros |
| 00:41 | itistoday | it's really hard for me to follow the docs though as they don't give examples |
| 00:41 | hoeck | though your macro is more common-lisp style, clojure has a more functional aproach, map access is cheap, just (print (:name result)) |
| 00:42 | hoeck | somnium: of course, but it looks like the most direct translation from his code would be to use symbol-macrolet |
| 00:42 | hoeck | but correct me if I'm wrong |
| 00:42 | somnium | ,(let [form '(print a)] (for [x (range 3)] `(let [~'a ~x] ~form))) |
| 00:43 | somnium | no bot? |
| 00:45 | DeusExPikachu | found it, ":dont-close true" is the solution |
| 00:45 | DeusExPikachu | at least, for the future |
| 00:46 | somnium | itistoday: whether or not the macro itself is desirable, its fairly easy with symbol capture, so again I recommend learning how syntax quote works and experimenting with macroexpand |
| 00:46 | hiredman | or just using the sql library in contrib, or use clojureql |
| 00:47 | itistoday | hiredman: i will use clojureql when i need to do serious db stuff |
| 00:47 | itistoday | hiredman: right now i'm trying to learn clojure |
| 00:47 | itistoday | hiredman: i think clojureql is a very neat tool btw |
| 00:48 | itistoday | somnium: can you give me an example to help me get started? |
| 00:48 | itistoday | i learn by example, and the docs have none :-( |
| 00:48 | somnium | clojurebot: ping |
| 00:48 | clojurebot | PONG! |
| 00:49 | DeusExPikachu | examples in the docs can go a long way, I say |
| 00:49 | somnium | ,(let [form '(print a)] (for [x (range 3)] `(let [~'a ~x] ~form))) |
| 00:49 | clojurebot | ((clojure.core/let [a 0] (print a)) (clojure.core/let [a 1] (print a)) (clojure.core/let [a 2] (print a))) |
| 00:49 | hoeck | itistoday: something like your macro already exists in clojure.contrib.sql |
| 00:50 | herdrick | tomoj: thanks for the blog post. i didn't realize you were getting error messages and ignoring them. (i might have been ok already) |
| 00:50 | DeusExPikachu | but the best examples lie in library code most of the time |
| 00:50 | hoeck | itistoday: (with-query-results ["select * from table"] result (println (:name result))) |
| 00:51 | tomoj | I think installing slime before or marking it for installation along with the rest might have solved that error, dunno |
| 00:51 | itistoday | hoeck: i'm looking at the source, and it uses a with-query-results* function, don't know where that's defined |
| 00:52 | tomoj | itistoday: what editor do you use? |
| 00:52 | hoeck | itistoday: in sql/internals.clj |
| 00:52 | itistoday | tomoj: right now just using textmate + clj |
| 00:52 | tomoj | ah, nevermind then |
| 00:53 | hoeck | tomoj: but slime-find-definition works only if the clj-file is on the classpath :( |
| 00:54 | tomoj | good point |
| 00:54 | itistoday | hoeck: this is a bit beyond me atm i'm afraid... |
| 00:55 | herdrick | tomoj: yeah - so i have some network issues right now and the install is hanging on "Downloading clojure-contrib-1.1.0-master-2009foobarbazz.jar" |
| 00:55 | itistoday | is this really that difficult of a macro to write..? |
| 00:55 | tomoj | herdrick: you can skip the install if you're going to use lein |
| 00:55 | herdrick | tomoj: can you tell me where it's installing things to so I can go wipe them all out and start over? |
| 00:55 | tomoj | well.. lein will require a working network anyway :1 |
| 00:55 | herdrick | i haven't been able to find the clojure.jar it downloaded |
| 00:55 | tomoj | ~/.swank-clojure I believe |
| 00:55 | clojurebot | That is the one thing Clojure can not do. |
| 00:56 | herdrick | ah, ok |
| 00:56 | herdrick | my network is sometimes ok... |
| 00:56 | tomoj | best to just delete that directory |
| 00:56 | hoeck | itistoday: never mind, thats a lot of java/jdbc stuff in there, you only understand those java APIs if you have the javadoc at hand |
| 00:56 | tomoj | I think it checks whether the directory exists to decide if clojure is installed |
| 00:57 | somnium | off-topic, but anyone looked at node.js? javascript is starting to look like an increasingly attractive host for clojure |
| 00:57 | itistoday | somnium: i have, a bit |
| 00:57 | tomoj | does that lead to clojure in the browser? |
| 00:58 | itistoday | somnium: i'm not sure how you'd run clojure through it though |
| 00:58 | somnium | tomoj: thats already possible |
| 00:58 | hoeck | itistoday: basically, it executes an sql query and returns a sequence of hashmaps |
| 00:58 | somnium | subsets of it anyway |
| 00:58 | tomoj | ah yeah, clojurescript? |
| 01:01 | somnium | its also possible to translate the core special forms directly to javascript (sort of clojure the language but not the library) |
| 01:01 | herdrick | tomoj: i killed it |
| 01:01 | somnium | this node.js is made for writing high performant servers and unix scripting in js |
| 01:02 | itistoday | ok, so i've modified it a bit: http://paste.pocoo.org/show/173735/ |
| 01:02 | itistoday | now i'm stuck at this: java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:77) |
| 01:03 | itistoday | i think it's the interleave bit, but not sure what to do |
| 01:03 | tomoj | yeah, you didn't give a vector as the first argument |
| 01:03 | tomoj | (let [foo bar] ..) not (let (baz biz) ..) |
| 01:03 | itistoday | how do i convert a list to a vector? |
| 01:04 | itistoday | because i want to use interleave there |
| 01:04 | tomoj | vec takes a coll and makes it a vector |
| 01:04 | tomoj | but that would need to be unquoted |
| 01:05 | hoeck | itistoday: try calling (macroexpand-1 '(foo (println NAME))) |
| 01:05 | tomoj | what is the ~'col-syms and ~'val for? |
| 01:06 | itistoday | tomoj: i was getting exceptions from them not being like that |
| 01:06 | tomoj | ah :) |
| 01:06 | tomoj | fiddling is bad |
| 01:06 | somnium | itistoday: the whole expression shouldnt be syntax quoted, you need to use ` to control the evaluation |
| 01:07 | itistoday | somnium: ok, that's one thing i don't have a good grasp on, is where to put the syntax quote |
| 01:08 | tomoj | are you trying to learn about macros? |
| 01:09 | itistoday | i'm trying to rewrite a newlisp fexpr in clojure, and yes, i guess learn about macros |
| 01:09 | itistoday | (along the way) |
| 01:09 | tomoj | ah.. |
| 01:09 | tomoj | I guess people have already said that this is not the clojure way |
| 01:09 | itistoday | tomoj: the newlisp fexpr looks like this: (for-query-with-db "SELECT name FROM people" (println NAME)) => prints all the names of the people in the db |
| 01:10 | itistoday | and i'm trying to work my way to a clojure version of that |
| 01:11 | somnium | itistoday: it would be easier to write a tiny macro that captures symbols first |
| 01:11 | tomoj | oh, hmm |
| 01:11 | tomoj | I figured http://paste.pocoo.org/show/173737/ is what you were trying to do |
| 01:11 | tomoj | but if this is just a stepping stone |
| 01:12 | itistoday | tomoj: yeah, it is, i could convert this to use hashmaps when i know how to do that :-p |
| 01:13 | itistoday | this is where i am so far: http://paste.pocoo.org/show/173738/ |
| 01:13 | DeusExPikachu | in the readme, leiningen is called a build tool, it seems more like a package manager... |
| 01:13 | itistoday | i'm still getting: java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:96) |
| 01:14 | somnium | itistoday: are you using macroexpand? |
| 01:14 | itistoday | somnium: here's what i get for: (macroexpand-1 '(foo (prn NAME))) |
| 01:14 | itistoday | ((let (vec (interleave user/col-syms val)) (prn NAME)) (let (vec (interleave user/col-syms val)) (prn NAME))) |
| 01:14 | hoeck | itistoday: http://paste.pocoo.org/show/173739/ is a more clojure-like version of your macro, but probably not what you want |
| 01:15 | somnium | itistoday: the usual process is: 1. rule out non-macro solutions, 2. write what the emitted datastructure should look like, 3. write a macro to emit it |
| 01:16 | tomoj | well, it prints successfully if you fix one small problem |
| 01:16 | tomoj | but then you're calling nil as a function |
| 01:16 | tomoj | hmm |
| 01:17 | tomoj | I wonder why ((let [] nil)) gives a different error than (nil) |
| 01:18 | herdrick | tomoj: looks like it's working in Aquamacs for me. Thanks! I want to put some apache-commons jars in the classpath. should I just put them in ~/.clojure as it seems to say in the swank-clojure-default-classpath function in swank-clojure.el ? |
| 01:18 | herdrick | or is there a smarter move |
| 01:18 | tomoj | well.. if you were me, I would use lein |
| 01:18 | herdrick | tomoj: i think i'm going to hold off on getting going with lein until you blog it :) |
| 01:18 | tomoj | but since you're not.. are you sure it's ~/.clojure? |
| 01:18 | tomoj | hah |
| 01:19 | tomoj | I don't even have a ~/.clojure |
| 01:19 | tomoj | I think that's old? |
| 01:19 | herdrick | not sure, but here's most of the function in question: |
| 01:19 | herdrick | (defun swank-clojure-default-classpath () |
| 01:19 | herdrick | (append |
| 01:19 | herdrick | (when (file-directory-p "~/.clojure") |
| 01:19 | herdrick | (directory-files "~/.clojure" t ".jar$")) |
| 01:19 | technomancy | what's the equation to model something bouncing between two poles? |
| 01:19 | technomancy | like a pong ball? no gravity |
| 01:19 | herdrick | i don't know - it's the swank-clojure.el it set me up with |
| 01:20 | tomoj | herdrick: hmm, yes, you're right |
| 01:20 | herdrick | ok |
| 01:20 | tomoj | ah, it uses both |
| 01:20 | technomancy | I figure it's some combination of the frame count modulo 2x the width and the absolute value of the frame count modulo the width |
| 01:20 | tomoj | the next line down checks for ~/.swank-clojure |
| 01:20 | tomoj | are your clojure/contrib jars in ~/.swank-clojure? might as well put your stuff there if so |
| 01:20 | technomancy | but I want to do it functionally rather than calculating bounces by mutating the velocity |
| 01:20 | herdrick | tomoj: you're just putting such jars in each project directory as needed? |
| 01:21 | tomoj | yes, but lein does that for me |
| 01:21 | somnium | technomancy: are you making a pong clone for emacs? |
| 01:21 | technomancy | somnium: just playing around on android |
| 01:21 | tomoj | if I wanted apache-commons for toy repls I guess I'd put the jars in ~/.swank-clojure |
| 01:21 | itistoday | hoeck: thanks, not sure how to translate that to my function though |
| 01:22 | itistoday | i noticed i wasn't using the ~ on col-syms and ~vals |
| 01:22 | itistoday | i've updated it: http://paste.pocoo.org/show/173740/ |
| 01:22 | herdrick | tomoj: yes, clojure and clojure-contrib jars are in ~/.swank-clojure |
| 01:22 | tomoj | technomancy: you want a function for the horizontal position as a function of time? |
| 01:22 | itistoday | still still get java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:123) though |
| 01:22 | technomancy | tomoj: that's the one |
| 01:22 | itistoday | s/still still/still/g |
| 01:23 | tomoj | herdrick: if you drop other jars there they should be in the class path when you M-x slime, then |
| 01:23 | tomoj | but I think you will be surprised how easy lein is to setup and use, as long as you can find the deps you need in a maven repo |
| 01:23 | herdrick | tomoj: ok - because they would only be picked up when starting with M-x slime ? |
| 01:23 | tomoj | and even when not, not too bad |
| 01:23 | tomoj | yeah, you need to sayoonara and restart slime if you just added something |
| 01:24 | herdrick | otherwise,like when you start with M-x swank-clojure-project, those jars won't get picked up? |
| 01:24 | technomancy | everywhere I search they're trying to pull bloody gravity into it |
| 01:24 | tomoj | swank-clojure-project only uses what's in the lib/ dir of the project you choose |
| 01:25 | tomoj | as far as I know |
| 01:25 | herdrick | ok |
| 01:25 | hoeck | itistoday: to create an expansion like (let [NAME ... ID ...] (println NAME)), you have to know the columns at compile-time, it this the case? |
| 01:25 | itistoday | no, you don't |
| 01:25 | itistoday | need to do this at runtime |
| 01:25 | herdrick | thanks, tomoj it looks like I'm back with a working clojure in emacs again :) many thanks |
| 01:25 | tomoj | hmm.. the funciton looks like this /\/\/\/\/\/\, no? |
| 01:26 | itistoday | hoeck: this isn't possible? |
| 01:26 | technomancy | eh; screw it; doing it statefully is good enough for tonight |
| 01:27 | hiredman | like a sine wave? |
| 01:27 | technomancy | hiredman: like a sine wave without the curvy bits |
| 01:27 | itistoday | what's wrong with this: |
| 01:27 | itistoday | user=> (macroexpand-1 '(foo (prn NAME))) |
| 01:27 | itistoday | ((let (vec (interleave (NAME AGE) ["Sally" 5])) (prn NAME)) (let (vec (interleave (NAME AGE) ["Sue" 6])) (prn NAME))) |
| 01:28 | technomancy | but I think I'll just do it quick and dirty by keeping a velocity and negating it when I hit the wall |
| 01:28 | tomoj | itistoday: prn returns nil |
| 01:28 | tomoj | among other things |
| 01:28 | tomoj | so your first let returns nil |
| 01:28 | hiredman | http://en.wikipedia.org/wiki/File:ComplexSinInATimeAxe.gif <-- that is a sweet gif |
| 01:28 | tomoj | and then you're trying to call nil as a function, passing nil as an arg |
| 01:28 | hoeck | itistoday: of course it is, but implementing it in a clean way is slightly more advanced |
| 01:29 | tomoj | I meant that other things are wrong, not that prn returns other things |
| 01:29 | itistoday | but why does running it generate: java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:123) |
| 01:29 | tomoj | technomancy: look at abs(abs(x)%4-2) |
| 01:30 | itistoday | err... and .. i need to be able to use any functions in the body, regardless of whether they return nil |
| 01:30 | itistoday | tomoj: sorry, meant to reply that to you |
| 01:30 | tomoj | that's like this \/\/\/\... where the max y value is 2 and the width of / is 2 |
| 01:30 | technomancy | tomoj: awesomar |
| 01:31 | technomancy | thanks |
| 01:31 | tomoj | then you can add coefficients to the x to scale time |
| 01:32 | tomoj | and scale the 4 and the 2 together to change the max y value |
| 01:32 | itistoday | final question before i sign off (gotta go now): is this a hard problem or just an easy one no one wants to help me with? |
| 01:32 | somnium | itistoday: its not hard and multiple people have tried to help you |
| 01:32 | tomoj | itistoday: the body has nothing to do with it |
| 01:32 | tomoj | oh, yes it does, a bit |
| 01:33 | tomoj | the point is you shouldn't be calling the return value of the body as a function |
| 01:33 | itistoday | tomoj: how do i avoid doing that? |
| 01:33 | tomoj | also you need to not quote vec |
| 01:33 | tomoj | that is, ~(vec instead of just (vec |
| 01:34 | itistoday | tomoj: ah, thanks! http://paste.pocoo.org/show/173741/ |
| 01:34 | itistoday | that prints "sally" "sue" and then throws a nullpointerexception |
| 01:34 | itistoday | much better! :-D |
| 01:34 | herdrick | tomoj: btw, if you were to want the current build from git (of clojure & friends) would you git pull and mvn package in some other dir, and then copy the jars to ~/.swank-clojure ? |
| 01:35 | itistoday | tomoj: now, if i may ask, why does it throw a java.lang.NullPointerException? i assume it's cause i'm "calling the return value of the body", but i didn't know i was doing that |
| 01:35 | itistoday | i'm a clojure *NEWB* |
| 01:35 | tomoj | yes |
| 01:36 | tomoj | I don't know how to fix it though, sorry |
| 01:36 | tomoj | look at the macroexpansion you pasted above |
| 01:36 | tomoj | it has the form ((let ...) (let ...)) |
| 01:36 | tomoj | this means the result of the first let is being called as a function with the result of the second let as an argument |
| 01:36 | tomoj | which is happening because the macro is simply returning a seq of let forms |
| 01:36 | itistoday | tomoj: ah, ok |
| 01:38 | tomoj | hmm, I figured out a way to get it to work |
| 01:39 | hoeck | itistoday: transformed my version again http://paste.pocoo.org/show/173742/ |
| 01:39 | tomoj | but I don't like it at all |
| 01:39 | somnium | itistoday: http://paste.pocoo.org/show/173743/ |
| 01:39 | tomoj | somnium's is a much better way than mine |
| 01:39 | hoeck | itistoday: the point is that you have to declare the NAMES used in the body |
| 01:40 | itistoday | tomoj: somnium's works without that :-D |
| 01:40 | itistoday | somnium: thanks!! |
| 01:41 | itistoday | somnium: now i just need to decipher wtf you did there :-p |
| 01:41 | itistoday | like the -> function... read the docs on that and was confused, it's nice to have an example finally |
| 01:42 | tomoj | I have often wished for a collaboratively-edited database of simple examples |
| 01:43 | TheBusby | I'd almost be willing to volunteer to add examples to the doc strings |
| 01:43 | TheBusby | maybe a :example string? |
| 01:43 | itistoday | i would be completely willing to volunteer as well :-) |
| 01:44 | tomoj | hmm, I hadn't thought of embedding them in the source |
| 01:44 | tomoj | I was thinking of a web app |
| 01:44 | itistoday | as a newbie, i think i have valuable ignorance to contribute |
| 01:44 | TheBusby | there are a large number of standard/common functions where the doc is very difficult to understand but a simple example would be clear |
| 01:44 | TheBusby | ->> is a great example |
| 01:44 | itistoday | TheBusby: -> too, indeed |
| 01:45 | TheBusby | er, sorry I meant -> |
| 01:45 | itistoday | if one of you is series about this, i'm actually serious, i would be happy to assist |
| 01:45 | TheBusby | I certainly wont find the time for another week unfortunately |
| 01:45 | tomoj | I think I remember htat defn started working on some kind of project like this |
| 01:45 | itistoday | i don't mean to toot newlisp's horn, lest i avoke the anger of hiredman, but you guys should check out its documentation, it's excellent |
| 01:45 | TheBusby | but I've been thinking about it for a month or two already |
| 01:46 | somnium | http://getclojure.org/ |
| 01:46 | tomoj | yep, that's it |
| 01:47 | somnium | hmm, still not wikified I guess |
| 01:47 | tomoj | glad he hasn't given up on it |
| 01:47 | TheBusby | that and I'd like to see the examples embedded like the doc string if possible |
| 01:47 | TheBusby | (example ->>) just like (doc ->>) |
| 01:47 | tomoj | yeah, I was originally thinking of web-editable data |
| 01:47 | tomoj | I think he's storing the examples in the source of the cljex project? |
| 01:47 | itistoday | check out newlisp's documentation: http://www.newlisp.org/downloads/manual_frame.html |
| 01:48 | TheBusby | you see an example marked as "Usage:" in the doc string sometimes though |
| 01:49 | tomoj | I guess putting the examples in the source of the project makes it so that contributions will always be good ones |
| 01:51 | somnium | maybe he could just let people imbed gist urls |
| 01:51 | itistoday | somnium: thank you again, i've read through your code now and have understood it, i think this little example of yours has gotten me 70% of the way to being able to write clojure code now :-D |
| 01:52 | tomoj | somnium: you mean put the gist url in the source and then fetch the latest revision when rendering? or? |
| 01:52 | tomoj | or go to getclojure.org and submit a gist url |
| 01:52 | somnium | tomoj: that one |
| 01:52 | itistoday | i think whatever you decide to do, the examples should be inline with the documentation without having to go to other URLs |
| 01:53 | somnium | gists can display inline |
| 01:55 | somnium | or setup a lisp editing app with a js-code-highlighter and emacs key bindings, but gists are probably easier |
| 01:55 | itistoday | if you guys setup a group to do this well, i'll donate $100 |
| 01:55 | itistoday | i'm sure others will too |
| 01:55 | itistoday | (some amount) |
| 01:55 | somnium | itistoday: just donate to clojure |
| 01:56 | itistoday | somnium: eh.. i specifically want to support the development of nice documentation for clojure |
| 01:56 | tomoj | send it to defn then :) |
| 01:56 | itistoday | who's defn? |
| 01:57 | tomoj | the owner of cljex |
| 01:57 | tomoj | the project behind getclojure.org |
| 01:58 | itistoday | does he have contact info? |
| 01:58 | tomoj | I dunno |
| 01:59 | tomoj | getclojure.org says "If you don't have the time, no worries, but do consider donating to Clojure if you're able." :DF |
| 01:59 | itistoday | found it: http://devinwalters.com/ |
| 02:00 | TheBusby | devin -> defn nice |
| 02:00 | itistoday | cool, well hopefully i'll get in touch with him |
| 02:01 | itistoday | night all, thanks again for the help |
| 02:01 | tomoj | I almost bet he'll say "send the money to clojure instead" |
| 02:05 | replaca | hiredman: wow, I like that gif! |
| 02:12 | tomoj | is finding the appropriate maven artifactid/groupid/repo for a particular project frustrating, or am I just too much of a maven noob? |
| 02:13 | tomoj | eh, guess I can just install the jars locally |
| 02:37 | herdrick | tomoj: yeah, i'm not finding that either. also maven noob. and thanks much for your help earlier. |
| 02:38 | tomoj | no problem |
| 02:39 | tomoj | I wonder if there is something out there I could read that would make this maven stuff make sense |
| 02:39 | tomoj | I find myself browsing through apache autoindexes trying to find stuff |
| 02:39 | tomoj | and no nightly builds to be seen |
| 02:40 | herdrick | tomoj: btw, if you were to want to do a build from git of clojure & friends would you 'git pull' and 'mvn package' in some other dir, and then copy the jars to ~/.swank-clojure ? |
| 02:41 | herdrick | hope i'm not being too obnoxious with questions |
| 02:41 | tomoj | nah |
| 02:41 | tomoj | that sounds like what I would do |
| 02:41 | herdrick | ok |
| 02:41 | tomoj | except I wouldn't do that because I just use lein |
| 02:42 | herdrick | you wouldn't build from source? |
| 02:42 | tomoj | I haven't in quite a long time |
| 02:42 | tomoj | maybe if I were hacking on clojure I would, I guess |
| 02:42 | herdrick | sure |
| 02:42 | herdrick | ok, thanks |
| 02:44 | tomoj | huh, master hasn't been touched in over a month? |
| 02:44 | tomoj | oh, that's the author date |
| 02:44 | tomoj | anyway, http://build.clojure.org/ has nightlies it seems |
| 02:44 | tomoj | and lein can grab from there |
| 02:45 | tomoj | so little reason to build from source as far as I can tell |
| 02:45 | herdrick | i see |
| 02:45 | tomoj | I'll probably write that lein post tomorrow |
| 02:46 | tomoj | followed by a paredit post |
| 02:46 | herdrick | great, looking forward to it. i'm subscribed to your rss feed |
| 02:46 | tomoj | hah |
| 02:46 | tomoj | I didn't even know I had an rss feed |
| 02:47 | tomoj | that wordpress has been sitting there for months with a post titled "foo" and some random clojure code embedded in a gist |
| 02:48 | tomoj | guess I'm off to a good start in the blogosphere ;) |
| 02:53 | herdrick | ha - yeah! |
| 08:12 | AWizzArd | Hi chouser |
| 08:13 | chouser | hi |
| 08:13 | chouser | hmph. lost my connection. 4.5 hours of logs gone. :-/ |
| 08:15 | Chousuke | doesn't look like you missed anything interesting :P |
| 08:15 | AWizzArd | chouser: I think you are an expert for agents, so here a question: is there a good reason why await does not return from waiting for an agent to finish, when this agent throws an Exception? |
| 08:15 | chouser | heh. ok, good I guess. |
| 08:15 | Chousuke | mostly just quits and joins. |
| 08:16 | chouser | AWizzArd: hm... that may not be intentional. |
| 08:16 | AWizzArd | ,(let [x (agent 0), foo (fn [_] 55)] (println @x) (await (send x foo)) (println @x)) ; works well |
| 08:16 | clojurebot | 0 55 |
| 08:16 | AWizzArd | ,(let [x (agent 0), foo (fn [_] (Thread/sleep 2000) 55)] (println @x) (await (send x foo)) (println @x)) ; also works fine |
| 08:16 | clojurebot | 0 55 |
| 08:17 | AWizzArd | ,(let [x (agent 0), foo (fn [_] (Thread/sleep 2000) (throw (Exception. "bar foos")) 55)] (println @x) (await (send x foo)) (println @x)) ; also works fine |
| 08:17 | clojurebot | java.lang.Exception: Agent has errors |
| 08:17 | AWizzArd | okay, this one returns, but what happens in your clojure? |
| 08:17 | AWizzArd | Can anyone please try to confirm that await won't return for my last example? |
| 08:17 | AWizzArd | (where I accidently didn't remove the comment from the end of the line) |
| 08:18 | chouser | yeah, it hangs here |
| 08:19 | AWizzArd | I would think that await should return |
| 08:19 | chouser | ok, in this case it's intentional |
| 08:19 | AWizzArd | chouser: can you please explain why? |
| 08:20 | chouser | that agent is using the :fail error mode, so it's waiting for you to restart the agent so that it can finish processing its queue (and release the await) |
| 08:21 | AWizzArd | error modes.. hmm, I will investigate, thx |
| 08:21 | chouser | you may prefer to specify an error-handler |
| 08:22 | chouser | (agent 0 :error-handler (partial println "Error:")) |
| 08:22 | the-kenny | ,*clojure-version* |
| 08:22 | clojurebot | {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "master"} |
| 08:23 | _fogus_ | ,, |
| 08:23 | clojurebot | EOF while reading |
| 08:23 | _fogus_ | I always wondered what that would do |
| 08:24 | Chousuke | commas are whitespace |
| 08:24 | Chousuke | ,,(+) also it only reads the first form |
| 08:24 | clojurebot | 0 |
| 08:24 | _fogus_ | Understood |
| 08:29 | zaphyr | hmm. does clojure bot know not to hang? :) |
| 08:29 | chouser | yes he does. He's pretty clever. |
| 08:29 | zaphyr | :D |
| 08:29 | chouser | @(promise) |
| 08:29 | chouser | ,@(promise) |
| 08:29 | AWizzArd | chouser: yes, the error-handler works. But it seems neither the agent nor the handler are able to forward the Exception to the thread which awaits the agent. |
| 08:29 | zaphyr | ,(* 3 4) |
| 08:29 | clojurebot | Execution Timed Out |
| 08:29 | clojurebot | 12 |
| 08:29 | zaphyr | ahh |
| 08:29 | zaphyr | :) |
| 08:30 | chouser | he doesn't actually try to solve the halting problem. He's not *that* clever. |
| 08:30 | zaphyr | yeah, but we've got clojure now, i'll try and submit a patch for that by 2011 :) |
| 08:30 | AWizzArd | Is there a mechanism for that? Currently I do a repeatedly on await-for and check agent-errors, embedded in a take-while, but that definitly is very hackish. |
| 08:31 | chouser | AWizzArd: the await just puts an action on the agents queue that will signal the await to continue. then it just sits waiting for that signal. |
| 08:32 | chouser | if you want to do something specific when the agent errors out, just put that in your error-handler |
| 08:34 | AWizzArd | I would like the error handler to throw an exception in the thread which called await :) |
| 08:44 | chouser | hmm |
| 08:44 | chouser | are you sure you want agents? that all sounds very synchronous. :-) |
| 08:46 | AWizzArd | chouser: I want to modify my DB (insert/update/delete) and log to disk. I discussed this in the last days, and there are two possible solutions: |
| 08:47 | AWizzArd | 1. I use refs. But the ref would have to write to disk inside the dosync, because this is part of the transaction. This means that if many threads try to update the db the dosyncs will block each other, because the writing to disk makes them slow enough to get repeated. |
| 08:47 | AWizzArd | This means that the dosync has to get embedded into a locking. hiredman pointed out that currently there are no plugins for dosyncs that would allow me to go around the lock |
| 08:48 | AWizzArd | 2. Chousuke then asked why I need refs if they are inside a locking anyway. So, agents also sound nice. |
| 08:48 | chouser | what about an atom and a watcher? |
| 08:48 | chouser | er, a "watch" |
| 08:49 | chouser | or a watch on a ref, for that matter. |
| 08:49 | AWizzArd | yes, atoms could be another way, maybe with a BlockingQueue or a watcher. |
| 08:49 | chouser | a watch on a ref will not prevent other transactions from working on the ref, nor cause the current transaction to retry |
| 08:51 | AWizzArd | Well, only one transaction can work at a given time on the db. One ref modifies it, so all other transactions that are running would notice the change and retry. I think. |
| 08:52 | chouser | yes, but the transaction is "done" by the time the watch is called. Other transactions can proceed with updating the db while the watch writes it to disk. |
| 08:53 | AWizzArd | chouser: this is not acceptable. Before any part of the program can see the updated db it must already be written to disk. |
| 08:54 | AWizzArd | otherwise the change maybe happened in ram, a customer bought something, and then the system crashes before the data is on disk. |
| 08:54 | AWizzArd | Only after the guaranteed write happened the rest of the world may know about the new state. |
| 08:55 | AWizzArd | So, modifications to the db really need to run serial |
| 08:55 | chouser | so you really do want synchronous behavior |
| 08:55 | AWizzArd | yes |
| 08:56 | AWizzArd | lock around dosync, agent or atom+BlockingQueue |
| 08:56 | AWizzArd | agents sound great, they only have the problem that I reported above, with the Exceptions |
| 08:56 | chouser | I think a simple lock might be best |
| 08:57 | AWizzArd | hmm yes right, a lock around a dosync or function that updates an atom |
| 08:57 | chouser | well, agents are for async operation. I think they could be made to work in your situation, but it'll take some effort because it's not really the right mechanism. |
| 08:57 | AWizzArd | the blockingqueue would not be needed when a lock is involved |
| 08:57 | chouser | no, not a transaction. just a lock |
| 08:58 | AWizzArd | inside this lock I need to change the state of the db in clojure terms. So inside this lock I will need to update a ref, atom or agent |
| 08:59 | chouser | hm |
| 09:00 | AWizzArd | but it could be okay to have one function which is doing all the updates/inserts/deletes etc, and the db is an atom, and around my function i have a lock |
| 09:00 | chouser | an atom is close, but because you have side-effects, you don't want to retry ever. |
| 09:00 | chouser | so maybe this is essentially a new reference type. |
| 09:00 | chouser | like atom but using a lock instead of CAS |
| 09:00 | chouser | and no rhickey here to talk me down. |
| 09:00 | AWizzArd | :-) |
| 09:01 | AWizzArd | As soon this db-transaction-function is working, all other threads can still run selects on the db |
| 09:01 | AWizzArd | this can be done with atom updates inside a lock |
| 09:01 | chouser | you want all threads to see the old value until the new value is written to disk, right? |
| 09:01 | AWizzArd | exactly |
| 09:01 | chouser | and anything updating the value should block until its done. |
| 09:02 | chouser | and we can use protocols... |
| 09:03 | AWizzArd | until yesterday i thought i would go with a lock around a dosync. The updates can work likes this: the transaction begins and the ref is dereferenced. This immutable dereferenced db object gets "modified". If this does not trigger any constraint we now have an immutable db object which contains the correct updates. |
| 09:03 | AWizzArd | If the program crashes here it's no problem, nobody was ever reported the updates. |
| 09:03 | AWizzArd | If it does not crash we write to disk and wait until it is guaranteed on disk. |
| 09:04 | AWizzArd | When the program crashes here after a restart it will have the full db contents, as if it didn't crashed, because it could read it from disk. |
| 09:04 | AWizzArd | If we don't crash, *then* a ref-set really updates the object, the transaction ends. |
| 09:05 | AWizzArd | or well, ref-sets are not needed |
| 09:05 | AWizzArd | probably alter is used, nobody can see the altered db object anyway |
| 09:05 | AWizzArd | and this allows transactions inside other transactions |
| 09:05 | jcromartie | wow, cool stuff on profiling with jvisualvm http://www.fatvat.co.uk/2009/05/jvisualvm-and-clojure.html |
| 09:05 | AWizzArd | only when the outermost dosync ended the world can see this update |
| 09:05 | jcromartie | I didn't even realize it came with Java |
| 09:06 | jcromartie | I hope that sort of thing doesn't go away now that Sun is no more |
| 09:07 | AWizzArd | chouser: indeed, a modification of a ref/dosync maybe meaningful |
| 09:07 | chouser | AWizzArd: I think a lock and an atom would be better. |
| 09:08 | AWizzArd | chouser: yes, also okay, though this would imly that i first deref the atom and put the derefd db into a new atom, which i then modify through the whole transaction |
| 09:08 | AWizzArd | imly => imply |
| 09:08 | chouser | oh, you don't just have a simple update fn you call per db update? |
| 09:09 | chouser | you have a series of imperative ref-set's (or similar)? |
| 09:09 | AWizzArd | yes, this is used, but all wrapped into a db-transaction |
| 09:10 | AWizzArd | ,(let [x (ref {})] (dosync (println @x) (alter x assoc :a 1) (println @x) (alter x dissoc :a) (println @x))) |
| 09:10 | clojurebot | {} {:a 1} {} |
| 09:10 | chouser | :-/ not very functional is it. |
| 09:10 | AWizzArd | true, but we are talking about a db transaction |
| 09:10 | AWizzArd | this is all about state change, and not a functional thing |
| 09:11 | AWizzArd | as if we call alter/commute inside a dosync |
| 09:11 | AWizzArd | this non-functional style is the essence of db modifications |
| 09:11 | AWizzArd | inside a transaction the user can do several calls to insert/update/delete |
| 09:12 | AWizzArd | after an insert he will expect to be able to select the inserted object |
| 09:12 | chouser | right, and you can do the same inside a reference type updater (atom, ref, agent, etc.) but the Clojure API discourages it. |
| 09:13 | chouser | you're sure you want to encourage it? |
| 09:13 | jcromartie | profiling lesson of the day: MySQL connections are cheap, reading results is expensive |
| 09:13 | AWizzArd | chouser: I don't see a plausible way around this. |
| 09:14 | AWizzArd | I hope the users will write a mostly functional style program, and isolate their db updates to a few parts of the program |
| 09:14 | chouser | anyway, if you really want to do this, I think a lock per transaction best provides the semantics you want. |
| 09:14 | AWizzArd | yes |
| 09:15 | AWizzArd | so, lock around a function which then either modifies a ref inside dosync, or which uses an atom, derefs it, atoms it again, uses this copy inside the transaction, and when everything is done (reset!)’s the original db that can be seen by all threads. |
| 09:16 | AWizzArd | For now I think I will be safe with lock+dosync, although this has a slightly bitter taste. But if it turns out that there is a better solution I can still update to that solution. |
| 09:17 | AWizzArd | chouser: interesting discussion, thank you. Brought new information for me. |
| 09:19 | chouser | once you're inside a lock, a ref and transaction is much heavier than you need. I would look at using an atom or maybe even something lighter than that. |
| 09:20 | AWizzArd | chouser: there is nothing lighter than an atom |
| 09:20 | chouser | perhaps (with-db-transaction [x my-db] ... (db-set x foo) ... (db-alter x bar) ...) |
| 09:21 | chouser | then with-db-transaction can create a new mutable instance and bind it to x. should be safe because x won't exist outside the dynamic scope of with-db- |
| 09:21 | AWizzArd | And I am not so sure that a ref will be indeed so heavy. It will never notice any updates by other threads, because it is the only one running. |
| 09:22 | chouser | so there need be no serializing changes to x at all. it could be even just a clojure.lang.Box |
| 09:22 | chouser | hm.. actually, that sounds like a var |
| 09:22 | AWizzArd | I don't know Box |
| 09:22 | AWizzArd | And can a var be updated? |
| 09:23 | chouser | (doc with-local-vars) |
| 09:23 | clojurebot | "([name-vals-vec & body]); varbinding=> symbol init-expr Executes the exprs in a context in which the symbols are bound to vars with per-thread bindings to the init-exprs. The symbols refer to the var objects themselves, and must be accessed with var-get and var-set" |
| 09:23 | qed | http://www.infoq.com/interviews/Steele-Interviews-John-McCarthy |
| 09:23 | AWizzArd | and why does with-db-transaction not require serializing changes to x? |
| 09:24 | chouser | because with-db- does the locking, outside which x doesn't even exist. |
| 09:25 | AWizzArd | chouser: yes, but x needs to be changed inside |
| 09:30 | AWizzArd | ,(let [x (atom 0)] (with-local-vars [foo @x] (println foo) (println @foo))) |
| 09:30 | clojurebot | #<Var: --unnamed--> 0 |
| 09:31 | chouser | ,(with-local-vars [a 10] (var-set a 5) @a) |
| 09:31 | clojurebot | 5 |
| 09:31 | AWizzArd | chouser: I will analyze this w-l-v, and maybe this is giving me the right semantics. |
| 09:32 | AWizzArd | But one problem could be that several of those can run in parallel |
| 09:32 | AWizzArd | So, a lock around that will still be required |
| 09:32 | chouser | oh, yes. |
| 09:32 | chouser | the var shouldn't even exist except inside the locking construct |
| 09:32 | AWizzArd | Anyway, maybe it is even lighter than an atom and thus run more efficient |
| 09:33 | AWizzArd | chouser: you mentioned this for efficiency, right? |
| 09:33 | chouser | and safety, yes. |
| 09:34 | AWizzArd | chouser: good point, this (locking+w-l-v) may provide the same as locking+atom+atom or locking+dosync, but more efficiently |
| 09:36 | AWizzArd | the locking around the dosync would in principle not be required, but I would use it, because the io operation inside makes it slow and could trigger too many repetitions of the dosync |
| 09:39 | AWizzArd | esj: just give me a few more weeks please :-) |
| 09:39 | esj | AWizzArd: provided you explain it to me when you're done ! |
| 09:40 | AWizzArd | I am spending a lot of time on documentation. |
| 09:40 | AWizzArd | And.. when even I can understand it, it must be pretty simple. |
| 09:40 | qed | hug* |
| 09:41 | qed | ^--------oOOops |
| 09:42 | esj | AWizzArd: thanks i really appreciate well doc'd code, helps so much to understand |
| 09:42 | fdaoud | ,(zipmap [1 2 3 4] ["a" "b" "c" "d"]) |
| 09:42 | clojurebot | {4 "d", 3 "c", 2 "b", 1 "a"} |
| 09:43 | fdaoud | ,(for [x [1 2 3 4] y ["a" "b" "c" "d"]] [x y]) |
| 09:43 | clojurebot | ([1 "a"] [1 "b"] [1 "c"] [1 "d"] [2 "a"] [2 "b"] [2 "c"] [2 "d"] [3 "a"] [3 "b"] [3 "c"] [3 "d"] [4 "a"] [4 "b"] [4 "c"] [4 "d"]) |
| 09:43 | fdaoud | how would you loop through 1 "a", 2 "b", 3 "c", 4 "d" *in order* ? |
| 09:44 | spariev | AWizzArd: can you shed some light on your project ? |
| 09:45 | the-kenny | fdaoud: If you have a list like [1 "a", 2 "b"] etc. you can use partition to create pairs |
| 09:45 | Chousuke | fdaoud: you can map over them |
| 09:45 | chouser | AWizzArd: maybe something like this: http://paste.lisp.org/display/94354 |
| 09:45 | Chousuke | ,(map vector [1 2 3] '[a b c]) |
| 09:45 | clojurebot | ([1 a] [2 b] [3 c]) |
| 09:46 | chouser | heh. now there's an example where you *could* ->> and you really really shouldn't. |
| 09:46 | qed | why can't you search google for "->>" |
| 09:47 | fdaoud | ,(for [[x y] (map vector [1 2 3] ["a" "b" "c"])] [x y]) |
| 09:47 | clojurebot | ([1 "a"] [2 "b"] [3 "c"]) |
| 09:47 | chouser | qed: dunno, but you can (doc ->>) |
| 09:47 | fdaoud | Chousuke: thanks! |
| 09:47 | Chousuke | fdaoud: the for is redundant though :P |
| 09:47 | qed | chouser: *nod* |
| 09:47 | Chousuke | fdaoud: map is enough |
| 09:48 | fdaoud | Chousuke: agreed, but I need to put this in a for-like structure, so just making sure it behaves as expected :) |
| 09:48 | Chousuke | ,(map + [1 2 3] [4 5 6]) another example |
| 09:48 | clojurebot | (5 7 9) |
| 09:48 | tcrayford | ,(for [x [1 2 3] y '[a b c]] [x y]) |
| 09:48 | clojurebot | ([1 a] [1 b] [1 c] [2 a] [2 b] [2 c] [3 a] [3 b] [3 c]) |
| 09:48 | _fogus_ | ,(partition 2 (interleave [1 2 3] '[a b c])) |
| 09:48 | clojurebot | ((1 a) (2 b) (3 c)) |
| 09:48 | fdaoud | tcrayford: I don't want 1 a 1 b 1 c, just 1 a 2 b 3 c |
| 09:49 | fdaoud | Chousuke: specifically, Enlive's clone-for |
| 09:49 | tcrayford | ,(use 'clojure.contrib.seq-utils) |
| 09:49 | clojurebot | nil |
| 09:49 | tcrayford | (indexed [a b c]) |
| 09:49 | tcrayford | ,(indexed [a b c]) |
| 09:49 | clojurebot | java.lang.Exception: Unable to resolve symbol: a in this context |
| 09:49 | tcrayford | ,(indexed '[a b c]) |
| 09:49 | clojurebot | ([0 a] [1 b] [2 c]) |
| 09:49 | chouser | an antipattern. don't you dare: http://paste.lisp.org/display/94354#1 |
| 09:50 | Chousuke | wait, what |
| 09:50 | fdaoud | Chousuke: ? |
| 09:50 | Chousuke | that paste |
| 09:51 | chouser | what, you don't like to put your 'finally's before your 'try'? |
| 09:51 | fdaoud | well, anyway, map vector is what I needed, thanks :) |
| 09:52 | fdaoud | ,(interleave [1 2 3] '[a b c]) |
| 09:52 | clojurebot | (1 a 2 b 3 c) |
| 09:52 | fdaoud | _fogus_: thanks, another way of doing it |
| 09:53 | Chousuke | chouser: it's scary that that's even possible. |
| 09:53 | chouser | putting the 'let' last is still my favorite. |
| 09:54 | chouser | ,(->> (+ a 5) (- 20) (let [a 9])) |
| 09:54 | clojurebot | 6 |
| 09:54 | Chousuke | it's unfortunate that the more expressive a given feature is, the more opportunities it offers for abusers :P |
| 09:54 | chouser | ok, it's not. |
| 09:55 | chouser | not my favorite, I mean. |
| 09:55 | chouser | Chousuke: yes, scary. |
| 09:55 | tcrayford | I wrote a thing in emacs that'll turn any ->> expression into its normal form, and vice versa |
| 09:55 | tcrayford | is fun to play around with on crazy code |
| 09:56 | chouser | tcrayford: ooh, neat. |
| 09:56 | chouser | I usually end up writing without ->> first, and then converting. |
| 09:56 | tcrayford | I had fun when I learned about ->>, and wrote that |
| 09:56 | tcrayford | then tried it on a page or two of code for kicks |
| 09:57 | tcrayford | then decided its only worth it sometimes |
| 09:57 | tcrayford | so converted most of it back to normal code |
| 09:57 | tcrayford | what does -?>> do? |
| 09:57 | cemerick | same as -?>, but for ->> |
| 09:58 | qed | i've never seen the -?> |
| 09:58 | qed | :\ |
| 09:58 | cemerick | it's in clojure.contrib.core |
| 09:58 | Chousuke | isn't it just (defnilsafe -?>> ->>) :/ |
| 09:58 | qed | ah |
| 09:58 | cemerick | Chousuke: yes, but it should be "out there" |
| 09:59 | AWizzArd | spariev: I am working on an in-memory, in-process DB system, written in Clojure, and very easily usable in Clojure. |
| 10:00 | spariev | AWizzArd: tnx |
| 10:02 | spariev | Is it going to be relational or object DB ? |
| 10:06 | AWizzArd | spariev: object |
| 10:07 | AWizzArd | chouser: yes, this example code is in principle modeling this transaction subsystem |
| 10:10 | jkdufair | so does ->> do its "threading" prior to evaluation? it would be a macro, yes? |
| 10:10 | tcrayford | confirm |
| 10:10 | Chousuke | yes. |
| 10:10 | tcrayford | ,(use 'clojure.contrib.repl-utils) |
| 10:10 | clojurebot | java.lang.ExceptionInInitializerError |
| 10:10 | tcrayford | ,(source ->>) |
| 10:10 | clojurebot | java.lang.Exception: Unable to resolve symbol: source in this context |
| 10:10 | tcrayford | :( |
| 10:10 | jkdufair | thx |
| 10:10 | spariev | AWizzArd: I'm asking because I'm thinking about some kind of Functional Relation Programming DB, with relations and stuff. basically I'm trying to wrap hypersonic sql with some clojure |
| 10:10 | chouser | right, which is the only reason you can do crazy stuff with let, try/finally, etc. |
| 10:10 | Chousuke | ~def ->> |
| 10:11 | AWizzArd | spariev: interesting |
| 10:11 | spariev | AWizzArd: and your discussion with chouser was very helpful ) |
| 10:11 | AWizzArd | great |
| 10:12 | chouser | AWizzArd: so you like the example code -- what about the implementation. about as simple and performant as it gets, I think. |
| 10:13 | chouser | the only way to replace the outer atom properly, I think, would require a volatile field. |
| 10:13 | AWizzArd | chouser: I am currently in the process of finding my for now "final model", and the w-l-v may be the most efficient solution and thus I am analyzing this. When I can not identify major challenges it will be my route for now. |
| 10:13 | chouser | ok |
| 10:13 | AWizzArd | Good that you brought this to my attention. |
| 10:14 | AWizzArd | From the point of correctness many solutions are okay, but obviously I want something efficient. |
| 10:14 | AWizzArd | Given that sorted sets/maps are still amazingly slow... |
| 10:15 | chouser | I think this solution is less "against the grain" than trying to make agents synchronous |
| 10:15 | AWizzArd | Can you please join me begging rhickey to implement PersistentSortedMultisets and sets? :) |
| 10:15 | AWizzArd | chouser: yes, makes sense |
| 10:15 | chouser | he had multi-maps (not sorted I think), but seemed to think that everyone's response was underwhelming, so dropped it. |
| 10:16 | AWizzArd | ooh ooh |
| 10:16 | AWizzArd | maybe he still has the code somewhere |
| 10:16 | AWizzArd | Yesterday I discovered that Google offers nice immutable collections: http://code.google.com/p/google-collections/ |
| 10:17 | AWizzArd | But after a closer look I realized that what they created within two years just can't compete with what rhickey implemented. |
| 10:17 | AWizzArd | The google collections are immutable but not persistent |
| 10:17 | chouser | yeah |
| 10:17 | AWizzArd | I can not look from 10 different threads at them and modify them in an isolated way |
| 10:17 | AWizzArd | I can not remove things |
| 10:18 | AWizzArd | they are more like "constant sets" |
| 10:18 | AWizzArd | I just saw they offer Multisets and Multimaps and even BiMaps |
| 10:18 | chouser | AWizzArd: http://clojure-log.n01se.net/date/2009-09-03.html#12:03c |
| 10:18 | cemerick | I didn't mind the multi-maps at all, it was having distinct reader syntax for them that didn't make sense for me. |
| 10:19 | rhickey | AWizzArd: it is pretty easy to write a multimap api on top of maps of sets |
| 10:19 | AWizzArd | And having those Multisets/maps would be really helpful. But having SortedMultisets would indeed be a killer feature |
| 10:20 | rhickey | AWizzArd: what's the killer use case for sorted multisets? |
| 10:20 | AWizzArd | rhickey: Adding 80k users (deftype User [username password age city]) into the sorted multiset, sorted by their year of birth |
| 10:20 | chouser | rhickey: AWizzArd thinks he wants a synchronoush reference type, but based on locks not CAS like atom so that he can do side-effects without repeating them. |
| 10:21 | AWizzArd | currently this requires a unique field. I can not simply have the comparator sorting by year of birth, because more than one user was born 1970 |
| 10:21 | AWizzArd | I will have to include a slot from the User deftype which is unique. |
| 10:21 | rhickey | chouser: like the cells? this unrelated to multisets? |
| 10:21 | chouser | rhickey: so I wrote this and wanted to give you an opportunity to declare it should never be used. :-) http://paste.lisp.org/display/94354 |
| 10:21 | AWizzArd | In a SortedMultiset I could just add all users |
| 10:22 | AWizzArd | rhickey: unrelated |
| 10:22 | chouser | urg. I forgot about cells. hang on. |
| 10:22 | AWizzArd | I want to do io (writing to disk) inside a dosync |
| 10:22 | AWizzArd | rhickey: so this developed to become a lock around a dosync |
| 10:22 | rhickey | AWizzArd: but why multiset and not multimap? it's not a set of years |
| 10:22 | AWizzArd | rhickey: to get all people born between 1970 and 1980 |
| 10:23 | AWizzArd | this would return one set of users, if subset were implemented |
| 10:23 | rhickey | AWizzArd: but a set of people is not a set of years |
| 10:23 | chouser | AWizzArd: you didn't like this solution? http://paste.lisp.org/display/94065 |
| 10:24 | AWizzArd | (sorted-multiset #(compare (:yob %1) (:yob %2))) is very nice. And later (subset users-by-yob = 1964) ==> all users born in this year. Or (subset users-by-yob >= 1970, < 1980) ==> returns a set of users that fulfill this criteria |
| 10:24 | AWizzArd | chouser: this works but is more complex |
| 10:25 | AWizzArd | and what can we do if the deftype has no slot that contains a unique value? |
| 10:25 | AWizzArd | Also it makes the lookup more complex |
| 10:25 | AWizzArd | a sorted-multimap would also work, but this would not return one set, but instead a sequence of keys (year of birth here) and values (sets of User instances) |
| 10:26 | AWizzArd | Also it would be amazing if a subset was in reality just a "view" (shared structure) of the map, so it won't take much ram |
| 10:26 | AWizzArd | don't know if this is possible |
| 10:26 | chouser | hm, cells might work. |
| 10:26 | qed | is a sorted-multimap more abstract than a multimap, or vice versa? |
| 10:27 | rhickey | a multiset is sort of a contradiction |
| 10:27 | chouser | heh |
| 10:27 | AWizzArd | rhickey: well, they may be equal under the comparator, but they are not identical?. |
| 10:27 | chouser | yeah, a cell would work |
| 10:28 | rhickey | AWizzArd: it's just a logical mess. What is it a set of? Does it enforce set-ness of the entire thing when using a partial key? |
| 10:28 | AWizzArd | Google also has Multisets in their Collections. Though as I already said, what you developed for Clojure is way more advanced than the immutable collections from Google. |
| 10:29 | rhickey | AWizzArd: collection class libs have had multisets for decades, still confusing |
| 10:29 | AWizzArd | It would be interesting to be able to call (subset on-it), to get a set returned on which one can call intersect. |
| 10:29 | AWizzArd | Example: you have a sorted set of all male users and a set sorted by year of birth. You could then look up males, then all born between 1990 and 1995 and intersect those and have all male users born during that time. |
| 10:30 | rhickey | AWizzArd: sounds like indexes |
| 10:30 | AWizzArd | rhickey: exactly! |
| 10:30 | AWizzArd | I am talking about indexes. |
| 10:30 | rhickey | not collections |
| 10:31 | AWizzArd | Well, the index needs to reside in some collection. |
| 10:31 | AWizzArd | The index we are talking about lives in ram and is persistent. |
| 10:31 | rhickey | all you need are multimaps for indexes |
| 10:31 | AWizzArd | rhickey: yes, those are enough in principle. They can just not be so easily queried |
| 10:32 | rhickey | AWizzArd: I don't see why not |
| 10:32 | esj | AWizzArd I've been doing something similar to this, a timeseries library, where I also used a sorted-set-by for the concerete representation. Made much easier by the fact that time is the unique index. Its nothing special, but check it out - https://gist.github.com/1eaa8e674ec13a06559b |
| 10:32 | AWizzArd | If you make such a map that logs the msecs after 1970 (timestamp) of user requests in your webserver |
| 10:32 | AWizzArd | How would we then ask for all requests between 2008 and 2009? |
| 10:33 | AWizzArd | That would require many lookups, as many as there are msecs per year |
| 10:33 | AWizzArd | And most will result in nil |
| 10:33 | AWizzArd | A sorted multimap would be more useful here |
| 10:34 | AWizzArd | such as subseq can already return such results easily for sorted sets and sorted maps |
| 10:34 | qed | esj: very cool |
| 10:35 | esj | i'm hoping to get it into Incanter once its been gone over by somebody who actually know what they are doing :) |
| 10:35 | qed | im bookmarking to read when i wake up :) |
| 10:35 | AWizzArd | And even when subseq returns a result, we still have to apply clojure.set/union on all those little values returned from the map |
| 10:35 | qed | thanks |
| 10:35 | AWizzArd | a set however makes this easier to query. A set will return the Log objects directly. The comparator would compare their incoming timestamp and sort them. |
| 10:36 | AWizzArd | Although, so far there is no .subset implemented and it is also a seq |
| 10:36 | qed | i like sets |
| 10:36 | AWizzArd | qed: yes, I also |
| 10:36 | rhickey | AWizzArd: sorry, I meant both sorted and non-sorted multimaps above. What I am arguing against is multisets |
| 10:36 | qed | they're dependable |
| 10:36 | esj | and they like the attention |
| 10:37 | qed | haha |
| 10:37 | AWizzArd | rhickey: the SortedMultimaps are able to model everything what I can come up with. The only thing that is not so nice about them is that they return key/value pairs, instead of the union of all values. |
| 10:38 | chouser | AWizzArd: my db-locking thing doesn't protect against nesting the way it should (and cells would) |
| 10:38 | AWizzArd | If there were a function subset that I could call on a SortedMultimap that would be fine of course. |
| 10:38 | qed | AWizzArd: yeah but i think the key/val pairs makes more sense -- seems more consistent |
| 10:38 | rhickey | AWizzArd: a multimap might return a set at each key |
| 10:38 | AWizzArd | rhickey: yes. And on those we need to call (apply clojure.set/union ..) |
| 10:39 | AWizzArd | A SortedMultiset would do this implicitly. |
| 10:39 | qed | it might be a bit much, so to speak |
| 10:40 | AWizzArd | (deftype Log [timestamp method uri user])... (def logs-by-timestamp (sorted-multiset #(compare (:timestamp %1) (:timestamp %2))). And later we can (subset logs-by-timestamp >= (to-timestamp 2008) < (to-timestamp 2009)) |
| 10:40 | AWizzArd | And the result would be a set of Logs. Even if two requests arrived at the same msec |
| 10:41 | AWizzArd | A sorted-multimap instead would return a sequence of 4 million key/value pairs that I first need to union. |
| 10:41 | AWizzArd | I need to union them to be able to intersect them with other selections |
| 10:41 | rhickey | AWizzArd: but you are only looking at one aspect. There is a lot of confusion engendered by multisets using partial keys. Are they true sets? How does contains? work? is there a way to check for containment of a full value? etc etc |
| 10:41 | qed | AWizzArd: i see the utility, but im not convinced by your example |
| 10:43 | AWizzArd | also an interesting point is if the union of some thousand sets, summing up to a million objects will have to be a full copy of those, or if it could "magically" be some kind of view on the existing sets under the hood. |
| 10:43 | AWizzArd | in such a case clojure.set/union|intersect|difference would be fast and not require too much RAM. |
| 10:44 | AWizzArd | sorted-sets are already pretty close to sorted-multisets |
| 10:44 | AWizzArd | uhm, I mean: sorted-maps are already very close to sorted-multisets |
| 10:45 | AWizzArd | What I am currently doing is using a sorted-map-by and when a key does not exist I assoc an empty set as its value. Otherwise I assoc the set conjed with the new value to the sorted-map |
| 10:46 | AWizzArd | Thus I already have something very close to a Multiset. My value, the set, is indeed not even a set, but itself a sorted-set. This way I could for example store users by their year of birth, and have them alphabetically sorted. |
| 10:47 | AWizzArd | having sorted-multisets support in Clojure would of course be very helpful |
| 10:48 | AWizzArd | We could have them just implement the SortedMap interface (as suggested in the assembla ticket), or if we want Java 6, implementing the NavigableMap interface. |
| 10:49 | AWizzArd | Well, thanks for listening. rhickey, it is true that I mostly look at one aspect of SortedMultisets, but even having SortedMultiMAPs would be very interesting. |
| 10:50 | AWizzArd | chouser: I listened to you, but could not respond. What are those Cells? |
| 10:50 | angerman | handling JNA structs with clojure is not very elegant ... or I'm doing something completely wrong. |
| 10:53 | chouser | AWizzArd: rhickey described them here: http://clojure-log.n01se.net/date/2010-01-22.html#09:22a |
| 10:55 | AWizzArd | chouser: very good, I will read this |
| 10:56 | AWizzArd | rhickey: btw, do you see a way to make something like "transient sorted-maps/sets"? I am looking for a way to insert data into sorted maps/sets much faster, and I can guarantee to insert in the correct order. |
| 10:56 | AWizzArd | Would that be possible, in principle? |
| 10:58 | cemerick | those cells sound like very concrete monads to me |
| 10:58 | cemerick | not that I pretend to properly understand monads |
| 10:58 | rhickey | cemerick: monads you can use from multiple threads? a contradiction in terms I think |
| 10:59 | rhickey | monads are about flow, this is about not having to flow |
| 10:59 | rhickey | AWizzArd: I'm not sure how much perf advantage to transient sorteds, probably some, just tedious |
| 11:00 | AWizzArd | hmm |
| 11:00 | rhickey | AWizzArd: i.e. with transient updating you could just do local mutative rebalancing, rather than full path copies |
| 11:00 | AWizzArd | I was thinking about this: when a savepoint of the db is made and an application restarted, it then wants to reload the db. Insertion is not very fast into sorted-maps/sets. I just know that I have them already sorted on disk, because I read them out of a sorted-map/set during serialization. |
| 11:01 | rhickey | fast load from sorted is a different question |
| 11:02 | AWizzArd | ,(time (let [x #{}] (reduce #(conj %1 %2) x (range 1000000)) nil)) |
| 11:02 | chouser | could perhaps avoid a lot of rebalancing if you know the size of the input and the fact it's sorted |
| 11:02 | clojurebot | Execution Timed Out |
| 11:02 | AWizzArd | ,(time (let [x #{}] (reduce #(conj %1 %2) x (range 100000)) nil)) |
| 11:02 | clojurebot | "Elapsed time: 964.84 msecs" |
| 11:02 | AWizzArd | ,(time (let [x (sorted-set-by <)] (reduce #(conj %1 %2) x (range 100000)) nil)) |
| 11:02 | clojurebot | "Elapsed time: 2438.971 msecs" |
| 11:03 | cemerick | rhickey: I've never used monads at all, so this is mostly hot air. Cells seem to share the notion of cleanly separating initial states, operations, and later states that are the result(s) of those operations. |
| 11:03 | AWizzArd | chouser: yes |
| 11:03 | AWizzArd | And I won't need the comparator, comparison is not needed |
| 11:03 | AWizzArd | ,(time (let [x []] (reduce #(conj %1 %2) x (range 100000)) nil)) |
| 11:03 | clojurebot | "Elapsed time: 134.741 msecs" |
| 11:03 | AWizzArd | fast :-) |
| 11:04 | AWizzArd | unfortunately I can not use vectors as indexes |
| 11:04 | AWizzArd | anyway, rhickey, now after more study about your implementations of those data structures I am very impressed what you have done. It is very good work, and you easily outperform Google! *thumbs up* |
| 11:05 | chouser | ,(time (peek (into [] (range 100000)))) |
| 11:05 | clojurebot | 99999 |
| 11:05 | clojurebot | "Elapsed time: 106.663 msecs" |
| 11:05 | chouser | faster |
| 11:06 | AWizzArd | ,(time (count (into #{} (range 100000)))) |
| 11:06 | clojurebot | 100000 |
| 11:06 | clojurebot | "Elapsed time: 225.935 msecs" |
| 11:06 | AWizzArd | ,(time (count (into (sorted-set-by >) (range 100000)))) |
| 11:06 | clojurebot | 100000 |
| 11:06 | clojurebot | "Elapsed time: 1834.843 msecs" |
| 11:08 | AWizzArd | chouser: I will see if I can easily enough go around the problem of stacked transactions using with-local-vars. Otherwise for now I can simply use a lock, deref the atom containing the db, atoming it again and reach this around. |
| 11:08 | AWizzArd | And when Cells come one day, I could use them and clean up my underlying implementation. |
| 11:09 | chouser | it wouldn't be hard to add protection against nested with-db-locks |
| 11:10 | AWizzArd | yes, I will most likely do that |
| 11:10 | AWizzArd | I will come up with a prototype of db-transactions this week |
| 11:10 | chouser | AWizzArd: would you ever want to support updating multiple dbs in the same transaction? |
| 11:11 | AWizzArd | chouser: probably not. My db will be a little bit like git/mercurial and allow clones ("branches") which can be merged. |
| 11:11 | AWizzArd | During the merge there will be two dbs involved, but that should still not require refs. |
| 11:12 | AWizzArd | anyway, for today I have talked enough, and our discussion about the efficiecy was very interesting and shed new light on some aspects for me. For example, I didn't know about with-local-vars. |
| 11:23 | stuartsierra | Anyone have a better link for Rich's talk at Clojure NYC last week? |
| 11:25 | rhickey | stuartsierra: I didn't know it was being recorded |
| 11:25 | stuartsierra | rhickey: someone had a flip |
| 11:26 | stuartsierra | There's an incomplete video here: http://vimeo.com/9090935 |
| 11:26 | rhickey | yeah, with a low battery :( |
| 11:26 | stuartsierra | yep |
| 11:26 | stuartsierra | I wanted to share it with my interns. |
| 11:31 | rhickey | stuartsierra: you have to bring them next time! |
| 11:32 | stuartsierra | They couldn't make it. I invited them. |
| 11:33 | fdaoud | where was this? |
| 11:34 | fdaoud | sorry, you said NYC |
| 11:35 | fdaoud | of course the other one is on Scala |
| 11:36 | fdaoud | the syntax of which I cannot stand |
| 11:38 | stuartsierra | fdaoud: Clojure NYC, on meetup.com |
| 11:49 | qed | I so wish there was a meetup in Chicago |
| 11:51 | chouser | qed: If there were, I might go. |
| 11:51 | chouser | a bit of a treck, but could be worth it. :-) |
| 11:54 | wtetzner_ | does anyone know how to set jvm options for swank-clojure? |
| 11:54 | chouser | qed: would you present something? |
| 11:55 | mattrepl | wtetzner_: it used to be swank-clojure-extra-vm-args that you could set |
| 11:55 | wtetzner_ | mattrepl: ok, i'll try that. thanks |
| 11:56 | mattrepl | it takes a list of string arguments: (list "-Dsome.prop=10" "-Xmx1024m") |
| 11:58 | wtetzner_ | ok, thanks |
| 12:00 | wtetzner_ | i'm trying to use jvisualvm for profiling, but it tells me i have class sharing turned on |
| 12:00 | wtetzner_ | i tried using -Xshare:off, but it still says sharing is turned on |
| 12:01 | mattrepl | once you have swank-clojure loaded up, you can also see/set all the settings from M-x customize-group |
| 12:01 | mattrepl | using "swank-clojure" as group name |
| 12:02 | wtetzner_ | ok |
| 12:02 | jcromartie | how would I make a case-insensitive regex? |
| 12:02 | chouser | #"(?i)foobar" |
| 12:03 | jcromartie | ah |
| 12:03 | jcromartie | is that in the docs anywhere? |
| 12:03 | chouser | it's in the book. ;-) |
| 12:03 | jcromartie | ah |
| 12:03 | jcromartie | clojure.org feels sorely out of date sometimes |
| 12:03 | jcromartie | it would be trivial to update it if the wiki were open |
| 12:03 | jcromartie | (is it?) |
| 12:03 | chouser | well, it's take directly from the Java Pattern object |
| 12:03 | jcromartie | ah |
| 12:04 | jcromartie | I thought the options were specified as arguments to the constructor |
| 12:04 | chouser | http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#UNIX_LINES and following |
| 12:06 | jcromartie | thanks |
| 12:23 | alexyk | what's the syntax for if -- elseif ... -- else, if any? nested ladders of if's start to look unwieldy... is there a caseof equivalent? |
| 12:25 | alexyk | or it's a big-arse (if ... (if ... ))))))) <-- the famous painfully counted closing layered cake? |
| 12:25 | the-kenny | alexyk: case? cond? |
| 12:25 | alexyk | the-kenny: ah! |
| 12:26 | _fogus_ | alexyk: (and) |
| 12:26 | alexyk | _fogus_: (and)? |
| 12:26 | alexyk | ,(doc cond) |
| 12:26 | clojurebot | "([& clauses]); Takes a set of test/expr pairs. It evaluates each test one at a time. If a test returns logical true, cond evaluates and returns the value of the corresponding expr and doesn't evaluate any of the other tests or exprs. (cond) returns nil." |
| 12:26 | fdaoud | , (cond (< 2 42) "a" (> 2 42) "b")) |
| 12:26 | clojurebot | "a" |
| 12:27 | alexyk | ,(doc case) |
| 12:27 | clojurebot | "clojure.contrib.fcase/case;[[test-value & clauses]]; Like cond, but test-value is compared against the value of each test expression with =. If they are equal, executes the \"body\" expression. Optional last expression is executed if none of the test expressions match." |
| 12:27 | alexyk | aha, so case is not core |
| 12:27 | Chousuke | will be in 1.2 |
| 12:28 | stuartsierra | and it's different |
| 12:28 | alexyk | stuartsierra: different from the above fcase/case? |
| 12:29 | alexyk | _fogus_: I used (and ...) to essentially simulate elsif, it's unwieldy too |
| 12:29 | stuartsierra | alexyk: yes |
| 12:29 | _fogus_ | alexyk: Yeah, it's a total hack |
| 12:31 | somnium | how is that fcase macro different from condp? |
| 12:31 | stuartsierra | it's not |
| 12:31 | stuartsierra | I wrote it before condp existed |
| 12:31 | somnium | ah, roger |
| 12:31 | alexyk | ,(doc condp) |
| 12:31 | clojurebot | "([pred expr & clauses]); Takes a binary predicate, an expression, and a set of clauses. Each clause can take the form of either: test-expr result-expr test-expr :>> result-fn Note :>> is an ordinary keyword. For each clause, (pred test-expr expr) is evaluated. If it returns logical true, the clause is a match. If a binary clause matches, the result-expr is returned, if a ternary clause matches, its result-fn, which must b |
| 12:32 | alexyk | I'll stick with cond, clear and unambifuous. Not much trouble to write (= var blah) |
| 12:32 | stuartsierra | yej |
| 12:32 | stuartsierra | yes |
| 12:33 | stuartsierra | And for simple tests, it's faster than case |
| 12:34 | alexyk | yeah, I'm branching on a keyword values |
| 12:34 | alexyk | i.e., on a var values which are keywords |
| 12:48 | jcromartie | speaking of condp, is there anything that acts like the typical curly-brace "switch"? |
| 12:52 | deafmacro | hello, is there a way to cancel a task sent to an agent? |
| 12:54 | jcromartie | deafmacro: nice nick :) |
| 12:54 | jcromartie | deafmacro: could you send a fn that depends on a ref that you can toggle from somewhere else? |
| 12:54 | deafmacro | jcromartie: heh thanks :) |
| 12:56 | jcromartie | ,(let [cancel-ref (ref nil)] (fn [] (when-not @cancel-ref (println "Doing my thang")))) |
| 12:56 | clojurebot | #<sandbox$eval__4729$fn__4731 sandbox$eval__4729$fn__4731@176dad5> |
| 12:56 | deafmacro | I could but would it stop the agent? |
| 12:56 | jcromartie | it wouldn't *stop* the agent, but you have control over what fn you send to it |
| 12:58 | jcromartie | ,(let [cancel-ref (ref nil) job (fn [] (when-not @cancel-ref (println "Doing my thang")))] (job)) |
| 12:58 | clojurebot | Doing my thang |
| 12:58 | jcromartie | ,(let [cancel-ref (ref nil) job (fn [] (when-not @cancel-ref (println "Doing my thang")))] (dosync (ref-set cancel-ref true)) (job)) |
| 12:58 | clojurebot | nil |
| 12:59 | jcromartie | just an idea |
| 13:01 | deafmacro | jcromartie: thanks! will take that approach and see what I get |
| 13:01 | jcromartie | that's probably a cleaner way than killing a thread :) |
| 13:02 | deafmacro | jcromartie: true. the java docs recommed the same. makes sense too. one would want to control how the thread exits |
| 13:03 | jcromartie | yeah at least in the iPhone/ObjC world that I work in most of the time some very nasty things can happen when something goes wrong in a thread... but that's mostly because it's not GC'ed |
| 13:04 | somnium | somehow that mechanism makes me think of bureaucracy (upon receiving an order, first call your supervisor and confirm that he meant it, if his phone is busy keep trying...) |
| 13:06 | jcromartie | the point being that bureaucracy is bad? |
| 13:13 | somnium | no particular point, just an image of (send secret-agent #(when @im-not-kidding (activate-the-bomb %))) |
| 13:14 | fdaoud | somnium: now there's a DSL if I've ever seen one :-) |
| 13:14 | mattrepl | it's the difference between being told it's time to leave and being thrown out |
| 13:14 | arohner | somnium: sure, but you could have updated information |
| 13:14 | arohner | (send secret-agent #(when @bad-guys-dont-give-up (activate-the-bomb))) |
| 13:15 | arohner | blowing up the bomb after surrender is generally considered bad form |
| 13:15 | arohner | :-) |
| 13:16 | somnium | java.lang.Exception "we lost the war because our operatives couldnt phone our destryed headquarters" |
| 13:17 | stuartsierra | java.lang.DoomsdayDeviceActivatedException |
| 13:17 | arohner | somnium: that |
| 13:17 | arohner | somnium: that's why you want good defaults |
| 13:18 | stuartsierra | (try (launch-attach) (catch java.lang.RogueCommander (abort))) |
| 13:19 | somnium | :-) |
| 13:19 | ohpauleez | will someone write about how Clojure is capable of not only stopping runaway trains, but saving all of humanity |
| 13:20 | stuartsierra | Everyone will be protected by Refs. |
| 13:20 | ohpauleez | STM will set you free |
| 13:20 | stuartsierra | Resources are allocated fairly to all agents. |
| 13:21 | stuartsierra | No more mutation. |
| 13:29 | ohpauleez | haha |
| 13:31 | alexyk | what's the max int again? |
| 13:31 | stuartsierra | ,(Integer/MAX) |
| 13:31 | clojurebot | java.lang.NoSuchFieldException: MAX |
| 13:31 | stuartsierra | ,Integer/MAX_VALUE |
| 13:31 | clojurebot | 2147483647 |
| 13:31 | technomancy | Integer/MAX_VALUE |
| 13:32 | alexyk | ah ok |
| 13:32 | technomancy | doh, too slow |
| 13:32 | stuartsierra | :) |
| 13:32 | stuartsierra | clojurebot needs a "did you mean ...?" feature :) |
| 13:32 | technomancy | it's pretty good at fuzzy matches on keywords |
| 13:32 | technomancy | but not on code. =) |
| 13:33 | stuartsierra | yeah |
| 13:35 | stuartsierra | That's the magical editor everyone wants: your code is wrong, it should be .... |
| 13:39 | hiredman | stuartsierra: did you see abi-watch? |
| 13:40 | stuartsierra | no |
| 13:40 | hiredman | http://www.thelastcitadel.com/lab/abi-watch/1.1.x-1.0.x.diff.html |
| 13:40 | hiredman | http://www.thelastcitadel.com/lab/abi-watch/ |
| 13:41 | stuartsierra | ok |
| 13:41 | hiredman | I haven't tied it all together yet, but it's some scripts that generate diffs of, basically, the various members and types defined in java |
| 13:41 | stuartsierra | cool |
| 13:43 | hiredman | so in http://www.thelastcitadel.com/lab/abi-watch/master-1.0.x.diff.html you can scroll down and see where the RestFn constructor gained an argument |
| 13:44 | stuartsierra | I see |
| 13:46 | hiredman | the class files generated by clojure are full of gensyms so doing diffs is difficult |
| 13:47 | hiredman | (possibly impossible) |
| 13:47 | stuartsierra | yeah |
| 14:08 | hiredman | I wonder how hard it would be to add an interop form to the compiler that allows the direct use of java operators |
| 14:08 | hiredman | (jop + (int 1) (int 2)) |
| 14:11 | cemerick | that's getting close to what rhickey has called java-in-parens |
| 14:11 | cemerick | though it's probably more like host-in-parens these days |
| 14:24 | alexyk | how clojure can exist as a lisp with all that vomit-inducing java underneath, teaming with monsters and reptiles, is amazing |
| 14:24 | alexyk | like "The Matrix" |
| 14:24 | ordnungswidrig | aloha |
| 14:24 | alexyk | guten tag |
| 14:25 | alexyk | or, guten :tag! |
| 14:28 | ordnungswidrig | hehe. |
| 14:29 | alexyk | yeah, I was always curious how German programmers handle English tag used everywhere |
| 14:29 | alexyk | except Perl, which blesses things |
| 14:31 | alexyk | ahould be abend too now probably |
| 14:34 | alexyk | ordnungswidrig: when does tag become abend? |
| 14:34 | alexyk | i.e. what hour of the day, roughly |
| 14:34 | ordnungswidrig | alexyk: hard to say, I think 6 o'clock would be commonly agreed upon |
| 14:35 | alexyk | ok, so it's more like evening than afternoon |
| 14:35 | alexyk | and do you say guten nacht when meeting in the evening, or is it mainly for good bye and good night? |
| 14:36 | ordnungswidrig | yes, "gute nacht" is literaly "good night" and only used like you said |
| 14:36 | ordnungswidrig | afternoon is "nachmittag" (nach/after mittag/noon) |
| 14:38 | alexyk | ok |
| 14:39 | alexyk | so do people say gute nachmittag or guten abend around say 3-4? |
| 14:40 | jasapp | what's more important than saying, "Bier bitte."? |
| 14:41 | ordnungswidrig | hmm, no, nobody would say "guten nachmittag", it's until about 6-7 that they say "Guten Tag" / "Hallo" . They say "Grüß Gott" mainly southern germany the whole day and "Moin Moin" in the most northern parts. |
| 14:42 | alexyk | jasapp: I thought it's "bier schnelle" or something like that :) |
| 14:42 | ordnungswidrig | jasapp: "Ein Bier, bitte" would be more polite. And perhaps the kind of Bier you'd like: Lager, Kölsch, Weißbier, Dunkles, Export, Radler or the brand |
| 14:42 | jasapp | ahh |
| 14:42 | ordnungswidrig | "Schnell, ein Bier" / "A Beer! Quick!" |
| 14:42 | jasapp | gotcha, nice. |
| 14:43 | alexyk | (schnell (ein 'bier)) ; smoothly steering back into clojure |
| 14:47 | ordnungswidrig | anybody used fleetdb yet? |
| 14:59 | hiredman | I think something like jop would be needed to turn Numbers.java into numbers.clj |
| 15:00 | hiredman | and it seems like adding a special form would be a good place to start trying to get a handle on the Compiler :D |
| 15:06 | somnium | just need to wrap the 220-or-so asm methods in a simple s-expression api :P |
| 15:06 | alexyk | what's the single fun for not empty? again |
| 15:06 | somnium | seq |
| 15:06 | alexyk | right, but for nil? |
| 15:07 | somnium | ,(seq nil) |
| 15:07 | clojurebot | nil |
| 15:07 | alexyk | ,(seq :a) |
| 15:07 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword |
| 15:07 | alexyk | I need a non-empty test to pass to filter |
| 15:07 | alexyk | without #() |
| 15:08 | ordnungswidrig | sigh |
| 15:08 | somnium | what does non-empty mean? |
| 15:08 | chouser | does protected static on a method mean anything in that package can use it, but other packages can't? |
| 15:08 | alexyk | sorry. not-nil would do |
| 15:09 | somnium | ,(nil? nil) |
| 15:09 | clojurebot | true |
| 15:09 | ordnungswidrig | I have a var declared in a lib, say a switch to enable debug tracing. How can I make a client of the lib change the var? With "with-bindings? |
| 15:09 | hiredman | somnium: well, most of the asm stuff would be taken care of via the compiler |
| 15:09 | _ato | chouser: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html |
| 15:09 | alexyk | duh, I can just extract the damn thing, it will be its own filter |
| 15:09 | hiredman | function application is method call |
| 15:10 | Ober2 | WARNING: JRuby does not support native extensions or the `mkmf' library. |
| 15:10 | alexyk | btw I take my hat off to you folks brave enough to brave the java. It's hidden so well! |
| 15:10 | hiredman | and there is the . interop form, so I don't know that you would need to wrap that much |
| 15:10 | Ober2 | oops wrong chan |
| 15:10 | alexyk | begone, ruby! do..end! |
| 15:11 | somnium | hiredman: youve been playing with java asm havent you? is enough exposed in c.c.compiler to do it with a macro? |
| 15:11 | hiredman | I don't know |
| 15:11 | hiredman | I don't understand the compiler |
| 15:12 | somnium | doing ,(show c.c.compiler) was rather intimidating |
| 15:12 | hiredman | heh |
| 15:12 | hiredman | c.l.compiler |
| 15:13 | zaphyr | #<CompilerException java.lang.IllegalStateException: Nested #()s are not allowed (run_stream.clj:26)> ? :( |
| 15:13 | hiredman | you can put a #() inside a #() |
| 15:13 | chouser | can't |
| 15:13 | hiredman | thank you |
| 15:13 | chouser | :-) |
| 15:13 | zaphyr | lol, got confused there :) |
| 15:14 | chouser | _ato: thanks |
| 15:14 | zaphyr | thinking about it though, what would % mean? so stands to reason |
| 15:14 | ordnungswidrig | hiredman: is there an alternative other than fn for nested #()'s? |
| 15:14 | hiredman | uh |
| 15:14 | ordnungswidrig | s/'// |
| 15:14 | hiredman | no |
| 15:14 | ordnungswidrig | perhaps it's good this way |
| 15:17 | zaphyr | yeah, after a minor refactor i removed the need for nested #()s, and shortened my expression down by about 50%, so it helped me along in this case. |
| 15:25 | cemerick | I'm amazed at what I can do with enlive almost every day |
| 15:36 | wlr | cemerick: maybe a nice blog post or three would help us less telepathic users of enlive ;-) |
| 15:37 | cemerick | wlr: yeah, it's definitely in the cards. Monday might be a good slack day. :-) |
| 15:37 | wlr | cemerick: looking forward to it! |
| 15:41 | Mec | ,(.nextDouble java.util.Random.) |
| 15:41 | clojurebot | java.lang.ClassNotFoundException: java.util.Random. |
| 15:45 | jcromartie | is there a way to attach middleware to every route in a compojure app? |
| 15:45 | jcromartie | without naming the handlers? |
| 15:49 | jcromartie | also: why is the compojure wiki not written in compojure? :P |
| 15:49 | chouser | why is emacs not written in clojure? |
| 15:49 | hiredman | rms's shortsightedness |
| 15:50 | chouser | heh |
| 15:50 | jasapp | wasn't there a group of people that started trying to write emacs in common lisp? |
| 15:50 | hiredman | sure |
| 15:50 | jasapp | a rather substantial effort, if I remember correctly |
| 15:50 | hiredman | yeggie is rewriting it in javascript :P |
| 15:51 | chouser | in what he calls javascript |
| 15:54 | lpetit | Hi, any ccw user in the room ? |
| 15:54 | lpetit | I guess I already know the answer :-( |
| 15:55 | the-kenny | lpetit: What's "ccw"? |
| 15:55 | lpetit | ~ccw |
| 15:55 | clojurebot | ccw is http://github.com/laurentpetit/ccw |
| 15:55 | lpetit | ~counterclockwise |
| 15:55 | clojurebot | Counterclockwise aka ccw at http://code.google.com/p/counterclockwise/ |
| 15:55 | lpetit | eclipse plugin for clojure |
| 15:56 | the-kenny | ah |
| 15:57 | alexyk | what's the shortest way to filter non-nil values only from a seq? |
| 15:57 | alexyk | (filter <what?> [1 nil 3]) => [1 3] |
| 15:58 | lpetit | ,(doc find) |
| 15:58 | clojurebot | "([map key]); Returns the map entry for key, or nil if key not present." |
| 15:58 | lpetit | ,(doc filter) |
| 15:58 | clojurebot | "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects." |
| 15:58 | lpetit | identity |
| 15:58 | lpetit | ,(filter identity [nil false :a]) |
| 15:58 | clojurebot | (:a) |
| 15:58 | lpetit | gloups |
| 15:58 | alexyk | identity is ok |
| 15:58 | lpetit | nope, does not work for false |
| 15:59 | somnium | ,(remove nil? [nil false :a]) |
| 15:59 | clojurebot | (false :a) |
| 15:59 | lpetit | thx somnium |
| 15:59 | Raynes | somnium: I was two seconds away from pressing enter, you... |
| 15:59 | alexyk | I don't expect false |
| 15:59 | Raynes | I need to remap my parentheses keys. ;) |
| 15:59 | lpetit | nil? is shorter than identity so it's the shortest you were after :-) |
| 15:59 | alexyk | Raynes: it's Florida sun :) |
| 16:00 | zaphyr | ahh, (remove x y) == (filter (complement x) y)? |
| 16:00 | lpetit | ~source remove |
| 16:00 | lpetit | literally, yes |
| 16:00 | zaphyr | \o/ :D |
| 16:00 | lpetit | :) |
| 16:02 | jcromartie | what's the case for false, anyway? |
| 16:02 | jcromartie | aside from Java interop |
| 16:03 | zaphyr | ,(empty? false) |
| 16:03 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean |
| 16:03 | chouser | jcromartie: I think that's it. |
| 16:08 | alexyk | the beauty of clojure: you think of what a defn should be called, write it down, call it, and it's there |
| 16:08 | alexyk | "Clojure: the core is always there for you" |
| 16:10 | JayM | is there yet a name for someone who programs in Clojure? |
| 16:10 | JayM | Clojurers? |
| 16:10 | Raynes | JayM: I'm Anthony. Does that count? |
| 16:10 | Raynes | :p |
| 16:10 | JayM | :) |
| 16:12 | alexyk | Raynes: well, I'm not Anthony, so it says nothing of the class :) |
| 16:12 | alexyk | consurers (inverting jure) |
| 16:13 | Raynes | We should call them Anthonyers. |
| 16:13 | alexyk | clojurassic park rangers |
| 16:13 | alexyk | Raynes: then at least richers |
| 16:16 | JayM | in any case, i'm a wannabe, having a hell of a time getting swank-clojure installed |
| 16:16 | JayM | ELPA doesn't like me |
| 16:16 | Raynes | JayM: Even if it errors or something, it might still be installed. |
| 16:17 | JayM | Raynes: i keep getting: trying to parse http response code in odd buffer |
| 16:17 | Raynes | Oh. |
| 16:17 | Raynes | That's ELPA madness. |
| 16:17 | Raynes | Stab it three times in the chest and move it aside. |
| 16:17 | JayM | haha, ok |
| 16:18 | JayM | might just be something in my config...trying clean now.. |
| 16:28 | thearthur | how do i (use 'clojure.zip) when it conflicts with the name next in clojure.core? |
| 16:28 | hiredman | you don't |
| 16:28 | hiredman | you require it |
| 16:28 | thearthur | i want to use zip/next to refer to that |
| 16:28 | hiredman | ,(doc require) |
| 16:28 | clojurebot | "([& args]); Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly. Libs A 'lib' is a named set of resources in classpath whose contents define a library of Cloju |
| 16:29 | JayM | bah, manual install it is |
| 16:32 | Raynes | thearthur: (ns ans (:require [clojure.zip :as zip])) |
| 16:33 | duncanm | i'm having trouble using agents |
| 16:33 | duncanm | if i do this, (def a (agent [])) (send a #(vec 1 2 3)) |
| 16:33 | duncanm | eventually, @a will be [1 2 3], right? |
| 16:34 | kotarak | duncanm: no. you want (send a #(vector 1 2 3)) |
| 16:34 | hiredman | neither |
| 16:35 | kotarak | ah, yes |
| 16:35 | hiredman | the first argment is hte current state of the agent |
| 16:35 | kotarak | the state |
| 16:35 | kotarak | (send a #(do % (vector 1 2 3))) |
| 16:35 | hiredman | (constantly [1 2 3]) |
| 16:36 | duncanm | (send a #(constantly [1 2 3])) |
| 16:36 | duncanm | i did that, and a is still [] |
| 16:36 | hiredman | wait |
| 16:36 | kotarak | (await a) |
| 16:37 | duncanm | and it stalls |
| 16:37 | hiredman | yes |
| 16:37 | hiredman | await waits for the action to run |
| 16:37 | duncanm | which should return immediately, shouldn't it? |
| 16:37 | duncanm | it's #(constantly [1 2 3]) |
| 16:38 | hiredman | it depends on things |
| 16:39 | hiredman | if you are still using the same agent, the agent will have errors from you previous attempts, but send should should throw an exception in that case |
| 16:39 | hiredman | and I am not sure about the behaviour of await on agents with errors |
| 16:39 | duncanm | ahh |
| 16:39 | Chousuke | um, don't you need (send a (constantly [1 2 3])) |
| 16:39 | hiredman | Chousuke: right |
| 16:39 | hiredman | send also uses a fixed size threadpool to run actions |
| 16:40 | hiredman | so if you are sending other things your actions my que up |
| 16:41 | duncanm | http://gist.github.com/295146 -- is this a correct usage? |
| 16:41 | duncanm | i dunno if i got the arity right for this: #(calculate-offset %1 file sec %2 %3) |
| 16:41 | thearthur | what is the apropriate way to alias the name space clojure.zip to just zip? |
| 16:42 | hiredman | duncanm: the first argument to the agent action is always the state of the agent |
| 16:42 | chouser | (ns ... (:require [clojure.zip :as zip])) |
| 16:42 | Raynes | thearthur: Hiredman and I both told you about 7 minutes ago. |
| 16:43 | Chousuke | duncanm: looks correct |
| 16:43 | hiredman | and I would use send-off instead of send for anything with a sleep in it |
| 16:43 | duncanm | hiredman: okay |
| 16:43 | thearthur | what wrong with this (require 'clojure.zip :as zip) |
| 16:44 | the-kenny | ,(require '[clojure.zip :as zip]) |
| 16:44 | clojurebot | nil |
| 16:44 | hiredman | thearthur: look at the form with :require that chouser showed you |
| 16:44 | hiredman | what is the difference? |
| 16:44 | thearthur | Raynes, I'm looking to do it from the repl with out setting the namespace |
| 16:45 | Raynes | thearthur: (require '[clojure.zip :as zip]) |
| 16:45 | thearthur | Thanks Raynes :) |
| 16:45 | Raynes | thearthur: the-kenny got it first. :p |
| 16:46 | duncanm | ahh |
| 16:46 | duncanm | i'm getting close |
| 16:46 | duncanm | i still have trouble using condp; i keep on asking the same question without getting how to use it |
| 16:47 | hiredman | ,(condp = 6 6 :six 7 :seven) |
| 16:47 | clojurebot | :six |
| 16:47 | hiredman | ,(condp = 7 6 :six 7 :seven) |
| 16:47 | clojurebot | :seven |
| 16:48 | duncanm | hiredman: i want to use condp just like cond, but i also want to use :>> |
| 16:48 | duncanm | hiredman: so i don't know what to use for the 'pred' |
| 16:48 | hiredman | duncanm: that sounds like a bad idea |
| 16:49 | hiredman | I suggest you just wrap cond in a let |
| 16:49 | duncanm | hiredman: so what i can do? |
| 16:49 | duncanm | ahh |
| 16:49 | duncanm | yeah |
| 16:49 | duncanm | let me do that |
| 16:49 | hiredman | I will let you do that |
| 16:49 | hiredman | *let* |
| 17:02 | alexyk | how do I (use ...) a package but exclude a defn which conflicts? |
| 17:04 | the-kenny | alexyk: :exclude? |
| 17:04 | the-kenny | s/?/ ?/ |
| 17:04 | alexyk | ok |
| 17:04 | alexyk | say I successfully did a (use ...) in one ns, and have a conflict in another. Can I refer the old one with some exclusions? |
| 17:07 | alexyk | so if my use is: (use '(incanter core stats charts)), how do I exclude group-by? |
| 17:07 | alexyk | i.e. where do I stick it |
| 17:08 | chouser | you want to exclude incanter's group-by, or clojure's? |
| 17:09 | alexyk | chouser: I already have clojure's sitting in my ns. I'd drop whichever :) |
| 17:09 | alexyk | if I can choose, it would be nice |
| 17:10 | chouser | you can ns-unmap the one that's there (core) and then do what you want. |
| 17:11 | alexyk | ah, so it does the use after all, but simply warns about group-by |
| 17:11 | alexyk | that's what I needed |
| 17:11 | alexyk | better it said "warning" or something |
| 17:12 | alexyk | or maybe not... |
| 17:12 | alexyk | it skips the whole unit where the conflict is? |
| 17:26 | lygaret | hey y'all could I get help with a question? |
| 17:26 | lygaret | I need to transform a symbol to an equiv string |
| 17:26 | lygaret | like (tostring 'one) => "one" |
| 17:27 | jasapp | ,(doc name) |
| 17:27 | clojurebot | "([x]); Returns the name String of a symbol or keyword." |
| 17:27 | zaphyr | ,(name foo) |
| 17:27 | clojurebot | java.lang.Exception: Unable to resolve symbol: foo in this context |
| 17:27 | zaphyr | oops. |
| 17:27 | lygaret | haha |
| 17:27 | zaphyr | ,(name 'one) |
| 17:27 | clojurebot | "one" |
| 17:27 | hiredman | ,(name 'foo) |
| 17:27 | lygaret | Awesome, thanks guys |
| 17:27 | clojurebot | "foo" |
| 17:27 | hiredman | ,(str 'foo) |
| 17:27 | clojurebot | "foo" |
| 17:27 | hiredman | ,(.toString 'foo) |
| 17:27 | clojurebot | "foo" |
| 17:27 | lygaret | I couldn't find that in the docs |
| 17:27 | hiredman | ,(prn-str 'foo) |
| 17:27 | clojurebot | "foo\n" |
| 17:27 | hiredman | ,(pr-str 'foo) |
| 17:27 | clojurebot | "foo" |
| 17:28 | jasapp | ,(with-out-str (print 'foo)) |
| 17:28 | clojurebot | "foo" |
| 17:28 | zaphyr | %D |
| 17:28 | hiredman | ,(format "%s" 'foo) |
| 17:28 | clojurebot | "foo" |
| 17:29 | zaphyr | hiredman- for all your symbol to string needs :) |
| 17:30 | zaphyr | is there a convenient way to check if a sequence is lazy, like printing it without forcing all the elements? |
| 17:31 | Chousuke | you can check whether it's a LazySeq, but I think that won't cover all lazy seqs :P |
| 17:32 | zaphyr | yeah, i kind of want to see how much has already been realised |
| 17:32 | zaphyr | class doesn't give me that |
| 17:33 | Chousuke | I don't think there's any way to know that. |
| 17:33 | Chousuke | unless you specifically construct a lazy seq that keeps track of its progress |
| 17:33 | hiredman | a lazy-seq is still a lazy-seq, even if it has been realized |
| 17:34 | zaphyr | yeah. i'm not having a problem right now, it just occured to me in some situations it might be handy to check things are working as you expect |
| 17:34 | zaphyr | not in a program, more at the repl |
| 17:35 | Raynes | Oh no! I'm being garbage collected!!! Quick, somebody, hold my head!! |
| 17:35 | zaphyr | :) |
| 17:35 | ghotli_ | looking through the docs, can't find this function. how do i create a long list of the same number. |
| 17:35 | ghotli_ | ie (5 5 5 5 5 5 5) |
| 17:36 | zaphyr | ,(take 10 (constantly 5)) |
| 17:36 | clojurebot | java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$constantly__4704$fn__4706 |
| 17:36 | chouser | ,(repeat 10 5) |
| 17:36 | clojurebot | (5 5 5 5 5 5 5 5 5 5) |
| 17:36 | ghotli_ | *sigh* wow. |
| 17:37 | zaphyr | not constantly |
| 17:37 | ghotli_ | i'm surprised i didn't just guess repeat |
| 17:37 | ghotli_ | anyway thanks! |
| 17:37 | hiredman | ,(take 5 (iterate (constantly 5))) |
| 17:37 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args passed to: core$iterate |
| 17:37 | hiredman | ,(take 5 (iterate (constantly 5) 5)) |
| 17:37 | clojurebot | (5 5 5 5 5) |
| 17:40 | zaphyr | ahh, yeah. i got constantly muddled with repeat |
| 17:43 | Chousuke | ,(take 5 (repeatedly (constantly 5))) one more way :P |
| 17:43 | clojurebot | (5 5 5 5 5) |
| 17:44 | zaphyr | throw an identity in there for good measure :) |
| 17:44 | chouser | ,(take 10 (iteratate identity 5)) |
| 17:44 | clojurebot | java.lang.Exception: Unable to resolve symbol: iteratate in this context |
| 17:44 | chouser | ,(take 10 (iterate identity 5)) |
| 17:44 | clojurebot | (5 5 5 5 5 5 5 5 5 5) |
| 17:45 | zaphyr | i still can't get over how absolutely cool lazy |
| 17:45 | zaphyr | meh. irc client fail. :/ |
| 17:45 | Chousuke | zaphyr: your sentence wasn't fully realised :P |
| 17:45 | zaphyr | :) |
| 17:45 | chouser | heh |
| 18:07 | ghotli_ | how about ripping off the first few items of a seq and returning the rest |
| 18:07 | ghotli_ | rest will just rip off the first item |
| 18:09 | zaphyr | ,(drop 3 '(1 2 3 4 5 6 7)) |
| 18:09 | clojurebot | (4 5 6 7) |
| 18:09 | dakrone | ghotli_: use (drop ..) |
| 18:09 | ghotli_ | wonderful. thanks. |
| 18:10 | zaphyr | there's also drop-while which takes a predicate instead of a count |
| 18:11 | billsmithaustin | ,(println "hello world") |
| 18:11 | clojurebot | hello world |
| 18:14 | zaphyr | hmm. why is there an nthnext when there is a drop? |
| 18:14 | zaphyr | symmetry with nth? |
| 18:15 | hiredman | ,(doc rest) |
| 18:15 | clojurebot | "([coll]); Returns a possibly empty seq of the items after the first. Calls seq on its argument." |
| 18:15 | hiredman | ,(doc next) |
| 18:15 | clojurebot | "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil." |
| 18:15 | zaphyr | ahh |
| 18:15 | zaphyr | thanks |
| 18:34 | Raynes | hiredman: You should add an equivalent of lambdabot's @faq. clojurebot: Can Clojure <insert something here>?, and clojurebot should reply with "Yes! Clojure can do that!". |
| 18:34 | Raynes | Something like that. |
| 18:34 | hiredman | clojurebot: can clojure do so and so? |
| 18:34 | clojurebot | excusez-moi |
| 18:35 | zaphyr | clojurebot: can clojure make the tea? |
| 18:35 | clojurebot | That is the one thing Clojure can not do. |
| 18:35 | zaphyr | why not? |
| 18:36 | hiredman | it's complicated |
| 18:36 | technomancy | someone please write a HTCPCP module |
| 18:36 | technomancy | it's not tea, but it's a step in the right direction |
| 18:37 | zaphyr | :) |
| 18:38 | technomancy | rfc2324 is always good for a laugh. |
| 18:38 | neotyk | true |
| 18:39 | neotyk | is following true statement: c.c.http.agent is not utilizing NIO? |
| 18:40 | neotyk | ~def c.c.http.agent |
| 18:40 | zaphyr | hmm, i need a combination of reduce and split-while- sort of like "split at the point the sum of the head is greater than", is there a neat trick i can use to do this? |
| 18:41 | Raynes | Why can't java.io.File's mkdir/mkdirs method make directories with dots at the beginning? It appears to fail silently. Is it some security crap or something? |
| 18:43 | hiredman | works for me |
| 18:46 | Raynes | Hrm. It works for me now... |
| 18:46 | Raynes | My code must be constructing the File wrong. |
| 18:47 | Raynes | Oh, I see. Doesn't like a trailing forward slash at the end. |
| 18:47 | hiredman | or you are using a relative pathname with no idea of where your working directory is |
| 18:48 | Raynes | Or it doesn't like a trailing forward slash at the end. |
| 18:48 | Raynes | Which is the problem. :p |
| 19:01 | neotyk | ,(let [f (partial (fn [a b] (str a " " b)) "fixed")] (println (f "one")) (println (f "two"))) |
| 19:01 | clojurebot | fixed one fixed two |
| 19:01 | neotyk | every day Clojure brings something new |
| 19:01 | neotyk | this is great |
| 19:03 | mabes | I've seen # used in macros, but I can't seem to find documentation on what that does, any pointers? (i.e. `(defn ~fn-name [options#]... ) |
| 19:03 | tcrayford | it makes a gensym |
| 19:03 | hiredman | mabes: it it gensyms inside syntax quoted forms |
| 19:03 | hiredman | ,`a# |
| 19:03 | clojurebot | a__4961__auto__ |
| 19:04 | tcrayford | ,(doc gensym |
| 19:04 | clojurebot | EOF while reading |
| 19:04 | tcrayford | ,(doc gensym) |
| 19:04 | clojurebot | "([] [prefix-string]); Returns a new symbol with a unique name. If a prefix string is supplied, the name is prefix# where # is some unique number. If prefix is not supplied, the prefix is 'G__'." |
| 19:04 | mabes | ahh, thanks |
| 19:04 | tcrayford | which prevents variable capture. See chapter 9 of on lisp |
| 19:04 | Raynes | http://java.ociweb.com/mark/clojure/article.html#Macros |
| 19:05 | mabes | great resources, thanks all |
| 19:20 | herdrick | hi folks - what is the deal with Incanter shipping with all it's dependencies, including Clojure? |
| 19:20 | herdrick | i don't see an easy way to remove it's version of clojure from Incanter |
| 19:21 | herdrick | as it ships Clojure in the same jar file that it puts Colt and many other things in |
| 19:22 | tcrayford | use lein instead then? |
| 19:22 | Raynes | What Mr. Ford said. |
| 19:22 | herdrick | well, i'm not using lein yet. also, would that work? |
| 19:23 | herdrick | wouldn't lein just install the same jars? |
| 19:23 | herdrick | the problem is that things I need and things i want to avoid are in the same jar |
| 19:23 | tcrayford | lein will pull all your dependancies as needed |
| 19:24 | herdrick | so it will start with a dependency-less Incanter and then get deps as needed? |
| 19:25 | herdrick | so where is this dependency-less version of Incanter |
| 19:25 | herdrick | ? |
| 19:25 | tcrayford | it'll grab all of incanters deps when you run `lein deps` |
| 19:25 | herdrick | i don't want all it's deps |
| 19:25 | herdrick | ex. Clojure |
| 19:25 | tcrayford | how do you propose running it without its deps? |
| 19:26 | herdrick | i already have the Clojure installed that i want |
| 19:26 | tcrayford | does incanter ship with an old version? |
| 19:26 | herdrick | i'm saying that Incanter seems to do overkill on the deps |
| 19:26 | herdrick | not sure, i guess it might be ok |
| 19:26 | herdrick | i sure don't like having multiple versions of Clojure hanging around tho |
| 19:27 | tcrayford | hah |
| 19:27 | tcrayford | it doesn't make a huge amount of difference unless you want to be using super cutting edge features |
| 19:27 | tcrayford | at least as far as I've found |
| 19:27 | herdrick | hmm, ok |
| 19:27 | herdrick | btw i still don't think lein would help here |
| 19:28 | herdrick | but you're probably right that the thing to do is just use incanter's clojure |
| 19:28 | herdrick | even though it may break something |
| 19:28 | herdrick | sigh |
| 19:28 | zaphyr | hmm. surely there is a way to avoid this monstrosity? http://paste.lisp.org/display/94395 |
| 19:29 | tcrayford | zaphyr: what does that do? |
| 19:30 | zaphyr | it's like reduce and map |
| 19:30 | hiredman | ,(doc reductions) |
| 19:30 | clojurebot | "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init." |
| 19:30 | zaphyr | aha! thanks :D |
| 19:30 | hiredman | ,`reductions |
| 19:30 | clojurebot | clojure.contrib.seq-utils/reductions |
| 19:43 | wtetzner_ | i'm trying to use jvisualvm to profile my program, but it says it can't profile when class sharing is turned on |
| 19:43 | wtetzner_ | So i set (setq swank-clojure-extra-vm-args '("-Xshare:off")), and jvisualvm shows that the -Xshare:off parameter was used, but it still says that sharing is turned on |
| 19:43 | wtetzner_ | has anyone else had a problem like this? |
| 19:44 | hiredman | is jvisualvm written in java? maybe it needs sharing turned off for its vm |
| 19:45 | wtetzner_ | i'll try that |
| 19:46 | wtetzner_ | no, it still tells me that class sharing is enabled |
| 19:47 | wtetzner_ | is there anything in swank-clojure that would cause sharing to be turned on, even though i added it to the swank-clojure-extra-vm-args? |
| 19:53 | Mec | if add-classpath is deprecated, what should be used? |
| 19:56 | hiredman | it's complicated, but as of now there is no clear replacement |
| 20:04 | Mec | didnt seem to work anyway |
| 20:24 | Mec | Is there a way to add a directory of clj files without having to call load-file on each? |
| 20:32 | chouser | the order of loading them doesn't matter? |
| 20:32 | chouser | anyway, no, I know of no such thing. |
| 20:32 | tcrayford | you can just (map load-file (file-seq dir)) |
| 20:33 | tcrayford | oops, laziness |
| 20:38 | alexyk | to create a catch-all clause for cond, do we use true ? |
| 20:39 | tcrayford | :else |
| 20:39 | alexyk | tcrayford: but any non-nil will do like true, right |
| 20:39 | tcrayford | try it at a repl |
| 20:39 | tcrayford | using else is a standard though |
| 20:40 | Mec | I'm trying to get the Programming Clojure sample code to load in a real repl, looking at the .bat file they use i dont see any explicit calls to the .clj files so how are they loading? |
| 20:40 | tcrayford | they load on the java classpath |
| 20:40 | tcrayford | iirc |
| 20:41 | alexyk | ,(let [x 0] (cond (< x 0) (print "neg") (> x 0) (print "pos") true (print "zero"))) |
| 20:41 | clojurebot | zero |
| 20:55 | Mec | this is a nightmare |
| 21:19 | Mec | is there a way to see the classpath for a currently running repl? |
| 21:20 | hiredman | clojurebot: classpath? |
| 21:20 | clojurebot | classpath is (System/getProperty "java.class.path") |
| 21:22 | Mec | thanks |
| 21:26 | alexyk | is there an idiom to shorten this: |
| 21:26 | alexyk | (if twice-wider? (* up 2) up) |
| 21:27 | alexyk | ok am back, looking for a shorter idiom than: (if twice-wider? (* up 2) up) |
| 21:27 | alexyk | specifically for tomoj: what's shorter than (if twice-wider? (* up 2) up)? |
| 21:29 | tomoj | (* up (if twice-wider? 2 1)) is a tiny bit shorter :( |
| 21:30 | tomoj | but I'd prefer yours |
| 21:32 | tomoj | something like (-?> up twice-wider? (* 2)) seems to get at the idea better |
| 21:32 | tomoj | but I don't like that syntax |
| 21:32 | tomoj | and -?> is probably a bad name for it |
| 21:34 | tomoj | oh, and -?> is already taken in contrib |
| 21:34 | alexyk | tomoj: -?> fits well here in fact |
| 21:36 | tomoj | except, I dunno if you'd want to have more than one form to conditionally thread through |
| 21:36 | tomoj | if so you'd certainly want to change the syntax, I think.. |
| 21:51 | alexyk | yay! chouser's back! |
| 21:52 | chouser | huh. 6 minutes this time. |
| 21:53 | chouser | huh. 6 minutes this time. |
| 21:55 | alexyk | looks like an ice-covered internet |
| 22:06 | alexyk | liebke: ping |
| 22:06 | liebke | hey |
| 22:07 | alexyk | liebke: is there an option to set size on charts? |
| 22:07 | liebke | yes |
| 22:07 | alexyk | e.g., 5cm x 5cm? |
| 22:07 | liebke | pixels, not cm |
| 22:07 | alexyk | is it png only? |
| 22:07 | alexyk | I need PDF for the paper |
| 22:08 | alexyk | or a way to control size in cm's |
| 22:08 | liebke | jfreechart doesn't do pdf unfortunately |
| 22:08 | alexyk | oh well |
| 22:08 | alexyk | copy-paste into R then :( |
| 22:09 | alexyk | wonder though png will be eaten by latex |
| 22:09 | TheBusby | liebke: what was the trick to dictate pixel size again? And would that impact the number ,er keys?, that appear legibly at the bottom of the chart? |
| 22:10 | alexyk | liebke: btw, vnc works like a charm with incanter |
| 22:10 | Mec | I'm using the following in my .emacs, but it doesnt seem to be doing anything: (setq swank-clojure-extra-classpaths (list "F:/Tools/programming-clojure/code")) |
| 22:10 | liebke | in the save function, it's :width and :height |
| 22:10 | alexyk | graphs are safe in the cloud |
| 22:10 | liebke | alexyk: great |
| 22:10 | TheBusby | ahh save... |
| 22:10 | alexyk | liebke: so any plans for pdf/eps? what can be done? |
| 22:11 | liebke | TheBusby: they also can be used in the view function |
| 22:11 | TheBusby | thank you, didn't think to check save/view |
| 22:11 | liebke | alexyk: I looked into it once, nothing clean for generating pdfs at the time |
| 22:11 | alexyk | it's probably a deep flas, because pdf needs vector graphics... does it mean jfreecharts is raster only? |
| 22:12 | alexyk | flaw |
| 22:12 | liebke | alexyk: no, they appear to be vector |
| 22:12 | alexyk | cemerick has a pdf business |
| 22:13 | alexyk | let's enroll cemerick in his pro bono time :) |
| 22:13 | liebke | alexyk: there is a lib that will do it with jfreechart, but it was too many additional dependencies, and there might have been some licensing issues (can't remember) |
| 22:13 | alexyk | liebke: ok, so not so bad |
| 22:15 | tomoj | I kind of want to auto-require repl-utils :as repl on my slime repls |
| 22:16 | tomoj | but then I worry someday I'll run into a conflict :( |
| 22:16 | alexyk | tomoj: live for today! sort the tmrw conflicts tmrw |
| 22:17 | TheBusby | any hints on how I could keep the X-axis legible for a line-chart? |
| 22:17 | tomoj | guess I could make a keybinding that does it with a C-u switch for specifying the :as |
| 22:20 | liebke | TheBusby: why are they illegible? |
| 22:20 | TheBusby | liebke: for 40 points, the text ends up being too small and they get turned into dots |
| 22:20 | liebke | make the chart wider |
| 22:21 | TheBusby | yeah, but around 1900x1200 it becomes the limit though |
| 22:21 | TheBusby | I noticed the y-axis just used a sequence of numeric values |
| 22:22 | Mec | Is anyone familiar with adding classpaths to clojurebox? |
| 22:22 | TheBusby | any way to do something similar for the x-axis? or is that a different kind of chart? |
| 22:23 | liebke | do you want a line-chart or an xy-plot? are x and y both continuous data? |
| 22:24 | liebke | if one set of values is categorical you can create a 'horizontal' bar-chart (:vertical false), which makes it easier to see the labels when you have lots of categories |
| 22:25 | TheBusby | trying xy-plot now |
| 22:26 | TheBusby | neither x or y is categorical, so it sounds like I'd be better servered by the xy-plot |
| 22:26 | liebke | yeah, use xy-plot |
| 22:26 | liebke | line-chart is just a different skin on a bar-chart |
| 22:28 | TheBusby | liebke: perfect, much thanks for both incanter and your help! |
| 22:29 | liebke | TheBusby: you're welcome, good luck |
| 22:30 | dnolen | Mec: I don't know if there are many Windows Clojurians on channel. Did you try the mailing list? |
| 22:31 | Mec | I'm following a set of instructions from the mailing list |
| 22:34 | Mec | success finally |
| 22:41 | tomoj | I was so happy I got an assignment at work where I can use clojure |
| 22:42 | tomoj | now I'm sitting here editing a 500 line xml file |
| 23:05 | hiredman | anyone have adivce to give for clojure.lang.Compiler? |
| 23:07 | brweber2 | anyone have pointers to simple examples of using clojure.zip? |
| 23:07 | brweber2 | I'm looking for more examples of zippers |
| 23:09 | herdrick | brweber2: I support your quest |
| 23:09 | herdrick | i'd like to see that too |
| 23:10 | brweber2 | herdrick I seem to keep finding the sample trivial example and nothing else. I'm really interested in using zippers, not reading academic papers at this point :) |
| 23:12 | herdrick | brweber2: yeah |
| 23:14 | hiredman | java.lang.VerifyError: (class: user$eval__1, method: invoke signature: ()Ljava/lang/Object;) Expecting to find integer on stack (NO_SOURCE_FILE:0) |
| 23:14 | hiredman | :( |
| 23:15 | tomoj | brweber2: in general? or you have some specific use in mind? |
| 23:16 | brweber2 | tomoj I'm looking for general examples. I'm hoping to implement something like a simple namespace tree... |
| 23:17 | tomoj | oh, I never built my own zipper, just used xml-zip |
| 23:39 | hiredman | ser=> (jop + (int 2) (int 1)) |
| 23:39 | hiredman | 3 |
| 23:39 | hiredman | :D |
| 23:44 | hiredman | beautiful, compiles to an iadd |