Local memoization without letrec?
The recipe for memoizing a recursive function is: (defn fib [x] ...) (def fib (memoize fib)) I want to do something like this for local functions, because I want to make a function that *produces* memoized functions (that way I can have a bunch of similar functions with their own memoized cache). So I need to create the memoized function locally and return it. But I can't think of any way to do this without letrec. Any suggestions? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
Something like (defn make-memoized [some-param] (let [cache (atom {})] (fn [ args] (when-not (contains? cache args) (swap! cache assoc args (expensive-computation some-param args))) (cache args ? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
On Thu, Jan 19, 2012 at 9:46 PM, Cedric Greevey cgree...@gmail.com wrote: Something like (defn make-memoized [some-param] (let [cache (atom {})] (fn [ args] (when-not (contains? cache args) (swap! cache assoc args (expensive-computation some-param args))) (cache args Two points: 1. I want the expensive-computation to be recursive. I think this can be done by adding name to the anonymous function between the fn and the [ args]. 2. Ideally, I don't want to clutter my code by restating the caching behavior every time I do this. I'd like to leverage something like the built in memoize. That's what I don't think is possible. However, you've given me an idea that maybe I can just write a macro, something like (memofn fib [x] (if (= n 1) n (+ (fib (dec n)) (fib (- n 2) which would expand into something that would work locally. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
I think this works: (defmacro memofn [name args body] `(let [cache# (atom {})] (fn ~name ~args (if-let [e# (find @cache# ~args)] (val e#) (let [ret# ~body] (swap! cache# assoc ~args ret#) ret#) If you spot any problems with this that I'm missing let me know. Thanks for brainstorming with me! -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
On Fri, Jan 20, 2012 at 1:34 AM, Mark Engelberg mark.engelb...@gmail.com wrote: I think this works: (defmacro memofn [name args body] `(let [cache# (atom {})] (fn ~name ~args (if-let [e# (find @cache# ~args)] (val e#) (let [ret# ~body] (swap! cache# assoc ~args ret#) ret#) If you spot any problems with this that I'm missing let me know. Multi-sexp bodies will screw this one up. Change ~body to (do ~@body) to fix that. Thanks for brainstorming with me! You're welcome. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
Fixed: (defmacro memofn [name args body] `(let [cache# (atom {})] (fn ~name ~args (if-let [e# (find @cache# ~args)] (val e#) (let [ret# (do ~@body)] (swap! cache# assoc ~args ret#) ret#) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Local memoization without letrec?
Hi, just in case you want a thread-safe, optimal version based on the classic memoize discussion[1]. (defmacro memofn [name args body] `(let [cache# (atom {})] (fn ~name [ args#] (let [update-cache!# (fn update-cache!# [state# args#] (if-not (contains? state# args#) (assoc state# args# (delay (let [~args args#] ~@body))) state#))] (let [state# (swap! cache# update-cache!# args#)] (- state# (get args#) deref)) Sincerely Meikel [1]: http://kotka.de/blog/2010/03/memoize_done_right.html -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Is 'declare' possibly the missing component here? On Dec 14, 3:37 pm, Razvan Rotaru razvan.rot...@gmail.com wrote: Yes. Assuming I have following macros: (button :id b1 :listener #(...)) = (let [b1 (new JButton)] ...) (panel [:id p1] (button :id b1 ...) (button :id b2 ...)) = (let [p1 (new JPanel) b1 (button :id b1 ...) b2 (button :id b2 ...)] ...) How to make the listener in b1 refer to b2? Razvan On Dec 14, 11:09 pm, David Nolen dnolen.li...@gmail.com wrote: Do you have a minimal example of what you are trying to do? On Wed, Dec 14, 2011 at 3:53 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: letfn defines functions. I'm just defining some values. The values contain anonymous functions which need to refer to other values.I know there are workarounds for this, but this means I must change the interface. Razvan On Dec 14, 9:56 pm, David Nolen dnolen.li...@gmail.com wrote: On Wed, Dec 14, 2011 at 2:53 PM, Razvan Rotaru razvan.rot...@gmail.com wrote: I don't quite understand why people are saying this. Anyway, It's not enough for me. What can't you solve your problem with what was suggested? David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
'declare' wouldn't be good because of the scope of vars. There's no sense using global (albeit namespaced) variables for what probably only need to be local identifiers. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Hi, to implement letrec in a language with eager evaluation strategy some kind of mutability is probably needed. Consider for example a self- referential definition such as (let [fibo (lazy-cat [1 1] (map + fibo (rest fibo)))] (take 10 fibo)) This will not work since fibo is not in scope when the binding is established. The standard solution would probably be something like this (let [fibo (promise)] (deliver fibo (lazy-cat [1 1] (map + @fibo (rest @fibo (take 10 @fibo)) Not as nice as the original version due to explicit dereferencing, but workable. As an alternative one could use a macro to expand to this and use a code walker (or symbol-macros) to automatically include the @ calls. The following is untested, but should be close: (defmacro letrec [binding body] (let [[var expr] binding g-var (gensym)] `(let [~g-var (promise)] (symbol-macrolet [~var @~g-var] (deliver ~g-var ~expr) ~@body and voila (letrec [fibo (lazy-cat [1 1] (map + fibo (rest fibo)))] (take 10 fibo)) produces (1 1 2 3 5 8 13 21 34 55). Best, Nils -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Hi, you'll probably have to rewrite your panel macro, so that it recognizes the button (and label, etc) macros ((= #'button (resolve env sym)) in 1.3) and extracts the ids from the subform. Then you construct a global let which contains all the individual id namings. Then you group all '...' parts (from your standalone button example) in the body of the let. Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Hi, if you always follow the let structure you outlined the following might work. Untested, though. Note, that things work recursively with this approach. (def ours? #{#'button #'label ...}) (defmacro panel [{:keys [id]} components] (let [[bindings body] (reduce (fn [[bindings body] component] (if (and (seq? component) (ours? (resolve env (first component (let [[_let local-bindings local-body] (macroexpand-1 component)] [(into bindings local-bindings) (into body local-body)]) ; Keep stuff we don't know. [bindings (conj body component)])) [[id `(JPanel.)] []] components)] `(let ~bindings ~@body ... ~id))) Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
letrec
Hi, Is there a reliable implementation of letrec in clojure? Anybody using it? I have found a post from 2008, with an implementation which I don't understand (and it's said to be slow), and which I don't know whether to trust.(It's also supposed to be slow). Thanks, Razvan -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
lazy-seq and letfn should cover anything you would need letrec for On Wed, Dec 14, 2011 at 11:09 AM, Razvan Rotaru razvan.rot...@gmail.com wrote: Hi, Is there a reliable implementation of letrec in clojure? Anybody using it? I have found a post from 2008, with an implementation which I don't understand (and it's said to be slow), and which I don't know whether to trust.(It's also supposed to be slow). Thanks, Razvan -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
I don't quite understand why people are saying this. Anyway, It's not enough for me. On Dec 14, 9:13 pm, Kevin Downey redc...@gmail.com wrote: lazy-seq and letfn should cover anything you would need letrec for On Wed, Dec 14, 2011 at 11:09 AM, Razvan Rotaru razvan.rot...@gmail.com wrote: Hi, Is there a reliable implementation of letrec in clojure? Anybody using it? I have found a post from 2008, with an implementation which I don't understand (and it's said to be slow), and which I don't know whether to trust.(It's also supposed to be slow). Thanks, Razvan -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
On Wed, Dec 14, 2011 at 2:53 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: I don't quite understand why people are saying this. Anyway, It's not enough for me. What can't you solve your problem with what was suggested? David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
letfn defines functions. I'm just defining some values. The values contain anonymous functions which need to refer to other values.I know there are workarounds for this, but this means I must change the interface. Razvan On Dec 14, 9:56 pm, David Nolen dnolen.li...@gmail.com wrote: On Wed, Dec 14, 2011 at 2:53 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: I don't quite understand why people are saying this. Anyway, It's not enough for me. What can't you solve your problem with what was suggested? David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Do you have a minimal example of what you are trying to do? On Wed, Dec 14, 2011 at 3:53 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: letfn defines functions. I'm just defining some values. The values contain anonymous functions which need to refer to other values.I know there are workarounds for this, but this means I must change the interface. Razvan On Dec 14, 9:56 pm, David Nolen dnolen.li...@gmail.com wrote: On Wed, Dec 14, 2011 at 2:53 PM, Razvan Rotaru razvan.rot...@gmail.com wrote: I don't quite understand why people are saying this. Anyway, It's not enough for me. What can't you solve your problem with what was suggested? David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: letrec
Yes. Assuming I have following macros: (button :id b1 :listener #(...)) = (let [b1 (new JButton)] ...) (panel [:id p1] (button :id b1 ...) (button :id b2 ...)) = (let [p1 (new JPanel) b1 (button :id b1 ...) b2 (button :id b2 ...)] ...) How to make the listener in b1 refer to b2? Razvan On Dec 14, 11:09 pm, David Nolen dnolen.li...@gmail.com wrote: Do you have a minimal example of what you are trying to do? On Wed, Dec 14, 2011 at 3:53 PM, Razvan Rotaru razvan.rot...@gmail.comwrote: letfn defines functions. I'm just defining some values. The values contain anonymous functions which need to refer to other values.I know there are workarounds for this, but this means I must change the interface. Razvan On Dec 14, 9:56 pm, David Nolen dnolen.li...@gmail.com wrote: On Wed, Dec 14, 2011 at 2:53 PM, Razvan Rotaru razvan.rot...@gmail.com wrote: I don't quite understand why people are saying this. Anyway, It's not enough for me. What can't you solve your problem with what was suggested? David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: RFC on my letrec macro
sorry, wrong gist. here's one that tests for a function and only calls trampoline on it. all three of your test cases work for it. http://gist.github.com/487019 g On Jul 22, 10:50 pm, Michał Marczyk michal.marc...@gmail.com wrote: On 23 July 2010 06:50, George Jahad cloj...@blackbirdsystems.net wrote: i like it a lot! what do you think of adding trampoline to it like so: http://gist.github.com/487019 Thanks! Trampoline in letrec automatically breaks all cases where the value being bound to the local is not a function, so it would interfere with what I'm trying to do. Having said that, it seems to me that it's a very cool idea for a custom letfn variant permitting mutual recursion of unbounded depth. I'll investigate this further. All the best, Michał -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: RFC on my letrec macro
Just realized there are many types of recursive functions for which trampoline can't be used in this way. It's an interesting problem though. I'm going to think some more about it. On Jul 22, 11:11 pm, George Jahad cloj...@blackbirdsystems.net wrote: sorry, wrong gist. here's one that tests for a function and only calls trampoline on it. all three of your test cases work for it. http://gist.github.com/487019 g On Jul 22, 10:50 pm, Michał Marczyk michal.marc...@gmail.com wrote: On 23 July 2010 06:50, George Jahad cloj...@blackbirdsystems.net wrote: i like it a lot! what do you think of adding trampoline to it like so: http://gist.github.com/487019 Thanks! Trampoline in letrec automatically breaks all cases where the value being bound to the local is not a function, so it would interfere with what I'm trying to do. Having said that, it seems to me that it's a very cool idea for a custom letfn variant permitting mutual recursion of unbounded depth. I'll investigate this further. All the best, Michał -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
RFC on my letrec macro
Hi All, I've written a letrec macro with the goal of hopefully tying the knot [1] in Clojure etc. Some examples of what it can do are included in the Gist (including -- as of now -- two not immediately rewritable in terms of letfn). So far I haven't caught any bugs, but hey, it's about an hour old and the knot is still untied... Any comments / suggestions / remarks on this being crazy? http://gist.github.com/486880 Sincerely, Michał [1] http://www.haskell.org/haskellwiki/Tying_the_Knot -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: RFC on my letrec macro
On 23 July 2010 06:50, George Jahad cloj...@blackbirdsystems.net wrote: i like it a lot! what do you think of adding trampoline to it like so: http://gist.github.com/487019 Thanks! Trampoline in letrec automatically breaks all cases where the value being bound to the local is not a function, so it would interfere with what I'm trying to do. Having said that, it seems to me that it's a very cool idea for a custom letfn variant permitting mutual recursion of unbounded depth. I'll investigate this further. All the best, Michał -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en