Re: Short-circuiting user-defined operators

2003-04-05 Thread Larry Wall
On Tue, Apr 01, 2003 at 08:26:38PM -0500, Joe Gottman wrote:
:Is there any way to write a user-defined operator so that it
: short-circuits, like  and || ?  This might be function trait, for
: instance,
: 
:   sub infix:!! ($lhs, $rhs) is short_circuit {...}

Honestly, you guys.  You make things so hard for yourselves.  I don't
see why that wouldn't just be:

sub infix:!! ($lhs, rhs) is equiv(infix:||) {...}

All closures are lazy by definition, and the rhs forces the right
side of !! to be a closure.  At worst, we'd have to change sub
to macro to give a special parsing rule to the right side.

Larry


Re: Short-circuiting user-defined operators

2003-04-03 Thread Austin Hastings
Dave Whipp wrote:

 Joe Gottman wrote:
 
  Alternatively, there might be a new parameter type that indicates 
  that the parameter is not evaluated immediately:
  
  sub infix:!! ($lsh, $rhs is deferred) {...}

 A nice concept! So nice, in fact, that it would be a shame to limit 
 it to function args. I could see myself writing:
 
 
my $a is lazy := expensive_fn1(...);
my $b is lazy := expensive_fn2(...);
 
print rand ?? $a :: $b;
 
 I'm not sure quite how the syntax would work (should I be binding or 
 assigning?); but there are definitely cases where this ability is 
 useful. Given this capability, defered evaluation of function args 
 would be trivial.
 
 Another, very different, situation where laziness is good is to 
 abstract fork/join situations:
 
 
my $a is lazy_thread := expensive_fn1(...);
my $b is lazy_thread := expensive_fn2(...);
 
print $a + $b;
 
 In this scenario, each expensive evaluation would be launched as a 
 separate thread. When the resulting value is later used, then the 
 thread would be joined, blocking if the thread is not complete.

This is very worth pursuing. 

I can see two ways to handle implicit threading -- at the object
level, or at the sub level.

Object Threading:
-
my Int $a is threaded = expensive_fn1(...);
...
print $a;   # Implicitly joins $a.thread() 

Sub Threading:
--
sub expensive_fn1(...) is threaded {...}

my Int $a = expensive_fn1();
...
print $a;

The sub threading version seems, at first blush, easier to implement --
since if the variable requires a thread, then things like := binding,
and expression evaluation, get more complex.

Also, of course, it seems easier for developers to grok the concept of
what's in parallel and what's not when using the Sub Threading
approach.

But what to do about matrix arithmetic and other simple threadable
tasks?

sub m_add(@a, @b)
{
  my @result;
  my $i, $j;

  @result = @a;
  for @result - $i {:is threaded   # Thread this block?
for @result[$i]; @b - $j; $b {
  $j += $b;
}
  }
}

Conversely, I have absolutely no idea what to do about threading on a
per-data-object basis:

sub m_add(@a is threaded, @b)
{
  ... What can the compiler figure out about threading @a?
}

This is one of those cases where the really smart guys who used to
spend time recoding the fortran compilers for Vaxen might be able to
clue us in on the cool tricks for vector processing, but how
generalizable will it all be?  (And, of course, is the internal
representation amenable to this?)

None of this addresses the issue of explicit threading -- cases where
the user wants to create and control her own threads. 


=Austin


Re: Short-circuiting user-defined operators

2003-04-03 Thread Paul

--- Austin Hastings [EMAIL PROTECTED] wrote:
 Dave Whipp wrote:
  Joe Gottman wrote:

Getting deep -- sorry. :)

   Alternatively, there might be a new parameter type that indicates
   that the parameter is not evaluated immediately:
   
   sub infix:!! ($lsh, $rhs is deferred) {...}

If the standard is pass-by-ref it wouldn't trip any side effects unless
you did so in your code, right? So is this necessary?

