2011-06-09
| 00:05 | jtszzzzz | dnolen, Here is what I am going for https://gist.github.com/1016032 |
| 00:20 | dnolen | jtszzzzz: does Submission have a fixed number of fields? |
| 00:20 | Scriptor_ | Hi everyone |
| 00:21 | jtszzzzz | dnolen, I don't intend to use Submission anymore. Sorry for confusion. I just intend to return a map keyed by the provided key on the FieldSpec |
| 00:22 | dnolen | jtszzzzz: I think your gist is too much context, a smaller complete example of what you want to do would helpful. |
| 00:22 | dnolen | jtszzzzz: but so far I'm suspecting you don't need a macro. |
| 00:29 | jtszzzzz | dnolen, I just added a Generalized.clj to that gist. This should really boil it down to the guts of the problem |
| 00:32 | justinko | I just created a new project via lein and added a function. How can I call that function in "lein repl"? |
| 00:33 | dnolen | jtszzzzz: so the issue is you need to create those keys based on the # of lists? |
| 00:33 | jtszzzzz | yes, and i need the let bindings based on the number of lsits |
| 00:33 | jtszzzzz | and the args into the map based on the number of lists |
| 00:38 | jtszzzzz | justinko .. you need to load your namespace .. do something like (require 'myproject.core) |
| 00:40 | jtszzzzz | then you can navigate to your namespace like this (ns myproject.core) |
| 00:41 | justinko | jtszzzzz: that worked, thanks |
| 00:41 | jtszzzzz | np |
| 00:41 | dnolen | jtszzzzz: https://gist.github.com/1016073 |
| 00:43 | justinko | jtszzzzz: just found out I can add ":main my-poject.core" to project.clj to automatically hop into that namespace |
| 00:44 | justinko | jtszzzzz: now is there a "reload" type function that reloads the clj source code? |
| 00:44 | justinko | for the repl |
| 00:46 | technomancy | justinko: (require 'foo.bar :reload) |
| 00:46 | jtszzzzz | dnolen, reading this now! |
| 00:48 | justinko | technomancy: thanks! |
| 00:52 | technomancy | np |
| 00:53 | jtszzzzz | dnolen, thanks a lot. That is really nice. I think this will work good for what I am doing! |
| 00:54 | dnolen | jtszzzzz: https://gist.github.com/1016088 another version that avoid metadata cleverness. |
| 00:57 | dnolen | jtszzzzz: update the last one for readability (IMO) |
| 00:57 | dnolen | s/update/updated |
| 00:57 | sexpbot | <dnolen> jtszzzzz: updated the last one for readability (IMO) |
| 00:58 | jtszzzzz | i like it! |
| 01:10 | justinko | omg you can define a :test metadata for inline tests? That is awesome. |
| 01:10 | justinko | do any of you guys actually use it? |
| 01:10 | justinko | or do you stick with the /test directory? |
| 01:20 | dnolen | justinko: I think usage was common in the early days when no tooling, now most people use maven or lein with /test dir. |
| 01:20 | dnolen | cake too |
| 03:29 | Dranik | hello all! |
| 03:29 | Dranik | I have a question |
| 03:29 | Dranik | I have the following variable: (def my (ref {:a 1, :b 2})) |
| 03:30 | Dranik | And I wanna a reference from inside the hash-map to my |
| 03:30 | justinko | nathanmarz: I just read your interview on geektalk |
| 03:30 | Dranik | (dosync (alter my assoc :c my))) |
| 03:31 | Dranik | but this leads to stack overflow |
| 03:31 | Dranik | is there a way to make a cyclic reference {:c my} inside 'my' ? |
| 03:33 | nathanmarz | justinko: cool |
| 03:33 | hoeck | Dranik: no, not with immutable maps |
| 03:33 | Dranik | hoeck: I need a mutable map |
| 03:33 | Dranik | that's why I use ref |
| 03:34 | hoeck | Dranik: right, but the map is still immutable |
| 03:34 | Dranik | hoeck: is there at least any way to do that? even not idiomatic? |
| 03:34 | hoeck | the :c key would have to be a ref too |
| 03:34 | Dranik | no, I've tried this also |
| 03:35 | Dranik | probably I should have used a common Java map... |
| 03:37 | hoeck | Dranik: having a ref in the map works, but can be kind of clumsy |
| 03:38 | hoeck | Dranik: when you use plain java maps, you loose the threadsafety and other guarantees of clojure maps |
| 03:38 | Fossi | probably you need to tell us more about your real problem |
| 03:39 | Fossi | then maybe somebody gcan tell you what would be idiomatic ;) |
| 03:39 | Fossi | what you are currently trying to do sounds like a huge mess to me tbh :> |
| 03:41 | hoeck | Fossi: circular datastructures are not that uncommon |
| 03:41 | Fossi | yes |
| 03:41 | hoeck | Fossi: well, maybe in the land of functional languages |
| 03:41 | Fossi | but this instance sounds messy |
| 03:42 | Fossi | esp with mutability and all |
| 03:42 | Dranik | Fossi: I'm impoementing a scheme interpreter in clojure using chapter 4 of SICP |
| 03:42 | Dranik | I need this cyclic reference when I create a procedure |
| 03:43 | Dranik | I define a binding for the body of the procedure and add the current environment to it |
| 03:43 | Dranik | hoeck: when I do (dosync (alter my assoc :c (ref my)))), it also throws the same exception |
| 03:44 | hoeck | Dranik: the printer throws that exception, because it fails to print your cyclic structure |
| 03:45 | Dranik | hoeck: looks like you're right! |
| 03:45 | Dranik | I'll try this... |
| 03:45 | hoeck | Dranik: I also have to correct myself, your first approach was correct, you don't have to use a nested ref |
| 03:47 | hoeck | ,(let [my (ref {:a nil})] (dosync (alter my assoc :a my)) (-> @my :a deref :a deref :a deref type)) |
| 03:47 | clojurebot | clojure.lang.PersistentArrayMap |
| 03:48 | Dranik | is there a way to disable the printer? |
| 03:49 | hoeck | implementing an interpreter using a circular datastructure does not feel 'right' in clojure |
| 03:50 | hoeck | Dranik: (set! *print-level* 10) on the repl |
| 03:50 | Dranik | trying this... |
| 03:50 | hoeck | limits printing of nested datastructures to n levels |
| 03:54 | Dranik | hoeck: you know what? just disabling the printer solved all the issues! :-) |
| 03:54 | Dranik | thanks a lot! |
| 03:55 | hoeck | Dranik: you're welcome |
| 05:34 | gilecham | Hmmm, anyone able to shed some light on why: |
| 05:34 | gilecham | (let (vector a 1) a) |
| 05:34 | gilecham | fails stating that "let requires a vector" |
| 05:35 | mrBliss` | gilecham: the syntax for let is: (let [a 1] a) |
| 05:49 | gilecham | mrBliss`: yes but (vector a 1) should return [a 1] ... |
| 05:51 | Chousuke | gilecham: when evaluated |
| 05:51 | Chousuke | gilecham: (vector a 1) is a list of two symbols and a number |
| 05:51 | Chousuke | evaluating it results in a vector of whatever a is and a number |
| 05:52 | Chousuke | s/a is/a evaluates to/ |
| 05:52 | sexpbot | <Chousuke> evaluating it results in a vector of whatever a evaluates to and a number |
| 05:53 | gilecham | Chousuke: so the problem is that, because let is a macro, the call to vector is not evaluated before evaluationg the call to vector? |
| 05:53 | Chousuke | gilecham: to put it another way, all code you write must be "literal". If a syntax requires a vector, then you must give it a literal vector. |
| 05:54 | Chousuke | gilecham: But when you *generate* code you can of course generate the vector dynamically. |
| 05:54 | mrBliss` | gilecham: right (let is actually a special form) |
| 05:55 | Chousuke | hm |
| 05:56 | gilecham | Drat. I'm trying to write something which will allow me to automatically replace all arguments of a function with new ones generated by a function call on the original. I was hoping to just wrap a let... round the body of my function |
| 05:56 | Chousuke | You can do something like this though: &&(let [a 2] `(let ~(vector ['a a]) (do whatever))) |
| 05:57 | Chousuke | hm |
| 05:57 | mrBliss` | ,`(let ~(vector 'a 1) ~'a)) |
| 05:57 | Chousuke | how does that inline evaluation wrok? |
| 05:57 | clojurebot | (clojure.core/let [a 1] a) |
| 05:57 | mrBliss` | Chousuke: ## |
| 05:57 | Chousuke | oh right |
| 05:57 | Chousuke | damn |
| 05:58 | Chousuke | gilecham: note that that ` form only generates the code. to get it to do something, it must be the result of a macro (so that it will be evaluated at runtime) or you must eval it manually |
| 05:58 | mrBliss` | gilecham: can you give a small example because I don't really understand |
| 05:58 | Chousuke | gilecham: you can probably do that with a macro. |
| 05:58 | Chousuke | or you could use the templating facility in core |
| 05:59 | gilecham | Chousuke, mrBliss`: Thanks! I thought there was macro magic in here somewhere |
| 05:59 | Chousuke | gilecham: this might help http://richhickey.github.com/clojure/clojure.template-api.html |
| 06:02 | gilecham | mrBliss`: Intent was to be able to write: |
| 06:02 | gilecham | (defn foo [a] |
| 06:02 | gilecham | (let [a (transform a)] |
| 06:02 | gilecham | (original-body a))) |
| 06:04 | gilecham | Off to read up on templates and return with more questions, thanks again |
| 06:06 | terom | Why not just use a higher order function? |
| 08:02 | void_ | hi there, what is this syntactic sugar please? -> |
| 08:03 | fliebel | void_: A thrush, almost at least. |
| 08:03 | manutter | Threading |
| 08:03 | manutter | Let me misuse it, as an illustration... |
| 08:03 | fliebel | &(1 (+ 1) (* 2)) |
| 08:03 | sexpbot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 08:03 | fliebel | &(-> 1 (+ 1) (* 2)) |
| 08:03 | sexpbot | ⟹ 4 |
| 08:03 | manutter | ,(-> 1 (inc) (println) (inc) (println)) |
| 08:03 | clojurebot | java.lang.NullPointerException |
| 08:04 | manutter | darn, too much abuse |
| 08:04 | manutter | so much for clarifying the issue |
| 08:04 | fliebel | &(macroexpand-1 '(-> 1 (+ 1) (* 2))) |
| 08:04 | sexpbot | ⟹ (clojure.core/-> (clojure.core/-> 1 (+ 1)) (* 2)) |
| 08:04 | fliebel | &(require 'clojure.walk) |
| 08:04 | sexpbot | ⟹ nil |
| 08:04 | void_ | &(doc ->) |
| 08:04 | sexpbot | ⟹ "Macro ([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc." |
| 08:05 | fliebel | &(clojure.walk/macroexpand-all '(-> 1 (+ 1) (* 2))) |
| 08:05 | sexpbot | ⟹ (* (+ 1 1) 2) |
| 08:05 | manutter | ,(-> (identity 1) (+ 1) (* 2)) |
| 08:05 | clojurebot | 4 |
| 08:06 | manutter | The basic idea is that it lets you take (foo (bar (baz x))) and turn it into (-> x (baz) (bar) (foo)), which can be more readable in certain circumstances |
| 08:07 | manutter | ,(-> (identity 1) (inc) (println) (inc) (println) (inc)) |
| 08:07 | clojurebot | java.lang.NullPointerException |
| 08:07 | void_ | oh I see |
| 08:07 | manutter | still cant' get that one to work |
| 08:07 | manutter | o well |
| 08:07 | void_ | yup, this is what google gave me, nice article: http://debasishg.blogspot.com/2010/04/thrush-in-clojure.html |
| 08:07 | fliebel | manutter: println return nil |
| 08:07 | void_ | &(doc identity) |
| 08:07 | sexpbot | ⟹ "([x]); Returns its argument." |
| 08:08 | manutter | doh, of course |
| 08:08 | fliebel | manutter: You can also skip the identity and enter 1 directly. |
| 08:08 | manutter | ,(-> 1 (inc) (inc) (* 2)) |
| 08:08 | clojurebot | 6 |
| 08:08 | void_ | &(-> (1) (inc) (inc)) |
| 08:08 | sexpbot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 08:08 | manutter | yeah, I was chasing a red herring there :) |
| 08:09 | void_ | &(-> 1 (inc) (inc)) |
| 08:09 | sexpbot | ⟹ 3 |
| 08:09 | fliebel | $(->> (range 10) (map #(* 2 %)) (reduce +)) |
| 08:09 | fliebel | &(->> (range 10) (map #(* 2 %)) (reduce +)) |
| 08:09 | sexpbot | ⟹ 90 |
| 08:09 | void_ | what does it mean if you use ->> instead of -> ? |
| 08:10 | manutter | -> comes in handy for things like setting up swing components, where you create something and then do x to it, then do y to it, then do z to it |
| 08:10 | fliebel | void_: it inserts the argument at the end instead. |
| 08:10 | manutter | The difference between -> and ->> is where the "running" total goes |
| 08:10 | raek | void_: (-> x (f a b c)) means (f x a b c), but (->> x (f a b c)) means (f a b c x) |
| 08:10 | manutter | let me try again |
| 08:10 | fliebel | manutter: Actually, for swing, most actions don't return anything, so you'd use doto. |
| 08:11 | void_ | this is cool |
| 08:11 | manutter | ok, I'm going to just shut up and drink my coffee, it's too early for me still! |
| 08:11 | manutter | :) |
| 08:12 | manutter | I don't use -> and ->> much yet, that's probably why I don't understand it as well as I think I do. |
| 08:14 | void_ | it's amazing how whole source of compojure takes 4 files https://github.com/weavejester/compojure/tree/master/src/compojure |
| 08:14 | raek | it helps removing nesting: (into {} (map #(Integer/parseInt %) (remove empty? (line-seq rdr)))) -> (->> rdr (line-seq) (remove empty?) (map #(Integer/parseInt %)) (into {})) |
| 08:15 | raek | then you can put each step at its own line, and the code becomes beautiful again... |
| 08:15 | manutter | there, that's a much better example |
| 08:17 | manutter | Yeah, I really like compojure, though the real power behind it is in Ring |
| 08:18 | void_ | guys, do you think it's a good idea to learn Clojure by building a web application? |
| 08:18 | manutter | I'd say so |
| 08:18 | manutter | especially if your goal is to learn how to write good web apps in clojure |
| 08:19 | void_ | I still feel very lost in clojure code |
| 08:19 | kephale1 | in the void so to speak |
| 08:19 | raek | one thing that can be fun to do is to build your own chat application and protocol |
| 08:20 | void_ | oh yeah definitely |
| 08:20 | raek | something very simple |
| 08:20 | void_ | use some sproutcore+websocket for clients |
| 08:20 | void_ | or backbone.js or whatever |
| 08:20 | raek | then you have a little bit of state management too |
| 08:20 | void_ | yeah I think that will be the next |
| 08:20 | void_ | I did something like that in node.js |
| 08:21 | raek | I was thinking about basic I/O with ordinary sockets, but by all means use whatever knowledge you have to make it fun :-) |
| 08:21 | void_ | but node.js seems so simple compared to clojure |
| 08:21 | void_ | raek: yesterday I made hangman game for telnet |
| 08:21 | manutter | void_: have you done the 4clojure.org exercises? |
| 08:21 | void_ | no sir |
| 08:22 | manutter | They're a good remedy for the "I feel lost in clojure" syndrome |
| 08:22 | void_ | now that looks very nice |
| 08:22 | void_ | I started koans |
| 08:22 | manutter | yeah, same idea |
| 08:22 | void_ | it's amaing how many learnin resources are out there |
| 08:23 | manutter | indeed |
| 08:29 | void_ | by the way "joy of clojure", anybody read it? |
| 08:29 | manutter | It's on my bookshelf, I'm partway thru it |
| 08:30 | manutter | It's not intended as an intro text, I like Clojure In Action for that |
| 08:30 | void_ | yeah, same feelings here - not an intro text |
| 08:31 | manutter | though I just got the "Rough Cuts" version of Clojure Programming, and it's looking pretty good too |
| 08:31 | void_ | rough cuts, like a beta version? |
| 08:31 | manutter | Yeah sort of |
| 08:32 | manutter | It's what O'Reilly calls their pre-release program |
| 08:32 | kephale1 | is Raynes' book finished yet? |
| 08:32 | manutter | not sure |
| 08:40 | void_ | hm, so I created a project with lein. And I would like to run REPL on tom of my existing code, is there any easy way to do it? |
| 08:40 | void_ | oh |
| 08:40 | void_ | lein repl |
| 08:41 | manutter | and if you're using emacs, you can use lein swank and then use M-x slime-connect to run a repl right in emacs |
| 08:41 | void_ | yeah I'm not |
| 08:41 | void_ | :) |
| 08:41 | void_ | textmate |
| 08:41 | manutter | Ah |
| 08:41 | manutter | I've never used that one |
| 08:41 | manutter | what OS is that/ |
| 08:41 | manutter | ? |
| 08:41 | void_ | Mac |
| 08:42 | manutter | Ah, ok |
| 08:42 | manutter | I should play with that some time |
| 08:45 | kephale1 | there was also a recently revitalized lisp GUI for OS X that now uses Clojure and can play fairly nicely with lein… unfortunately the name of it has completely slipped my mind |
| 08:46 | manutter | doh! |
| 08:46 | kephale1 | there is* |
| 08:47 | manutter | Hmm, first google result is Emacs... |
| 08:47 | manutter | Lemonodor? |
| 08:47 | manutter | MCLIDE? |
| 08:48 | void_ | kephale1: I would like to try that |
| 08:48 | kephale1 | MCLIDE! |
| 08:49 | kephale1 | right because it was developed for MCL |
| 08:49 | void_ | oh ok |
| 08:49 | manutter | Might have to give that a whirl |
| 08:49 | manutter | First I'm going to stop by and submit the web site to web-sites-that-suck.com tho :P |
| 08:50 | void_ | If I wanted to play with my code without reloading jvm each time (I use lein run), what is the best way? |
| 08:50 | void_ | except emacs |
| 08:50 | void_ | because I'm not in the mood for learning new editor |
| 08:50 | void_ | manutter: that link is dead :P |
| 08:50 | manutter | eh, I probably spelled it wrong |
| 08:50 | kephale1 | manutter: lol |
| 08:50 | manutter | but still |
| 08:50 | void_ | http://www.webpagesthatsuck.com/ |
| 08:51 | manutter | That were it! :) |
| 08:53 | mrBliss` | void_: are you using https://github.com/swannodette/textmate-clojure ? |
| 08:53 | void_ | mrBliss`: yes |
| 08:53 | void_ | but that still doesn't give me repl |
| 08:54 | void_ | I mean I can execute one line |
| 08:54 | void_ | which is the same ... |
| 08:54 | manutter | omg even the MCLIDE *icon* is that horrible plaid |
| 08:54 | mrBliss` | Command-Shift-L loads a file |
| 08:55 | kephale1 | manutter: at the least I think the project is pretty recently revived… lets hope they're putting all their efforts into the backend ; ) |
| 08:55 | kephale1 | i concur, emacs FTW |
| 08:55 | kephale1 | especially when it comes to lisps |
| 08:56 | manutter | +1 on both counts |
| 09:02 | Vinzent | Is there function combinators somewhere in core or contrib? like (map (fn/and string? empty?) ["" [] ()] => (true false false) |
| 09:03 | void_ | anybody uses mongo with clojure? |
| 09:03 | manutter | Vinzent: there's comp and partial, though from your example I'm not sure that's what you're looking for |
| 09:05 | Vinzent | manutter, (fn/and string? empty?) should return the predicate that returns true for things that are strings and empty |
| 09:05 | kephale1 | Vinzent: i think you'd have an issue with the and since its a macro |
| 09:05 | kephale1 | but 1 sec i may have an idea |
| 09:05 | Vinzent | same as #(and (string? %) (empty? %)), but shorten |
| 09:06 | raek | Vinzent: I think fogus suggested such functions on the clojure dev mailing list a while ago |
| 09:06 | hoeck | Vinzent: I'm looking for that too :) |
| 09:06 | mrBliss` | found it: http://dev.clojure.org/jira/browse/CLJ-729 |
| 09:08 | raek | and the discussion: http://groups.google.com/group/clojure-dev/browse_thread/thread/899349c6a9b526e0/10233af5f5f13831 |
| 09:08 | kephale1 | Vinzent: I think you'd have to write a function like the one fogus is suggesting |
| 09:08 | kephale1 | but you might be able to use juxt in it |
| 09:09 | Vinzent | found the lib: https://github.com/zahardzhan/fn |
| 09:10 | Vinzent | kephale1, right, juxt suites me in my case |
| 09:11 | Vinzent | but it's more verbose |
| 09:12 | kephale1 | yeah, but you can use it to write your function which might be something like a comp of a partial and of a juxt |
| 09:12 | kephale1 | err that last and is the macro, not the conjunction |
| 09:12 | kephale1 | trying to get it to work now |
| 09:22 | kephale1 | though i'm avoiding using that fn library... |
| 09:22 | kephale1 | ,(every? #(apply (fn [x y] (and x y)) ((juxt string? empty?) %)) (list "" "")) |
| 09:22 | clojurebot | true |
| 09:22 | kephale1 | ,(every? #(apply (fn [x y] (and x y)) ((juxt string? empty?) %)) (list "" '(a b))) |
| 09:22 | clojurebot | false |
| 09:23 | kephale1 | kinda ugly, but you could wrap something like that into a funcion |
| 09:23 | kephale1 | function* |
| 09:23 | kephale1 | hooray for a reason to use juxt : P |
| 09:26 | kephale1 | again there is weirdness in this because i'm not using fn/and but: |
| 09:26 | kephale1 | (def predicator (fn [& predicates] #(apply (fn [x y] (and x y)) ((apply juxt predicates) %)))) |
| 09:28 | kephale1 | someone might have a better idea than the nested application there though |
| 09:30 | mrBliss` | (defn every-pred [& preds] (fn [& args] (every? #(apply % args) preds))) |
| 09:31 | kephale1 | thats the one fogus presented right? |
| 09:32 | kephale1 | hrm, yeah mine is far from solving the 0 arg issue |
| 09:32 | raek | ,(every? odd? []) |
| 09:32 | clojurebot | true |
| 09:35 | kephale1 | ,(and) |
| 09:35 | clojurebot | true |
| 09:35 | __name__ | Interestin |
| 09:35 | __name__ | *Interesting even |
| 10:25 | Dranik | Is there a way to add a library to leiningen project's classpath and not import it into the local maven repository? |
| 10:25 | clgv | Dranik: yes, just copy it to your lib directory |
| 10:26 | clgv | Dranik: and use :disable-implicit-clean true in your project.clj |
| 10:26 | Dranik | when does leiningen clean the lib directory? |
| 10:27 | raek | Dranik: when you run lein deps, I think |
| 10:27 | Dranik | ah, yeah... |
| 10:27 | Dranik | thanks |
| 10:27 | raek | Dranik: are you sure the lib is not in Clojars or Maven Central? |
| 10:28 | raek | if you make this project publically available, it's much simpler for others if there is an artifact for the dependency |
| 10:28 | Dranik | its j2ee5-api.jar... |
| 10:29 | fliebel | http://blogs.oracle.com/henrik/entry/moving_to_openjdk_as_the |
| 10:30 | kephale1 | Dranik: or you can just run your own repository with something like archiva |
| 10:30 | raek | Dranik: http://jarvana.com/jarvana/search?search_type=project&project=javaee-api |
| 10:31 | Dranik | raek: what's that? |
| 10:31 | raek | jarvana? |
| 10:32 | Dranik | aha |
| 10:33 | raek | jarvana is a search engine for maven artifacts |
| 10:33 | Dranik | wow! thanks! |
| 10:33 | raek | ...the place to look at for non-clojure libraries |
| 10:34 | clgv | raek: great. didnt know that before |
| 10:43 | dnolen | fliebel: https://gist.github.com/1016858 |
| 10:43 | dnolen | tabling fixed |
| 10:43 | fliebel | dnolen: yea, got a notice from jira, great! |
| 10:44 | dnolen | fliebel: caveat at the moment is you can't table defns only def + fn because of lexical scoping issue. |
| 10:44 | dnolen | bbl |
| 10:44 | fliebel | dnolen: Does htis also mean run is no longer lazy? |
| 10:49 | devn | must...find...book: http://www.amazon.com/Art-Prolog-Second-Programming-Techniques/dp/0262193388/ref=reg_hu-rd_add_1_dp |
| 10:49 | devn | (for less than 105.00, preferably) |
| 10:52 | joly | Am I correct that trampolined functions can't return a vector or map since they implement IFn? |
| 10:53 | joly | ,(trampoline (fn [a] [1 a 3]) 2) |
| 10:53 | clojurebot | [1 2 3] |
| 10:53 | joly | ... I guess not |
| 10:54 | joly | ah, parentheses error locally |
| 10:54 | mrBliss` | ,(map fn? [(fn []) [] {} #{}]) |
| 10:54 | clojurebot | (true false false false) |
| 10:56 | joly | thanks, I was doing a 4clojure trampoline problem and was using (instance? clojure.lang.IFn r). Totally missed fn?. |
| 10:59 | zenoli | devn: AbeBooks has a bunch of copies listed ...2nd ed for ~$40, 1st ed for ~$10. |
| 11:10 | anonymouse89 | is there a way to exclude a function/macro from being "used" by another ns without explicitly excluding? |
| 11:10 | anonymouse89 | or to rephrase, something like defn- for defmacro? |
| 11:11 | fliebel | anonymouse89: If you can add metadata to a macro, you can say ^:private I guess. |
| 11:12 | raek | anonymouse89: (defn- foo ...) is the same as (defn ^{:private true} foo ...) and you can use the latter way for macros |
| 11:12 | fliebel | raek: Sure? ##(doc defmacro) |
| 11:12 | sexpbot | ⟹ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Like defn, but the resulting function name is declared as a macro and will be used as a macro by the compiler when it is called." |
| 11:13 | anonymouse89 | fliebel, raek: yes, this works. Thanks! |
| 11:15 | raek | I think that basically (defmacro foo [x y] ...) is equvalent to (defn ^{:macro true} foo [x y &env &form] ...) |
| 11:16 | raek | hrm, yes. using an attribute map looks prettier: (defmacro foo {:private true} ...) |
| 11:16 | anonymouse89 | raek: for whatever reason (defn- mymacro ^{:macro true} ... ) gives me a StackOverflow when I call it |
| 11:20 | mrBliss` | ,(macroexpand '(defmacro m [args] 1)) |
| 11:20 | clojurebot | DENIED |
| 11:20 | mrBliss` | (do (clojure.core/defn m [args] 1) (. (var m) (setMacro)) (var m)) |
| 11:20 | mrBliss` | so it's not ^{:macro true}, but (.setMacro ..) |
| 11:21 | devn | zenoli: thanks! |
| 11:43 | dnolen | fliebel: so I think I have an approach that can work for Rel, will be more involved to implement but will address the generality that I want. |
| 11:43 | fliebel | dnolen: Coll, I'm all ears :) |
| 11:44 | dnolen | fliebel: write a macro that generates the Rel type for all IFn methods, 1-21 args. |
| 11:45 | dnolen | Rel will take 23 params, name meta and 21 fns, possibly initial nil, these are unsynchronized mutable, setters will generate for all o these. |
| 11:45 | dnolen | Clojure will all automatically pack all args past 20 into the rest parameter. |
| 11:45 | dnolen | the 21st arg I mean. |
| 11:48 | dnolen | will need to think about dealing with indexing, but I think this approach can work. I'm interested in a syntax for indexing any arg, as well compound indexes. |
| 11:50 | fliebel | dnolen: Okay, so we're now writing a NoSQL db for relations? :) |
| 11:50 | dnolen | fliebel: no, some Prologs support this from what I understand. |
| 11:51 | dnolen | fliebel: but yeah, large knowledge bases could be queried efficiently. |
| 11:51 | fliebel | So Prolog contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of MongoDB. |
| 11:51 | dnolen | fliebel: other way around. |
| 11:52 | fliebel | So MongoDB contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Prolog. |
| 11:54 | fliebel | dnolen: But, sure sounds cool and all. Only... 20 args! I assume Clojure does this for efficiency? |
| 11:55 | clgv | fliebel: "Nobody will need more than 20 args!" |
| 11:55 | dnolen | fliebel: no Clojure supports arbitrary number of args, so will Rel. it just that anything more than 20 gets packed into a rest arg, so you need to unpack them yourself. |
| 11:56 | dnolen | so only fast path for 1-20. |
| 11:56 | fliebel | clgv: Nobody will need more then 5 args 90% of the time, so 20 + varargs seems a weak optimization with a bad sideeffect. |
| 11:56 | dnolen | fns that take > 10 args are gross. |
| 11:57 | fliebel | dnolen: On the other hand, think about functions like defn and vector... |
| 11:57 | clgv | my juxt-map cannot handle varargs yet, since it was too much work and I was content with 8 pairs = 16 args... |
| 11:58 | dnolen | fliebel: ? |
| 11:58 | fliebel | dnolen: (vector 1 2 3 4) goes over 20 args real quick. |
| 11:58 | clgv | fliebel: how often do you specify it manually like this? ;) |
| 11:58 | fliebel | clgv: Juxt-map? |
| 11:59 | dnolen | fliebel: vector does take arbitrary args, it takes 5 at most. |
| 11:59 | fliebel | clgv: Not at all, but I do define functions with more than 20 statements.... maybe.... sometimes |
| 11:59 | dnolen | s/doesn/doesn't |
| 11:59 | dnolen | s/does/doesn't |
| 11:59 | sexpbot | <dnolen> s/doesn'tn/doesn'tn't |
| 11:59 | clgv | fliebel: like juxt but instead of buildin a seq/vec it does build a map with specified keys |
| 11:59 | dnolen | ergs |
| 12:17 | Vinzent | In midje, how can I say that fn returns approximately some number? |
| 12:18 | manutter | Round off the result and say it equals exactly some number |
| 12:19 | manutter | Hmm, I'm trying to think of a way to make that more specific... |
| 12:20 | manutter | Ok, let me rephrase that: |
| 12:20 | mprentice | how can i get the direct children of a type in a hierarchy created with make-hierarchy? |
| 12:20 | manutter | The value x is approximately equal to y if the absolute value of (x - y) is less than some "close enough" factor |
| 12:22 | manutter | so write your midje test to calculate the absolute value of target number minus actual number, and assert that it is < e (where "e" is the margin of error) |
| 12:23 | Vinzent | Yes, I can do it, but the right way is to use roughly: |
| 12:23 | Vinzent | (fact (/ 666666.666 13) => (roughly 51282)) |
| 12:24 | manutter | roughly? |
| 12:24 | manutter | Oh, is that a midje function? |
| 12:24 | Vinzent | Yep |
| 12:25 | Vinzent | or, if I want to specify "close enough" number: (fact (/ 666 13.0) => (roughly 51 0.5)) |
| 12:25 | manutter | well there you go, now I learned something |
| 12:26 | Vinzent | Midje is really awesome, isn't it? :) |
| 12:26 | manutter | mprentice: I don't know how to get the direct descendants of a type in a hierarchy, but if I had to try, I'd get (descendants h type) and then compare them to each other with isa? to discard the ones that are not direct descendants |
| 12:26 | manutter | Yeah, I love midje |
| 12:29 | mprentice | manutter: hmm, i guess i'm trying to use hierarchy in a way it's not designed for. i want to pre-walk the hierarchy |
| 12:31 | dnolen | mprentice: yeah there's parents, but no children. |
| 12:32 | manutter | mprentice: can you build your tree structure first, and then use that to build your hierarchy? |
| 12:33 | manutter | That way they'd be parallel structures, but you could walk the one, and use the other for isa? testing and so on. |
| 12:33 | mprentice | i don't need the hierarchy, i was just hoping to use it as an easy way to build a tree |
| 12:34 | mprentice | but i don't think i gained anything by doing that |
| 12:35 | manutter | yeah hierarchies are more a tool for describing relationships I think |
| 13:33 | void_ | hi. I asked this before but: Is there any way to start REPL from inside my program. Something like read-line -> evaluate it in an infinite loop. |
| 13:33 | void_ | I was just wondering if there is anything that does this. |
| 13:36 | manutter | hmm, there's a clojure.repl namespace |
| 13:37 | void_ | nah there's only things like dir, source, apropos |
| 13:37 | manutter | Ah, no I found it |
| 13:37 | technomancy | clojure.main/repl |
| 13:37 | void_ | oh that |
| 13:37 | manutter | omg technomancy out-typed me again |
| 13:37 | void_ | dvorak |
| 13:37 | void_ | right technomancy? ;) |
| 13:37 | manutter | lol |
| 13:37 | technomancy | absolutely |
| 13:38 | technomancy | also terseness |
| 13:39 | void_ | I love how anybody can add examples to http://clojuredocs.org/clojure_core/clojure.main/repl |
| 13:39 | void_ | or clojuredocs.org |
| 13:42 | void_ | awesome! |
| 13:43 | void_ | this (clojure.main/repl) |
| 13:57 | timvisher | hey all |
| 13:57 | timvisher | anyone know where I can read some good docs on compojure sessions? |
| 13:58 | manutter | compojure sessions or ring sessions? |
| 13:58 | timvisher | i suppose that compojure would just be using ring sessions |
| 13:58 | timvisher | i'm not sure |
| 13:58 | timvisher | is there such a thing as compojure sessions? |
| 13:59 | timvisher | better yet, all I'm trying to do is stuff a string into a session |
| 13:59 | timvisher | i found some references to session-assoc |
| 13:59 | timvisher | but i can't find that in the source anywhere |
| 14:01 | manutter | all I can find is this: http://clojuredocs.org/ring/ring.middleware.session/wrap-session |
| 14:01 | dnolen | timvisher: compojure is really just a routing DSL these days, all session stuff comes from Ring |
| 14:02 | manutter | looks like the wrap-session handler just adds a hash map to the :session key on the request object, and you store stuff by putting it in a hash-map your attach to the :session key on the response object |
| 14:02 | manutter | (but don't quote me) |
| 14:05 | timvisher | so my site is defined using the handler/site function |
| 14:05 | timvisher | which auto-wraps sessions around all the routes |
| 14:05 | timvisher | I'm trying to figure out how to alter the session now |
| 14:05 | timvisher | that's where I'm falling down |
| 14:06 | manutter | so if I'm understanding the docs correctly, you should be getting a request map that contains a :session key |
| 14:06 | Vinzent | timvisher, just get :session key from request map and assoc what you need |
| 14:07 | manutter | The :session key on the request is your session data coming in, and then to modify it, create a new map (just use ordinary assoc on the map you get from session) and attach it to a :session key in your response |
| 14:08 | timvisher | gotcha |
| 14:08 | timvisher | i think i was expecting things to be more complex. :) |
| 14:08 | timvisher | shame on me |
| 14:08 | manutter | well, I'm passing on what I think I've heard, so grain of salt, etc |
| 14:08 | manutter | but I think that's all there is to it |
| 14:09 | manutter | If you use Sandbar there's some more complex session handling available |
| 14:09 | manutter | but Ring is pretty vanilla |
| 14:09 | timvisher | gotcha |
| 14:09 | Vinzent | iirc you should write your middleware to save session, if your handler doen't modify it |
| 14:10 | manutter | I think that the standard wrap-session middleware updates the session data |
| 14:10 | manutter | The docs say that if you add a :session key to the response, "the session is updated with the new value" |
| 14:11 | manutter | If I'm understanding that correctly, that should preserve any session values that you did not change |
| 14:13 | Vinzent | manutter, may be, I just remember I've read somewhere about it |
| 14:14 | manutter | Yeah, I played with it a while ago, I'm trying to remember what I discovered at the time |
| 14:14 | manutter | but I think I'm somewhere in the ballpark anyway |
| 14:14 | timvisher | is the referrer sent when a form posts to a url? |
| 14:15 | amalloy | timvisher: should be, but you also shouldn't really rely on it |
| 14:15 | timvisher | here's the big picture of what i'm trying to do. |
| 14:16 | timvisher | I've got a long page with a bunch of small elements, I'd like to |
| 14:16 | timvisher | send a post to a route, and then focus the result of the function |
| 14:16 | timvisher | called there when I return to the previous page |
| 14:16 | timvisher | i'd like to return to whatever url they were on previously, as well. |
| 14:16 | timvisher | although at the moment i just redirect to root |
| 14:17 | amalloy | timvisher: a popular way to do the latter is to post to /myform?backto=somepage |
| 14:18 | timvisher | amalloy: brilliant. :) don't know why i didn't think of storing the window.location in the form |
| 14:18 | timvisher | ok, so that solves that problem |
| 14:19 | timvisher | then, i can store the title in the session on the way back and focus it there |
| 14:19 | timvisher | awesome |
| 14:53 | lawfulfalafel | how do you find out the size of a list? |
| 14:53 | amalloy | count |
| 14:54 | amalloy | &(map count ["string" '(some list) [1 2 3 4]]) |
| 14:54 | sexpbot | ⟹ (6 2 4) |
| 14:54 | amalloy | lawfulfalafel: ^ |
| 14:59 | lawfulfalafel | thanks you amalloy |
| 15:05 | pdk | does anyone know if clojure bit-shift-right is equivalent to java >> or >>> |
| 15:05 | pdk | iirc >>> sets the high order bits to 0 |
| 15:05 | TimMc | ,(bit-shift-right -1) |
| 15:05 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$bit-shift-right |
| 15:05 | TimMc | ,(bit-shift-right -1 5) |
| 15:05 | clojurebot | -1 |
| 15:07 | TimMc | Looks like sign-extend to me. |
| 15:09 | pdk | ,(type (bit-shift right 255 1)) |
| 15:09 | clojurebot | java.lang.Exception: Unable to resolve symbol: bit-shift in this context |
| 15:09 | pdk | ,(type (bit-shift-right 255 1)) |
| 15:09 | clojurebot | java.lang.Integer |
| 15:10 | zakwilson | Am I understanding correctly that I can't do variable capture in a Clojure macro? |
| 15:11 | pdk | you should be able to |
| 15:12 | pdk | it has a reader macro for gensym after all |
| 15:12 | dnolen | zakwilson: you can, ~'foo |
| 15:12 | dnolen | ,`(foo) |
| 15:12 | clojurebot | (sandbox/foo) |
| 15:12 | dnolen | ,`(~'foo) |
| 15:12 | clojurebot | (foo) |
| 15:13 | zakwilson | dnolen: thanks |
| 15:14 | zakwilson | pdk: not using gensyms where they would ordinarly be called for usually throws an exception. |
| 15:14 | pdk | ,~'foo |
| 15:14 | clojurebot | java.lang.IllegalStateException: Var clojure.core/unquote is unbound. |
| 15:15 | pdk | wait durr |
| 15:28 | pdk | is there a changelog for 1.2.1 |
| 15:34 | miwillhite | @technomancy, one time I was in here asking how to get environment variables…when you told me you prefixed the function call with a comma (it was something like ",(System/getenv)")…was that a typo, or does the comma mean something when used that way? |
| 15:35 | Chousuke | miwillhite: on this channel , invokes clojurebot |
| 15:35 | raek | miwillhite: comma is whitespace in clojure. it is also the prefix clojurebot listens to for code evaluation |
| 15:35 | miwillhite | ah okay, thanks :P |
| 15:36 | miwillhite | ,(+ 1 1) |
| 15:36 | clojurebot | 2 |
| 15:36 | miwillhite | sweet |
| 15:36 | ampleyfly | ,_ |
| 15:36 | clojurebot | java.lang.Exception: Unable to resolve symbol: _ in this context |
| 15:36 | TimMc | ,,,,,, |
| 15:36 | clojurebot | EOF while reading |
| 15:39 | amalloy | is there a good/standard way to implement IFn by hand rather than with (fn …)? I've written (reify IFn (invoke [this] …)), and that works for 0 args. if i call it with any args, it throws an AbstractMethodError. in some ways that's fine since i don't want to allow any args, but it would be nice if it threw an arity exception instead |
| 15:39 | amalloy | i can proxy AFn, but it's my understanding that you should stay away from proxy if you can help it |
| 15:40 | amalloy | to avoid an XY issue: i'm doing this because i want to implement IDeref as well as IFn |
| 15:43 | hiredman | A nasty way to do it would be to use a Var |
| 15:44 | hiredman | actually, well, the fullfils what you said in the most pointless way |
| 15:46 | amalloy | well. the more i poke at it the less certain i am that implementing IFn is really a good idea anyway |
| 15:49 | lawfulfalafel | can someone help me with this code? http://pastebin.com/AytnsLps |
| 15:49 | dnolen | amalloy: I would write a helper macro to throw ArityException on the other arities. I'm planning on implementing IFn and I see there's a lot of boilerplate that could be abstracted away. |
| 15:49 | lawfulfalafel | I don't really get how I am supposed to keep the numbers I am generating |
| 15:49 | bhenry | lawfulfalafel: you're not thinking functionally |
| 15:50 | hiredman | yeah, a deftype+helper macro for replacing AFn is just waiting to be written |
| 15:50 | lawfulfalafel | bhenry: so where is the error in my thinking? |
| 15:51 | raek | lawfulfalafel: use let instead of def inside functions |
| 15:51 | raek | def is not for local variables |
| 15:51 | bhenry | ,(doc let) |
| 15:51 | clojurebot | "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein." |
| 15:52 | raek | lawfulfalafel: have you learned about loop and recur? |
| 15:54 | raek | lawfulfalafel: also, in a functional solution, you will typically not have any calls to 'do', 'doseq' or any other construct that is made for side-effects |
| 15:55 | raek | lawfulfalafel: example of a loop in Clojure to sum all numbers between 0 and x: (loop [acc 0, i x] (if (zero? i) acc (recur (+ acc i) (dec i)))) |
| 16:05 | amalloy | lawfulfalafel: also line 15 you need whitespace after the + |
| 16:14 | naeu | is there a simple way of listing a given object's fields/methods? |
| 16:14 | raek | naeu: show |
| 16:15 | naeu | raek: thanks |
| 16:15 | naeu | now i need to figure out how to unfreeze emacs |
| 16:15 | naeu | i tried this in a slime repl: (println (vec (.getMethods (class f)))) |
| 16:15 | naeu | and it totally froze up |
| 16:15 | raek | clojure.contrib.repl-utils/show |
| 16:16 | naeu | killing emacs seems cruel |
| 16:16 | raek | naeu: I think you can press C-c C-c in the repl |
| 16:16 | naeu | raek: yeah, i've tried that |
| 16:17 | raek | so it froze emacs itself, and not the swank server? |
| 16:18 | naeu | raek: yup |
| 16:18 | naeu | raek: i even killed the swank server and emacs is still frozen |
| 17:08 | raek | has anyone successfully managed to use autodoc lately? |
| 17:09 | raek | if I use the standalone jar with java -jar, it chokes on my usage of clojure.java.io (seems like autodoc evals the code in clojure 1.1) |
| 17:10 | raek | if I add it as a dev-dependency, it fails because clojure-contrib 1.1.0-master-SNAPSHOT does not exist anymore |
| 17:11 | void_ | so I was thinking .. Android is running on JVM. Clojure produces JVM bytecode. Can you create Android apps with Clojure? |
| 17:11 | void_ | I mean, yes you can (I googled that), but does anybody do it? |
| 17:12 | raek | void_: it is possible, but quite slow currently. I hear they are working on it: http://dev.clojure.org/display/design/Android+Support |
| 17:15 | offby1 | void_: actually, Android doesn't run on the JVM. Google wrote their own, incompatible VM called "Dalvik". |
| 17:15 | offby1 | In theory, however, it is probably possible to add a Dalvik backend to the Clojure compiler |
| 17:15 | void_ | oh yeah I now recall that they have their own |
| 17:16 | void_ | so Google have their own Java compiler too? |
| 17:20 | void_ | ohhh ->/->> is cool |
| 17:20 | void_ | (->> |
| 17:20 | void_ | (mongo/fetch :expenses) |
| 17:20 | void_ | (map (fn [e] (:title e))) |
| 17:20 | void_ | ) |
| 17:20 | void_ | this is such beautiful code |
| 17:21 | raek | void_: if you tend to use 'map' with anonynous functions a lot, consider using 'for' instead |
| 17:21 | Chousuke | void_: why not just (map :title)? |
| 17:21 | raek | (for [e (mongo/fetch :expenses)] (:title e)) |
| 17:21 | void_ | thanks guys thanks ;) |
| 17:22 | raek | eh, what Chousuke said ;-) |
| 17:22 | void_ | Chousuke: didn't know you can do that |
| 17:22 | Chousuke | it's one of the little awesome features that Clojure has :P |
| 17:22 | raek | but seriously. the autodoc deps seems to have been broken for half a year now. |
| 17:23 | raek | is the conclusion that nobody document their code? |
| 17:23 | raek | or have everyone switched to Marginalia? |
| 17:23 | raek | (Marginalia is very neat, but not what I want in this case) |
| 17:25 | ohpauleez | raek: I use Raynes' autodoc AND marginalia in my stuff |
| 17:25 | ohpauleez | and generate both |
| 17:25 | Raynes | ohpauleez: I'm fine with just using marginalia, fyi. |
| 17:26 | raek | ah, now Raynes' version works for me. wonder what I were doing wrong. |
| 17:26 | solussd | ,(->> 3 (* 3) (/ 4) (* 5)) ;it can make ugly code too! |
| 17:27 | clojurebot | 20/9 |
| 17:27 | Raynes | I have a version of autodoc? |
| 17:27 | Raynes | Cool. |
| 17:27 | raek | Raynes: thanks for fixing it |
| 17:27 | raek | [org.clojars.rayne/autodoc "0.8.0-SNAPSHOT"] |
| 17:27 | Raynes | You're welcome. I'd tell you how I did it if I could remember actually doing it. |
| 17:27 | Raynes | I seem to recall doing something minor to it for my cake autodoc plugin. |
| 17:41 | void_ | hmm why doesn't "\n" make a newline? |
| 17:42 | void_ | \newline neither |
| 17:42 | void_ | oh I got it |
| 17:42 | void_ | I wouldn't pass it to println |
| 18:00 | lawfulfalafel | just out of curiosity, why does the empty list evaluate to true? |
| 18:01 | lawfulfalafel | It seems like it would be useful for recursive functions that are being passed a list |
| 18:01 | lawfulfalafel | or maybe that's just my n00b opinion |
| 18:01 | dnolen | lawfulfalafel: you have (seq foo) for that. only nil and false are false-y thank heavens. |
| 18:02 | raek | lawfulfalafel: the rules for truthiness is that nil and false are falsey, everything else is truthy |
| 18:02 | raek | that something empty can be non-nil allows for more laziness |
| 18:03 | raek | otherwise a lazy-seq producing function would have to force the first element to check whether it should return nil or not |
| 18:51 | zakwilson | Is there a built-in inverse of coll? (like CL's atom) |
| 18:52 | hiredman | coll? doesn't just test for collections, it tests for IPersistentCollection |
| 18:53 | Raynes | (comp not coll?) |
| 18:53 | hiredman | so java collections will all return false |
| 18:53 | hiredman | etc |
| 18:54 | amalloy | zakwilson: no, mainly because clojure has a fuzzier dividing line. it's not "lists vs everything else" |
| 18:56 | zakwilson | I'd be safe ignoring Java collections in this case, but is there a generic test for single values versus collections that works on everything? |
| 18:57 | hiredman | it really depends on what you are doing with it, there is no generic always safe test |
| 18:58 | hiredman | if you are writing a macro and dealing with clojure forms coll? and (comp not coll?) are good enough |
| 19:01 | zakwilson | That's exactly what I'm doing. |
| 19:01 | hiredman | I figured as much |
| 19:02 | hiredman | I imagine it being part of some elaborate system of macros |
| 19:02 | hiredman | and then I sigh and try to think of something else |
| 19:03 | choffstein | Hey all -- I have a question. I have a situation where I am building html content using hiccup with different functions. In on area, I have something like "[:li {:id "myTab"} (fn-to-render-content arg1 arg2)]". My issue is that I need fn-to-render-content to return two vectors, not a vector of two vectors. I was thinking about constructing some sort of macro to "unwrap" a vector and return the individual elements ... like "(u |
| 19:03 | choffstein | [1 2 3 [4 5]]))" becomes "1 2 3 [4 5]" |
| 19:03 | choffstein | Is that possible? |
| 19:04 | hiredman | sounds horrid, but zakwilson is a macro writer, so he can help you |
| 19:05 | zakwilson | No elaborate system of macros, but the macro does call a multimethod to mangle its arguments. |
| 19:07 | zakwilson | choffstein: you could (apply u [1 2 3 [4 5]]) |
| 19:07 | zakwilson | Well, not u(nwrap), but whatever function it is you want to call on 1 2 3 [4 5] |
| 19:09 | choffstein | zakwilson: I don't want to apply a function though |
| 19:10 | choffstein | something more like "[a b c (unwrap [d e f])]" would return "[a b c d e f]" |
| 19:10 | hiredman | not possible |
| 19:10 | amalloy | choffstein: that's not possible |
| 19:11 | choffstein | boo |
| 19:11 | amalloy | and for good reason |
| 19:11 | choffstein | alright. can't know unless you ask, right? :) |
| 19:11 | zakwilson | ,(flatten [1 2 3 [4 5]]) |
| 19:11 | clojurebot | (1 2 3 4 5) |
| 19:11 | zakwilson | that's about as close as it gets |
| 19:12 | choffstein | Yeah ... but not quite what I am looking for unfortunately. It is alright. |
| 19:12 | choffstein | I'll figure it out |
| 19:12 | amalloy | wait, choffstein, you want to use this for hiccup? |
| 19:12 | zakwilson | It can be done in Common Lisp, but Clojure doesn't have multiple return values. |
| 19:12 | choffstein | yes |
| 19:12 | amalloy | just return (list [ret1…] [ret2…]) |
| 19:13 | amalloy | hiccup renders seqs by expanding them into the parent element, roughly |
| 19:13 | choffstein | amalloy: hiccup seems to be running into issue having a parent element with no tag |
| 19:13 | amalloy | choffstein: with a *list* parent element? vectors are not lists |
| 19:13 | choffstein | doh. |
| 19:14 | amalloy | choffstein: try (html [:ul '([:li 1] [:li 2])]) |
| 19:14 | amalloy | i think that ought to return a :ul with two children |
| 19:15 | choffstein | list worked ... vector didn't. doh. |
| 19:15 | choffstein | feeling stupid. |
| 19:15 | choffstein | thanks :) |
| 19:15 | amalloy | choffstein: that's because vectors are for introducing html elements, and you don't want to introduce an html element ;) |
| 19:15 | choffstein | that makes a completely reasonable amount of sense :) |
| 19:40 | gigamonkey | So everybody seen Fogus's interview with Hickey? http://www.codequarterly.com/2011/rich-hickey/ |
| 19:41 | brehaut | gigamonkey: and the companion interview with abelson? ;) |
| 19:42 | hiredman | I sure hope everyone has seen it, it's been online for *hours* |
| 19:44 | gigamonkey | brehaut: yeah, you can read than one too. ;-) |
| 19:44 | gigamonkey | hiredman: come on, we're on Internet time here. |
| 19:44 | hiredman | sorry |
| 19:45 | hiredman | it's been online for *beats* |
| 19:45 | gigamonkey | heh. |
| 19:46 | brehaut | hah |
| 19:46 | devn | gigamonkey: i have now |
| 19:48 | offby1 | what devn said :) |
| 19:53 | offby1 | "optional type hints", eh? Cool |
| 20:17 | offby1 | "Hammock-Driven Development". I'd sign up for that. |
| 20:19 | Moominpapa | I imagine I'll get a "doc" answer for this one, but is there a function in the standard library equivalent to (fn [coll f] (reduce #(assoc %1 %2 (f %2)) {} coll))? |
| 20:21 | brehaut | (into {} (map (juxt identity f) coll)) |
| 20:22 | hiredman | wrong |
| 20:22 | brehaut | figures |
| 20:22 | hiredman | Moominpapa: not really |
| 20:22 | hiredman | ,(let [a {:a 1}] (zipmap (keys a) (map inc (vals a)))) |
| 20:22 | clojurebot | {:a 2} |
| 20:23 | Moominpapa | I guess group-by does the opposite... |
| 20:23 | hiredman | brehaut: pardon me, I think I misread that |
| 20:24 | brehaut | hiredman: no problem |
| 20:27 | Moominpapa | Thanks. |
| 20:32 | technomancy | clojurebot: uh oh |
| 20:32 | clojurebot | Excuse me? |
| 20:33 | Moominpapa | It uses leiningen... :) |
| 20:52 | __name__ | Nice nick, btw :) |
| 20:53 | offby1 | there's an offbyone out there, too; we run into each other occasionally and duel |
| 20:54 | __name__ | Heh |
| 21:36 | mattb[] | howdy |
| 21:37 | mattb[] | brand new to clojure, lisp, and functional programming in general (raised on C) |
| 21:37 | mattb[] | I was looking at different fibonacci implementations and found one using data recursion rather than function recursion: |
| 21:38 | mattb[] | (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))) |
| 21:38 | mattb[] | two questions about this: |
| 21:38 | amalloy | mattb[]: yeah, brehaut likes that one |
| 21:39 | mattb[] | 1. does evaluating (rest fib-seq) and fib-seq in the map reevaluate the sequence for *each*, or once the lazy sequence is evaluated does it cache the values? |
| 21:39 | amalloy | lazy seqs are cached |
| 21:39 | mattb[] | 2. how does the functional community look at problems like this; prefer data recursion, or prefer function recursion? |
| 21:39 | mattb[] | alright cool, I figured |
| 21:39 | amalloy | mattb[]: the definition there is one that's popular in haskell |
| 21:39 | mattb[] | something about data recursion seems ridiculously elegant to me |
| 21:39 | brehaut | data recursion like that is good in haskell, less good in clojure |
| 21:40 | mattb[] | ah |
| 21:40 | brehaut | because its hard to define that in a non-global way |
| 21:40 | brehaut | s/hard/awkard/ |
| 21:40 | sexpbot | <brehaut> because its awkard to define that in a non-global way |
| 21:40 | mattb[] | gotcha |
| 21:40 | dnolen | brehaut: I disagree. |
| 21:40 | dnolen | mattb[]: that style is natural in Clojure as it has neither TCO nor Haskell laziness. |
| 21:40 | amalloy | in clojure i like ##(take 15 (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))) |
| 21:40 | sexpbot | ⟹ (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377) |
| 21:42 | mattb[] | I've come to appreciate s-expressions pretty quickly, but I still have a crazy hard time wrapping my head around code |
| 21:42 | amalloy | $google clojure rosetta-code fibonacci |
| 21:42 | sexpbot | First out of 61 results is: Fibonacci sequence - Rosetta Code |
| 21:42 | sexpbot | http://rosettacode.org/wiki/Fibonacci_sequence |
| 21:42 | brehaut | dnolen: im weak on binding-fu and vars, but i dont know how to create a definition of fib like the recurvsive one mattb[] showed that doesnt have a global var (and the head-retention that goes along with it) |
| 21:42 | amalloy | mattb[]: an explanation of my code is there |
| 21:43 | mattb[] | awesome thanks amalloy |
| 21:43 | brehaut | dnolen: what have i got wrong ? |
| 21:43 | dnolen | brehaut: you can name anon fns. |
| 21:43 | brehaut | dnolen: im not sure if we are talking about the same thing? |
| 21:43 | brehaut | oh |
| 21:44 | brehaut | actually we are and i misread the definition |
| 21:44 | dnolen | mattb[]: lazy-seqs are particularly powerful as they can be mutually recursive. |
| 21:45 | mattb[] | so this wikipedia article claims the haskell-inspired fib to be "more elegant"; what makes you prefer the iterate version amalloy? |
| 21:45 | amalloy | mattb[]: well, if someone on rosettacode says it's more elegant, it must be true... |
| 21:46 | mattb[] | oh lol this isn't wikipedia.. duh |
| 21:47 | amalloy | mattb[]: the way the haskell version is implemented on rosetta code involves holding the head of the lazy sequence, so would eventually run out of memory |
| 21:47 | mattb[] | "map first ;; throw away the "metadata" (see below) to view just the fib numbers" it doesn't explain this; what's the deal with metadata? |
| 21:47 | mattb[] | ahh ok |
| 21:47 | mattb[] | that's what was meant by head retention |
| 21:47 | amalloy | dnolen is probably right in that it could be implemented better |
| 21:48 | amalloy | mattb[]: when i wrote that, i meant something like "turn each [prev, next] pair into just one integer" |
| 21:48 | amalloy | feel free to edit in a way as to make that clearer |
| 21:48 | mattb[] | ah k |
| 21:50 | mattb[] | this does seem a lot more sane than the "more elegant" version |
| 21:51 | amalloy | it's an acquired taste, i'm sure |
| 21:53 | mattb[] | thanks for the help guys |
| 21:55 | mattb[] | by the way, in the doc for iterate: "f must be free of side-effects" how is this explicitly enforced? are builtins flagged for whether or not they allow side effects? |
| 21:55 | brehaut | mattb[]: its not |
| 21:55 | danlarkin | it should read "f _should_ be free of side-effects" |
| 21:56 | mattb[] | k |
| 21:57 | brehaut | mattb[]: an effects tracking system is requires a lot of complexity (see also: haskell) akin to (or part of) a type system |
| 21:57 | mattb[] | aye |
| 21:58 | mattb[] | am I right in seeing haskell as more of a research language than for practical use? |
| 21:58 | brehaut | mattb[]: http://www.codequarterly.com/2011/rich-hickey/ search for "I think Haskell is a fantastic" and read the next 3 paragraphs |
| 21:58 | dnolen | mattb[]: not true these days, people using haskell for pratical things. |
| 21:58 | brehaut | mattb[]: not really. |
| 21:58 | brehaut | mattb[]: its practical once you master it, its just not easy to master |
| 21:59 | mattb[] | ah |
| 21:59 | dnolen | mattb[]: also possible to get verification for Clojure via Datalog/Prolog, I'm working on that. |
| 21:59 | mattb[] | nice link brehaut |
| 22:03 | mattb[] | something I was having a hard time finding is in situ algorithms in functional languages; the quicksort example I saw for clojure specifically mentioned that "this isn't really quicksort since it's not in situ" |
| 22:03 | mattb[] | what would something like that look like? |
| 22:04 | brehaut | it would look like the imperative example that had been mangled a little, and it would operate on a transient |
| 22:04 | brehaut | in the future it might operate inside a pod, and in haskell it would exist inside an effectful type context. |
| 22:04 | mattb[] | is this a case where such an algorithm would just be a poor choice for a functional implementation? |
| 22:05 | brehaut | it depends? |
| 22:06 | mattb[] | I mean, do you reap the memory benefits of an in situ algorithm if it's not in situ? |
| 22:06 | dnolen | mattb[]: remember Clojure's not didactic about purity, you can implement quicksort on a mutable array if you like. |
| 22:06 | mattb[] | aye, I'm thinking more from a general functional context though |
| 22:06 | dnolen | functional languages like OCaml and Standard ML have similar escape hatches. |
| 22:06 | mattb[] | still trying to wrap my head around how you guys get anything done without state :p |
| 22:06 | brehaut | mattb[]: we use state when we need to |
| 22:07 | brehaut | clojure excels at handling state |
| 22:07 | mattb[] | I see |
| 22:07 | dnolen | mattb[]: Clojure probably has more state management facilities than pretty much any language out there except Haskell. |
| 22:07 | brehaut | as dnolen said, theres mutable arrays, we have access to javas mutable collections, transient versions of clojures collections, and a grab bag of great reference types |
| 22:10 | brehaut | mattb[]: imperitive state is also trivially modelable as a bunch of functions that take a 'world' and return a new 'world, and through the power of higher order functions, you can abstract that away |
| 22:12 | brehaut | you might have encountered these in C# or F# as Linq or Workflows if you've lived in dotnet land |
| 22:13 | mattb[] | yep, coming from C# actually |
| 22:13 | brehaut | C# is actually a pretty decent halfway point to functional languages |
| 22:13 | brehaut | its just the average stdlib that lets it down |
| 22:13 | brehaut | (ie, all the old stuff) |
| 22:14 | mattb[] | the biggest hurdle so far is remembering what data structures look like in clojure; I keep trying to pass an integer from a vector to map lol |
| 22:14 | mattb[] | the whole lisp thing is eating my brain |
| 22:14 | brehaut | i dont follow |
| 22:15 | mattb[] | just misinterpreting what I'm actually passing around |
| 22:16 | mattb[] | is that "ants" demo from rich hickey still a good example to learn from? I know a few minor things changed syntax-wise |
| 22:16 | mattb[] | (e.g. vec in lieu of apply vector) |
| 22:17 | brehaut | theres also a few fairly significant library additions that make the ode a bunch cleaner |
| 22:17 | brehaut | and defstruct has been deprecated |
| 22:17 | mattb[] | aha |
| 22:17 | mattb[] | that's good to know |
| 22:17 | brehaut | it uses (dorun (for …)) or something (could be doall, or have a map or something) where doseq would be better |
| 22:18 | brehaut | and it uses send-off in place of (for example) future from memory |
| 22:19 | mattb[] | dorun retains the head like doall? |
| 22:19 | brehaut | nah one of them doesnt |
| 22:20 | mattb[] | k |
| 22:20 | brehaut | but doseq should generally be your first choice for side-effects on sequences |
| 22:20 | brehaut | not least of all because it has full comprehension notation supported |
| 22:21 | brehaut | doall retains the head btw, dorun discards |
| 22:21 | mattb[] | yeah |
| 22:22 | mattb[] | found a couple list messages about them |
| 22:23 | mattb[] | by the way, can fn [_] be anonymized? I found I couldn't get it to infer an argument in an anonymous function without using it |
| 22:23 | mattb[] | (by anonymous I mean #, maybe that's just sugar?) |
| 22:23 | brehaut | by fn [_] you mean a functio nthat ignores its argument? |
| 22:24 | mattb[] | yea |
| 22:24 | brehaut | you cant use the #() reader form to abbreviate it no |
| 22:24 | mattb[] | k |
| 22:24 | brehaut | but constantly might be what you are after |
| 22:24 | brehaut | &(map (constantly :a) (range 10)) |
| 22:24 | sexpbot | ⟹ (:a :a :a :a :a :a :a :a :a :a) |
| 22:25 | amalloy | &(map #(do % :a) (range 10)) |
| 22:25 | sexpbot | ⟹ (:a :a :a :a :a :a :a :a :a :a) |
| 22:25 | brehaut | amalloy: yuk :P |
| 22:25 | mattb[] | haha |
| 22:25 | amalloy | not recommended, but fulfills the stated requirements |
| 22:26 | mattb[] | what does evaluating the arguments even do? |
| 22:26 | amalloy | ? |
| 22:27 | mattb[] | if you did that to a list with a function in it, would it call the function? |
| 22:27 | mattb[] | (the do %) |
| 22:27 | amalloy | no |
| 22:27 | amalloy | it's a no-op, although it might not get entirely compiled away |
| 22:27 | mattb[] | k |
| 22:28 | mattb[] | when was defstruct deprecated? it's not documented as such in the api ref |
| 22:28 | brehaut | it was deprecated when defrecord was introduced |
| 22:30 | brehaut | http://clojure.org/data_structures#Data%20Structures-StructMaps |
| 22:30 | brehaut | the word 'depreciated' isnt used |
| 22:30 | mattb[] | indeed |
| 22:30 | mattb[] | I disregarded that note before |
| 22:30 | brehaut | "Note: Most uses of StructMaps would now be better served by http://clojure.org/datatypes." |
| 22:30 | mattb[] | so defstruct was a hashmap and defrecord is an actual java class with final fields? |
| 22:31 | brehaut | defrecord is still a map |
| 22:31 | brehaut | but yes, its backed by a custom class |
| 22:32 | brehaut | consider them an intermediate feature of the language though, you dont need them |
| 22:33 | mattb[] | so in hickey's example, (defstruct cell :food :pher) would be better served by defrecord or a different structure entirely? |
| 22:34 | brehaut | 'better' how? |
| 22:34 | brehaut | for performance, yeah a record |
| 22:34 | brehaut | but a map would suffice |
| 22:34 | mattb[] | in terms of deprecation/more "functional" |
| 22:34 | mattb[] | k |
| 22:34 | brehaut | neither is 'more functional' |
| 22:35 | brehaut | structs were just maps with certain keys given a performance optimisation |
| 22:35 | mattb[] | aye |
| 22:36 | brehaut | the clojure idiom is to write your code in terms of the abstraction, in this case maps (with keyword keys) |
| 22:36 | brehaut | and maps are the general case of that |
| 22:37 | brehaut | with structs and records as implementation details |
| 22:37 | mattb[] | gotcha |
| 22:37 | brehaut | thats good, cause i made a meal of the typing ;) |
| 23:08 | dnolen | man I love macros |
| 23:10 | brehaut | dnolen: any particular reason today? |
| 23:11 | dnolen | brehaut: implementing IFn deftype in pure Clojure, lots of crazy boilerplate eliminated. |
| 23:11 | brehaut | oh true cool |
| 23:12 | brehaut | ifn has a million arg variations right? |
| 23:12 | dnolen | yeah |
| 23:47 | amalloy | psh. i'm sure careful consideration went into each line of AFn.java |
| 23:48 | brehaut | im sure it was either a hand manging emacs chord or an arcane jumble of vim |
| 23:50 | dnolen | AFn.java would drive anyone screaming to macros. |
| 23:51 | amalloy | dnolen: so you might think, but look at MouseAdapter in awt |
| 23:52 | mattb[] | hahaha |
| 23:52 | mattb[] | just looked up afn.java |
| 23:53 | mattb[] | I'd like to believe someone did this by hand |