Local memoization without letrec?

2012-01-19 Thread Mark Engelberg
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?

2012-01-19 Thread Cedric Greevey
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?

2012-01-19 Thread Mark Engelberg
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?

2012-01-19 Thread Mark Engelberg
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?

2012-01-19 Thread Cedric Greevey
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?

2012-01-19 Thread Mark Engelberg
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?

2012-01-19 Thread Meikel Brandmeyer (kotarak)
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

2011-12-15 Thread Daniel
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

2011-12-15 Thread Bobby Eickhoff
'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

2011-12-15 Thread Nils Bertschinger
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

2011-12-15 Thread Meikel Brandmeyer
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

2011-12-15 Thread Meikel Brandmeyer
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

2011-12-14 Thread Razvan Rotaru
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

2011-12-14 Thread Kevin Downey
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

2011-12-14 Thread Razvan Rotaru
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

2011-12-14 Thread David Nolen
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

2011-12-14 Thread Razvan Rotaru
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

2011-12-14 Thread David Nolen
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

2011-12-14 Thread Razvan Rotaru
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

2010-07-23 Thread George Jahad
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

2010-07-23 Thread George Jahad
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

2010-07-22 Thread Michał Marczyk
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

2010-07-22 Thread Michał Marczyk
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