Next author

  A nice concept! So nice, in fact, that it would be a shame to limit
  it to function args. I could see myself writing:
  
 my $a is lazy := expensive_fn1(...);
 my $b is lazy := expensive_fn2(...);
 print rand ?? $a :: $b;

I could certainly see some sweet uses for this. Any input from the
design team on whether this is a pipe dream or not?

  I'm not sure quite how the syntax would work (should I be binding
  or  assigning?);

I'd say binding was right. $a is an implicit call to expensive_fn1(),
right? But that just looks like a tie to me. Maybe I misread it.

  but there are definitely cases where this ability is 
  useful. Given this capability, defered evaluation of function args 
  would be trivial.
  Another, very different, situation where laziness is good is to 
  abstract fork/join situations:
  
 my $a is lazy_thread := expensive_fn1(...);
 my $b is lazy_thread := expensive_fn2(...);
 print $a + $b;
 
  In this scenario, each expensive evaluation would be launched as a 
  separate thread. When the resulting value is later used, then the 
  thread would be joined, blocking if the thread is not complete.

So in this case you're saying to thread and execute the functions *now*
so that $a and $b can be coprocessing? That's different from the above
example. Sounds like a designer's nightmare, but a beautiful concept if
the language could take advantage of implicit threading that easily.

Next author

 This is very worth pursuing. 
 I can see two ways to handle implicit threading -- at the object
 level, or at the sub level.
 
 Object Threading:
 -
 my Int $a is threaded = expensive_fn1(...);
 ...
 print $a;   # Implicitly joins $a.thread() 
 
 Sub Threading:
 --
 sub expensive_fn1(...) is threaded {...}
 my Int $a = expensive_fn1();
 ...
 print $a;
 
 The sub threading version seems, at first blush, easier to implement
 -- since if the variable requires a thread, then things like :=
 binding, and expression evaluation, get more complex.

Agreed, though I'd say (in fact I did, abover :) that := binding would
probably be necessary for that sort of per-object threadingwhich
kind of makes it equivelent to the per-sub threading. If the sub is
threaded and you bind it to an object, then that's a compile-time bind,
right? pre-spawning the thread, maybe? Then when the runtime call
occurs the thread receives the relevant arg values and starts
proceccing them immediately, etc. Still sounds like an elaborate tie()
to me, but a beautiful way to do it.

 Also, of course, it seems easier for developers to grok the concept
 of what's in parallel and what's not when using the Sub Threading
 approach.

Agreed, though anyone using threading this way should obviously be VERY
careful about it threads are not something to do accidentally. I
might even say that such ability should only be available upon explicit
pragmatic request

  use threads :implicit; # maybe?
  use implicit :threads; # better?

or is that a horrifically inappropriate use of Larry's colon? :)

 But what to do about matrix arithmetic and other simple threadable
 tasks?
 
 sub m_add(@a, @b) {
   my @result;
   my $i, $j;
   @result = @a;
   for @result - $i {:is threaded   # Thread this block?
 for @result[$i]; @b - $j; $b {
   $j += $b;
 }
   }
 }

isn't $i an element alias rather than an index there?
Basically, I just failed to parse all that. Sorry -- internal P6 parser
still incomplete.

 Conversely, I have absolutely no idea what to do about threading on a
 per-data-object basis:
 
 sub m_add(@a is threaded, @b) {
   ... What can the compiler figure out about threading @a?
 }

I'd say this is unlikely to work, but again, I haven't exactly thought
it all through very thoroughly.

 This is one of those cases where the really smart guys who used to
 spend time recoding the fortran compilers for Vaxen might be able to
 clue us in on the cool tricks for vector processing, but how
 generalizable will it all be?  (And, of course, is the internal
 representation amenable to this?)
 None of this addresses the issue of explicit threading -- cases
 where the user wants to create and control her own threads. 

