Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-26 Thread Aristotle Pagaltzis
* Aristotle Pagaltzis pagalt...@gmx.de [2009-01-02 23:00]:
 That way, you get this combination:

 sub pid_file_handler ( $filename ) {
 # ... top half ...
 yield;
 # ... bottom half ...
 }

 sub init_server {
 # ...
 my $write_pid = pid_file_handler( $optionspid_file );
 become_daemon();
 $write_pid();
 # ...
 }

It turns out that is exactly how generators work in
Javascript 1.7:
https://developer.mozilla.org/en/New_in_JavaScript_1.7

Regards,
-- 
Aristotle Pagaltzis // http://plasmasturm.org/


Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-26 Thread Larry Wall
On Tue, Jan 27, 2009 at 12:27:56AM +0100, Aristotle Pagaltzis wrote:
: * Aristotle Pagaltzis pagalt...@gmx.de [2009-01-02 23:00]:
:  That way, you get this combination:
: 
:  sub pid_file_handler ( $filename ) {
:  # ... top half ...
:  yield;
:  # ... bottom half ...
:  }
: 
:  sub init_server {
:  # ...
:  my $write_pid = pid_file_handler( $optionspid_file );
:  become_daemon();
:  $write_pid();
:  # ...
:  }
: 
: It turns out that is exactly how generators work in
: Javascript 1.7:
: https://developer.mozilla.org/en/New_in_JavaScript_1.7

As I said before, it's trivially easy to return a closure, and I
generally like my closures to be explicit:

sub pid_file_handler ( $filename ) {
# ... top half ...
return {
 # ... bottom half ...
}
}

If you tell me that another language does something a particular way,
I'll take it as a possible recommendation maybe 10% of the time,
and as a dire warning the other 90% of the time.  :)

Larry


Re: Coroutines in Perl 6 (Was: Re: Converting a Perl 5 pseudo-continuation to Perl 6)

2009-01-02 Thread Daniel Ruoso
Em Sex, 2009-01-02 às 08:34 -0300, Daniel Ruoso escreveu:
   token routine_def:coro {...}

Actually, I was just looking at STD, and the correct token would be

  token routine_declarator:coro { sym routine_def }

I was also looking at the spec files, and I realized that DRAFT S17
mentions coroutines, but its definition is a bit different then the one
I suggested, and the example poses a good reason:

  coro dbl { yield $_ * 2; yield $_; };
  (1..4).map:{ dbl($_) }
  # should result in 2 2 6 4

This example suggests that it will not install an alias in the caller
scope, but the code object itself stores its state.

The other difference is that falling out of a coro makes it restart
immediatly without returning any value (this one is a bit weird, I'd
expect it to return the last statement on the routine as well).

But one way or another yield (yes, I wrote it wrong in the previous
post) is still implemented as a control exception that is caught by the
implicit CONTROL block of the coro.

daniel



Coroutines in Perl 6 (Was: Re: Converting a Perl 5 pseudo-continuation to Perl 6)

2009-01-02 Thread Daniel Ruoso
Em Qui, 2009-01-01 às 12:34 -0800, Geoffrey Broadwell escreveu:
 In the below Perl 5 code, I refactored to pull the two halves of the PID
 file handling out of init_server(), but to do so, I had to return a sub
 from pid_file_handler() that acted as a continuation.  The syntax is a
 bit ugly, though.  Is there a cleaner way to this in Perl 6?

Well,

If the STD Perl 6 doesn't support that, you can always declare a
sub-grammar that implements a 

  token routine_def:coro {...}

then you have something in the lines of:

  coro pid_file_handler {
  ... # first half
  yeld $something;
  ... # second half
  }

It's even easy to implement how it should work. Basically, yeld throws a
resumable control exception, the implicit CONTROL block of the routine
will then contain the code to handle that exception by aliasing the coro
in that state in the caller lexical scope, overriding the current
definition. And once the routine is called again, and returns or leaves,
you simply re-binds to the original routine. 

The above solution assumes a coro state is only available in the same
lexical scope as the first call, which may be a good idea to avoid
action-at-a-distance.

But maybe we even convince larry to push that into STD... since it's
such a nice feature...

daniel



Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-02 Thread Leon Timmermans
When going OO, I'd say an augment()/inner() approach would be
cleanest. See 
http://search.cpan.org/~drolsky/Moose/lib/Moose/Cookbook/Basics/Recipe6.pod
for an example. I don't know how to express that in Perl 6 though.

