Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-26 Thread Jack Firth
On Wednesday, April 26, 2017 at 9:48:56 AM UTC-7, David K. Storrs wrote:
> On Wed, Apr 26, 2017 at 12:21 AM, Jon Zeppieri  wrote:
> I don't know that there's a right way, but if your functions are
> 
> nullary, then promises are a decent fit:
> 
> 
> 
> (define conf
> 
>   (delay
> 
>     (with-input-from-file ...)))
> 
> 
> 
> Then just (force conf) whenever you want the value.
> 
> 
> 
> Yeah, that works well.  Thanks!
> 
> 
> Any thoughts on how to do it for non-nullary functions? 

For non-nullary functions, you're looking for memoization / caching. There's a 
couple packages that do this, along with relate

- In the `sugar` package, the `sugar/cache` module gives you exactly this, in 
the form of a `define/caching` macro.
- The `tmemoize` package provides similar functionality for Typed Racket 
functions.
- The `with-cache` package gives you promise-like behavior for thunks that use 
an external storage system.
- The `remember` package gives you caching behavior for compile-time 
expressions that can be remembered across compilation runs.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-26 Thread Jon Zeppieri
On Wed, Apr 26, 2017 at 12:48 PM, David Storrs  wrote:
>
>
> On Wed, Apr 26, 2017 at 12:21 AM, Jon Zeppieri  wrote:
>>
>> I don't know that there's a right way, but if your functions are
>> nullary, then promises are a decent fit:
>>
>> (define conf
>>   (delay
>> (with-input-from-file ...)))
>>
>> Then just (force conf) whenever you want the value.
>
>
> Yeah, that works well.  Thanks!
>
> Any thoughts on how to do it for non-nullary functions?
>>

The more complicated your function signatures get, the more worthwhile
it will be to use the memoize package. But for, say, unary functions
you can easily use a hash table:

#lang racket