Or how they would interact. If you're doing implicit threading in a
program using explicit threading, things could get REALLY tang-toungled

__
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
http://tax.yahoo.com


Re: Short-circuiting user-defined operators

2003-04-03 Thread Mark Biggar
Paul wrote:
--- Austin Hastings [EMAIL PROTECTED] wrote:

Dave Whipp wrote:

Joe Gottman wrote:


Getting deep -- sorry. :)


Alternatively, there might be a new parameter type that indicates
that the parameter is not evaluated immediately:
sub infix:!! ($lsh, $rhs is deferred) {...}


If the standard is pass-by-ref it wouldn't trip any side effects unless
you did so in your code, right? So is this necessary?
There are two reasonable semantics for deferred parameters:

1) lazy evaluation with caching, where the evaluation of the
actual expression in the call is deferred until the sub
actauly makes use of it and the result is then cached and
reused as necessary.  Any side effects happen only once.
2) ALGOL style pass by name, where the actual expression from the
call is turned into a clouser called a thunk which is called
when ever the sub access the parameter.  Note that the thunk
may need to be an lvalue clouser to handle is rw paramenters.
Side effects happen each time the thunk is called.  Also changes
to the thunks environment can effect its value when called.
Either of those can have threading added as well.

--
Mark Biggar
[EMAIL PROTECTED]
[EMAIL PROTECTED]



Re: Short-circuiting user-defined operators

2003-04-03 Thread Austin Hastings

--- Paul [EMAIL PROTECTED] wrote:
  But what to do about matrix arithmetic and other simple threadable
  tasks?
  
  sub m_add(@a, @b) {
my @result;
my $i, $j;
@result = @a;
for @result - $i {:is threaded   # Thread this block?
  for @result[$i]; @b - $j; $b {
$j += $b;
  }
}
  }
 
 isn't $i an element alias rather than an index there?

Yeah, but I'm assuming a 2d matrix. @result[$i] is another array.

 Basically, I just failed to parse all that. Sorry -- internal P6
 parser still incomplete.

No, just bad writing on my part. Sorry.

 
  Conversely, I have absolutely no idea what to do about threading on
 a
  per-data-object basis:
  
  sub m_add(@a is threaded, @b) {
... What can the compiler figure out about threading @a?
  }
 
 I'd say this is unlikely to work, but again, I haven't exactly
 thought it all through very thoroughly.

I'm pretty sure it *could* work. Likewise, I'm sure we could live
without this for the first release, if we but grab the namespace we
think we'll need in advance. That's why this stuff should all be hints
to the interpreter -- what the box is actually capable of is not
something we can know.

Certainly it's trivial to thread basic vector processing:

1. Get max# of useful threads (#cpu's - 1)?

2. Every computation of a threaded vector member gets allocated to 
   a new thread, round-robin.

3. Any read of a threaded vector member forces a join on the allocated
   thread before proceeding.

This isn't optimal, but it would work. But knowing how much benefit
you're going to see will be part of the equation, too. So you want the
runtime to balance the startup/shutdown cost versus the execution cost,
if possible. Also, you want to favor threading when a blocking
operation might occur in the threadable code. That kind of stuff.

  This is one of those cases where the really smart guys who used to
  spend time recoding the fortran compilers for Vaxen might be able
  clue us in on the cool tricks for vector processing, but how
  generalizable will it all be?  (And, of course, is the internal
  representation amenable to this?)
  None of this addresses the issue of explicit threading -- cases
  where the user wants to create and control her own threads. 
 
 Or how they would interact. If you're doing implicit threading in a
 program using explicit threading, things could get REALLY
 tang-toungled

Implicit threading must be transparent to the coder, or it's not
implicit, icit?

So if I have two explicit threads:

my ViewControlTask = new Task(...);
my ViewControlThread = new Thread(priority = 1, 
  task = ViewControlTask);

my ComputationTask = new Task(...);
my ComputationThread = new Thread(priority = 19,
  task = ComputationTask);