Regards,

Leon

On Fri, Jan 2, 2009 at 2:08 AM, Steve Lukas lukas...@yahoo.com wrote:
 Hello,
 I'd vote for the OO-style.
 My reason is that the major criteria should be the reader perspective.
 It should be as clear as possible what's going on in the main code
 even if the reader doesn't know the hottest p6 tricks!
 What you are doing here is: two operations on the same thing (the pidfile).
 So the code should point out that it works twice on the same thing.

 I think it's best to have an object to show this
 whereas returning the sub/closure feels a bit confusing.
 Your right, this style is busy work, but it's not pointless.

 I would suggest a locally visible class to bring out the
 local, one time usage of that class. Btw. what is the best way to do so?

 Kind regards
 Stefan


 --- On Thu, 1/1/09, Geoffrey Broadwell ge...@broadwell.org wrote:
 From: Geoffrey Broadwell ge...@broadwell.org
 Subject: Converting a Perl 5 pseudo-continuation to Perl 6
 To: perl6-us...@perl.org, perl6-language@perl.org
 Date: Thursday, January 1, 2009, 3:34 PM

 In the below Perl 5 code, I refactored to pull the two halves of the PID
 file handling out of init_server(), but to do so, I had to return a sub
 from pid_file_handler() that acted as a continuation.  The syntax
 is a
 bit ugly, though.  Is there a cleaner way to this in Perl 6?

 ##
 sub init_server {
my %options  = @_;

# ...

# Do top (pre-daemonize) portion of PID file handling.
my $handler = pid_file_handler($options{pid_file});

# Detach from parent session and get to clean state.
become_daemon();

# Do bottom (post-daemonize) portion of PID file handling.
$handler-();

# ...
 }

 sub pid_file_handler {
# Do top half (pre-daemonize) PID file handling ...
my $filename = shift;
my $basename = lc $BRAND;
my $PID_FILE = $filename || $PID_FILE_DIR/$basename.pid;
my $pid_file = open_pid_file($PID_FILE);

# ... and return a continuation on the bottom half
 (post-daemonize).
return sub {
$MASTER_PID  =  $$;
print $pid_file $$;
close $pid_file;
};
 }
 ##

 When I asked this question on #perl6, pmurias suggested using
 gather/take syntax, but that didn't feel right to me either -- it's
 contrived in a similar way to using a one-off closure.

 pmichaud offered several possibilities (I've converted some of his
 suggestions expressed as prose into code, so the errors there are mine):

 1. Take advantage of Perl 6 syntax reduction to turn 'return sub {...}'
   into 'return {...}' (or even just fall of the end with
 '{...}', I
   suppose).  This is visually slightly better, but still leaves the
   bottom half inside a block that merely exists to satisfy Perl, not
   actually representing anything intrinsic about the problem.

 2. Throw a resumable exception in the middle:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file});
   become_daemon();
   pid_file_handler();
   # ...
   }

   sub pid_file_handler {
   # ... top half ...
   throw ResumableException;
   # ... bottom half ...
   }

   He also suggested a variant syntax with an adverb on return:

   sub pid_file_handler {
   # ... top half ...
   return :resumable;
   # ... bottom half ...
   }

   I suggested a naked yield syntax:

   sub pid_file_handler {
   # ... top half ...
   yield;
   # ... bottom half ...
   }

   These all desugar to the same thing, of course.

 3. Make become_daemon a part of pid_file_handler, or vice-versa.
   I rejected both of these on the basis of separating different
   things into different subs.  The two tasks are only tangentially
   related, and neither really seems like a subordinate op of the
   other.

 4. In order to keep the sub separate, but still not split the
   pid_file_handler call, I came up with a variation of #3 in which
   pid_file_handler takes a callback parameter:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file}, become_daemon);
   # ...
   }

   sub pid_file_handler($pid_file, callback) {
   # ... top half ...
   callback();
   # ... bottom half ...
   }

   That seems like a silly contortion to hide the problem, and
   doesn't represent my intent well -- the pid file handler doesn't
   need to send a message, it needs to yield control while waiting
   for something else to happen.

 5. Make a new PidHandler class and address the problem in OO fashion:

   sub init_server {
   # ...
   my $pid_handler = PidHandler.new(file = $options{pid_file});
   $pid_handler.top();
   become_daemon();
   $pid_handler.bottom();
   #...
   }

   This is certainly workable, but again feels like a contrived
   workaround

Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-02 Thread Geoffrey Broadwell
On Fri, 2009-01-02 at 14:19 +0200, Leon Timmermans wrote:
 When going OO, I'd say an augment()/inner() approach would be
 cleanest. See 
 http://search.cpan.org/~drolsky/Moose/lib/Moose/Cookbook/Basics/Recipe6.pod
 for an example. I don't know how to express that in Perl 6 though.

