Re: unusual invocants

2009-10-22 Thread Ben Morrow
Quoth tho...@sandlass.de (TSa (Thomas =?utf-8?q?Sandla=C3=9F?=)):
 
 Here is a direct syntax for the freeze feature of the paper:
 
   class C does T1 does T2
   {
   freeze T1::x for foo;
   freeze T2::x for bar;
   method x {...} # for all other methods
   }
 
 The implementation is strait forward: on entry to foo and bar
 the dispatch table of the invocant is temporarily patched to
 contain the right x. After the call the original is restored.

Isn't this just sugar for something like

class C does T1 does T2
{
method foo {
my $tmp = self but role { 
method x { return self.T1::x }
};
return $tmp.foo;
}

method x { ... }
}

(Excuse me if I have any syntactic details wrong.)

The most important detail here is that the *class* gets to pick which
imported methods need to be wrapped. Most of the time you want a method
x in the class to be called from a method foo in the role: that's the
point.

What this doesn't fix is that some other code (outside the class) will
be expecting C::x to have T1::x semantics, and some will be expecting it
to have T2::x semantics. If these are contradictory, there is no way to
write an x which works. That's where the 'hats' idea comes in, so you
could write something like

class C does T1 does T2
{
method T1::x { ... }
method T2::x { ... }
}

and have callers that thought they were getting a T1 call the
appropriate override. However, there's still a problem with callers that
know they have a C: which method do they get?

AFAICS the only real solution to this is something like COM, where you
say 'I would like to talk to this object as though it were a T1 now'.
Might it be possible to use the type system to make this less painful
than it usually is?

Ben



Re: Embedded comments: two proposed solutions to the comment-whole-lines problem

2009-08-11 Thread Ben Morrow
Quoth markjr...@gmail.com (Mark J. Reed):
 
 I still like the double-bracket idea. I don't much mind the extra
 character; 5 characters total still beats the 7 of HTML/XML.

I much prefer double-bracket to double-#: double-# gets caught out when
you do s/^/# on code which already includes line-starting # comments.

However, I would much rather see a general syntax like

(# ... )
{# ... }
[# ... ]

with no whitespace allowed between the opening bracket and the #: this
doesn't seem to conflict with anything. Allowing # ...  in rules would
also be nice.

Ben



Re: Clarification of S04 closure traits

2009-08-11 Thread Ben Morrow
Sorry for the delay in replying, but I was busy with other things and I
wanted to give other people a chance to reply. Since noone has, might it
be possible to get the attached patches committed? I'm not familiar with
the protocol for such things so, again, I'm sorry if I've got it wrong.

Ben

--- S04-control.pod.orig	2009-08-11 08:43:36.0 +0100
+++ S04-control.pod	2009-08-11 09:03:42.0 +0100
@@ -1232,6 +1232,21 @@
 before CBEGIN, CCHECK, or CINIT, since those are done at compile or
 process initialization time).
 
+If an exception is thrown through a block without a CCATCH block, the
+CLEAVE, CUNDO and CPOST blocks will be run at that point, with
+C$! set to the in-flight exception.  If there is no in-flight
+exception when these blocks are run, C$! will be Cundef.  The last
+exception caught in the outer block is available as C OUTER::$! ,
+as usual. 
+
+An exception thrown from an CENTER block will abort the CENTER
+queue, but one thrown from a CLEAVE block will not.  The exceptions
+thrown by failing CPRE and CPOST blocks cannot be caught by a
+CCATCH in the same block, which implies that CPOST blocks are not
+run if a CPRE block fails.  If a CPOST fails while an exception is in
+flight the CPOST failure doesn't replace C$! but goes straight into
+C$!.pending.
+
 For blocks such as CKEEP and CPOST that are run when exiting a
 scope normally, the return value (if any) from that scope is available
 as the current topic.  (It is presented as a CCapture object.)
Index: S04-closure-traits/enter-leave.t
===
--- S04-closure-traits/enter-leave.t	(revision 27955)
+++ S04-closure-traits/enter-leave.t	(working copy)
@@ -2,7 +2,7 @@
 
 use Test;
 
-plan 11;
+plan 19;
 
 # LS04/Closure traits/ENTER at every block entry time
 # LS04/Closure traits/LEAVE at every block exit time
@@ -92,4 +92,92 @@
 }), 1, 'leave triggers LEAVE {}';
 }
 