Anything which happens *implicitly* in the ComputationTask must be
invisible to the coder. So the task will automatically be split and
automatically be joined (or not) based on the convenience of the
interpreter -- the only thing I'm doing in code is giving hints about
what can/should be split into threads.

So ideally, Parrot notices that I'm doing threads, or maybe that the
interpreter thinks that threads are going to be valuable. So it engages
the threadomizer and creates 8 OS level threads, one per CPU. Then
perl queries parrot, gets the number of threads created, and allocates
explicit threads and implicit threads accordingly -- this is what I
don't know how to do.

So there's a mixture:

ViewControlTask - - - --*-- - * - 
  + implicit thread 1 - -/ \- --/

ComputationTask - - - - - * - - 
  + implicit thread 1 - - - ---/
  + implicit thread 2 - - - ---/
  + implicit thread 3 - - - ---/
  + implicit thread 4 - - - ---/

=Austin



Re: Short-circuiting user-defined operators

2003-04-03 Thread Paul

--- Austin Hastings [EMAIL PROTECTED] wrote:
 --- Paul [EMAIL PROTECTED] wrote:
   But what to do about matrix arithmetic and other simple
   threadable tasks?
   sub m_add(@a, @b) {  my @result;  my $i, $j;  @result = @a;
 for @result - $i {:is threaded   # Thread this block?
   for @result[$i]; @b - $j; $b {
 $j += $b;
   } } }
  
  isn't $i an element alias rather than an index there?
 
 Yeah, but I'm assuming a 2d matrix. @result[$i] is another array.

Ah. I should have seen that. (BTW, I personally find it slightly
amusing and certainly useful to reformat code to minimize space when
it's a quote of a quote of a quote, but still offer apologies for the
resulting mishmash.)

  Basically, I just failed to parse all that. Sorry -- internal P6
  parser still incomplete.
 
 No, just bad writing on my part. Sorry.

I disagree. Once I know what it's doing, it looks fine. :)

   Conversely, I have absolutely no idea what to do about threading
   on a per-data-object basis:
   
   sub m_add(@a is threaded, @b) {
 ... What can the compiler figure out about threading @a?
   }
  
  I'd say this is unlikely to work, but again, I haven't exactly
  thought it all through very thoroughly.
 
 I'm pretty sure it *could* work. Likewise, I'm sure we could live
 without this for the first release, if we but grab the namespace we
 think we'll need in advance. That's why this stuff should all be
 hints to the interpreter -- what the box is actually capable of is
 not something we can know.

ah -- and if it isn't feasable, the compiler just ignores those hints,
builds it the old-fashioned way, and goes on about it's business. If
the hardware and the OS provide sufficient support, on the other hand,
the compiler might take advantage of them when the code suggests it.
Ok, I could see that.

 Certainly it's trivial to thread basic vector processing:
 1. Get max# of useful threads (#cpu's - 1)?
 2. Every computation of a threaded vector member gets allocated to 
a new thread, round-robin.
 3. Any read of a threaded vector member forces a join on the
allocated thread before proceeding.
 
 This isn't optimal, but it would work. But knowing how much benefit
 you're going to see will be part of the equation, too. So you want
 the runtime to balance the startup/shutdown cost versus the execution
 cost, if possible. Also, you want to favor threading when a blocking
 operation might occur in the threadable code. That kind of stuff.

More nightmares for the designers. :)
Maybe that's P8? :)

   This is one of those cases where the really smart guys who used
   to spend time recoding the fortran compilers for Vaxen might be
   able clue us in on the cool tricks for vector processing, but
   how generalizable will it all be?  (And, of course, is the
   internal representation amenable to this?)
   None of this addresses the issue of explicit threading -- cases
   where the user wants to create and control her own threads. 
  
  Or how they would interact. If you're doing implicit threading in a
  program using explicit threading, things could get REALLY
  tang-toungled
 
 Implicit threading must be transparent to the coder, or it's not
 implicit, icit?