There's no description on that page, just sample code, but it looks like
augment performs a similar function to the .wrap method on Routines in
Perl 6.  That's an interesting variation of my approach #4, I think:

  4. In order to keep the sub separate, but still not split the
pid_file_handler call, I came up with a variation of #3 in which
pid_file_handler takes a callback parameter:
 
sub init_server {
# ...
pid_file_handler($options{pid_file}, become_daemon);
# ...
}
 
sub pid_file_handler($pid_file, callback) {
# ... top half ...
callback();
# ... bottom half ...
}

I like your idea a little better than the callback method, because I can
see the logic behind saying I want to make an enhanced version of
become_daemon that is *also* able to handle PID files.  However, it ties
the two together -- the PID file handling cannot be used in any context
other than becoming a daemon, and in particular it's not obvious how you
would unit test it.


-'f




Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-02 Thread Aristotle Pagaltzis
* Geoffrey Broadwell ge...@broadwell.org [2009-01-01 21:40]:
 In the below Perl 5 code, I refactored to pull the two halves of the PID
 file handling out of init_server(), but to do so, I had to return a sub
 from pid_file_handler() that acted as a continuation.  The syntax is a
 bit ugly, though.  Is there a cleaner way to this in Perl 6?

 ##
 sub init_server {
 my %options  = @_;

 # ...

 # Do top (pre-daemonize) portion of PID file handling.
 my $handler = pid_file_handler($options{pid_file});

 # Detach from parent session and get to clean state.
 become_daemon();

 # Do bottom (post-daemonize) portion of PID file handling.
 $handler-();

 # ...
 }

 sub pid_file_handler {
 # Do top half (pre-daemonize) PID file handling ...
 my $filename = shift;
 my $basename = lc $BRAND;
 my $PID_FILE = $filename || $PID_FILE_DIR/$basename.pid;
 my $pid_file = open_pid_file($PID_FILE);

 # ... and return a continuation on the bottom half (post-daemonize).
 return sub {
 $MASTER_PID  =  $$;
 print $pid_file $$;
 close $pid_file;
 };
 }
 ##

 When I asked this question on #perl6, pmurias suggested using
 gather/take syntax, but that didn't feel right to me either --

 it's contrived in a similar way to using a one-off closure.

Contrived how? I always found implicit continuations distasteful
in the same way that `each` and the boolean flip-flop are bad in
Perl 5: because they tie program state to a location in the code.
When there is state, it should be passed around explicitly. So I
think the return-a-closure solution is actually ideal.

F.ex. it keeps you entirely clear of the troublesome question of
when a subsequent call should restart the sub from the beginning
or resume it – should that happen when identical arguments are
passed? Or when no arguments are passed? Are there any rules
about the proximity of the calls in the code? Or does the
coroutine state effectively become global state (like with `each`
and `pos` in Perl 5)?

When you have an explicit entity representing the continuation,
all of these questions resolve themselves in at once: all calls
to the original routine create a new continuation, and all calls
via the state object are resumptions. There is no ambiguity or
subtlety to think about.

So from the perspective of the caller, I consider the “one-off”
closure ideal: the first call yields an object that can be used
to resume the call.

However, I agree that having to use an extra block inside the
routine and return it explicity is suboptimal. It would be nice
if there was a `yield` keyword that not only threw a resumable
exception, but also closed over the exception object in a
function that, when called, resumes the original function.

That way, you get this combination:

sub pid_file_handler ( $filename ) {
# ... top half ...
yield;
# ... bottom half ...
}

sub init_server {
# ...
my $write_pid = pid_file_handler( $optionspid_file );
become_daemon();
$write_pid();
# ...
}

Regards,
-- 
Aristotle Pagaltzis // http://plasmasturm.org/


Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-02 Thread Geoffrey Broadwell
On Fri, 2009-01-02 at 22:56 +0100, Aristotle Pagaltzis wrote:
  When I asked this question on #perl6, pmurias suggested using
  gather/take syntax, but that didn't feel right to me either --
  it's contrived in a similar way to using a one-off closure.
 
 Contrived how?