+{
+my $str;
+try {
+ENTER { $str ~= '(' }
+LEAVE { $str ~= ')' }
+$str ~= 'x';
+die 'foo';
+}
+is $str, '(x)', 'die calls LEAVE blocks';
+}
+
+{
+my $str;
+try {
+LEAVE { $str ~= $! // 'undef' }
+die 'foo';
+}
+is $str, 'foo', '$! set in LEAVE if exception thrown';
+}
+
+{
+my $str;
+{
+LEAVE { $str ~= (defined $! ? 'yes' : 'no') }
+try { die 'foo' }
+$str ~= (defined $! ? 'aye' : 'nay');
+}
+is $str, 'ayeno', '$! not set in LEAVE if exception not thrown';
+}
+
+{
+my $str;
+try {
+$str ~= '(';
+try {
+ENTER { die 'foo' }
+$str ~= 'x';
+}
+$str ~= ')';
+}
+is $str, '()', 'die in ENTER caught by try';
+}
+
+{
+my $str;
+try {
+$str ~= '(';
+try {
+LEAVE { die 'foo' }
+$str ~= 'x';
+}
+$str ~= ')';
+}
+is $str, '(x)', 'die in LEAVE caught by try';
+}
+
+{
+my $str;
+try {
+$str ~= '(';
+try {
+ENTER { $str ~= '['; die 'foo' }
+LEAVE { $str ~= ']' }
+$str ~= 'x';
+}
+$str ~= ')';
+}
+is $str, '([])', 'die in ENTER calls LEAVE';
+}
+
+{
+my $str;
+try {
+ENTER { $str ~= '1'; die 'foo' }
+ENTER { $str ~= '2' }
+}
+is $str, '1', 'die aborts ENTER queue';
+}
+
+{
+my $str;
+try {
+LEAVE { $str ~= '1' }
+LEAVE { $str ~= '2'; die 'foo' }
+}
+is $str, '21', 'die doesn\'t abort LEAVE queue';
+}
+
 # vim: ft=perl6
Index: S04-closure-traits/pre-post.t
===
--- S04-closure-traits/pre-post.t	(revision 27955)
+++ S04-closure-traits/pre-post.t	(working copy)
@@ -9,7 +9,7 @@
 # TODO: 
 #  * Multiple inheritance + PRE/POST blocks
 
-plan 18;
+plan 25;
 
 sub foo(Num $i) {
 PRE {
@@ -125,4 +125,82 @@
 lives_ok { $pt.test(2) }, 'POST receives return value as $_ (succeess)';
 dies_ok  { $pt.test(1) }, 'POST receives return value as $_ (failure)';
 
+{
+my $str;
+{
+PRE  { $str ~= '('; 1 }
+POST { $str ~= ')'; 1 }
+$str ~= 'x';
+}
+is $str, '(x)', 'PRE and POST run on ordinary blocks';
+}
+
+{
+my $str;
+{
+POST  { $str ~= ')'; 1 }
+LEAVE { $str ~= ']' }
+ENTER { $str ~= '[' }
+PRE   { $str ~= '('; 1 }
+$str ~= 'x';
+}
+is $str, '([x])', 'PRE/POST run outside ENTER/LEAVE';
+}
+
+{
+my $str;
+try {
+{
+PRE { $str ~= '('; 0 }
+PRE { $str ~= '*'; 1 }
+ENTER   { $str ~= '[' }
+$str ~= 'x';
+LEAVE   { $str ~= ']' }
+POST{ $str ~= ')'; 1 }
+}
+}
+is $str, '(', 'failing PRE runs nothing else';
+}
+
+{
+my $str;
+try {
+{
+POST  { $str ~= 'x'; 0 }
+LEAVE { $str ~= 'y' }
+POST  { $str ~= 'z'; 1 }
+ 

Re: Embedded comments: two proposed solutions to the comment-whole-lines problem

2009-08-11 Thread Ben Morrow
At  6PM +0200 on 11/08/09 you (Moritz Lenz) wrote:
 Ben Morrow wrote:
  
  However, I would much rather see a general syntax like
  
  (# ... )
  {# ... }
  [# ... ]
  
  with no whitespace allowed between the opening bracket and the #: this
  doesn't seem to conflict with anything. Allowing # ...  in rules would
  also be nice.
 
 That severely violates the principle of least surprise. To me [#...]
 looks like an array ref which contains a comment, which is *not* what
 you propose (I think).

No, it wasn't. The idea was modelled after TT2's [%# ... %] syntax, and
other languages that mark comments just inside the delimiters.

 It also feels like a step backwards. In Perl 6 we try to make things
 clear from the beginning, not only from the second char on. Regex
 modifiers at the, anybody? or (?#...) as comments in regexes in Perl 5?
 
 In all other cases of quote like constructs are the semantics are
 explicit first (think of Q, qx, m, , «), the delimiter comes later.
 Changing that all of a sudden seems very unintuitive and wrong.

This appears to be leading to a :comment modifier on quotables, with
some suitable shortcut. Perhaps 'q#'? Or are we not allowed mixed alpha
and symbols? 

Ben

(I really want to suggest £, just to teach USAnians '#' isn't called
'pound'... :) )



Re: Clarification of S04 closure traits

2009-07-28 Thread Ben Morrow

Moritz Lenz wrote:

Ben Morrow wrote:


- Presumably when an exception is thrown through a block, the LEAVE and
  POST queues are called (in that order).


POST was inspired from the Design By Contract department, and are meant
to execute assertions on the result. If you leave a block through an
exception you don't have a result, so I don't think running a POST block
makes sense.


OK, if POST is only for asserting on the return value that would make 
sense. But I thought POST was also supposed to be able to assert that 
global state had been left as it should, in which case it should be run 
even on exceptional exit? I'm not sure how any given POST block is 
supposed to distinguish between an ordinary undef return and an 
exception, though, to avoid checking the return value. Some sort of 
guarantee that $! is undef in a POST block unless an exception is 
currently being thrown might be helpful, but I'm not sure how that 
interacts with the Perl 6 exception model as a whole.



I'm not sure about running LEAVE blocks either, because that's what
CATCH blocks are for.


LEAVE blocks I am certain *should* be run, no matter how the block is 
exitted (well, unless a PRE fails: see below). They are equivalent to 
'finally' blocks in other languages, and AIUI they are for cleanup: 
closing files, tearing down database connections and the like.



What if a PRE block fails: is
  the POST queue on the same block called? (Do you have to satisfy your
  post-conditions even if your pre-conditions failed?)


I'd say that if a PRE block fails, nothing else is run (neither LEAVE
nor POST nor ...)


I agree that none of ENTER, LEAVE or the main body of the block should 
be run. However, if a POST block is asserting, say, that a global holds 
a valid value, shouldn't that still be checked even if your 
preconditions failed? I admit I haven't read much about DBC.



- If a POST block is called as a result of a thrown exception, and it
  fails, which exception 'wins'?


Question obsoleted by previous answer ;-)


...maybe :).


- Can a try block catch an exception thrown from its own ENTER or LEAVE
  queue? 


Yes.


OK. What about PRE/POST? It seems wrong somehow to be able to catch 
failure of your own pre-/post-conditions: they are meant for the caller 
to catch. Does that seem right?


Ben



Clarification of S04 closure traits

2009-07-26 Thread Ben Morrow
I'm iworking on a patch for Perl 5 that implements the Perl 6 closure
traits (ENTER/LEAVE/...) as special blocks. There are several details
that aren't clear to me from either S04 or the spec tests; I apologize
if these have been discussed before, as I haven't been following p6l.
I'm also not subscribed, so if people could keep me in the CC that would
be appreciated.

- Presumably when an exception is thrown through a block, the LEAVE and
  POST queues are called (in that order). What if a PRE block fails: is
  the POST queue on the same block called? (Do you have to satisfy your
  post-conditions even if your pre-conditions failed?)

- If a POST block is called as a result of a thrown exception, and it
  fails, which exception 'wins'?

- Presumably if an ENTER block dies, the rest of that ENTER queue is
  abandoned. Does that also apply to the LEAVE queue? What should

{
LEAVE { say leave1 }
LEAVE { say leave2; die foo; }
}

  print? Similarly POST: once one post-condition has failed, are
  subsequent post-conditions checked?

- Can a try block catch an exception thrown from its own ENTER or LEAVE
  queue? For example in this case:

try {

try {
ENTER { die foo }
CATCH { default { say caught inside } }
}

CATCH { default { say caught outside } }
}

  which CATCH block gets the exception? What about PRE/POST: can you
  CATCH failure of your own pre-/post-conditions?

- Does it make any difference in any of the above if 'die' is replaced
  by 'exit'?

Ben



Re: Smooth or Chunky?

2007-01-24 Thread Ben Morrow

Quoth [EMAIL PROTECTED] (Larry Wall):
 I should also mention I did (briefly) consider the null reduce
 operator:
 
 [] zip(1,2;3,4)
 
 to mean slap [] around each element, but it runs into ambiguity with
 the existing [] form indicating an empty list.

Would using [[]] instead work? This is (at least to me) nicely visually
indicative of 'build a list of lists'. It is a little punctuation-heavy,
of course; though we could always allow \x{27E6}\x{27E7} as an
alternative :).

Ben

-- 
   Although few may originate a policy, we are all able to judge it.
   Pericles of Athens, c.430 B.C.
  [EMAIL PROTECTED]


Re: renaming grep to where

2006-09-20 Thread Ben Morrow

Quoth [EMAIL PROTECTED]:
 On Tue, Sep 19, 2006 at 04:38:38PM +0200, Thomas Wittek wrote:
  Jonathan Lang schrieb:
   IMHO, syntax should be left alone until a compelling reason to change
   it is found.  While I think it would be nice to have a more intuitive
   name for grep
  What would be the disadvantage of renaming it to a more intuitive name?
  I can only see advantages.
 
 Lost culture perhaps.  There's a long strong tradition of the term
 grep in perl and it would be a shame to toss that away without some
 serious thought.

I would second that strongly. Perl6 is already different enough from
Perl5 for good reasons; making it different for bad reasons seems to me
a really bad idea.

If this sort of change is on the cards, then for consistency a serious
effort should be made to remove *all* Unixisms from Perl (unlink, flock,
fork, and all the signal stuff spring to mind; a case could be made for
the filetest ops as well). I think that that level of culture- and
history-loss would be a real shame; I can see however that others may
think it more important to make Perl more platform-agnostic in
character as well as in implementation.

Ben

-- 
'Deserve [death]? I daresay he did. Many live that deserve death. And some die
that deserve life. Can you give it to them? Then do not be too eager to deal
out death in judgement. For even the very wise cannot see all ends.'
[EMAIL PROTECTED]


Re: === and array-refs

2006-08-17 Thread Ben Morrow

Quoth [EMAIL PROTECTED] (Mark J. Reed):
 On 8/17/06, David Green [EMAIL PROTECTED] wrote:
  $a=[1, 2, [EMAIL PROTECTED];
  $c=[1, 2, [EMAIL PROTECTED];
  $d=[1, 2, [EMAIL PROTECTED];
  
  So $a, $c, and $d may all have the same *value*
  (or snapshot, when evaluated all the way down
  through nesting and references), i.e. they might
  be eqv, but only $a and $c are === because they
  have the same contents [unevaluated contents]
  and $d doesn't.
 
 In this case, it seems like [===] @$a, @$c would do what you want,
 yes?  It would return true, while [===] @$a,@$d would return false...

 In the general case - well, I think the thread demonstrates that it's
 hard to define a general case for what you want to do.   Based on your
 example, I assumed you wanted one-level dereferencing, regardless of
 the contents. But it sounds like what you want is infinite
 dereferencing as long as the referent is anonymous,  and no
 dereferencing if the referent is a named variable?

Surely that's a meaningless distinction? A named variable can become
anonymous if its name goes out of scope; an anon can be bound to a name.

Just to make sure I've got all this straight:

=:= compares names
=== compares containers
eqv compares values

So given an array @W, 

my @X := @W;# @X =:= @W
my @Y =  @W;# @Y === @W but @Y !=:= @W
my @Z =  @W.clone;  # @Z eqv @W but @Z !=== @W

? This seems like a useful set of distinctions to me...

lurk

Ben

-- 
  The cosmos, at best, is like a rubbish heap scattered at random.
   Heraclitus
  [EMAIL PROTECTED]