lol -- but I don't necessarily *totally* agree. I make explicit use of
implicit behavior a little too much of the time, depending on what you
mean. I think the common term for it is cryptocontext. :)

Still, your point is valid. Implicit threading (or anything else) is
something done quietly, like implicit dereferencing of arrays. I was
just thinking that if the user is using explicit threads, he might do
things that implicitly interfere with or receive interferance from
implicit threads but then, I can't exactly come up with an example,
so the point is probably entirely moot.

 So if I have two explicit threads:
 
 my ViewControlTask = new Task(...);
 my ViewControlThread = new Thread(priority = 1, 
   task = ViewControlTask);
 my ComputationTask = new Task(...);
 my ComputationThread = new Thread(priority = 19,
   task = ComputationTask);
 
 Anything which happens *implicitly* in the ComputationTask must be
 invisible to the coder. So the task will automatically be split and
 automatically be joined (or not) based on the convenience of the
 interpreter -- the only thing I'm doing in code is giving hints
 about what can/should be split into threads.

Ok. I still say that should be pragmatic, though.
Easy enough in P6 to Cuse implicit 'threads'; and have the language
magically morph to add those hints to the rest of the compilation
process.
 
BTW, what *is* the applicability of adverbs to Cuse statements?
Is that entirely bogus?

 So ideally, Parrot notices that I'm doing threads, or maybe that
 the interpreter thinks that threads are going to be valuable. So
 it engages the threadomizer and creates 8 OS level threads, one
 per CPU. Then perl queries parrot, gets the number of threads
 

Re: Short-circuiting user-defined operators

2003-04-03 Thread Luke Palmer
 Paul wrote:
  --- Austin Hastings [EMAIL PROTECTED] wrote:
  
 Dave Whipp wrote:
 
 Joe Gottman wrote:
  
  
  Getting deep -- sorry. :)
  
  
 Alternatively, there might be a new parameter type that indicates
 that the parameter is not evaluated immediately:
 
 sub infix:!! ($lsh, $rhs is deferred) {...}
  
  
  If the standard is pass-by-ref it wouldn't trip any side effects unless
  you did so in your code, right? So is this necessary?
  
 
 There are two reasonable semantics for deferred parameters:
 
 1) lazy evaluation with caching, where the evaluation of the
 actual expression in the call is deferred until the sub
 actauly makes use of it and the result is then cached and
 reused as necessary.  Any side effects happen only once.
 
 2) ALGOL style pass by name, where the actual expression from the
 call is turned into a clouser called a thunk which is called
 when ever the sub access the parameter.  Note that the thunk
 may need to be an lvalue clouser to handle is rw paramenters.
 Side effects happen each time the thunk is called.  Also changes
 to the thunks environment can effect its value when called.

I think (2) would be best.  Because of:

while $a  $b { ... }

That wouldn't be possible with just evaluating it once.  I like the
interface better, too (for the writer of Cwhile), but that's just
me.

Luke


Re: Short-circuiting user-defined operators

2003-04-03 Thread Austin Hastings

--- Luke Palmer [EMAIL PROTECTED] wrote:
  Paul wrote:
   --- Austin Hastings [EMAIL PROTECTED] wrote:
   
  Dave Whipp wrote:
  
  Joe Gottman wrote:
   
   
   Getting deep -- sorry. :)
   
   
  Alternatively, there might be a new parameter type that
 indicates
  that the parameter is not evaluated immediately:
  
  sub infix:!! ($lsh, $rhs is deferred) {...}
   
   
   If the standard is pass-by-ref it wouldn't trip any side effects
 unless
   you did so in your code, right? So is this necessary?
   
  
  There are two reasonable semantics for deferred parameters:
  
  1) lazy evaluation with caching, where the evaluation of the
  actual expression in the call is deferred until the sub
  actauly makes use of it and the result is then cached and
  reused as necessary.  Any side effects happen only once.
  
  2) ALGOL style pass by name, where the actual expression from the
  call is turned into a clouser called a thunk which is called
  when ever the sub access the parameter.  Note that the thunk
  may need to be an lvalue clouser to handle is rw paramenters.
  Side effects happen each time the thunk is called.  Also changes
  to the thunks environment can effect its value when called.
 
 I think (2) would be best.  Because of:
 
 while $a  $b { ... }
 
 That wouldn't be possible with just evaluating it once.  I like the
 interface better, too (for the writer of Cwhile), but that's just
 me.