Meaning, the gather/take syntax doesn't make much sense, because we're
not gathering anything; the PID file handler has nothing to return.
We'd only be using it for the side effect of being able to pause the
callee's execution and resume it later.

 When you have an explicit entity representing the continuation,
 all of these questions resolve themselves in at once: all calls
 to the original routine create a new continuation, and all calls
 via the state object are resumptions. There is no ambiguity or
 subtlety to think about.

I like this argument.  I'm not sure it's applicable in every case, but
it certainly applies to the class of situations containing my problem.

 So from the perspective of the caller, I consider the “one-off”
 closure ideal: the first call yields an object that can be used
 to resume the call.
 
 However, I agree that having to use an extra block inside the
 routine and return it explicity is suboptimal. It would be nice
 if there was a `yield` keyword that not only threw a resumable
 exception, but also closed over the exception object in a
 function that, when called, resumes the original function.
 
 That way, you get this combination:
 
 sub pid_file_handler ( $filename ) {
 # ... top half ...
 yield;
 # ... bottom half ...
 }
 
 sub init_server {
 # ...
 my $write_pid = pid_file_handler( $optionspid_file );
 become_daemon();
 $write_pid();
 # ...
 }

That's pretty nice.  Perhaps we can make it even cleaner with a few
small tweaks to init_server():

sub init_server(:$pid_file, ...) {
# ...
my write_pid := pid_file_handler($pid_file);
become_daemon();
write_pid();
# ...
}

So far, this variant is winning for me, I think.  It's slightly more
verbose on the caller's side than the yield variant I had proposed, but
it's also more explicit, and allows (as you said) a clean syntactic
separation between starting the PID file handler and continuing it.

It does bring up a question, though.  What if pid_file_handler() needed
to be broken into three or more pieces, thus containing multiple yield
statements?  Does only the first one return a continuation object, which
can be called repeatedly to continue after each yield like this?

sub init_server(:$pid_file, ...) {
# ...
my more_pid_stuff := pid_file_handler($pid_file);
become_daemon();

more_pid_stuff();
do_something();

more_pid_stuff();
do_something_else();

more_pid_stuff();
# ...
}

Or does each yield produce a fresh new continuation object like this?

sub init_server(:$pid_file, ...) {
# ...
my write_pid   := pid_file_handler($pid_file);
become_daemon();

my fold_pid:= write_pid();
do_something();

my spindle_pid := fold_pid();
do_something_else();

spindle_pid();
# ...
}

(Note that I assume you can simply ignore the returned object if you
don't plan to continue the operation any more, without raising a
warning.)

Certainly the first version has less visual clutter, so I tend to lean
that way by default.  But the second design would allow one to create a
tree of partial executions, by calling any earlier continuation object
again.  That's a very powerful concept that I don't want to give up on.

Supporting both feels like it might be an adverb on the invocation
(possibly with a frosty sugar coating available).  It would be nice to
support invoking a continuation in ratcheting and forgetful modes.

Thoughts?


-'f




Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-02 Thread Mark J. Reed
On Fri, Jan 2, 2009 at 9:06 PM, Geoffrey Broadwell ge...@broadwell.org wrote:
 It does bring up a question, though.  What if pid_file_handler() needed
 to be broken into three or more pieces, thus containing multiple yield
 statements?  Does only the first one return a continuation object, which
 can be called repeatedly to continue after each yield like this?

IMO, that's not much better than not having the explicit continuation
object in the first place.  A true continuation should essentially be
an immutable value object that can be repeatedly invoked to resume
processing at the same point.

my more_pid_stuff := pid_file_handler($pid_file);

How does binding work with an rvalue like that?

 Or does each yield produce a fresh new continuation object like this?

That would definitely be my vote.

-- 
Mark J. Reed markjr...@gmail.com


Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-01 Thread Geoffrey Broadwell
In the below Perl 5 code, I refactored to pull the two halves of the PID
file handling out of init_server(), but to do so, I had to return a sub
from pid_file_handler() that acted as a continuation.  The syntax is a
bit ugly, though.  Is there a cleaner way to this in Perl 6?

