2011-06-02
| 00:11 | tomoj | clojure support?? wow |
| 00:18 | kornys | tomoj: yep - see https://gist.github.com/1001206 - it's pretty awesome |
| 00:34 | offby1 | $36/month isn't that bad. |
| 00:34 | offby1 | EC2 micro is a bit cheaper, but not much |
| 00:50 | dnolen | hiredman: ping |
| 00:50 | kornys | offby1: yep, though for a tiny demo app, free would be better :) |
| 00:52 | hiredman | dnolen: pong |
| 00:53 | dnolen | hiredman: I've addressed some but perhaps not all of the issues. LVar and LCons now take metadata for doing custom things. |
| 00:53 | dnolen | hiredman: (unifier '(?x . ?y) [1 2]) (binding-map '(?x . ?y) [1 2]) work for first and rest matching. |
| 00:54 | hiredman | ah, cool |
| 00:55 | dnolen | hiredman: one thing I'm on the fence about is allowing people to directly pass LCons instances to the unifier ... |
| 00:56 | dnolen | hiredman: if you wan to create something that you can spit out from a macro, will emitting (lcons 1 (lcons 2 ...)) not work for you? core.logic also provides convenience macro llist for doing this. |
| 00:56 | hiredman | well, if they have a pre-prepped thing, and the pre-prepping happens to create an LCons |
| 00:57 | hiredman | dnolen: possibly, since you mention prepping is expensive in the readme, and my patter is static at compile time I have the macro do the prepping |
| 00:57 | hiredman | patterns |
| 00:57 | hiredman | are |
| 00:58 | hiredman | since I am not familiar with lcons I went with what seemed like the highest fidelity (pulling the fields and passing them to the constructor again) |
| 00:59 | dnolen | yeah I have to think about LOGIC-7 some more. let me know if (unifier '[(?x . ?y) 3] '[(1 2) 3]) support satisfies 5 & 6. |
| 01:01 | hiredman | seems like it would, but yes, I'll kick it around |
| 01:01 | dnolen | latest is on github and clojars. |
| 03:15 | chouser | there. pushed a very early version of data.xml |
| 03:15 | chouser | Hm, needs a README. https://github.com/clojure/data.xml |
| 03:20 | brehaut | heh "; blame Chouser for anything broken or ugly." |
| 03:22 | brehaut | chouser: is it 1.2 compatible? |
| 05:08 | andrewclegg | chouser: is data.xml fully lazy, i.e. can you parse really big files as a stream of chunks? |
| 05:08 | andrewclegg | v. handy if so |
| 07:48 | manutter | lol, I *so* cheated on 4clojure question #65 |
| 07:50 | manutter | https://gist.github.com/1004288 |
| 07:50 | mrBliss | manutter: quite clever! |
| 07:51 | manutter | I couldn't resist |
| 07:52 | manutter | expect one more function to be added to the Do Not Use list very soon now... |
| 07:56 | tufflax | Does swap! "block" the thread calling swap! until it is successful? Or is it a new thread? |
| 08:35 | chouser | tufflax: swap! spins. It will not return until it is successful. |
| 08:35 | tufflax | ok |
| 08:38 | chouser | andrewclegg: That's the intention, but it needs more testing before I'm willing to claim that. |
| 08:42 | tufflax | I've got a really nasty but on my hands, has to do with java socketchannels. If anyone want to take a look it's here: http://pastebin.com/Xymx9ZgE |
| 08:42 | tufflax | thank you chouser btw :) |
| 08:48 | tufflax | s/but/bug and s/want/wants :p |
| 08:57 | timvisher | hey all |
| 08:58 | tufflax | hi |
| 08:59 | timvisher | I'm trying to serialize a seq to disk in a file using `pr` and then read it back in and I'm encountering `error: java.lang.ClassFormatError: Invalid method Code length 361053 in class file wallpaper_manager_core/core$eval2183` |
| 08:59 | timvisher | My only guess is that it's trying to execute a function because the seq is serialized as `(...)` |
| 09:00 | timvisher | Any thoughts? |
| 09:00 | stuartsierra | What are you using to read it back in? |
| 09:00 | tufflax | Paste the code |
| 09:00 | timvisher | (load-file) |
| 09:00 | stuartsierra | There's your problem. :) |
| 09:00 | stuartsierra | `load-file` means read & eval. You just want `read` |
| 09:00 | timvisher | Ah |
| 09:01 | timvisher | so should I make the file into a string and then call read on it? |
| 09:01 | timvisher | or is there a convenience function for that? |
| 09:01 | tufflax | in that case read-string |
| 09:01 | raek | timvisher: no, 'read' reads from a stream. |
| 09:01 | timvisher | raek: nice! |
| 09:02 | raek | summary: pr and read work on streams (*out* and *in*, which can be rebound with 'binding'), pr-str and read-string work on strings |
| 09:21 | andrewclegg | chouser: I'll test it by throwing some gigs at it and seeing what happens |
| 09:30 | markskil1eck | Any idea why get-datasets for incanter is returning some html? |
| 09:31 | kephale1 | what is the best way to download files w/in clojure (files of arbitrary type incl binary)? |
| 09:32 | kephale1 | a la curl |
| 09:33 | drewr | kephale1: you can do something with (clojure.java.io/reader "http://foo") |
| 09:34 | raek | kephale1: if you don't need to control the headers, the simplest way is probably to pass a URL to clojure.java.io/reader (text) or clojure.java.io/input-stream (binary) |
| 09:34 | chouser | andrewclegg: cool. let me know what you find. Do beware of head-holding, though. |
| 09:34 | kephale1 | drewr & raek: aha! ty |
| 09:35 | drewr | was thinking reader would polymorphically give you an input-stream, but that wouldn't really make sense |
| 09:36 | tufflax | If anyone was trying to figure my bug out, i solved it. |
| 09:36 | raek | kephale1: it is probably a good idea to pass the url string through clojure.java.io/as-url and then verify that the scheme is http or https |
| 09:37 | raek | kephale1: my friends helped me find a bug/feature in my title-printing IRC bot but asking it to look up the title for the URL file:///dev/random |
| 09:38 | raek | s/but/by/ |
| 09:38 | sexpbot | <raek> kephale1: my friends helped me find a bug/feature in my title-printing IRC bot by asking it to look up the title for the URL file:///dev/random |
| 09:38 | raek | tufflax: what caused it? |
| 09:38 | kephale1 | raek: oh good point |
| 09:40 | raek | kephale1: another point: if you want to read text, you specify the encoding of the text (the "file format" of the characters) with the :encoding option: (clojure.java.io/reader url :encoding "UTF-8") |
| 09:40 | raek | if it is left out, UTF-8 will be used |
| 09:41 | kephale1 | cool, i'm mostly going to be shuffling jars around, but might have some text |
| 09:42 | tufflax | raek: I was reading into the wrong buffer. On line 128 in my paste i should have saved the new c in the global *players*, because i was relying on :read-tmp to be set right. Now if I didnt get any more data after reading the length of the message i forgot the new read-tmp and next time read into the buf for getting the lengths |
| 09:47 | tufflax | I gotta come up with a better way to debug my programs. I ran the server in a future, and prints dont show from the new thread. What I ended up doing was conjing debug msgs into a global. btw i tried bound-fn but it didnt help. In other languages ive mostly used prints to debug but it's not very convenient in clojure. is there a good debugger? |
| 09:47 | raek | tufflax: are you using emacs, btw? |
| 09:47 | tufflax | vim |
| 09:48 | raek | the prints should appear somewhere |
| 09:48 | tufflax | not before my eyes ;) |
| 09:48 | raek | in emacs, the repl and stdout are distinct, so prints from the repl thread appears in the repl and prints from other threads appear in stdout |
| 09:49 | raek | tufflax: you could try (intern 'clojure.core '*out* *out*) in the repl where you want the prints |
| 09:49 | tufflax | oh, that explains why bound-fn didnt work |
| 09:49 | raek | this will change the root binding |
| 09:49 | raek | tufflax: strange, bound-fn should work too |
| 09:50 | tufflax | but still, prints is not so convenient, because sometimes one needs to add a (do ... ) or something like that. what do you use for debugging? |
| 09:51 | raek | for stateful code? prints I guess... :) |
| 09:51 | tufflax | hehe |
| 09:51 | raek | for purely functional code, you can always test things in isolation in the repl |
| 09:52 | tufflax | yeah of course, functional is better :p |
| 09:52 | raek | I tend to build a purely functional layer first that does parsing and operations on domain data |
| 09:52 | kephale1 | is there a pretty way to empty an input stream into an output stream? |
| 09:52 | kephale1 | copy into, i should say |
| 09:52 | tufflax | raek did you read my code? any tips on style? |
| 09:53 | raek | kephale1: yes, 'copy' :-) http://clojuredocs.org/clojure_core/clojure.java.io/copy |
| 09:53 | kephale1 | raek: yay, ty again |
| 09:54 | raek | tufflax: I briefly looked though it. I'm not very familiar with how you program using the java.nio classes. my first idea was that this would probably be simpler using a thread/connection and streams |
| 09:55 | raek | but I know that one thread per connection does not scale very well... |
| 09:55 | tufflax | Yeah thats why i didnt want that |
| 09:58 | raek | one advice is to try to limit the number of kinds of side-effects per function |
| 09:59 | raek | for example read-from-client both reads data and changes the atom |
| 10:00 | raek | if it would return the data instead, it would be easier to test it in isolation |
| 10:00 | tufflax | yeah that migth be a good idea |
| 10:01 | tufflax | s/migth/might/ |
| 10:01 | sexpbot | <tufflax> yeah that might be a good idea |
| 10:01 | Cozey | Which Mustache library would you recommend? clostache, stencil, mustache.clj ? |
| 10:01 | raek | in general, try moving state-changing stuff out from functions if possible |
| 10:01 | raek | I think add-new-client is fine here, since it *only* does mutation |
| 10:12 | Cozey | what would you recomment for app configuration? property file? file with clojure code ? |
| 10:13 | abedra | Cozey, it depends on what you are configuring and if that configuration needs to change while the program is running |
| 10:14 | Cozey | i'd say it won't be update by the app, but maybe it would be nice to change the conf and notify an application - do You have something in mind? |
| 10:14 | Cozey | this would actually not be easy to implement in a smart way |
| 10:15 | abedra | Cozey, having a clj file as configuration data makes it a little easier to reach in and modify configuration |
| 10:15 | Cozey | yes |
| 10:15 | Cozey | true |
| 10:16 | Cozey | it would be in lisp philosophy |
| 10:16 | chouser | but not if there are comments in the config file |
| 10:16 | abedra | I tend to use properties files for configuration data that I know won't change |
| 10:16 | abedra | :) |
| 10:17 | oelewapperke | if you know it won't change don't you want the compiler to optimize it out ? |
| 10:18 | abedra | oelewapperke, I mean won't change after it is configured |
| 10:18 | abedra | oelewapperke, I want it to be configurable by others though |
| 10:19 | abedra | that may not know how to edit a clj file |
| 10:28 | tufflax | Does bound-fn only install the bindings in the lexical scope? |
| 10:30 | stuartsierra | bound-fn is for dynamic, not lexical scope |
| 10:31 | raek | tufflax: if I understand it correclty, it should remember the values of the dynamically bound vars in the dynamic scope where bound-fn is called. when the resulting fn is called, the body is evaluated in a dynamic scope with those remembered bindings in place |
| 10:33 | raek | (def *x* 1) (def f (binding [*x* 2] (bound-fn [] *x*))) (f) => 2 |
| 10:35 | tufflax | Hm what are the dynamically bound vars? How come (future-call (bound-fn [] (println "arst"))) prints in my repl but not (future-call (bound-fn [] (fn-which-calls-println))), and not (future (println "asr")) |
| 10:39 | raek | tufflax: vars that are intended to be dynamically rebound are those named with *earmuffs* (there is no need for special naming of constants in clojure, since vars should not be metutaded for maintaining application state) |
| 10:40 | raek | they are often used to as "implicit" arguments to functions |
| 10:41 | raek | e.g. print prints to the stream in *out*. to print to another stream, one temporarily and dynamically rebinds the value: (binding [*out* ...] (print ...)) |
| 10:41 | tufflax | what about earmuffs on global refs and atoms btw? |
| 10:42 | raek | sip them if you don't intend to rebind them with 'binding' |
| 10:42 | tufflax | ok |
| 10:42 | raek | in (def r (ref ..)), r is a constant (it always points to the same ref) |
| 10:42 | tufflax | i see |
| 10:43 | raek | tufflax: anyway, there should be no difference in writing (binding [*out* ...] (print ...)) and (binding [*out* ..] (function-that-calles-print ...)) |
| 10:43 | tufflax | hmm, strange :p |
| 10:44 | raek | ...unless that function was made with bound-fn |
| 10:45 | raek | (boudn-fn* f) can be seen as (fn [& args] (binding [...all the bound vars...] (apply f args))) |
| 10:48 | raek | s/metutaded/mutated/ (in one of my previous lines) |
| 10:49 | tufflax | i made a new fn that prints, and it worked as you described, but not my fns in my pasted code hmm. (yes i evaluated them again) |
| 10:49 | Cozey | Hmm. I'd like to add a template name to a compojure route - so a wrapper function can render route's response with a proper temlate... I thought maybe about using metadata for this, but I'm not sure how to implement this. any ideas? |
| 10:50 | tufflax | maybe it has to do with where they were evaluated... or something :p |
| 10:51 | tufflax | i mean, defined |
| 10:52 | raek | tufflax: yes, bound-fn remembers the bindings from the point where it is evaluated |
| 10:53 | raek | tufflax: also, there are debuggers for clojure: http://georgejahad.com/clojure/cdt.html |
| 10:54 | tufflax | I mean defined as in where the defn of the fn that prints where evaluated, all bound-fns were evaluated in the same repl |
| 11:01 | tufflax | So, to clarify: I write (ns some.ns) (defn test [] (println "dsrtd")) in a file and eval it. Then in the repl in ns some.ns i write (defn test2 [] (println "rst")). Then in the same repl (future-call (bound-fn [] (test))) does not print but (future-call (bound-fn [] (test2))) does |
| 11:01 | tufflax | gotta go afk a bit... |
| 11:08 | raek | tufflax: what does #'test return in the repl? #'some.ns/test or #'clojure.core/yesy |
| 11:08 | raek | *test |
| 11:09 | raek | I think the file was somehow not loaded correctly and you're accidentally using clojure.core/test |
| 11:23 | tufflax | raek #'game.networking/test |
| 11:25 | raek | tufflax: so calling it directly work, but (future-call (bound-fn* test)) does not? |
| 11:25 | tufflax | yup |
| 11:26 | raek | and the body just contains (print "asdf")? |
| 11:26 | tufflax | or wait, that works |
| 11:26 | tufflax | but not (bound-fn [] (test)) |
| 11:26 | tufflax | inside a future |
| 11:26 | raek | oh, of course... |
| 11:27 | tufflax | ? :) |
| 11:27 | raek | (future ((bound-fn [] (test)))) expands to (future-call (fn [] ((bound-fn [] (test))))) |
| 11:27 | raek | the bound-fn ends up beining evaluated in the wwring thread |
| 11:27 | raek | *wrong |
| 11:28 | raek | (let [f (bound-fn [] (test))] (future (f))) should work though |
| 11:29 | raek | maybe it would be nice to have something like (bound-future ...code...) |
| 11:29 | raek | (defmacro [& body] `(future-call (bound-fn [] ~@body))) |
| 11:30 | tufflax | but wasnt that exactly what i did? dont u mean bound-fn*? |
| 11:33 | raek | tufflax: which example? |
| 11:33 | tufflax | the macro |
| 11:34 | raek | tufflax: you said that (bound-fn [] (test)) didn't work inside a future, so I assumed you were doing something like (future ((bound-fn [] (test)))) |
| 11:34 | Cozey | Help! I cannot (require) clojure.contrib.condition - it can't find Condition__init method but it's there in the jar (clojure 1.3). How can I deal with that? |
| 11:35 | raek | Cozey: what toold do you use to start clojure? |
| 11:35 | Cozey | it's cake |
| 11:35 | Cozey | but let me check with normal repl |
| 11:36 | tufflax | raek Sorry for the confusion, what I was doing was exactly what I said when i said "So, to clarify". Also i still have not understood the difference between test and test2 |
| 11:37 | raek | hrm. there shoudn't be any difference between them... |
| 11:37 | tufflax | :p |
| 11:37 | raek | (future-call (bound-fn [] ...))) should do the right thing |
| 11:37 | raek | tufflax: and you can call (test) and (test2) at the repl and both works? |
| 11:38 | tufflax | yes |
| 11:38 | raek | and it's not something basic, like that you forgot to save the file? |
| 11:39 | raek | also, you said this behaves differently when you are are using bound-fn* instead of bound-fn? |
| 11:39 | tufflax | yes |
| 11:40 | tufflax | well |
| 11:40 | tufflax | hmm |
| 11:40 | raek | ,(macroexpand-1 '(bound-fn [] (test))) |
| 11:40 | clojurebot | (clojure.core/bound-fn* (clojure.core/fn [] (test))) |
| 11:40 | tufflax | it gets stranger |
| 11:41 | raek | tufflax: and you didn't miss the parentheses around (test)? |
| 11:44 | tufflax | raek hmm sometimes it works and sometimes not, maybe it's vims fault http://pastebin.com/qT3VXA4Y |
| 11:45 | raek | tufflax: another idea: try using println instead of print (and maybe even add a flush call). maybe this is a buffering issue. |
| 11:46 | tufflax | it is all printlns |
| 11:48 | raek | tufflax: does (defn test [] (println "arst") (flush)) make any difference? |
| 11:49 | tufflax | no, sometimes it still doesnt show up |
| 11:50 | tufflax | im getting tierd of this problem :p |
| 11:50 | tufflax | tired |
| 11:52 | Cozey | raek: some dependency pulled contrib 1.2 - that was the problem i think |
| 11:54 | Dantas | Hi all, reading a nice post about metaprogramming, im wondering what *ns* means (intern *ns* 'hello (fn [] println "Hello World")) |
| 11:57 | andrewclegg | dantas: that's your current namespace |
| 11:57 | raek | Dantas: it's a var that contains a reference to the current namespace of the repl |
| 11:57 | andrewclegg | user=> (in-ns 'clojure.core) |
| 11:57 | andrewclegg | #<Namespace clojure.core> |
| 11:57 | andrewclegg | clojure.core=> *ns* |
| 11:57 | andrewclegg | #<Namespace clojure.core> |
| 11:57 | andrewclegg | etc. |
| 11:58 | tufflax | So a final question about bound-fn; what gets bound in the new function? "bindings in effect" -- things bound with binding? But im not binding anything, and apparently *out* gets bound anyway. Does every regular var count as a binding in effect? |
| 12:03 | raek | tufflax: you didn't bind *out* yourself, but your repl runs inside a binding form that binds it |
| 12:05 | Dantas | raek: andrewclegg : the var symbol is *ns* ?? |
| 12:05 | Dantas | is the var symbol *ns* ? |
| 12:05 | raek | something like (binding [*in* ..., *out* ...] (loop [] (-> (read) (eval) (println)) (recur))) |
| 12:06 | Dantas | thanks |
| 12:06 | raek | Dantas: in the source code, *ns* is an ordinary symbol, just like intern and fn are |
| 12:06 | Dantas | yeah, thank u |
| 12:07 | raek | the symbol names the var #'clojure.core/*ns* |
| 12:08 | raek | just like intern names the var #'clojure.core/intern |
| 12:09 | raek | tufflax: i.e. your repl (but not the threads you start) runs in a dynamic scope where *out* is rebound |
| 12:13 | tufflax | raek ok, so not every regular var counts then |
| 12:13 | tufflax | i guess that makes sense |
| 12:14 | tufflax | raek ok now im gonna get on with my project. thank you very much for always helping me |
| 12:29 | timvisher | is clojure.contrib.logging deprecated in favor of tools.logging? |
| 12:29 | stuartsierra | yes |
| 12:29 | timvisher | awesome |
| 12:30 | stuartsierra | Basically, everything in the monolithic clojure-contrib is deprecated after 1.2 |
| 12:30 | timvisher | what if i'm on 1.2? |
| 12:30 | stuartsierra | up to you then |
| 12:30 | timvisher | so tools.logging should work even on 1.2? |
| 12:31 | stuartsierra | It should, yes. |
| 12:31 | technomancy | timvisher: that's what we're doing |
| 12:31 | technomancy | it's a lot more convenient than contrib.logging |
| 12:37 | mabes | technomancy: why do you find it more convenient? isn't it the same API as contrib.logging? |
| 12:38 | technomancy | mabes: no, it doesn't make you to call format everywhere |
| 12:38 | timvisher | is it easier to set logging levels in tools.logging? |
| 12:38 | technomancy | it takes var-args and makes a string for you |
| 12:38 | technomancy | timvisher: no, that is implementation-dependent. there's no way to do it across all the loggers tools.logging supports. |
| 12:39 | mabes | technomancy: ah, that is nice |
| 12:39 | timvisher | gotcha |
| 12:40 | timvisher | so is this information still relevent if i were to use tools.logging? http://www.paullegato.com/blog/setting-clojure-log-level/ |
| 12:41 | technomancy | probably. I haven't used j.u.logging or apache logging. |
| 12:42 | timvisher | cool. thanks for the help |
| 12:48 | zitchie | list |
| 12:48 | zitchie | ,(defn foo 'adsf') |
| 12:48 | clojurebot | Unmatched delimiter: ) |
| 12:52 | wastrel | hi |
| 14:46 | pdk | ,(/ 1000 16.0) |
| 14:46 | clojurebot | 62.5 |
| 15:01 | gfrlog | (fn [_] (do (foo) (bar))) is redundant, right? |
| 15:03 | wastrel | hi |
| 15:04 | ataggart | gfrlog: the do is redundant, yes |
| 15:15 | gfrlog | ataggart: thanks |
| 15:15 | gfrlog | wastrel: hi |
| 15:18 | wastrel | vampire day massacre |
| 15:18 | wastrel | sorry connection lag |
| 15:27 | bartj | why can't this be done: |
| 15:27 | bartj | (fmap #(+ 1 %) (for [i (range 10)] i)) |
| 15:27 | chouser | what's fmap? |
| 15:28 | hiredman | ,(doc fmap) |
| 15:28 | clojurebot | No entiendo |
| 15:28 | hiredman | clojurebot: jerk |
| 15:28 | clojurebot | No entiendo |
| 15:29 | hiredman | ,(require 'clojure.contrib.generic.functor) |
| 15:29 | clojurebot | java.io.FileNotFoundException: Could not locate clojure/contrib/generic/functor__init.class or clojure/contrib/generic/functor.clj on classpath: |
| 15:29 | hiredman | ,(require 'clojure.contrib.generic.functors) |
| 15:29 | clojurebot | java.io.FileNotFoundException: Could not locate clojure/contrib/generic/functors__init.class or clojure/contrib/generic/functors.clj on classpath: |
| 15:29 | hiredman | bleh |
| 15:29 | hiredman | there is an fmap somewhere in contrib vaguely like that |
| 15:29 | bartj | hiredman, yes, I know |
| 15:29 | bartj | Applies function f to each item in the data structure s and returns |
| 15:29 | bartj | a structure of the same kind. |
| 15:30 | hiredman | bartj: I wasn't pointing it out to you |
| 15:30 | hiredman | (for [i (range 10)] i) is redundant btw |
| 15:31 | hiredman | bartj: I imagine it doesn't work because there is no fmap implemented in that library for seqs |
| 15:32 | bartj | hmm |
| 15:33 | bartj | seems strange though |
| 15:34 | hiredman | fmap is not used very often, so missing functionality is too be exepected |
| 15:35 | bartj | raek, help? |
| 15:35 | stuartsierra | You want ordinary `map` |
| 15:39 | bartj | stuartsierra, yes, I guess, fmap is supposed to be applied to maps, etc only |
| 15:39 | bartj | stuartsierra, but, I am puzzled and curious why it doesn't work in this guess |
| 15:39 | bartj | *case |
| 15:39 | stuartsierra | because the author didn't implement it. |
| 15:40 | stuartsierra | `fmap` and the other c.c.generic stuff never went through a design review. |
| 15:40 | stuartsierra | They're not part of the language. |
| 15:41 | hiredman | bartj: the only real advantage of fmap is it can map over values in maps, most people are likely to just roll their own |
| 15:42 | hiredman | ,(let [a {:a 1}] (zipmap (keys a) (map inc (vals a)))) |
| 15:42 | clojurebot | {:a 2} |
| 15:42 | hiredman | ,(into {} (for [[k v] {:a 1}] [k (inc v)])) |
| 15:42 | clojurebot | {:a 2} |
| 15:42 | hiredman | etc |
| 15:43 | bartj | stuartsierra, thanks! |
| 15:43 | bartj | hiredman, thank you for your time and help |
| 15:45 | zakwilson | I want a library for handling HTTP requests that lets me define handlers with typed arguments and define how the string parameters get converted in to the appropriate types. I don't know of such a thing and expect I'll have to write it myself, but I figured I'd ask first. |
| 15:46 | zakwilson | To give an example of the sort of code I want to write: (defhandler foo [id :int name :string img :file] ...) |
| 15:49 | hiredman | zakwilson: if defhandler is a macro you could just as easily use type hints instead of keywords, fwiw |
| 15:51 | hiredman | and I would suggest just generating a function that takes a map of params or whatever and returns a map coerced to the correct types |
| 15:51 | zakwilson | hiredman: Would type hints work if I wanted to make the type conversions a multifn dispatching on the name of the desired type where the return value might be an arbitrary data structure (e.g. a map representing a database row)? |
| 15:52 | hiredman | zakwilson: oh, the macro would examine the tag metadata on the symbol and do the right thing, it would look like type hints to the user, but they would never make it to the compiler |
| 15:53 | zakwilson | I'm also considering an optional throw-on-null - e.g. (defhandler foo [id [:int :required]] ...) |
| 15:53 | hiredman | that sounds more like validation |
| 15:54 | hiredman | (defvalidator foo ...) (defhandler bar ...) ((comp foo bar) some-request) |
| 15:54 | hiredman | er, reverse those |
| 15:54 | hiredman | (comp bar foo) |
| 15:54 | zakwilson | Yes. I'm not sure if I should conflate validation and ensuring that the handler doesn't have to worry about types in its body. |
| 15:54 | stuartsierra | When in doubt, separate. |
| 15:56 | zakwilson | Some languages treat null checks as part of the type system, and it seems like that might go well with this little island of static typing, but it does sound more flexable to have separate validators that can do anything. |
| 16:04 | zakwilson | The other question that comes to mind for me is whether and how to deal with session variables (sandbar stateful-session). My instinct is to not do it, but it could be kind of cool to have handlers take everything a web request might need to deal with as arguments. |
| 16:06 | hiredman | the functional way to do it would be with the state monad |
| 16:07 | hiredman | but mentioning that tends to make people break out in hives |
| 16:08 | pjstadig | clojure is not a pure functional language, you're free to use vars, atoms, etc. |
| 16:08 | pjstadig | that's why they're there |
| 16:09 | gfrlog | there are still best practices about when to use them though |
| 16:09 | pjstadig | yeah but there is no reason to have to use monads |
| 16:10 | pjstadig | rich took the practical road with concurrently semantic reference types |
| 16:10 | pjstadig | but you're free to use monads too if you want |
| 16:10 | pjstadig | what do i care? |
| 16:10 | hiredman | pjstadig: monads and mutable reference types are orthogonal |
| 16:11 | pjstadig | how so? |
| 16:11 | pjstadig | you're talking about mutable state |
| 16:11 | robbe- | If I make-array an array, and share it amongst thread, the array is copied I presume? i.e. if I want to make changes that should be reflected in other threads, I could use e.g. an array of refs? |
| 16:11 | hiredman | gotta run, rides here |
| 16:11 | robbe- | threads* |
| 16:12 | pjstadig | an array shared amongst threads will need some kind of locking |
| 16:13 | robbe- | That means the array *is* shared amongst threads, and no thread-local copy is made when a thread starts |
| 16:13 | pjstadig | i guess you could use an array of refs, but why not a vector |
| 16:13 | robbe- | right? |
| 16:13 | pjstadig | right no copying unless you do it |
| 16:13 | robbe- | thanks |
| 16:14 | robbe- | Considering alternatives at the moment. :-) |
| 16:15 | robbe- | Ah, I the requirement (not set by me) is O(1) access time, and clojure documentation states: "Vectors support access to items by index in log32N hops." |
| 16:15 | robbe- | Which is still plenty fast, but not constant time. |
| 16:16 | robbe- | And I can't change the requirements because it's a school assignment. :P |
| 16:16 | gfrlog | robbe-: you could argue that it is constant, given bounds on the size of the computer and all that |
| 16:17 | gfrlog | although I suppose by that argument any halting algorithm is constant :-/ |
| 16:17 | robbe- | Indeed, but I expect the assistant to be nitpicking about it. I'll just ask to be sure. |
| 16:17 | gfrlog | clojure is not a good tool for school assignments that are biased against clojure |
| 16:18 | raek | robbe-: I'd say: renegotiate the O(1) requirement to include the practically constant time of clojure's data structures |
| 16:18 | robbe- | Yeah, but you probably mean "not constant but incredibly low bound, which is in this case low enough to be considered constant." or something along those lines. :-) |
| 16:19 | robbe- | Thanks for the advice. :-) Will mail him shortly. |
| 16:19 | raek | for a vector with 2^32 elements, the lookup requires 6 or 7 steps, IIRC |
| 16:19 | gfrlog | robbe-: Also make the case that arrays are not quite constant either due to caching and paging and such |
| 16:19 | raek | and for hash-maps you can't have more than 2^32 distinct hashes |
| 16:20 | gfrlog | raek: what's the collision algorithm? |
| 16:20 | robbe- | gfrlog: <devils advocate> but you can fix that with more ram |
| 16:20 | gfrlog | robbe-: the point is that in practice the distinction is quite murky |
| 16:21 | robbe- | I agree. Just trying to come up with anything he might have to counter the arguments. :-) |
| 16:21 | gfrlog | well I imagine it's his perogative to say "cuz I sed so" |
| 16:22 | robbe- | :D |
| 16:22 | robbe- | Well, I have to go now, it's getting late over here, so I should mail and go to bed. Thanks everyone for the input. |
| 16:23 | gfrlog | enjoy your time zone |
| 16:23 | robbe- | Surely am, 20 past 10 pm and still light outside, I like that. Winter sucks though. :-) |
| 16:24 | gfrlog | enjoy your latitude as well then :) |
| 16:25 | raek | gfrlog: I think it has a special kind of node in the tree for hash collisions that linearly searches through an array of the objects with the same hash value |
| 16:26 | gfrlog | raek: that sounds like it would allow >(2^32) entries then, just with quickly decreasing performance? |
| 16:26 | raek | yeah, that's true |
| 16:27 | pjstadig | yes |
| 16:28 | pjstadig | so if you have a terrible hashing algorithm the data structure is actually log(n) |
| 16:28 | gfrlog | I'd think it'd be O(n) |
| 16:29 | gfrlog | if "terrible" means "worst case" |
| 16:29 | gfrlog | given raek said "linearly searches" |
| 16:30 | pjstadig | hehe |
| 16:30 | pjstadig | oops |
| 16:30 | pjstadig | i meant O(n) |
| 16:30 | raek | gfrlog: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentHashMap.java#L719 |
| 16:30 | raek | https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentHashMap.java#L784 |
| 16:31 | ordnungswidrig | ,(extend Object (ns-resolve *ns* (defprotocol Z))) |
| 16:31 | clojurebot | DENIED |
| 16:31 | ordnungswidrig | (extend Object (ns-resolve *ns* (defprotocol Z)));; this works |
| 16:32 | ordnungswidrig | (extend Object (ns-resolve *ns* (defprotocol Z (x [this]))){:x (constantly 42)}) ;; -> #'user/Z is not a protocol |
| 16:32 | ordnungswidrig | any clues |
| 16:34 | pjstadig | i believe defprotocol returns a symbol |
| 16:34 | pjstadig | not the protocol |
| 16:35 | pjstadig | oh |
| 16:35 | pjstadig | right but you're trying to resolve |
| 16:35 | pjstadig | ah but there is a #' there |
| 16:37 | pjstadig | yeah add an @ in front of the defprotocol |
| 16:37 | pjstadig | err |
| 16:37 | pjstadig | the ns-resolve |
| 16:37 | pjstadig | (extend Object @(ns-resolve *ns* (defprotocol Z (x [this]))){:x (constantly 42)}) |
| 16:37 | ordnungswidrig | pjstadig: thanks, nice catch. |
| 16:56 | TimMc | Well, I wrote a thing to do dynamically scoped "binding" in Java. |
| 16:56 | TimMc | Now I'm passing it around for my coworkers to poke holes in. :-P |
| 17:01 | gfrlog | TimMc: wut |
| 17:06 | raek | TimMc: does it use ThreadLocal? http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html |
| 18:29 | TimMc | raek: InheritableThreadLocal, yeah. |
| 18:30 | TimMc | I'll see if I can get permission to post it -- I coded it on the clock, so by default it is company code. |
| 18:30 | TimMc | My test rig for multi-threaded well-behavedness is amusing. |
| 18:31 | TimMc | gfrlog: try { LocalConfig.push("key", "val"); /* stuff */ } finally { LocalConfig.pop("key") } |
| 19:06 | miwillhite | hey all…anyone got an app running on Heroku yet? |
| 19:58 | miwillhite | hey…I'm trying to run my clojure app with `lein run -m stammer.core` (relevant files: http://pastebin.com/wfQJ3C9c)…but I keep getting the exception in the pastebin…any ideas? (using lein 1.5.2) |
| 20:00 | sritchie | hey all -- what protocol would I extend to cover all sequences? |
| 20:00 | sritchie | I had thought it would be aseq, but this misses vectors |
| 20:01 | hiredman | vectors are not seqs |
| 20:02 | sritchie | I think iterable is what I'm looking for |
| 20:18 | miwillhite | can I access environment variables in clojure? (like RACK_ENV in ruby for example) |
| 20:18 | technomancy | ,(System/getenv "HOME") |
| 20:18 | clojurebot | java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.HOME) |
| 20:19 | miwillhite | awesome thanks! |
| 20:21 | technomancy | sure |
| 20:23 | __name__ | ,(Runtime.getRuntime) |
| 20:23 | clojurebot | java.lang.ClassNotFoundException: Runtime.getRuntime |
| 20:23 | __name__ | ,(Runtime/getRuntime) |
| 20:23 | clojurebot | #<Runtime java.lang.Runtime@12996d6> |
| 20:24 | __name__ | ,((. Runtime/getRuntime availableProcessors)) |
| 20:24 | clojurebot | java.lang.Exception: Unable to find static field: getRuntime in class java.lang.Runtime |
| 20:24 | __name__ | ,((. Runtime getRuntime availableProcessors)) |
| 20:24 | clojurebot | java.lang.Exception: Unable to resolve symbol: availableProcessors in this context |
| 20:24 | __name__ | ,((.. Runtime getRuntime availableProcessors)) |
| 20:24 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 20:24 | __name__ | ,(.. Runtime getRuntime availableProcessors) |
| 20:24 | clojurebot | 1 |
| 20:25 | __name__ | Sorry. |
| 20:42 | TimMc | __name__: You can also privmsg clojurebot |
| 20:43 | __name__ | TimMc: I know. |
| 20:43 | __name__ | I always thought it would work and wanted to share the result. |
| 20:43 | __name__ | #scala's bot still is cooler. |
| 20:43 | __name__ | It gives you 42 :) |
| 20:44 | TimMc | weird |
| 20:52 | korny | hi folks - is there something like partition-by that splits a seq by a boolean fn into two seqs, rather than repeatedly splitting? |
| 20:52 | korny | &(partition-by odd? [1 2 3 4 5 6]) |
| 20:52 | sexpbot | ⟹ ((1) (2) (3) (4) (5) (6)) |
| 20:52 | korny | whereas I'd like ((1,3,5)(2,4,6)) |
| 20:53 | hiredman | ,(group-by odd? (range 10)) |
| 20:53 | clojurebot | {false [0 2 4 6 8], true [1 3 5 7 9]} |
| 20:53 | korny | hiredman: thanks |
| 20:59 | pickles | I am about to tear my hair out over this: (def x [obj obj]), (.method (first x)) -> true, (map '.method x) -> [nil nil] |
| 21:01 | hiredman | do you understand what quoting a symbol does? |
| 21:01 | brehaut | ,(map #(.toString %) [(Object.) (Object.)]) |
| 21:01 | clojurebot | ("java.lang.Object@1c0ae76" "java.lang.Object@fde7ba") |
| 21:02 | pickles | hiredman: i have an idea, but no, i do not |
| 21:02 | brehaut | ,(type 'foo) |
| 21:02 | clojurebot | clojure.lang.Symbol |
| 21:02 | TimMc | ,(type '.method) |
| 21:02 | clojurebot | clojure.lang.Symbol |
| 21:02 | TimMc | grah, I am slow |
| 21:03 | brehaut | pickles: symbols are ifn's, so it can be passed it |
| 21:03 | brehaut | as an argument to map |
| 21:03 | brehaut | ,(ifn? '.method) |
| 21:03 | clojurebot | true |
| 21:03 | brehaut | but its not a handle on a method |
| 21:03 | hiredman | pickles: http://www.apl.jhu.edu/~hall/lisp/Lisp-Quote-Hints.text is written for common lisp, but similar enough |
| 21:04 | brehaut | ,(map 'foo [{'foo 1} {'foo 2}]) |
| 21:04 | clojurebot | (1 2) |
| 21:04 | pickles | when I do (map .terminates? x) i get an exception |
| 21:04 | hiredman | correct |
| 21:05 | TimMc | pickles: .method is a Java interop form |
| 21:05 | hiredman | because the name '.terminates?' is not bound locally or globally to anything |
| 21:05 | TimMc | It can't be passed around. |
| 21:05 | pickles | mmm |
| 21:05 | TimMc | pickles: However, #(.method %) can be. :-) |
| 21:05 | hiredman | (macroexpand '(.foo bar)) |
| 21:05 | pickles | so i need to do a lambda |
| 21:05 | hiredman | ,(macroexpand '(.foo bar)) |
| 21:05 | clojurebot | (. bar foo) |
| 21:05 | pickles | aha |
| 21:05 | pickles | i c |
| 21:08 | pickles | many thanks all |
| 21:08 | pickles | hopefully i'm through being a n00b for the day |
| 21:16 | pickles | rock on, it's working, thanks again! |
| 21:52 | leif-p | Hi. Anyone know how to make clojure.pprint print metadata like (set! *print-meta* true) in the REPL does? |
| 22:21 | crowbar | Can someone please give me feedback on how I'm handling a point in 3d space? I'm currently trying to hold it as a map with {:x 1 :y 10 :z -4}. To simplify creation of a 3d point I have (defn point [a b c] {:x a :y b :z c}). Is this idiomatic? |
| 22:26 | chouser | crowbar: yep, it's fine. Also consider defrecord |
| 22:30 | crowbar | thanks chouser. exactly what I was after. |
| 23:07 | no_mind | I have some functions returning hash maps. I want to add the returned hash-maps to a sequence and return the sequence. How do I do this ? When I try to use concat or conj or cons, the returned sequence breaks hash-map elements into smaller sequqnces, something I do not want |
| 23:08 | hiredman | it means you are doing something that calls 'seq' on your maps |
| 23:08 | hiredman | (seq {:a 1}) |
| 23:08 | hiredman | ,(seq {:a 1}) |
| 23:08 | clojurebot | ([:a 1]) |
| 23:11 | no_mind | hiredman: yes and I want to know how to avois this ? |
| 23:12 | no_mind | hiredman: I want result like this ({:a 1, :b 2} {:c 3, :d4}) where {:a 1 :b 2} and {:c 3, :d 4} are returned from two different functions, lets say abc and xyz |
| 23:22 | bpr | no_mind: (conj existing-sequence (seq hash1 hash2 ...)) |
| 23:23 | hiredman | bpr: nope |
| 23:23 | bpr | ? |
| 23:23 | bpr | then list rather than seq? |
| 23:23 | hiredman | bpr: what does seq do? how many args does it take? |
| 23:24 | bpr | yeah then list |
| 23:26 | bpr | lol, god i feel silly now |
| 23:27 | bpr | hiredman: thanks for pointing that out |
| 23:48 | bdesham | hi all |
| 23:48 | bdesham | I'm trying to write a function like flatten, except that it works with sets instead of sequences |
| 23:48 | bdesham | I came up with this: https://gist.github.com/1005837 |
| 23:49 | hiredman | ,(flatten #{#{:a} #{:a}}) |
| 23:49 | clojurebot | Duplicate key: #{:a} |
| 23:49 | hiredman | bleh |
| 23:49 | hiredman | ,(flatten #{#{:a} #{#{:a}}}) |
| 23:49 | clojurebot | () |
| 23:49 | hiredman | huh |
| 23:49 | bdesham | it works fine, except that I'd like some way to make sure there are no duplicates in the input... for example, (flatten-sets [:a :b :a]) should generate some kind of output that lets me know there's a problem |
| 23:49 | bdesham | hiredman: right ;-) I tried that |
| 23:50 | hiredman | ,(set (remove set? (tree-seq set? seq #{#{:a} #{#{:a}}}))) |
| 23:50 | clojurebot | #{:a} |
| 23:50 | bdesham | ,(filter (complement set?) (rest (tree-seq set? seq (set [:a #{:b} #{:c #{:d #{:e :f} :g}} :h))))) |
| 23:50 | clojurebot | Unmatched delimiter: ) |
| 23:50 | bdesham | damn |
| 23:51 | hiredman | ,(set (remove set? (tree-seq set? seq #{#{:a} #{#{:a}} #{:a :b :c {:d :e :f}}}))) |
| 23:51 | clojurebot | 3 |
| 23:51 | bdesham | ,(filter (complement set?) (rest (tree-seq set? seq (set [:a #{:b} #{:c #{:d #{:e :f} :g}} :h]))))) |
| 23:51 | clojurebot | (:c :g :d :f :e :a :b :h) |
| 23:51 | bdesham | ,(set (remove set? (tree-seq set? seq #{#{:a} #{#{:a}} #{:a :b :c #{:d :e :f}}}))) |
| 23:51 | clojurebot | #{:a :c :b :f :d :e} |
| 23:51 | hiredman | clojurebot: seriously? |
| 23:51 | clojurebot | I don't understand. |
| 23:51 | bdesham | lol |
| 23:52 | bdesham | hiredman: that seems to do the same kind of thing |
| 23:53 | bdesham | but I'd like something that would detect duplicates, no matter how deeply nested they are |
| 23:54 | hiredman | creating a set removes duplicates |
| 23:56 | bdesham | I guess I can check for duplicates at top level with (= v (vec (set v))) |
| 23:56 | bdesham | but I could do that with distinct? just as easily |
| 23:56 | bdesham | hmm... |
| 23:58 | hiredman | sets cannot contain duplicates |
| 23:58 | hiredman | thats what a set is |
| 23:59 | hiredman | ,(conj #{:a} :a) |
| 23:59 | clojurebot | #{:a} |
| 23:59 | bdesham | hiredman: right |
| 23:59 | hiredman | so you cannot possibly check for duplicates in a set, because there will never be any |