In a message dated Thu, 31 Aug 2006, Juerd writes:
Hm. I don't know how "but" works exactly, but in the realm of syntactic
sugar, this is appealing:

   $foo but s/foo/bar/

I like it.

This should be easy to make work in theory, but for the problem with C<but>'s semantics which I'll get to in a moment. C<but> can already take a closure in addition to a role or enum:

  my Point $p .= new;
  $p.x = 3;
  $p.y = 0;

  my Point $z = $p but { .y = 17 };

in which case,

  $x but { ... }

just translates into

  do given $x { ...; $_ }

So extending it so that

  $x but s/foo/bar/

just translates into

  $x but { s/foo/bar/ }

seems like very simple and natural sugaring. You can obviously already use that latter syntax of simply wrapping the substitution in a closure. Except distressingly it doesn't do anything....

I think these semantics are Almost Right, but yet Entirely Wrong. The problem is that C<but> reads to me as a *mutating* operator. That is, I would expect the above code snippet to give me a C<$z.y> of 17, but leave C<$p.y> as 0. Surely this is what one would expect from analogy of

  0 but True

which I wouldn't think anyone wants to cause all uses of 0, from then on, to booleanize true.

But yet C<but> with a closure doesn't copy, given the translation above, or even allow modification, since C<given> doesn't either. $_ (in the above case, $p) is set to point to the same object, and so $p.y and $z.y are both modified (or rather, they both refer to the same object, which is modified during assignment).

In other words, I would actually expect

  $x but { ... }

to translate to

  do given $x -> $_ is clone { ...; $_ }

where C<is clone> is a conjectural way of calling .clone if the argument is an object type but reduces to C<is copy> if the argument is a value type. (Neglecting for the moment that a pointy block doesn't appear to be a valid argument for C<given>. Is this correct? If so, why?)

I do not think that C<but> should mutate its LHS, regardless what its RHS is.


Reply via email to