##
sub init_server {
my %options  = @_;

# ...

# Do top (pre-daemonize) portion of PID file handling.
my $handler = pid_file_handler($options{pid_file});

# Detach from parent session and get to clean state.
become_daemon();

# Do bottom (post-daemonize) portion of PID file handling.
$handler-();

# ...
}

sub pid_file_handler {
# Do top half (pre-daemonize) PID file handling ...
my $filename = shift;
my $basename = lc $BRAND;
my $PID_FILE = $filename || $PID_FILE_DIR/$basename.pid;
my $pid_file = open_pid_file($PID_FILE);

# ... and return a continuation on the bottom half (post-daemonize).
return sub {
$MASTER_PID  =  $$;
print $pid_file $$;
close $pid_file;
};
}
##

When I asked this question on #perl6, pmurias suggested using
gather/take syntax, but that didn't feel right to me either -- it's
contrived in a similar way to using a one-off closure.

pmichaud offered several possibilities (I've converted some of his
suggestions expressed as prose into code, so the errors there are mine):

1. Take advantage of Perl 6 syntax reduction to turn 'return sub {...}'
   into 'return {...}' (or even just fall of the end with '{...}', I
   suppose).  This is visually slightly better, but still leaves the
   bottom half inside a block that merely exists to satisfy Perl, not
   actually representing anything intrinsic about the problem.

2. Throw a resumable exception in the middle:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file});
   become_daemon();
   pid_file_handler();
   # ...
   }

   sub pid_file_handler {
   # ... top half ...
   throw ResumableException;
   # ... bottom half ...
   }

   He also suggested a variant syntax with an adverb on return:

   sub pid_file_handler {
   # ... top half ...
   return :resumable;
   # ... bottom half ...
   }

   I suggested a naked yield syntax:

   sub pid_file_handler {
   # ... top half ...
   yield;
   # ... bottom half ...
   }

   These all desugar to the same thing, of course.

3. Make become_daemon a part of pid_file_handler, or vice-versa.
   I rejected both of these on the basis of separating different
   things into different subs.  The two tasks are only tangentially
   related, and neither really seems like a subordinate op of the
   other.

4. In order to keep the sub separate, but still not split the
   pid_file_handler call, I came up with a variation of #3 in which
   pid_file_handler takes a callback parameter:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file}, become_daemon);
   # ...
   }

   sub pid_file_handler($pid_file, callback) {
   # ... top half ...
   callback();
   # ... bottom half ...
   }

   That seems like a silly contortion to hide the problem, and
   doesn't represent my intent well -- the pid file handler doesn't
   need to send a message, it needs to yield control while waiting
   for something else to happen.

5. Make a new PidHandler class and address the problem in OO fashion:

   sub init_server {
   # ...
   my $pid_handler = PidHandler.new(file = $options{pid_file});
   $pid_handler.top();
   become_daemon();
   $pid_handler.bottom();
   #...
   }

   This is certainly workable, but again feels like a contrived
   workaround in the same way that gather/take and return {...} do.
   Plus, writing a new class and using OO/method call syntax just to
   allow a sub to be split seems like pointless busy work.  Not
   as bad in Perl 6 as in Perl 5, but still.

In the end, I think I like the 'naked yield' idea best of the ones we
have so far.  Any comments or other ideas? [1]


-'f

[1] Other than that I've used the word 'contrived' too many times.  :-)




Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-01 Thread Leon Timmermans
I can't help wondering why does pid_file_handler need to be split up
in the first place? Why wouldn't it be possible to simply call
pid_file_handler after become_daemon?

Regards,

Leon Timmermans

