HaloO,
John M. Dlugosz wrote:
Do we still get to keep the current semantics if we specificially
declare a string? e.g.
I'd vote for that.
I'd vote for it as well with the following rational. Note that
a simple scalar parameter involves three types:
1) the constraint of the parameter
2) the constraint of the argument container
(for an uncontained value this is the impossible constraint
'where {False}')
3) the type of the argument value (the WHAT)
I think we are checking 3 against 1 and dispatching on 3. The natural
use of 2 is in writable args but the first question is how would
a string increment implementation get it?
sub incr (Any $x is rw)
{
if $x.VAR.WHAT ~~ Str {...} # "-100" -> "-101"
else {...} # "-100" -> "-99"
}
This doesn't work because $x.VAR accesses the inner container and
that has constraint Any which effectively is 'where {True}'. So,
the natural solution to get at the constraint of the container the
caller uses to keep the argument value is capturing it:
sub incr (Any ::Type $x is rw)
{
if Type ~~ Str {...} # "-100" -> "-101"
else {...} # "-100" -> "-99"
}
BTW, calling incr with an rvalue can be handled as well
sub incr (Any ::Type $x is rw)
{
my $ret;
if Type ~~ Str {...; $ret = ...}
else {...; $ret = ...}
::T $x = $ret if T ~~ Type; # don't violate caller's constraint
return $ret;
}
say incr(5); # print 6, no error
my int8 $i = 5;
incr($i); say $i; # prints 6
$i = 127; incr($i); say $i; # prints 127, no error
I wonder if the constraint check can be written as I did. A version
with explicit WHAT is defined to have a bad smell, though. I believe
capturing the caller's container type is implicitly done by the
compiler to check constraint violation of rw parameters.
Here's one riddle for the linguists. We have '::Any ::= where {True}'
as the constraint that permits any value. Would then '::All ::= where
{False}' work as expected? That is does it intuitively mean that it
forbids all values? I know that english natives have issues with
stringent boolean negation in the sense of !Any == All. IOW, I negated
"permits any" to "forbids all" which is strangely twisted for the
german eye. We have "erlaubt alles" and "verbietet alles" respectively.
Also there are the other negations "erlaubt nichts" and "verbietet nichts".
However I've no clever idea how to denote a contra-variant constraint
on the caller's container's constraint in an rw sub. Perhaps
sub foo (FooOut <-- FooIn $x is rw) {...}
The arrow is of course optional. Its absence means that the caller has
to provide an unconstraint container to be type save. The visual problem
with this arrow is that is cousin --> is not per parameter but for the
whole sub. Alternatively it could be a signature on the trait.
sub foo (FooIn $x is rw:(FooOut)) {...}
or a type parameter
sub foo (FooIn $x is rw[FooOut]) {...}
As well as a hand full of adjectives.
$x++ :p5 # do it the old way, I just ported my program.
$x++ :field # I'm interested in preserving lengths of runs
$x++ :num # Preserve meanings of things that look like numeric
literals
$x++ :order # I'm interested in preserving comparison order
Just an idea, especially the first one.
This is a very good idea. But I would replace :field with :length.
Regards, TSa.
--
"The unavoidable price of reliability is simplicity"
-- C.A.R. Hoare