(define read-conf
  (let ([h (make-hash)])
(λ (arg)
  (hash-ref! h
 arg
 (thunk ...)

You can extend this to multiple arguments by using lists as keys, if
you want. Of course, you need to make sure that `equal?` is usefully
defined on your argument types.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-26 Thread David Storrs
On Wed, Apr 26, 2017 at 12:21 AM, Jon Zeppieri  wrote:

> I don't know that there's a right way, but if your functions are
> nullary, then promises are a decent fit:
>
> (define conf
>   (delay
> (with-input-from-file ...)))
>
> Then just (force conf) whenever you want the value.
>

Yeah, that works well.  Thanks!

Any thoughts on how to do it for non-nullary functions?

>
>
>
> On Wed, Apr 26, 2017 at 12:12 AM, David Storrs 
> wrote:
> > Reading configuration files is a good example of a run-once function.
> It's
> > effectively self-memoizing -- it should run once, cache its result, and
> on
> > future calls just return the cached value.  I could pull in
> > https://docs.racket-lang.org/memoize/index.html or
> > http://docs.racket-lang.org/mischief@mischief/memoize.html to do that,
> but
> > adding an extra module to the project just for one or two functions feels
> > pretty heavy. (Also, memoizing is overkill if the functions are
> thunks.)  Is
> > there a simple way to do this in pure Racket?
> >
> > In Perl I would do something like this (for simplicity I'm ignoring
> encoding
> > and assuming that the config file is JSON):
> >
> > use JSON;
> > sub read_conf {
> >   state $conf = do {
> > local $/;
> > open my $fh, "<", "db.conf" or die "failed to open config: $!";
> > from_json( <$fh> )
> >   };
> >   $conf
> > }
> >
> >
> > I could do this in Racket using set!, but that's not very Rackety:
> >
> > (require json)
> > (define conf #f)
> > (define (read-conf)
> >(or conf
> >  (begin
> >(set! conf (with-input-from-file "db.conf" (thunk
> (read-json
> >conf)))
> >
> >
> > I could do it with a parameter but that's only sweeping the above
> ugliness
> > under the rug:
> >
> > (define conf (make-parameter #f))
> > (define (read-conf)
> >(or (conf)
> >  (begin
> >(conf (with-input-from-file "db.conf" (thunk (read-json
> >(conf
> >
> > What is the right way?
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Racket Users" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to racket-users+unsubscr...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-26 Thread Matthias Felleisen

#lang racket

(define read-conf
  (let [(conf (delay (with-input-from-file “db.conf" (thunk (displayln "hello") 
(read)]
(thunk 
 (force conf

(read-conf)
(read-conf)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-26 Thread Tim Brown
On Wednesday, April 26, 2017 at 5:21:41 AM UTC+1, Jon Zeppieri wrote:
> (define conf
>   (delay
> (with-input-from-file ...)))
> 
> Then just (force conf) whenever you want the value.

I tend to call promises xxx-promise (e.g. conf-promise),
to remind me not to use them without force'ing them.

Does anyone else hold to a convention for naming promises?

Tim

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-25 Thread Jon Zeppieri
I don't know that there's a right way, but if your functions are
nullary, then promises are a decent fit:

(define conf
  (delay
(with-input-from-file ...)))

Then just (force conf) whenever you want the value.



On Wed, Apr 26, 2017 at 12:12 AM, David Storrs  wrote:
> Reading configuration files is a good example of a run-once function.  It's
> effectively self-memoizing -- it should run once, cache its result, and on
> future calls just return the cached value.  I could pull in
> https://docs.racket-lang.org/memoize/index.html or
> http://docs.racket-lang.org/mischief@mischief/memoize.html to do that, but
> adding an extra module to the project just for one or two functions feels
> pretty heavy. (Also, memoizing is overkill if the functions are thunks.)  Is
> there a simple way to do this in pure Racket?
>
> In Perl I would do something like this (for simplicity I'm ignoring encoding
> and assuming that the config file is JSON):
>
> use JSON;
> sub read_conf {
>   state $conf = do {
> local $/;
> open my $fh, "<", "db.conf" or die "failed to open config: $!";
> from_json( <$fh> )
>   };
>   $conf
> }
>
>
> I could do this in Racket using set!, but that's not very Rackety:
>
> (require json)
> (define conf #f)
> (define (read-conf)
>(or conf
>  (begin
>(set! conf (with-input-from-file "db.conf" (thunk (read-json
>conf)))
>
>
> I could do it with a parameter but that's only sweeping the above ugliness
> under the rug:
>
> (define conf (make-parameter #f))
> (define (read-conf)
>(or (conf)
>  (begin
>(conf (with-input-from-file "db.conf" (thunk (read-json
>(conf
>
> What is the right way?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Best way to write run-once-and-cache functions?

2017-04-25 Thread Philip McGrath
In this very simple case, I would probably not define a function at all,
just something like

(define conf
  (with-input-from-file "db.conf"
read-json))


You may also find yourself wanting define-runtime-path from
racket/runtime-path.

On Tue, Apr 25, 2017 at 11:12 PM, David Storrs 
wrote:

> Reading configuration files is a good example of a run-once function.
> It's effectively self-memoizing -- it should run once, cache its result,
> and on future calls just return the cached value.  I could pull in
> https://docs.racket-lang.org/memoize/index.html or
> http://docs.racket-lang.org/mischief@mischief/memoize.html to do that,
> but adding an extra module to the project just for one or two functions
> feels pretty heavy. (Also, memoizing is overkill if the functions are
> thunks.)  Is there a simple way to do this in pure Racket?
>
> In Perl I would do something like this (for simplicity I'm ignoring
> encoding and assuming that the config file is JSON):
>
> use JSON;
> sub read_conf {
>   state $conf = do {
> local $/;
> open my $fh, "<", "db.conf" or die "failed to open config: $!";
> from_json( <$fh> )
>   };
>   $conf
> }
>
>
> I could do this in Racket using set!, but that's not very Rackety:
>
> (require json)
> (define conf #f)
> (define (read-conf)
>(or conf
>  (begin
>(set! conf (with-input-from-file "db.conf" (thunk (read-json
>conf)))
>
>
> I could do it with a parameter but that's only sweeping the above ugliness
> under the rug:
>
> (define conf (make-parameter #f))
> (define (read-conf)
>(or (conf)
>  (begin
>(conf (with-input-from-file "db.conf" (thunk (read-json
>(conf
>
> What is the right way?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Best way to write run-once-and-cache functions?

2017-04-25 Thread David Storrs
Reading configuration files is a good example of a run-once function.  It's
effectively self-memoizing -- it should run once, cache its result, and on
future calls just return the cached value.  I could pull in
https://docs.racket-lang.org/memoize/index.html or
http://docs.racket-lang.org/mischief@mischief/memoize.html to do that, but
adding an extra module to the project just for one or two functions feels
pretty heavy. (Also, memoizing is overkill if the functions are thunks.)
Is there a simple way to do this in pure Racket?

In Perl I would do something like this (for simplicity I'm ignoring
encoding and assuming that the config file is JSON):

use JSON;
sub read_conf {
  state $conf = do {
local $/;
open my $fh, "<", "db.conf" or die "failed to open config: $!";
from_json( <$fh> )
  };
  $conf
}


I could do this in Racket using set!, but that's not very Rackety:

(require json)
(define conf #f)
(define (read-conf)
   (or conf
 (begin
   (set! conf (with-input-from-file "db.conf" (thunk (read-json
   conf)))


I could do it with a parameter but that's only sweeping the above ugliness
under the rug:

(define conf (make-parameter #f))
(define (read-conf)
   (or (conf)
 (begin
   (conf (with-input-from-file "db.conf" (thunk (read-json
   (conf

What is the right way?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.