On Thu, Jan 1, 2009 at 10:34 PM, Geoffrey Broadwell ge...@broadwell.org wrote:
 In the below Perl 5 code, I refactored to pull the two halves of the PID
 file handling out of init_server(), but to do so, I had to return a sub
 from pid_file_handler() that acted as a continuation.  The syntax is a
 bit ugly, though.  Is there a cleaner way to this in Perl 6?

 ##
 sub init_server {
my %options  = @_;

# ...

# Do top (pre-daemonize) portion of PID file handling.
my $handler = pid_file_handler($options{pid_file});

# Detach from parent session and get to clean state.
become_daemon();

# Do bottom (post-daemonize) portion of PID file handling.
$handler-();

# ...
 }

 sub pid_file_handler {
# Do top half (pre-daemonize) PID file handling ...
my $filename = shift;
my $basename = lc $BRAND;
my $PID_FILE = $filename || $PID_FILE_DIR/$basename.pid;
my $pid_file = open_pid_file($PID_FILE);

# ... and return a continuation on the bottom half (post-daemonize).
return sub {
$MASTER_PID  =  $$;
print $pid_file $$;
close $pid_file;
};
 }
 ##

 When I asked this question on #perl6, pmurias suggested using
 gather/take syntax, but that didn't feel right to me either -- it's
 contrived in a similar way to using a one-off closure.

 pmichaud offered several possibilities (I've converted some of his
 suggestions expressed as prose into code, so the errors there are mine):

 1. Take advantage of Perl 6 syntax reduction to turn 'return sub {...}'
   into 'return {...}' (or even just fall of the end with '{...}', I
   suppose).  This is visually slightly better, but still leaves the
   bottom half inside a block that merely exists to satisfy Perl, not
   actually representing anything intrinsic about the problem.

 2. Throw a resumable exception in the middle:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file});
   become_daemon();
   pid_file_handler();
   # ...
   }

   sub pid_file_handler {
   # ... top half ...
   throw ResumableException;
   # ... bottom half ...
   }

   He also suggested a variant syntax with an adverb on return:

   sub pid_file_handler {
   # ... top half ...
   return :resumable;
   # ... bottom half ...
   }

   I suggested a naked yield syntax:

   sub pid_file_handler {
   # ... top half ...
   yield;
   # ... bottom half ...
   }

   These all desugar to the same thing, of course.

 3. Make become_daemon a part of pid_file_handler, or vice-versa.
   I rejected both of these on the basis of separating different
   things into different subs.  The two tasks are only tangentially
   related, and neither really seems like a subordinate op of the
   other.

 4. In order to keep the sub separate, but still not split the
   pid_file_handler call, I came up with a variation of #3 in which
   pid_file_handler takes a callback parameter:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file}, become_daemon);
   # ...
   }

   sub pid_file_handler($pid_file, callback) {
   # ... top half ...
   callback();
   # ... bottom half ...
   }

   That seems like a silly contortion to hide the problem, and
   doesn't represent my intent well -- the pid file handler doesn't
   need to send a message, it needs to yield control while waiting
   for something else to happen.

 5. Make a new PidHandler class and address the problem in OO fashion:

   sub init_server {
   # ...
   my $pid_handler = PidHandler.new(file = $options{pid_file});
   $pid_handler.top();
   become_daemon();
   $pid_handler.bottom();
   #...
   }

   This is certainly workable, but again feels like a contrived
   workaround in the same way that gather/take and return {...} do.
   Plus, writing a new class and using OO/method call syntax just to
   allow a sub to be split seems like pointless busy work.  Not
   as bad in Perl 6 as in Perl 5, but still.

 In the end, I think I like the 'naked yield' idea best of the ones we
 have so far.  Any comments or other ideas? [1]


 -'f

 [1] Other than that I've used the word 'contrived' too many times.  :-)





Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-01 Thread Geoffrey Broadwell
On Fri, 2009-01-02 at 00:30 +0200, Leon Timmermans wrote:
 I can't help wondering why does pid_file_handler need to be split up
 in the first place? Why wouldn't it be possible to simply call
 pid_file_handler after become_daemon?

Two answers:

1. If an error occurs that will not allow the PID file to be created
   (another copy of the daemon is already running, the user doesn't
   have required root permissions, or what have you), the program
   should die visibly at the command line, rather than *appearing* to
   launch but actually just spitting an error into the syslog and
   disappearing silently.  Checking for another running daemon and
   taking ownership of the pid file should be an atomic operation
   (or at the very least err on the side of failing noisily if
   something fishy happens), so I can't just check for an existing
   pid file before daemonizing, and then create the new pid file after.

   It's not visible in the code I posted, but the program should also
   do a number of other sanity checks before it daemonizes, for the
   very same reasons.  For example, it should load all modules it
   expects to use before becoming a daemon, and complain loudly if
   it can't.

2. The particular code I used is just a decent example to ask about
   the general question of a better syntax for interrupting and
   continuing a sub.  So even if I could do what you say, I'd still
   have the question.  :-)


-'f




Re: Converting a Perl 5 pseudo-continuation to Perl 6

2009-01-01 Thread Steve Lukas
Hello,
I'd vote for the OO-style. 
My reason is that the major criteria should be the reader perspective.
It should be as clear as possible what's going on in the main code 
even if the reader doesn't know the hottest p6 tricks!
What you are doing here is: two operations on the same thing (the pidfile).
So the code should point out that it works twice on the same thing.

