Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Types of literals

8 views
Skip to first unread message

Deborah Ariel Pickett

unread,
Apr 13, 2003, 8:58:47 PM4/13/03
to perl6-l...@perl.org
Simple question, and it does (eventually) relate to A6. . .

My question is about literals, and their types (value-types, of course,
since literals don't have containers in any normal sense of the term).

Some are obvious, though I haven't made an Int/int distinction here:

Literal Type
----------------------------------------
666 Int (or Num)
666.66 Num
6e6 Num
"6" Str
'6' Str
<<HEREDOC... Str
(6, 6, 6) List [0]

Some are a little fiddly:

Literal Type
----------------------------------------------
[6, 6, 6] (Ref to) Array of Scalar [1]
{"6" => 6} (Ref to) Hash of Scalar [1]

But what about this:

Literal Type
----------------------------------------
undef Scalar

? Just "Scalar"? Maybe that isn't useful. Read on...

What if I want a literal that's of a different type? Normally not an
issue, because we're assigning it to a container that has a
container-type. But what about using a literal in multimethods? For
example (a little contrived, but imaginable):

class Frotz {...}
class Blorb {...}

# If $b is undef, return a new Blorb object,
# else use the current $b object.
multi thingy returns Blorb (Frotz $a, Blorb $b: *@extras) {...}

my Frotz $abc;
$abc.init();

# Make new $obj.
my Blorb $obj = thingy($abc, undef); # note

for $x (@something)
{
# Use existing $obj.
thingy($abc, $obj, $x);
}

The line marked "note" passes undef as the second argument. Multimethod
dispatch won't find that, because that call is looking for a multimethod
multi thingy returns Blorb (Frotz $a, Scalar $b: *@extras) {...}
(note the "Scalar") and there isn't one.

This could be solved with a bit of typecasting - or, because this is
Perl, applying "Blorb" context to undef. Is there a syntax for that?
Something like:
thingy($abc, Blorb undef);
or
thingy($abc, undef is Blorb); # "is", so compile-time?
or
thingy($abc, undef but Blorb); # "but", so run-time?
? I'd go for the second one, but maybe I'm wrong.

I know that typecasts are evil, but I don't see how to avoid them with
multimethod dispatch unless:
- multimethods are very, very smart about coercing types,
- you dictate that all multimethod invocants must be in variables (which
can have object types),
- you have the ability to cast a literal to be of a certain object type,
or
- you forbid the kind of programming style of my example, and don't
allow undef et al in these situations to indicate empty slots. But
the problem may emerge in other situations, such as disambiguating
types of array elements, maybe.

Or is it none of the above?


[0] Lists are still sort of second-class types, so perhaps this is not
entirely correct.
[1] Or "Ref to Array/Hash of Int"? I doubt it somehow.

--
Debbie Pickett http://www.csse.monash.edu.au/~debbiep deb...@csse.monash.edu.au
"But - you'll have your man. Life's full of tough choices, innit?" - _The Little
Mermaid_

Damian Conway

unread,
Apr 14, 2003, 12:41:42 AM4/14/03
to perl6-l...@perl.org
Deborah Ariel Pickett wrote:

> Literal Type
> ----------------------------------------
> undef Scalar

Just Scalar.


> What if I want a literal that's of a different type?

You can't have it. Not without messing about with the parser, at least.


> class Frotz {...}
> class Blorb {...}
>
> # If $b is undef, return a new Blorb object,
> # else use the current $b object.
> multi thingy returns Blorb (Frotz $a, Blorb $b: *@extras) {...}

That's:

multi thingy (Frotz $a, Blorb $b: *@extras) returns Blorb {...}


> my Frotz $abc;
> $abc.init();
>
> # Make new $obj.
> my Blorb $obj = thingy($abc, undef); # note
>
> for $x (@something)
> {
> # Use existing $obj.
> thingy($abc, $obj, $x);
> }
>
> The line marked "note" passes undef as the second argument. Multimethod
> dispatch won't find that, because that call is looking for a multimethod
> multi thingy returns Blorb (Frotz $a, Scalar $b: *@extras) {...}
> (note the "Scalar") and there isn't one.

Correct.


> This could be solved with a bit of typecasting - or, because this is
> Perl, applying "Blorb" context to undef. Is there a syntax for that?

No. You can't typecast in that way. Declaring the parameter $b to be of type
Blorb is a promise that what's in $b will swim like a Blorb, quack like a
Blorb, etc. An undef can't.


> I know that typecasts are evil,

Indeed.


> but I don't see how to avoid them with
> multimethod dispatch unless:
> - multimethods are very, very smart about coercing types,

Probably not Evil Genius smart, no.


> - you dictate that all multimethod invocants must be in variables (which
> can have object types),

No. That's unnecessarily restricting. And wouldn't help in this case anyway
since the undef still "jest ain't raght" as a Blorb.


> - you have the ability to cast a literal to be of a certain object type,

Nope.


> - you forbid the kind of programming style of my example, and don't
> allow undef et al in these situations to indicate empty slots.

Bingo!

If you need to be able to indicate an "empty slot", you do it like this:

# "Real Blorb" version
multi thingy (Frotz $a, Blorb $b: *@extras) returns Blorb {...}

# "Empty slot where my Blorb should have been" version
multi thingy (Frotz $a: *@extras) returns Blorb {...}

Or else you use a junction:

multi thingy (Frotz $a, Blorb|Scalar $b: *@extras) returns Blorb {
given $b {
when Blorb {...}
when undef {...}
default { croak "Second arg must be Blorb or undef" }
}
}

Damian

Dave Whipp

unread,
Apr 14, 2003, 11:23:02 PM4/14/03
to perl6-l...@perl.org
Deborah Ariel Pickett wrote:

> This could be solved with a bit of typecasting - or, because this is
> Perl, applying "Blorb" context to undef. Is there a syntax for that?
> Something like:
> thingy($abc, Blorb undef);
> or
> thingy($abc, undef is Blorb); # "is", so compile-time?
> or
> thingy($abc, undef but Blorb); # "but", so run-time?
> ? I'd go for the second one, but maybe I'm wrong.

class Blorb
{
class UndefBlorb is Blorb {...};
our $undef is const = UndefBlorb.new;

method undef () returns Blorb { $undef };
}

thingy($abc, Blorb.undef);


Dave.

0 new messages