Since parms are defaulting to reference, could I just say:

sub foo($arg) { while $arg = 0  { print $arg; } }

foo( \{ $i-- } ); 
or: foo \{ $i-- };
or: foo {$i--};

and get that behavior? Is that a good idea?

Regardless, consider:

$a || $b  $c

This translates to:

infix:||($a, infix:($b, $c))

so if I want to write infix:!! I could do:

infix:!!($left, right is expression) is equiv(infix:||)
{
  return unless predicate($left);
  return $left  right;
}

But this have the unfortunate side-effect of requiring that all use of
the !! operator take place after the declaration -- not the end of the
world except when you want to overload a known symbol and make a
short-circuit bitwise or operator that does something other than
bitwise-or, perhaps.

In which case, go code C++, or write a macro, or get your declaration
to the top of the pile.

But this WILL impact the code generator/optimizer. Perhaps P6 needs the
notion of sequence points...


 
 Luke

=Austin



Re: Short-circuiting user-defined operators

2003-04-03 Thread Joe Gottman

- Original Message -
From: Luke Palmer [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Sent: Thursday, April 03, 2003 6:39 PM
Subject: Re: Short-circuiting user-defined operators


  Paul wrote:
   --- Austin Hastings [EMAIL PROTECTED] wrote:
  
  Dave Whipp wrote:
  
  Joe Gottman wrote:
  
  
   Getting deep -- sorry. :)
  
  
  Alternatively, there might be a new parameter type that indicates
  that the parameter is not evaluated immediately:
  
  sub infix:!! ($lsh, $rhs is deferred) {...}
  
  
   If the standard is pass-by-ref it wouldn't trip any side effects
unless
   you did so in your code, right? So is this necessary?
  
 
  There are two reasonable semantics for deferred parameters:
 
  1) lazy evaluation with caching, where the evaluation of the
  actual expression in the call is deferred until the sub
  actauly makes use of it and the result is then cached and
  reused as necessary.  Any side effects happen only once.
 
  2) ALGOL style pass by name, where the actual expression from the
  call is turned into a clouser called a thunk which is called
  when ever the sub access the parameter.  Note that the thunk
  may need to be an lvalue clouser to handle is rw paramenters.
  Side effects happen each time the thunk is called.  Also changes
  to the thunks environment can effect its value when called.

 I think (2) would be best.  Because of:

 while $a  $b { ... }

 That wouldn't be possible with just evaluating it once.  I like the
 interface better, too (for the writer of Cwhile), but that's just
 me.


I prefer 1).  When I posted the original thread I wanted to emulate the
effect of $a  $b or ($a) ?? $b :: $c.  The parameters in these might get
evaluated zero or one times, but not more than once.  Having a side effect
happen more than once brings back painful memories of C-style macros.

Joe Gottman




Re: Short-circuiting user-defined operators

2003-04-03 Thread Dave Whipp
Joe Gottman wrote:

There are two reasonable semantics for deferred parameters:

1) lazy evaluation with caching, where the evaluation of the
actual expression in the call is deferred until the sub
actauly makes use of it and the result is then cached and
reused as necessary.  Any side effects happen only once.
2) ALGOL style pass by name, where the actual expression from the
call is turned into a clouser called a thunk which is called
when ever the sub access the parameter.  Note that the thunk
may need to be an lvalue clouser to handle is rw paramenters.
Side effects happen each time the thunk is called.  Also changes
to the thunks environment can effect its value when called.
I think (2) would be best.  Because of:

   while $a  $b { ... }

That wouldn't be possible with just evaluating it once.  I like the
interface better, too (for the writer of Cwhile), but that's just
me.
I prefer 1).  When I posted the original thread I wanted to emulate the
effect of $a  $b or ($a) ?? $b :: $c.  The parameters in these might get
evaluated zero or one times, but not more than once.  Having a side effect
happen more than once brings back painful memories of C-style macros.
I tend to agree; but I note that it is possible to implement (1) over 
the semantics of (2) by simply assigning to a tmp variable. The reverse 
is not true. So if only one of the two is provided, then it should be 
(2). Multiple properties can be applied, so is deferred is cached 
would give (1).

Dave.
--
http://dave.whipp.name


Re: Short-circuiting user-defined operators

2003-04-02 Thread Matthijs van Duin
Is there any specific reason this was a reply to Michael Lazarro's Re: 
== vs. eq dated Tue, 1 Apr 2003 16:30:00 -0800 ?

(What I mean is, PLEASE don't use reply when you're not replying at all)

--
Matthijs van Duin  --  May the Forth be with you!


Short-circuiting user-defined operators

2003-04-01 Thread Joe Gottman
   Is there any way to write a user-defined operator so that it
short-circuits, like  and || ?  This might be function trait, for
instance,

  sub infix:!! ($lhs, $rhs) is short_circuit {...}

Alternatively, there might be a new parameter type that indicates that the
parameter is not evaluated immediately:

sub infix:!! ($lsh, $rhs is deferred) {...}

   In this case, it might be possible to make ordinary functions
short-circuit also

sub conditional(bool $condition, $trueCase is deferred, $falseCase is
deferred)
{
return ($condition) ?? $trueCase :: $falseCase;
}

   I have no idea how difficult it would be to implement either of these
concepts.   Also, if a parameter is deferred, would we need a new keyword to
say when to actually evaluate it?

Joe Gottman




Re: Short-circuiting user-defined operators

2003-04-01 Thread Dave Whipp
Joe Gottman wrote:

Alternatively, there might be a new parameter type that indicates that the
parameter is not evaluated immediately:
sub infix:!! ($lsh, $rhs is deferred) {...}
A nice concept! So nice, in fact, that it would be a shame to limit it 
to function args. I could see myself writing:

  my $a is lazy := expensive_fn1(...);
  my $b is lazy := expensive_fn2(...);
  print rand ?? $a :: $b;

I'm not sure quite how the syntax would work (should I be binding or 
assigning?); but there are definitely cases where this ability is 
useful. Given this capability, defered evaluation of function args would 
be trivial.

Another, very different, situation where laziness is good is to abstract 
fork/join situations:

  my $a is lazy_thread := expensive_fn1(...);
  my $b is lazy_thread := expensive_fn2(...);
  print $a + $b;

In this scenario, each expensive evaluation would be launched as a 
separate thread. When the resulting value is later used, then the thread 
would be joined, blocking if the thread is not complete.



Re: Short-circuiting user-defined operators

2003-04-01 Thread Luke Palmer
Dave Whipp writes:
 Another, very different, situation where laziness is good is to abstract 
 fork/join situations:
 
 
my $a is lazy_thread := expensive_fn1(...);
my $b is lazy_thread := expensive_fn2(...);
 
print $a + $b;
 
 In this scenario, each expensive evaluation would be launched as a 
 separate thread. When the resulting value is later used, then the thread 
 would be joined, blocking if the thread is not complete.

That is gorgeous.  Clazy_thread isn't a good name, but it's a
marvelous concept.  Thanks.

Luke