I think it's best to have an object to show this
whereas returning the sub/closure feels a bit confusing.
Your right, this style is busy work, but it's not pointless.

I would suggest a locally visible class to bring out the 
local, one time usage of that class. Btw. what is the best way to do so?

Kind regards
Stefan


--- On Thu, 1/1/09, Geoffrey Broadwell ge...@broadwell.org wrote:
From: Geoffrey Broadwell ge...@broadwell.org
Subject: Converting a Perl 5 pseudo-continuation to Perl 6
To: perl6-us...@perl.org, perl6-language@perl.org
Date: Thursday, January 1, 2009, 3:34 PM

In the below Perl 5 code, I refactored to pull the two halves of the PID
file handling out of init_server(), but to do so, I had to return a sub
from pid_file_handler() that acted as a continuation.  The syntax
is a
bit ugly, though.  Is there a cleaner way to this in Perl 6?

##
sub init_server {
my %options  = @_;

# ...

# Do top (pre-daemonize) portion of PID file handling.
my $handler = pid_file_handler($options{pid_file});

# Detach from parent session and get to clean state.
become_daemon();

# Do bottom (post-daemonize) portion of PID file handling.
$handler-();

# ...
}

sub pid_file_handler {
# Do top half (pre-daemonize) PID file handling ...
my $filename = shift;
my $basename = lc $BRAND;
my $PID_FILE = $filename || $PID_FILE_DIR/$basename.pid;
my $pid_file = open_pid_file($PID_FILE);

# ... and return a continuation on the bottom half
(post-daemonize).
return sub {
$MASTER_PID  =  $$;
print $pid_file $$;
close $pid_file;
};
}
##

When I asked this question on #perl6, pmurias suggested using
gather/take syntax, but that didn't feel right to me either -- it's
contrived in a similar way to using a one-off closure.

pmichaud offered several possibilities (I've converted some of his
suggestions expressed as prose into code, so the errors there are mine):

1. Take advantage of Perl 6 syntax reduction to turn 'return sub {...}'
   into 'return {...}' (or even just fall of the end with
'{...}', I
   suppose).  This is visually slightly better, but still leaves the
   bottom half inside a block that merely exists to satisfy Perl, not
   actually representing anything intrinsic about the problem.

2. Throw a resumable exception in the middle:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file});
   become_daemon();
   pid_file_handler();
   # ...
   }

   sub pid_file_handler {
   # ... top half ...
   throw ResumableException;
   # ... bottom half ...
   }

   He also suggested a variant syntax with an adverb on return:

   sub pid_file_handler {
   # ... top half ...
   return :resumable;
   # ... bottom half ...
   }

   I suggested a naked yield syntax:

   sub pid_file_handler {
   # ... top half ...
   yield;
   # ... bottom half ...
   }

   These all desugar to the same thing, of course.

3. Make become_daemon a part of pid_file_handler, or vice-versa.
   I rejected both of these on the basis of separating different
   things into different subs.  The two tasks are only tangentially
   related, and neither really seems like a subordinate op of the
   other.

4. In order to keep the sub separate, but still not split the
   pid_file_handler call, I came up with a variation of #3 in which
   pid_file_handler takes a callback parameter:

   sub init_server {
   # ...
   pid_file_handler($options{pid_file}, become_daemon);
   # ...
   }

   sub pid_file_handler($pid_file, callback) {
   # ... top half ...
   callback();
   # ... bottom half ...
   }

   That seems like a silly contortion to hide the problem, and
   doesn't represent my intent well -- the pid file handler doesn't
   need to send a message, it needs to yield control while waiting
   for something else to happen.

5. Make a new PidHandler class and address the problem in OO fashion:

   sub init_server {
   # ...
   my $pid_handler = PidHandler.new(file = $options{pid_file});
   $pid_handler.top();
   become_daemon();
   $pid_handler.bottom();
   #...
   }

   This is certainly workable, but again feels like a contrived
   workaround in the same way that gather/take and return {...} do.
   Plus, writing a new class and using OO/method call syntax just to
   allow a sub to be split seems like pointless busy work.  Not
   as bad in Perl 6 as in Perl 5, but still.

In the end, I think I like the 'naked yield' idea best of the ones we
have so far.  Any comments or other ideas? [1