Damian Conway <[EMAIL PROTECTED]> writes:

> Luke Palmer wrote:
>
>
>>     sub a_pure_func(Num $n) returns Num {
>>         class is Num {
>>             method FETCH { $n * $n } }.new     }
>> Yes?  No?
>
> Not quite.
>
>
>  >     sub a_pure_func(Num $n) returns Num {
>  >         class is Num {
>  >             has Num $cache;
>  >             method FETCH { $cache //= $n * $n } } }
>
>
> Still not quite.
>
> You don't want a C<FETCH> method (which won't be called unless the
> object somehow becomes the implementation of a tied variable).
>
> What you want are conversion-to-(num|str|bool) methods:
>
>        sub a_pure_func(Num $n) returns Num {
>            class is Num {
>                has Num $cache;
>                sub value { $n * $n }
>                method operator:+ ($self:) { +($cache //= value ) }
>                method operator:~ ($self:) { ~($cache //= value ) }
>                method operator:? ($self:) { ?($cache //= value ) }
>            }.new
>        }

So, we'd have 'is lazy' do something like the following to the
declared sub?

    sub make_lazy(&func) {
      my $new_func = {
        &func.returns.make_deferred_object( &func, *@_ }
      };
      $new_func.signature(&func.signature);
      return $new_func;
    }

And then, say:

    class Object {
      method make_deferred_object($class is Class : &func, *@args) {
        class is $class {
          has $class $cache;
          sub value { &func(*@args) }
          method operator:+  { +($cache //= value) }
          method operator:~  { ~($cache //= value) }
          method operator:?  { ?($cache //= value) }
        }.new
      }
    }

Which is somewhat dependent on being able to do C<class is $class>. If
that's not possible then I'd hope you could do something like:

    given my $anon_class = Class.new {
      my $cache;
      .isa($class);
      .add_sub    'value'      => { &func(*@args) }
      .add_method 'operator:+' => {...}
      .add_method 'operator:~' => {...}
      .add_method 'operator:?' => {...}
      return .new;
    }

Hang on, couldn't you rewrite things to not use the cache?

    class is $class {
      sub value { &func(*@args) }
      method operator:+ ($self is rw:) { +($self = value) }
      method operator:~ ($self is rw:) { ~($self = value) }
      method operator:? ($self is rw:) { ?($self = value) }
    }.new

I don't know if I hope that works or hope it fails miserably. 

Also note that, if you were feeling sufficiently lazy with numbers,
you could define the set of binary operators for your deferred
numbers:

  method operator:+ ($self: Num $other) is lazy { +($self) + $other }
  method operator:* ($self: Num $other) is lazy { +($self) * $other }
  method operator:/ ($self: Num $other) is lazy { +($self) / $other }
  method operator:- ($self: Num $other) is lazy { +($self) - $other }

Or would that just be evil, Bad And Wrong?

-- 
Piers

   "It is a truth universally acknowledged that a language in
    possession of a rich syntax must be in need of a rewrite."
         -- Jane Austen?

Reply via email to