2008-11-04
| 00:00 | sohail | my java knowledge is showing... under what situations does -Djava.library.path=/foo not work but export LD_LIBRARY_PATH=/foo work? |
| 00:03 | sohail | hm, being banned from ##java doesn't help me solve this problem either |
| 00:23 | albino | heh |
| 00:24 | sohail | so if I have a.b.c(foo,bar) in Java, what is the cleanest way to write it in Clojure? |
| 00:25 | albino | Is c an instance of a class? |
| 00:31 | sohail | albino, no a function |
| 03:34 | lash | how do i join together a sequence of strings? like php's implode(), python's string.join, etc |
| 03:38 | hoeck | lash: (apply str '("foo" "bar" "baz")) |
| 03:40 | lash | cool. how would i add a space between each one? |
| 03:44 | hoeck | lash: then i would simply use print-str instead of str |
| 03:44 | hoeck | like (apply print-str '("foo" "bar" "baz")) |
| 03:46 | lash | yes, that's a nice way |
| 03:49 | tWip | or you could (apply str (interleave ["foo" "bar" "baz"]) (repeat " "))) |
| 03:49 | tWip | minus one ) |
| 03:49 | hoeck | tWip: (butlast (interleave ... |
| 03:50 | hoeck | had the same idea :) |
| 03:50 | tWip | yeah, that to remove the unnecessary last space |
| 03:52 | tWip | (reduce #(str %1 " " %2) ["foo" "bar" "baz"]) |
| 03:52 | tWip | will work also |
| 04:10 | lash | http://pastebin.com/d1a0d4590 is this a good use for macros? is it correct? seems to work at least :p |
| 04:13 | jdz | lash: that macro is wrong |
| 04:13 | jdz | lash: and yes, that's a case when a macro should be used\ |
| 04:15 | jdz | lash: if you used 'when' instead of 'if' then you'd be ok. |
| 04:21 | hoeck | jdz: are you shure? (if condition expr) works in clojure |
| 04:21 | jdz | hoeck: but there can be more than one expr, right? |
| 04:22 | hoeck | ah, i see, sorry |
| 04:23 | hoeck | i first thought you that macro is wrong because of the if only having a "then" clause |
| 04:23 | hoeck | but its the missing do around body (which the "when" implies) |
| 04:24 | hoeck | r/you/you mean |
| 04:24 | lash | jdz: well, then you'd use "do", right? |
| 04:24 | lash | that's how i figured |
| 04:25 | lash | and with this i get something like unless with an else ;) |
| 04:26 | jdz | lash: building on existing code has many benefits: your code is smaller, you remove code duplication, somebody else smarter than you might have got it right, and you have less ways to get it wrong. |
| 04:27 | lash | yes |
| 04:27 | jdz | lash: writing more code just because you can is a wrong attitude, imo. |
| 04:29 | lash | is it really wrong that my if has the same behaviour as an inverse if? |
| 04:29 | lash | s/my if/my unless/ |
| 04:30 | jdz | lash: if has two branches, so it already is an inverse of itself depending on the ordering of then/else expressions. |
| 04:30 | lash | yep |
| 04:31 | jdz | and there are 'when' and 'unless' in common lisp already, which have defined semantics... |
| 04:31 | lash | did not know :) |
| 04:31 | lash | that's the best argument i suppose |
| 04:31 | jdz | first rule of good software design: somebody somewhere has already writted what you have in mind :) |
| 04:32 | lash | yeah, that's why i was suprised to not find unless in clojure already |
| 04:32 | lash | i haven't used common lisp before |
| 04:32 | jdz | i avoid using it because i always have to pause for a minute or so to figure out what exactly is happening. especially if the condition contains an 'and' or 'or' |
| 04:33 | hoeck | lash: its called when-not |
| 04:33 | lash | i mainly wrote it because i wanted to try to write a macro |
| 04:34 | hoeck | jdz: yeah, i have the same problems with unless, i prefer the verbosity of (if (not )) in this case |
| 04:34 | jdz | hoeck: and i just switch the then/else expressions :) |
| 04:35 | jdz | or sometimes just make it so that the shorter expression comes in the then spot |
| 04:35 | jdz | if the other is relatively long |
| 04:36 | jdz | lash: i hope you learned the lesson that getting macros right is a bit harder than just ordinary functions because you must foresee all the uses of it. |
| 04:40 | lash | jdz: yes |
| 08:29 | jkantz | in common lisp I would do (find-if 'evenp '(1 2 3 4)) ... what's the idiomatic thing to do in clojure? |
| 08:29 | Chouser | that returns true as soon as it finds one? |
| 08:30 | duck1123 | jkantz: I believe filter is what you're looking for |
| 08:30 | AWizzArd | Chouser: yes |
| 08:30 | AWizzArd | ==> 2 |
| 08:30 | AWizzArd | filter is in Common Lisp remove-if |
| 08:30 | Chouser | hm. (first (filter even? [1 2 3 4])) |
| 08:31 | jkantz | ok that works for me |
| 08:31 | jkantz | b/c filter returns a lazy sequence |
| 08:33 | Chouser | jkantz: right |
| 08:34 | Chouser | fewer built in functions is a goodthing |
| 08:37 | AWizzArd | the (first (filter ..)) approach is a bit more "chatty" vs (find-if even? [1 2 3 4]), but also more flexible. |
| 08:42 | duck1123 | you could always write find-if to wrap that up if you find yourself doing it a lot. |
| 08:43 | duck1123 | you could even do a (first-even [1 2 3 4]) |
| 08:45 | gnuvince | what does FIND-IF do? |
| 08:45 | gnuvince | Returns true or false if an element is even? |
| 08:46 | Chouser | gnuvince: apparently it returns the first element for which the pred is true. |
| 08:46 | gnuvince | ah |
| 08:46 | gnuvince | If it had only returned true or false, `some� would've been appropriate. |
| 08:47 | Chouser | yep |
| 08:52 | jdz | there are some, every, notevery and notany in common lisp, too |
| 08:56 | Cark | hey there ... i come with a question |
| 08:56 | Cark | using slime (widows) i can't seem to make the gui examples work |
| 08:56 | Cark | it just hangs |
| 08:56 | Cark | while it works from the *inferior-lisp* |
| 08:57 | Cark | any idea on how to fix this ? |
| 09:01 | hoeck | Cark: have you any examples?, just opening swing frames (using cgrands wonderful javadoc) works here (slime + w2k) |
| 09:03 | Cark | i just copy pasted the temperatur converter example at in a file http://en.wikibooks.org/wiki/Clojure_Programming |
| 09:03 | Cark | then (require 'my-file) |
| 09:05 | Cark | i also tried doing this manually ... you know : import the java classes, then create and setVisible a frame from the repl |
| 09:07 | hoeck | sometimes java windows just don't appear for the first time, or they are hidden behind all other windows |
| 09:08 | Cark | it's not behind a window ... i checked that =) |
| 09:09 | Cark | but yes, once i do it from the *inferior-lisp* it works under slime-repl |
| 09:09 | Cark | just can't do it from slime first or it will lock it |
| 09:09 | hoeck | well, maybe its hidden in other obscure ways |
| 09:09 | Cark | btw i tried the cgrand javadoc and same thing |
| 09:14 | Cark | that wouldn't prevent slime's next prompt to show up |
| 09:14 | hoeck | right |
| 09:23 | SnowBuddy | is it not possible to run a .clj file without pasting into the REPL, or am I just incompetent? ;) |
| 09:24 | gnuvince | SnowBuddy: it is possible |
| 09:24 | gnuvince | SnowBuddy: java -cp clojure.jar clojure.lang.Script foo.clj |
| 09:25 | Cark | or (load-file "my-file.clj") from the repl |
| 09:33 | SnowBuddy | hmm, ClassNotFoundException when I try running it through clojure.lang.script. i think i just don't understand how this stuff is supposed to work |
| 09:33 | Cark | uppercase S in clojure.lang.Script ? |
| 09:34 | hoeck | Cark: i just tried to open a swing frame on windows vista with slime+xemacs+jdk6_10 without any problems except the window doesn't appear on top the first time its opened |
| 09:34 | SnowBuddy | with or without uppercase S, same result |
| 09:34 | Cark | hoeck : there must be some problem with my slime installation ... i'll just open it first from the inferior-lisp |
| 09:34 | Cark | thanks anyways |
| 09:42 | abrooks | clojure-spec looks like a nice example+test mechanism: http://www.bitbucket.org/BestFriendChris/clojure-spec/wiki/Home |
| 09:42 | Chouser | SnowBuddy: you can get a repl, though? |
| 09:43 | SnowBuddy | Chouser: yep, everything works fine interactively |
| 09:43 | Chouser | SnowBuddy: what if you just add a filename at the end of the command-line you use to start the repl? |
| 09:44 | SnowBuddy | same thing, class not found exception on clojure.lang.Repl instead of clojure.lang.Script |
| 09:45 | Chouser | but it must be finding the class when you don't provide a .clj |
| 09:45 | Chouser | can you paste your whole command-line and the whole stack trace? |
| 09:46 | Chouser | at http://paste.lisp.org/new/clojure |
| 09:47 | lisppaste8 | SnowBuddy pasted "Error running script" at http://paste.lisp.org/display/69696 |
| 09:48 | lisppaste8 | Chouser annotated #69696 with "try this instead" at http://paste.lisp.org/display/69696#1 |
| 09:51 | SnowBuddy | Chouser: no errors now, but nothing seems to happen. it pauses for a moment and then goes back to the command prompt |
| 10:12 | Chouser | SnowBuddy: well, what does scratch.txt do? is it supposed to print anything? |
| 10:19 | SnowBuddy | that's it. i wasn't doing anything that would show an effect ^_^ |
| 10:21 | Chouser | i had exactly the same "problem" when I started. |
| 11:03 | kib2 | hi, did someone here played with the Processing backend ? |
| 11:04 | Lau_of_DK | Hi guys |
| 11:05 | Chouser | hi |
| 11:05 | duck1123 | hey Lau_of_DK |
| 11:40 | sohail | any of you guys ever see 2 prints with the same output when you only expected one? |
| 11:41 | tomppa | with SLIME? |
| 11:41 | sohail | tomppa, yes |
| 11:42 | jdz | sohail: are you sure they are both prints? one of them might be the return value of the expression you evaluated. |
| 11:42 | sohail | jdz, pretty sure because this isn't the last statement in the function |
| 11:43 | tomppa | at least some older versions of clojure-slime evaled expressions twice |
| 11:43 | sohail | tomppa, ok I don't think that is my problem |
| 11:43 | tomppa | but I think it has been fixed in the latest versions |
| 11:43 | sohail | well might as well do an update anyway |
| 12:21 | fyuryu | kib2: I played with it |
| 13:05 | tomppa | what is the right way to build paths and filenames in Java? I'd need to have a list of paths and |
| 13:06 | tomppa | then go through them and find if a specific file exists in one of them |
| 13:06 | tomppa | I guess the paths would be URLs |
| 13:06 | Cark | there is the File class i think for that |
| 13:07 | leafw | Chouser: I can't get your pasted jambi example to work |
| 13:07 | leafw | Chouser: http://paste.lisp.org/display/69450 |
| 13:07 | tomppa | Cark, I found it, thanks |
| 13:08 | leafw | Chouser: two errors: first, the *command-line-args* may be null (easy to solve) |
| 13:08 | Chouser | ah, sorry. |
| 13:08 | Cark | tomppa : all-files (. (new File base-path) (listFiles)) |
| 13:08 | leafw | Chouser: second, the .ui file: I made a simple .ui file in the qt designer, but I get this error on the clojure side: com.trolltech.qt.designer.QUiLoaderException: Unsupported language: '', expected 'jambi' |
| 13:08 | leafw | Chouser: should one specify somewhere this "language" option? |
| 13:09 | leafw | Chouser: in the designer, I mean. |
| 13:09 | Chouser | leafw: yeah, I don't know what that's about, but that's why I have the comment in there about editing the .ui file manually |
| 13:09 | leafw | Chouser: oops, should read better myself, thanks. |
| 13:10 | Chouser | someone who knows jambi better should find the "right" way to set the language. |
| 13:10 | leafw | Chouser: ok, that's a small problem, there must be an option among the gazilions somewhere in the designer app. |
| 13:12 | leafw | also fails for silly things like unsupported properties such as Qt::LeftToRight enum for a QMenu widget ... weird |
| 13:12 | leafw | because that's the default |
| 13:14 | leafw | also, I had to explicitly add the LD_LIBRARY_PATH to /usr/lib/jni ... or jambi .so files could not be found. |
| 13:15 | leafw | Chouser: (doc into-array) claims to accept only one argument |
| 13:15 | leafw | Chouser: but your example used (into-array String *command-line-args*), which fails. |
| 13:20 | Chouser | leafw: maybe I have a newerversion of clojure? |
| 13:21 | Chouser | sorry,my space key is failing today. |
| 13:21 | leafw | np |
| 13:42 | lau_ | Has anybody here got the JLine functionality working in Emacs ? |
| 13:44 | leafw | Chouser: also, strangely enough, I can't run the example from the interpreter (gets an exception). But when pasted line by line, it works. |
| 13:44 | Chouser | weird. let me try it again |
| 13:44 | leafw | I mean, from a file as in (load-file "/path/to/file.clj") |
| 13:46 | Chouser | oh! ok. |
| 13:47 | Chouser | works fine for me, with main.clj on the command line or with load-file |
| 13:48 | leafw | weird |
| 13:48 | Chouser | I'm using latest svn clojure -- doesn't seem to have a problem with an empty *command-line-args* either. |
| 13:48 | leafw | also, from the interpreter, if I quit the application and then just run it again with (QApplication/exec), then the UI doesn't show ... and the interpreter is locked. Lots of gotchas. |
| 13:49 | Chouser | proper use of Qt will, I think, require some special thread and/or repl setup. |
| 13:50 | Chouser | the Qt gui functions must be run in the main thread, QApplication should only be exec'ed once, etc. |
| 13:50 | Chouser | these are all well documented in Qt, but not quite as natural as swing. |
| 13:51 | Chouser | ...although apparently swing stuff is supposed to be runin it's own thread as well, it's just not as enforcedas Qt's restriction. |
| 13:51 | leafw | I did Qt in c++ years ago, most faded ... but the native look in ubuntu of the gui is very appealing. |
| 13:52 | leafw | Swing does not enforce anything: one must run it all via SwingUtilities.invokeLater(new Runnable() { ...} ) |
| 13:52 | leafw | which is a pain -- just so it gets executed in the queue of the EventDispatchThread. |
| 13:52 | Chouser | I'm a bit of a Qt fanboy for C++, but very much less so in Java, andeven less than that for Clojure. |
| 13:53 | leafw | Swing is a pain to build guis with --I've done many. Mostly manually, in the end. |
| 13:53 | Lau_of_DK | I think Qt can be used in a very limted scope in Clojure, but it definately has its purposes |
| 13:55 | leafw | unless jdk7 solves the non-native look of java apps, Qt-jambi-java has plenty of future with clojure, Lau_of_DK . |
| 13:55 | Chouser | For me the upsides of Qt in Clojure would include very fast native libraries with good support forhardware accel., integrated opengl with accel, featureful gui designer, well-designed and beautiful-looking multi-language text support. |
| 13:57 | Chouser | downsides: 3rd party lib, including platform-specific downloads, awkward thread requirements, some use of global state (QApplication, for example), and requirement to do have some direct clojure support to handle signals and slots fully and easily. |
| 13:59 | leafw | is there any clojure function to empty the current namespace? |
| 13:59 | leafw | i.e. forget all vars |
| 14:00 | AWizzArd | yes |
| 14:00 | Lau_of_DK | leafw, depends a little on how you look at it. The threading in QtJambi is not very intelligently designed. For instance when you start using slots and signals you'll find out that any fail will drop silently and QApplication will ignore it. That means that if all goes well, no problem, but if/when somethings breaks, you'll never know about it. I expect that for larger apps we'll see concurrency issues and the likes. This might all be fixed, but so far Q |
| 14:00 | Lau_of_DK | t is useful for good looking simple GUIs and such |
| 14:01 | AWizzArd | leafw: (ns-interns 'user) ==> map of all your bindings |
| 14:01 | leafw | woah and now qt java segfaulted the VM ... when trying to re-run a QApplication. |
| 14:01 | Chouser | leafw: you could try: (doseq [n v] (ns-interns *ns*) (ns-unmap *ns* n)) |
| 14:01 | leafw | thanks AWizzArd |
| 14:01 | Chouser | leafw: yeah, you can't do that. |
| 14:01 | AWizzArd | (ns-unmap 'namespace 'yourvar) ==> removes the var |
| 14:02 | leafw | thanks |
| 14:02 | Chouser | leafw: the "right way" to do qt would be to start a new repl prompt in another thread, allowing Qt to "own" the main thread so you don't need to re-run QApplication |
| 14:02 | Chouser | I think. |
| 14:03 | leafw | I see what you mean about requiring some clojure support from within |
| 14:07 | leafw | Chouser: latest svn is what I have, from 6 days ago, and the (into-array String *command-line-args*) fails |
| 14:07 | AWizzArd | To release all your vars you could do something like: |
| 14:07 | AWizzArd | (map #(ns-unmap 'user %) (keys (ns-interns 'user))) where 'user is your namespace |
| 14:08 | leafw | thanks AWizzArd, I figured that one out :) |
| 14:08 | Chouser | AWizzArd: you missed my post? :-) you'd have to watch out that "map" is lazy. |
| 14:08 | AWizzArd | Chouser: I just saw it when scrolling back *sigh* |
| 14:08 | AWizzArd | maybe I need more sleep |
| 14:09 | Chouser | AWizzArd: thanks for ns-interns, though. I only knew of ns-publics which would have been insufficient. |
| 14:09 | AWizzArd | Chouser: btw, good explanation in the GG about Stuarts code with his (map identity map) thing |
| 14:10 | Chouser | AWizzArd: thanks! |
| 14:10 | Chouser | that was a tricky one |
| 14:30 | AWizzArd | about what "Clojure actors" is Rich talking in posting 4 here? http://groups.google.com/group/clojure/browse_frm/thread/2a2b24ffef5d1631/f4c4cdf44d00f70c?tvc=1 |
| 14:31 | Chouser | that's old! |
| 14:31 | AWizzArd | yes |
| 14:31 | Chouser | they're called "agents" now |
| 14:32 | AWizzArd | so with idle actors he means: threads in a threadpool, yes? (not running) |
| 14:33 | Chouser | no, an agent that is not running doesn't have a thread |
| 14:35 | Chouser | when you send an action to an agent (using"send"), the agent either gets a thread from the pool or gets queued up for when a thread is available. |
| 14:44 | AWizzArd | So what does he mean with having millions of agents ideling around? |
| 14:45 | Chouser | an agent is an object. It holds onto a state value. You can have millions of those idle |
| 14:45 | AWizzArd | oh okay, sure |
| 14:46 | Chouser | if you want to change an agent's state value, you send it an action, at which point the action executes on a thread or gets queued up to do so in the future. |
| 14:47 | AWizzArd | Yes, this I fully understand. I was just mislead to think about Erlang having tens of thousands of processes running at the same time, and so came to the idea of threads. |
| 14:48 | AWizzArd | So conceptually Rich just had a collection of some million objects in memory. In this case it were agents, but it could have been numbers as well |
| 14:48 | Chouser | right. I think partof why Clojure uses the word agent is to remind us they're not quite like erlang actors. |
| 14:48 | AWizzArd | yes |
| 14:49 | Chouser | AWizzArd: sure, but agents are not just numbersof course, they have their own semantics. Specifically they manage mutability. |
| 14:49 | AWizzArd | yes, I just wanted to express that it is IMO nothing spectecular of them in a col |
| 14:50 | AWizzArd | It would be nice if they were actually running on a 10mio-Core cpu ;-) |
| 14:50 | Chouser | well, if you had that many cores and that much work to do,they would. |
| 14:51 | AWizzArd | In fact, I could probably easily get billions of those systems to 100% load for my problems |
| 14:51 | Chouser | it's not in itself "impressive" that he's got amillion of them, but when you're designing a solution in some frameworks you'd use athread instead of an agent. |
| 14:52 | AWizzArd | btw, to have millions of them one has to start java with a respective heap size I guess |
| 14:52 | Chouser | having a million threads may not work well, even if they're idle. so by providing agents, clojure lets you deal with a useful abstraction that allows millions. |
| 14:54 | Lau_of_DK | kotarak, good evening |
| 14:54 | AWizzArd | Does java offer some constructs that allow me to fine tune the priority of threads? Maybe I want that some agents get very much cpu time, while others are really not important at all |
| 14:54 | kotarak | hi Lau_of_DK |
| 14:54 | AWizzArd | Moin kota :-) |
| 14:54 | Chouser | AWizzArd: I've no idea. I don't really know Java well. |
| 15:10 | rapido | question: immutable data OK. But is it possible to have immutable functions/code? (or immutable curried functions) |
| 15:11 | rapido | if code is data and data is immutable - why not? |
| 15:11 | wwmorgan | rapido: functions are immutable |
| 15:13 | wwmorgan | eg. (partial + 2) returns a new function and doesn't change + |
| 15:13 | rapido | wwmorgan: good example |
| 15:14 | rapido | wwmorgan: but the top level environment is mutable |
| 15:14 | rapido | the definition of + is mutable |
| 15:14 | AWizzArd | it would be even better if we had currying, so we could say $(+ 2) instead |
| 15:15 | wwmorgan | rapido: not quite. The name + can be changed to refer to a different function (or any value), but if you did (def plus +) and then (def + -) then (plus 2 2) would still be 4 |
| 15:16 | rapido | what does (+ 2 2) mean without an definition of +? |
| 15:16 | rapido | the environment is implicit |
| 15:17 | rapido | to get absolute immutability, the environment should be made explicit in the context of every expression. |
| 15:18 | AWizzArd | rapido: what do you mean by that? |
| 15:18 | wwmorgan | since the underlying functions aren't changing, functions are immutable. I think you're suggesting that it shouldn't be possible to change the value of vars |
| 15:19 | Chouser | clojure isn't tryingto get absolute immutability. |
| 15:20 | Chouser | I think clojure's aiming for minimal and well-managed mutability. |
| 15:21 | gnuvince | Quick announcement: because of my incapability at composing a decent blog post in French, I'll be writing my draft in English and I'll translate to French afterwards. Again, if some people are interested in proof-reading, I'll be posting the link to a draft in the coming days. |
| 15:21 | rapido | Chouser: yes, i know - i'm just theorizing about immutable environments, together with immutable expressions and immutable data :) |
| 15:23 | AWizzArd | rapido: Clojure is a dynamic system. We *want* it to be changable. Only during programming in the repl, or later for administration you would overwrite existing bindings with a (def ...) |
| 15:24 | rapido | naively, immutable code can be achieved with namespaces + version numbers |
| 15:24 | Chouser | rapido: sounds like a poor man's monad. |
| 15:24 | rapido | i want to refer to a specific piece of code that is immutable |
| 15:24 | AWizzArd | And only there those cases it should happen that you overwrite something. You *could* do it anytime, but you *should* not. |
| 15:25 | AWizzArd | rapido: just store that piece of code in a collection |
| 15:25 | AWizzArd | and collect code pieces there |
| 15:26 | rapido | AWizzArd: when i 'overwrite' code i want a new immutable version (just like clojure data) |
| 15:27 | rapido | that maximally shares code 'structure' with the 'overwritten' version |
| 15:28 | wwmorgan | rapido: clojure is a compiled language. Once that code is read in, the S-expressions are no longer retained |
| 15:28 | rapido | it's just an idea |
| 15:29 | rapido | wwmorgan: i know s-expressions |
| 15:29 | danlarkin | clojure code _is_ immutable |
| 15:29 | kib2 | gnuvince : I can help in French if you want to |
| 15:29 | danlarkin | remember code is data |
| 15:29 | AWizzArd | rapido: put the function into a hashmap on which you have a ref and do not use defn instead |
| 15:30 | AWizzArd | or write a macro that puts the functions into a defn for nice usability, but also adds it to a copy of the collection |
| 15:30 | gnuvince | kib2: the words just don't come as easily in French as in English when I write about programming. I'll just get something down in English and do the translation afterward. |
| 15:30 | kib2 | gnuvince : as you want, I suppose it's better for all that you write in English. |
| 15:31 | Chouser | functions are just another data object. In fact, some data objects are also functions. Thus they can be stored in any of the ways other clojure data is stored: immutably in locals, or in the mutable objects var, ref, or agent |
| 15:31 | rapido | danlarkin: what about redefinitions in the top level environment? |
| 15:32 | gnuvince | kib2: I still intend to post the final draft in French: I have not seen any mention of Clojure on any French web site or blog or forum. I would like to stir the interest of the French programmers just a little bit. |
| 15:32 | danlarkin | rapido: that isn't changing code, it's just changing where the variable points to. The old function still exists unchanged (until it gets GCed of course) |
| 15:33 | kib2 | gnuvince : good idea indeed. I saw you were in 'Developpez!' forum, that may be a good idea to start from there. |
| 15:33 | gnuvince | kib2: that's where I want to start. |
| 15:33 | gnuvince | kib2: post something in the Java and Functional Programming sections and see if anyone seems interested. |
| 15:33 | rapido | danlarkin: true - but doesn't that change the definition of all the 'immutable' code that refers to that variable? |
| 15:34 | gnuvince | (I'm guessing I'll have more success in the Lisp forum) |
| 15:34 | AWizzArd | rapido: you can look at some example code here: http://paste.lisp.org/display/69638 |
| 15:35 | AWizzArd | there you will have a basic macro that you could use for making your own, to define functions but keeping their sources |
| 15:35 | wwmorgan | lisppaste8: url |
| 15:35 | lisppaste8 | To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste. |
| 15:35 | danlarkin | rapido: clojure is dynamic, so if I get passed a variable called foo, I'm not getting passed a pointer to a memory location, I'm basically getting passed a name that resolves at runtime |
| 15:35 | kib2 | gnuvince : yes, I think there will be some interest from the FP forum, I don't know about the Java one (and in fact I don't know anything about Java yet) . |
| 15:36 | Chouser | danlarkin: umm... I'm not sure that's quite right. |
| 15:36 | rapido | danlarkin: ok, so it's essentially about variables, not about immutable code/data whatever |
| 15:36 | danlarkin | Chouser: isn't it? |
| 15:36 | rapido | variables that are resolved at runtime defy immutability |
| 15:37 | Chouser | (let [foo (Object.)] (my-fn foo)) ; in this case my-fn is passed essentially a pointer to the Object I created. |
| 15:37 | wwmorgan | rapido: the canonical example is "today". "today" is a name that refers to the current date. The date that it refers to changes |
| 15:37 | Chouser | my-fn doesn't have any way of know it was in any way related to something called "foo" |
| 15:38 | rapido | would it be feasible to make clojure's environment immutable? |
| 15:38 | AWizzArd | rapido: just offer your own version of def |
| 15:38 | AWizzArd | write a macro for that.. it won't allow redefinition |
| 15:39 | AWizzArd | then you would say (defconstant ...) instead of (def ...) |
| 15:39 | AWizzArd | The thing is: you *should* treat (def ..) as if it were a constant |
| 15:39 | Chouser | rapido: if A calls B and I create a new version of B, you want A to continue to behave the old way? |
| 15:39 | AWizzArd | In principle you can use def as you use = in Java |
| 15:40 | rapido | couldn't redefinition copy the old environment to a new environment with the redefinition? |
| 15:40 | AWizzArd | this was explicitly not wanted |
| 15:40 | AWizzArd | in static systems like Haskell or ML it works like that |
| 15:41 | AWizzArd | in their repl you can define a function foo, then bar which calls foo and then redifne foo. Bar will still call the first foo. |
| 15:41 | AWizzArd | Clojure explicitly does not want this. It is a dynamic system. |
| 15:41 | AWizzArd | For administrative tasks you want to be able to override code. |
| 15:42 | rapido | Chouser: yes, i want A to explicitly bind to the new B instead of impliticly |
| 15:42 | AWizzArd | This will allow you to fix bugs in a running computer program without restarting it. |
| 15:42 | AWizzArd | It is regarded as bad style to overwrite functions outside of the repl and you should never do this in principle. |
| 15:43 | AWizzArd | But in Lisp you log in to the computer of your customer and while his program is running you integrate a compiled version of the function that is now patched. |
| 15:43 | rapido | AWizzArd: I understand the practicality of implicit redefinitions - but i work for a bank :) |
| 15:43 | AWizzArd | While you have your customer on the telephone and talk with him you will fix his bug. |
| 15:44 | Chouser | rapido: how would you accomplish explicitly re-binding A? Provide the code for it again, so the reference to B could be resolved to thelatest version? |
| 15:44 | AWizzArd | rapido: then simply store your functions inside a ref. |
| 15:44 | AWizzArd | In a ref on a vector or map I mean |
| 15:44 | rapido | Chouser: A shouldn't be bound to B in the first place |
| 15:44 | AWizzArd | whenever you first touch (get-the-right-one-out-of @your-functions) it will continue to support that version. |
| 15:45 | lisppaste8 | danlarkin pasted "immutable code/data" at http://paste.lisp.org/display/69712 |
| 15:45 | AWizzArd | this is MCC, Clojures Multiversion Concurrency Control system |
| 15:45 | rapido | if A refers to B this should be resolved against a specific version of the environment |
| 15:46 | rapido | i mean: A shouldn't be bound to a specific version of B |
| 15:46 | lisppaste8 | wwmorgan pasted "IOW, rapdio: this is NOT what you want" at http://paste.lisp.org/display/69713 |
| 15:46 | Chouser | rapido: I'm not following you -- that sounds like the opposite of what you were asking for before. |
| 15:48 | rapido | env1 -> (A -> B B) (B -> 1) |
| 15:48 | rapido | ooops |
| 15:48 | rapido | env1 -> (A=B B) (B=1) |
| 15:49 | rapido | damn it: smileys get in the way |
| 15:49 | AWizzArd | I see no smileys |
| 15:50 | Chouser | me neither |
| 15:50 | rapido | env1 = (A=B B, B=1) |
| 15:50 | rapido | env2 = (A=B B, B=2) |
| 15:50 | rapido | env1 and env2 share the defintion of A |
| 15:50 | rapido | env1 and env2 differ in the definition of B |
| 15:50 | AWizzArd | yes, you want the same thing that ML or OCaml are doing |
| 15:51 | rapido | but ML nor OCaml shares (immutable) structure between env1 and env2 |
| 15:52 | AWizzArd | Well, you got some suggestions how to solve this in Clojure. It's now your choise what you will do |
| 15:53 | AWizzArd | choice even |
| 15:55 | rapido | AWizzArd: thanks - i'm going to try your suggestion: the redefinition of def |
| 15:56 | wwmorgan | rapido: you actually can't redefine def, because it's a special form |
| 15:56 | Chouser | rapido: note that clojure hash-maps have specifically the sharing of common entries that you seem to desire for the "environment" |
| 15:56 | AWizzArd | but in your own namespace you can offer a new version of def |
| 15:56 | AWizzArd | or call it defconstant |
| 15:58 | rapido | AWizzArd: let me try to hack it - and see if i can achieve it in plain clojure (no java source hacking) |
| 15:59 | duck1123 | is it possible to set up some sort of security policy where re-definition would not be allowed? |
| 15:59 | AWizzArd | sure, this is possible |
| 15:59 | duck1123 | you would ruin the power of the repl, but that's what you get |
| 16:00 | AWizzArd | It's against the Clojure way to solve thins and more MLs way of doing it. But with some macros you can integrate that behaviour into Clojure as well and let it seem more natural. |
| 16:01 | rapido | got to run, later... |
| 16:02 | duck1123 | truthfully, if you lock it down properly, someone who has access to the repl, probably has access to do other nasty things to the system anyway. |
| 16:04 | AWizzArd | yes |
| 16:04 | AWizzArd | seems there is no 100% safety |
| 16:04 | Chouser | clojure doesn't have features to protect against malicious code |
| 16:04 | Chouser | you can switch to the clojure namespace and wreak havok |
| 16:05 | AWizzArd | in the real world you are not supposed to drive into trees with your car, but in principle you *could* do it |
| 16:05 | AWizzArd | (probably not very often though, if you are not really slow) |
| 16:05 | Chouser | but it's pretty good about helping you avoid doing bad things. |
| 16:09 | AWizzArd | Why does (take 8 fac) result in a stackoverflow for (def fac (lazy-cat [1 2 6 24 120] [(* (last fac) (inc (count fac)))])) ? |
| 16:09 | AWizzArd | at the same time I can (def fac [1 2 6 24 120]) and in the repl repeat (def fac (assoc fac (count fac) (* (last fac) (inc (count fac))))) a few times without problems |
| 16:12 | gnuvince | Wouldn't it be easier to do: (def fact [x] (reduce * (range 1 (+ 1 x)))) (def facts (map fact (iterate inc 0))) ? |
| 16:13 | wwmorgan | AWizzard: for the same reason that (def foo (lazy-cat [4] [(last foo)])) generates a stack overflow |
| 16:13 | Hun | that's a pretty stupid algorithm. it throws away the precomputed factorials |
| 16:16 | AWizzArd | gnuvince: I was thinking about (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs)))), so, doing it without defn |
| 16:16 | wwmorgan | I think what you're looking for is (def facts (lazy-cat [1] (map * facts (iterate inc 1)))) |
| 16:17 | gnuvince | AWizzArd: ok. |
| 16:18 | AWizzArd | wwmorgan: why can fibs continue appending numbers to the vector although it does not produce an infinite sequence? |
| 16:19 | wwmorgan | AWizzArd: because lazy-cat, map, and drop are lazy |
| 16:19 | AWizzArd | oh okay, drop is lazy too |
| 16:20 | AWizzArd | didn't look into its doc, sorry |
| 16:38 | AWizzArd | gnuvince: using a lazy sequence has the advantage of automatic memoization. So if (time (nth lazy-seq 10000)) takes 10 seconds, then (time (nth lazy-seq 10001)) will only take one msec. And every access between 0 and 10k will return immediate results |
| 16:40 | AWizzArd | But you could also write a macro for memoization... (memoize my-function)... and from then on a call to my-function will return its result immediately when called with the same arguments as before. |
| 16:40 | AWizzArd | Peter Norvig showed this in 1990 in his book, which is btw one of the very best about programming in general |
| 16:41 | Lau_of_DK | Theres a memoize in Clojure.contrib |
| 16:41 | AWizzArd | great |
| 16:41 | Lau_of_DK | But Wizkid, are you sure that lazy is auto memoized ? |
| 16:41 | AWizzArd | I wanted to suggest anyway to have that |
| 16:42 | AWizzArd | yes Lau, see: (def sum (lazy-cat [0] (map + sum (iterate inc 1)))) and then: (time (nth sum 80000)) needs 522 msecs for me. But (time (nth sum 81000)) is done within 24 msecs |
| 16:42 | Lau_of_DK | ok cool |
| 16:42 | Lau_of_DK | I just noticed a tremendous slowdown as you parse further and further down the lazy seq |
| 16:42 | Lau_of_DK | So much that I had to abandon that approach entirely for certain calculations |
| 16:43 | AWizzArd | and it comes with the disadvantage of eating up your ram |
| 16:48 | AWizzArd | Lau_of_DK: do you have an example for the tremendous slowdown at hand? |
| 16:48 | Lau_of_DK | No sorry Im on my Work PC atm |
| 17:45 | AWizzArd | is there something like (Math/pow ..) that returns BigDecimals? |
| 17:46 | Lau_of_DK | (.pow (Bigint %) %) |
| 17:46 | Lau_of_DK | (bigint, not Bigint) |
| 17:48 | AWizzArd | hmm, (Math/pow (bigint 3) (bigint (Math/pow 3 3))) ==> 7.625597484987E12 and not 7625597484987 |
| 17:48 | Lau_of_DK | .pow |
| 17:48 | Lau_of_DK | user=> (.pow (bigint 3) (.pow (bigint 3) 3)) |
| 17:48 | Lau_of_DK | 7625597484987 |
| 17:54 | Lau_of_DK | AWizzArd, you got it? |
| 17:58 | lisppaste8 | AWizzArd pasted "how to convert to bigints?" at http://paste.lisp.org/display/69721 |
| 17:59 | AWizzArd | no Lau, I can't use .pow but only Math/pow instead |
| 17:59 | AWizzArd | .pow is unknown |
| 18:00 | Lau_of_DK | Get the latest version then |
| 18:00 | AWizzArd | I have the one from Oct. 29 |
| 18:01 | Lau_of_DK | You must have done something with the namespace |
| 18:01 | Lau_of_DK | Its standard |
| 18:01 | Lau_of_DK | Anyway, gotta hit the sack, as you saw, it worked on mine, which is the latest :) |
| 18:01 | wwmorgan | my guess, AWizzArd, is that you're not passing an int to pow |
| 18:02 | AWizzArd | (.pow 2 4) ==> java.lang.IllegalArgumentException: No matching method found: pow for class java.lang.Integer |
| 18:03 | wwmorgan | (.pow (bigint 2) 4) |
| 18:06 | AWizzArd | I see |
| 18:06 | lisppaste8 | wwmorgan annotated #69721 with "another way to do it" at http://paste.lisp.org/display/69721#1 |
| 18:07 | wwmorgan | although I'm not quite sure what graham's number is so the math might be wrong |
| 18:07 | wwmorgan | it sure grows fast, though |
| 18:08 | AWizzArd | wwmorgan: yes.. but this is even not grahams number |
| 18:08 | AWizzArd | for x=4 it explodes already |
| 18:08 | wwmorgan | is that right? |
| 18:08 | AWizzArd | yes |
| 18:09 | AWizzArd | Ackermanns function is a bad joke in comparison ;-) |
| 18:09 | wwmorgan | well. That's not a very useful function then |
| 18:09 | AWizzArd | it is very useful |
| 18:09 | AWizzArd | it's used for a mathematical proof |
| 18:10 | AWizzArd | and it (Grahams Number) holds the record of being the biggest number ever used in a meaningful proof |
| 18:10 | wwmorgan | I mean compared to (def grahams-number-test [3 27 7625597484987]) |
| 18:10 | AWizzArd | ah okay ;-) |
| 18:27 | AWizzArd | OT but funny: http://andrewsullivan.theatlantic.com/the_daily_dish/2008/11/a-different-rac.html |
| 18:32 | AWizzArd | Again OT, but even funnier: a voting machine elected itself to be next president: http://www.theonion.com/content/node/89550 ;-) |
| 18:32 | AWizzArd | There is definitly some AI around in these voting machines. Probably programmed in Clojure |
| 20:01 | kwatford | Beta is out for Programming Clojure: http://www.pragprog.com/titles/shcloj/programming-clojure |
| 20:03 | duck1123 | sweet |
| 20:05 | gnuvince_ | yay! |
| 20:06 | duck1123 | I wish I wasn't so broke right now, or I'd buy it now |
| 20:08 | kwatford | It does still have a bunch of empty chapters, so probably no need to rush |
| 20:09 | Chouser | kwatford: you bought it already, eh? pretty cool. |
| 20:10 | kwatford | Yeah, I've been itching to use my praprog coupon. |
| 20:12 | Chouser | nice |
| 20:13 | duck1123 | kwatford: how did you get a coupon? |
| 20:15 | kwatford | People who have purchased books from them recently got coupons for their anniversary celebration. |
| 20:42 | AWizzArd | n8 |
| 20:58 | Drakeson | how do you serialize/pickle? python has cPickle.dump(...,fd). Is there an easy way to serialize into an XML or S-expr file, and also do the reverse? |
| 21:02 | Chouser | prn and read |
| 21:03 | Drakeson | is there a with-open-file? |
| 21:04 | Chouser | there's a with-open |
| 21:05 | Chouser | but it doesn't open a file, it just closes it at the end of the block |
| 21:06 | Drakeson | Is it what we should use when we open and close files (in addition to something that actually opens the file)? |
| 21:07 | Chouser | yep |
| 21:08 | Drakeson | good. thanks :) |
| 21:08 | Chouser | files, urls, sockets, anything with a .close method. |
| 21:09 | kwatford | I believe it closes the object almost always, yes? |
| 21:10 | Chouser | it calls the .close method of whatever you've got. |
| 21:11 | Drakeson | is it possible to compile .clj's into bytecode? |
| 21:11 | Chouser | it's the only way it works. there is no interpreter |
| 21:13 | kwatford | Right, but does it *guarantee* that it calls .close (in all reasonable situations)? The API page mentions a finally block, so I'm assuming it does. |
| 21:13 | Drakeson | I mean, can I get a compiled file/directory as a way to deployment on an inferior platform? |
| 21:13 | Chouser | kwatford: ah, yes. |
| 21:13 | Chouser | Drakeson: ah, to a .class file. Around here we call that AOT compilation, and it as of today: no |
| 21:14 | Chouser | but it's in the works, should be available before too long. |
| 21:14 | kwatford | Drakeson: You can produce a jar file with clojure and your cljs in it. Haven't tried it though. |
| 21:16 | Drakeson | kwatford: but the cljs need to be compiled on the inferior machine as well |
| 21:17 | Drakeson | What are the important options for a web application server? Are there many good ones? |
| 21:17 | kwatford | Drakeson: That's ok, since you can put clojure in with them, and it is small. A stub main class can launch the script. |
| 21:18 | Chouser | Drakeson: yes. as of today, you can bundle up a .jar with everything you need, as long as the target has a "regular" JVM. |
| 21:18 | Chouser | but if you need .class files to convert them to something else, for example to run on an Android phone, you can't do that without AOT |
| 21:19 | sohail | are there any android phones? |
| 21:19 | kwatford | yes, the G1 from T-mobile |
| 21:21 | sohail | is it out? |
| 21:21 | sohail | can I buy it? |
| 21:21 | sohail | can I hack it? |
| 21:21 | sohail | seriously? I hate iPhone |
| 21:21 | Drakeson | I have to build the target myself. Is Jetty a good option? |
| 21:22 | Drakeson | (I have no idea what are popular/good java based web servers) |
| 21:22 | kwatford | sohail: http://www.t-mobile.com/shop/phones/Cell-Phone-Detail.aspx?cell-phone=T-Mobile-G1-with-Google-Black |
| 21:27 | RadioApeShot | Anyone else using compojure? |
| 21:27 | RadioApeShot | Or have experience with jetty? |
| 21:27 | albino | Drakeson: I have a friend who like Jetty and Tomcat both a lot |
| 21:28 | duck1123 | RadioApeShot: I am using compojure |
| 21:28 | RadioApeShot | So where should I put my stylesheets? |
| 21:29 | RadioApeShot | I can't seem to make my pages see them. |
| 21:29 | duck1123 | do you read the mailing list |
| 21:29 | RadioApeShot | Not actively |
| 21:29 | duck1123 | there was just recently a thread about this |
| 21:29 | RadioApeShot | I have searched (via google) for compojure and stylesheets |
| 21:29 | RadioApeShot | But had no luck |
| 21:30 | RadioApeShot | Can you give me a link? |
| 21:30 | duck1123 | http://groups.google.com/group/compojure/browse_thread/thread/c2dae4830ac04008 |
| 21:30 | RadioApeShot | duck1123: Thanks. |
| 21:30 | duck1123 | the method should be the same for stylesheets |
| 21:33 | RadioApeShot | Excellent |
| 21:33 | RadioApeShot | I will see if I can make it work |
| 21:34 | duck1123 | np |
| 21:36 | duck1123 | RadioApeShot: I don't know how much you've done, but have you been finding you need the request object in many of your page view fns? |
| 21:36 | duck1123 | I'm trying to get support for making request/response thread-local, but my experience may be atypical |
| 21:37 | RadioApeShot | I haven't implemented very much yet |
| 21:37 | RadioApeShot | Just a very basic skeleton |
| 21:37 | RadioApeShot | I am not that experienced with the web. |
| 21:37 | RadioApeShot | I put together a rails app while back |
| 21:37 | RadioApeShot | But that is about it |
| 21:38 | RadioApeShot | I am more of a scientist by trade. |
| 21:38 | duck1123 | so far the only things I've really gotten done is basic CRUD operations, and OpenID authentication |
| 21:39 | duck1123 | I only work on it when I have free time |
| 21:39 | RadioApeShot | I am not even sure what CRUD stands for |
| 21:39 | RadioApeShot | I have this super simple project I am doing more for fun than anything |
| 21:39 | RadioApeShot | I am really glad to have found Clojure |
| 21:39 | duck1123 | Create Read Update Delete |
| 21:40 | RadioApeShot | I am pretty sure Clojure is a Lisp I will basically stick with from here out. |
| 21:40 | RadioApeShot | Common Lisp is too old and crusty |
| 21:43 | arohner | do clojure maps implement java maps yet? |
| 21:45 | Chouser | arohner: yes |
| 21:46 | Chouser | since Oct 6 |
| 21:49 | arohner | cool, thanks |
| 21:49 | arohner | is there any easy way to figure that out? I remember reading the discussion on the mailing list, but didn't remember if it ever made it in |
| 21:50 | Chouser | the way I just did it was using git log and searching for "java.*map" |
| 21:51 | duck1123 | isn't there a implements? type call in java? |
| 21:51 | Chouser | but that was to get the date |
| 21:52 | Chouser | (supers (class {})) |
| 21:52 | Chouser | or for your specific question: ((supers (class {})) java.util.Map) |
| 21:53 | Chouser | or yes, (instance? java.util.Map {}) |
| 21:54 | arohner | very cool, thanks |
| 22:25 | arohner | is there a way to cast a java.util.Map that is a generic? |
| 22:25 | arohner | i.e. java.util.Map <String,Object> |
| 22:25 | Chouser | just ignore the generic part. It'll work. |
| 22:26 | arohner | sorry, is there a way to pass a clojure map to a function that expects a Generic map? |
| 22:26 | duck1123 | coerce ? |
| 22:26 | Chouser | you shouldn't have to do anything special. |
| 22:27 | Chouser | just make sure the actual keys in your clojure map are Strings, and you should be able to pass it right in. |
| 22:28 | arohner | hrm. ok. maybe I'm doing something else wrong |
| 22:28 | kwatford | Are you passing it in from the Clojure side or the Java side? |
| 22:29 | arohner | yeah, looks like I was doing something else stupid. misreading the javadocs of the API I was calling |
| 22:29 | arohner | kwatford: I was creating a clojure map and trying to pass it to a java function |
| 22:30 | kwatford | Right, but that doesn't tell me what language you're doing it from |
| 22:33 | arohner | oh, I was creating a clojure map literal in clojure |
| 22:35 | kwatford | I assumed so, but having to juggle generics made me wonder |
| 22:48 | wwmorga1 | is metadata attached to the Symbol or the Var? |
| 22:49 | kwatford | to the object |
| 22:53 | wwmorga1 | what about when you do (defn #^{:a :b} foo [] 1) |
| 22:56 | kwatford | Both the function and the symbol foo are objects, but it doesn't look like either of those have the metadata you're trying to put on. |
| 22:57 | wwmorga1 | you have to do ^#'foo to get at it. Alternatively (meta (var foo)) |
| 22:57 | kwatford | ah, right |
| 22:58 | kwatford | in that case, it's on the function, not the var or the symbol |
| 22:58 | wwmorga1 | So it looks like the metadata is attached to the Var, but the documentation says metadata is associated with symbols & collections only |
| 22:58 | kwatford | I think |
| 22:58 | kwatford | hmm, maybe not. |
| 22:59 | wwmorga1 | it isn't attached to the function, else ^foo would work |
| 22:59 | kwatford | yeah, gotta be the var then |
| 22:59 | Chouser | when you def a var and attach metadata, yes, it goes on the var |
| 23:00 | wwmorga1 | that's what I thought, but this recent post on the google group has thrown me for a loop |
| 23:00 | Chouser | (def foo #^{:a :b} []) |
| 23:00 | Chouser | that attaches to the val: ^foo |
| 23:03 | sohail | Chouser, what is making you sad |
| 23:03 | kwatford | hmm, should (def foo #^{:a :b} (fn [] 1)) put the metadata on the function? |
| 23:04 | wwmorga1 | kwatford: functions can't have metadata. Only collections, and symbols and/or vars can |
| 23:05 | wwmorga1 | I think I'm just going to have to wait for someone smarter than me to answer the question |
| 23:05 | kwatford | Ah. That explains why it didn't work the last time I wanted to do that, but why? |
| 23:07 | wwmorga1 | that's a language design choice that I don't quite understand. I'm sure rhickey has explained it before |
| 23:08 | kwatford | I wonder how non-helpful a search for "metadata on functions" on the list would be... |
| 23:13 | Chouser | sohail: non-clojure, and therefore off topic. :-) |
| 23:14 | sohail | Chouser, nonsense, if clojure can't save the world, there is no hope |
| 23:14 | Chouser | :-) |
| 23:22 | arohner | one thing I find amusing and slightly annoying about working in clojure: |
| 23:22 | arohner | I've found that using clojure to call the java API of some libraries is *less* verbose than their usual XML configuration |
| 23:23 | arohner | except that the java guys all expect that you want to use the XML interface, so the programmatic way is usually poorer documented than the XML way |