Perl data types

D

David Holmes

I have a few questions regarding perl composite data types:

firstly product types, as I see it the only way of doing this is to use
Class::Struct. This will allow the use of multiple variables to be
identified as a single value.

secondly, does this make a hash a product type, because the keys are
referenced by scalars, and these point to variables, which i guess could be
anything but allows a simple structure.

thirdly, does perl support sum types, as far as I can tell, since perl is
not a typed language as such it is imposible to tell the differnce between
the types, for example a case statement is impossible. The could obviously
be overcome using the a regex to an extent to tell whether a scalar is a
number or a string, but apart from that it is not really possible.

Regards

Dave
 
E

Eric Schwartz

David Holmes said:
firstly product types, as I see it the only way of doing this is to use
Class::Struct. This will allow the use of multiple variables to be
identified as a single value.

What is a "product type"? I've not heard this terminology before.
secondly, does this make a hash a product type, because the keys are
referenced by scalars, and these point to variables, which i guess could be
anything but allows a simple structure.

Not knowing what a product type is, I can't help.
thirdly, does perl support sum types

What is a 'sum type'?
as far as I can tell, since perl is not a typed language as such it
is imposible to tell the differnce between the types, for example a
case statement is impossible.

Case statements are possible, they're just not built into the
language. See perlfaq7, "How do I create a switch or case statement?".

And perl is typed, albeit loosely.
The could obviously be overcome using the a regex to an extent to
tell whether a scalar is a number or a string, but apart from that
it is not really possible.

You don't (generally) care if it's a number or a string. If you use
it like a string, it's a string. If you use it like a number, it's a
number.

$foo = '4';

$bar = $foo + 3; # $bar is now 7

print "bar is [$bar]" if $bar eq '7';

-=Eric
 
A

AlV

Eric said:
[snip]
as far as I can tell, since perl is not a typed language as such it
is imposible to tell the differnce between the types, for example a
case statement is impossible.


Case statements are possible, they're just not built into the
language. See perlfaq7, "How do I create a switch or case statement?".

And perl is typed, albeit loosely.

Just to add my two cents, Damian Conway has made a module named
Attribute::Types which adds strong typing (at run time, not compile
time) to Perl 5:

http://search.cpan.org/~dconway/Attribute-Types-0.10/lib/Attribute/Types.pm
(this module requires Attribute::Handlers)

Have a nice day,
 
D

David Holmes

Hi,

The definition of a product type is a type that collects together a number
of data items in a single value. This is why I think that it is a struct. I
know that a product type would be a strinct in c, and in java it would just
be a case of specifying multiple variables, to a class.

Basically I dont know what languages you know but take java for example,
which of course would be similar for c++. If you have an object called Test
that has two string variables, you can deal with the Test object as an
individual item, but can get access to the individual elements.

Similar in a way to a perl hash, you can deal with the hash as a whole
thing, whilst being able to get access to the keys and values, as if they
are two variables of the hash object.

As for sum types, they are subtly different. Values of a sum type are
tagged. This can take several forms but again in the example of a java.
Incase you cant tell this is the language I use most. If you have a base
class that extends a superclass1 and a superclass2. You can initialise a
variable as the base class, and then say:

if (instanceOf(superclass1)) { do something }
else if (instanceOf(superclass2)) { do something else }

As I said the values of a sum type are tagged, so I guess in perl since
there are few primative types, it would be like taking a variable,
initialising it to some value and asking:

if this is a scalar { do something }
else if it is a hash { foreach hash { do something }}
else if it is an array.....


Hope that at least makes some sense.

Regards

Dave

Eric Schwartz said:
David Holmes said:
firstly product types, as I see it the only way of doing this is to use
Class::Struct. This will allow the use of multiple variables to be
identified as a single value.

What is a "product type"? I've not heard this terminology before.
secondly, does this make a hash a product type, because the keys are
referenced by scalars, and these point to variables, which i guess could be
anything but allows a simple structure.

Not knowing what a product type is, I can't help.
thirdly, does perl support sum types

What is a 'sum type'?
as far as I can tell, since perl is not a typed language as such it
is imposible to tell the differnce between the types, for example a
case statement is impossible.

Case statements are possible, they're just not built into the
language. See perlfaq7, "How do I create a switch or case statement?".

And perl is typed, albeit loosely.
The could obviously be overcome using the a regex to an extent to
tell whether a scalar is a number or a string, but apart from that
it is not really possible.

You don't (generally) care if it's a number or a string. If you use
it like a string, it's a string. If you use it like a number, it's a
number.

$foo = '4';

$bar = $foo + 3; # $bar is now 7

print "bar is [$bar]" if $bar eq '7';

-=Eric
 
B

Ben Morrow

David Holmes said:
I have a few questions regarding perl composite data types:

I take it you are coming from a Pascal/ML-ish background? From what
little I know of such languages, Perl works quite differently. You do
not need to worry about types in the same way.
firstly product types, as I see it the only way of doing this is to use
Class::Struct. This will allow the use of multiple variables to be
identified as a single value.

secondly, does this make a hash a product type, because the keys are
referenced by scalars, and these point to variables, which i guess could be
anything but allows a simple structure.

I take it a 'product type' is something like a C struct, where you
define that a Foo, foo, consists of a Bar, foo.bar, and a baz,
foo.baz?

Class::Struct is indeed one way of doing this, although for simple
situations it is overkill. The standard Perl way is, as you say, with
a hash:

my %foo = (bar => "something", baz => "something else");

or with an anonymous hash:

my $foo = { bar => "something", baz => "something else");

my $x = { y => $foo, z => "Z" };

You can build up complex data structures like this on the fly, without
needing to declare the types beforehand.
thirdly, does perl support sum types, as far as I can tell, since perl is
not a typed language as such it is imposible to tell the differnce between
the types, for example a case statement is impossible. The could obviously
be overcome using the a regex to an extent to tell whether a scalar is a
number or a string, but apart from that it is not really possible.

Again, I take it a 'product type' is like a C union, where a Foo is
either a Bar or a Baz but not both, and you can switch on the runtime
type? This is not really something you need in Perl: as the data
structures are all flexible, you just switch on the values instead.

Having never got my head round one of the 'type-oriented' languages, I
don't really know what you'd use them for to tell you how to do that
in Perl. If you can give me an example of a situation where you'd want
to use one, I'll think how I'd code it.

Ben
 
B

Ben Morrow

[don't top-post]

David Holmes said:
As for sum types, they are subtly different. Values of a sum type are
tagged. This can take several forms but again in the example of a java.
Incase you cant tell this is the language I use most. If you have a base
class that extends a superclass1 and a superclass2.

Surely you mean 'you have a base class that is extended by a subclass1
and a subclass2'? You're talking normal single inheritance, rather
than a class which has two base classes (or implements two interfaces,
or whatever mess Java's made of multiple inheritance)?
You can initialise a variable as the base class, and then say:
if (instanceOf(superclass1)) { do something }
else if (instanceOf(superclass2)) { do something else }

Well, you can do that in Perl perfectly easily.

package Base;
sub new { return bless {}, shift } # a constructor

sub method {
my $self = shift;
if ($self->isa("Sub1")) {
# do summat
}
elsif ($self->isa("Sub2")) {
# do summat else
}
}

package Sub1;
push @ISA, "Base"; # set up inheritance
sub new {
my $class = shift;
my $self = $class->SUPER::new;
my $self->{sub1} = "data";
}

package Sub2;
push @ISA, "Base"; # set up inheritance
sub new {
my $class = shift;
my $self = $class->SUPER::new;
my $self->{sub2} = "data";
}

IMHO, Perl's OO is *really* well done. It supports all the concepts if
you need them, but doesn't force them down your throat the way Java
and C++ do. Of course, if you're a fan of Java you're likely to
disagree... :)

Ben
 
E

Eric Schwartz

David Holmes said:
The definition of a product type is a type that collects together a number
of data items in a single value. This is why I think that it is a struct.

As Ben Morrow pointed out, you'd use a hash for this in Perl, as a
rule.
As for sum types, they are subtly different. Values of a sum type are
tagged. This can take several forms but again in the example of a java.
Incase you cant tell this is the language I use most. If you have a base
class that extends a superclass1 and a superclass2. You can initialise a
variable as the base class, and then say:

if (instanceOf(superclass1)) { do something }
else if (instanceOf(superclass2)) { do something else }

But that's crappy OO programming. You should do

object.method()

instead, and let inheritance take care of what gets done, no?
As I said the values of a sum type are tagged,

How are they tagged? I don't see anything like that in your example.
so I guess in perl since there are few primative types, it would be
like taking a variable, initialising it to some value and asking:

if this is a scalar { do something }
else if it is a hash { foreach hash { do something }}
else if it is an array.....

But in Perl, you already know what type it is, by the sigil in front
of the variable:

$var is a scalar
@var is an array
%var is a hash

So what would be the point?
Hope that at least makes some sense.

Sorry, not really. I don't see what you'd want to use a sum type for.

And please don't top-post, it's rude, and it's against the Posting
Guidelines which are posted regularly to this group.

-=Eric
 
J

Jürgen Exner

Eric said:
What is a "product type"? I've not heard this terminology before.

It's a type whose elements are the mathematical product (sometimes called
cross product) of two sets.
For example, the cross product of string and number could be used to create
data elements, which contain a name and the associated income.
A familar product type would be e.g. the "RECORD" type in Pascal or Modula.

Corrrection: the keys are are actual scalars

Well, I wouldn't call it "point to", but essentially you are right.
And yes, hashes could be considered to be a form of a product type.
What is a 'sum type'?

A sum type is the mathematical sum of its constituents, e.g. the enumeration
of elements in a Pascal SET type.

You are mistaken, Perl is a strictly typed language. However, the types are
not what you would normally consider types. The Perl data types are scalar,
array, and hash. You just need to get used to that notion of type.

jue
 
T

Tassilo v. Parseval

Also sprach Eric Schwartz:
But that's crappy OO programming. You should do

object.method()

instead, and let inheritance take care of what gets done, no?

No, not in Java. Due to broken-by-design method dispatch, you will
constantly be checking the type and then do a typecast. If you have a
class "Foo" with a method "bar" and you stuff 10 Foo objects into

Object array[10];

you can't just say 'array[0].bar'. Instead you have to write

((Foo)array[0]).bar();

This gets worse if 'array' contains Foo and Bar objects and both have a
"bar" method. Then this becomes:

if (array[0] instanceof Foo) {
((Foo)array[0]).bar();
} else {
((Bar)array[0]).bar();
}

Thus, it is often required in Java to do the type checking by hand.
Therefore I never quite understood how SUN can claim that Java has
polymorphism at all.

Tassilo
 
E

Eric Schwartz

Tassilo v. Parseval said:
Also sprach Eric Schwartz:

No, not in Java. Due to broken-by-design method dispatch, you will
constantly be checking the type and then do a typecast.

<snip the horror... THE HORROR!>

Well, no wonder I dislike statically-typed OO languages. :p Your
explanation is cogent, sensible, and completely inane. I can't
believe Java programmers stand for that sort of thing.

-=Eric
 
M

Malcolm Dew-Jones

Tassilo v. Parseval ([email protected]) wrote:
: Also sprach Eric Schwartz:


: >> As for sum types, they are subtly different. Values of a sum type are
: >> tagged. This can take several forms but again in the example of a java.
: >> Incase you cant tell this is the language I use most. If you have a base
: >> class that extends a superclass1 and a superclass2. You can initialise a
: >> variable as the base class, and then say:
: >>
: >> if (instanceOf(superclass1)) { do something }
: >> else if (instanceOf(superclass2)) { do something else }
: >
: > But that's crappy OO programming. You should do
: >
: > object.method()
: >
: > instead, and let inheritance take care of what gets done, no?

: No, not in Java. Due to broken-by-design method dispatch, you will
: constantly be checking the type and then do a typecast. If you have a
: class "Foo" with a method "bar" and you stuff 10 Foo objects into

: Object array[10];

If they are Foo objects, then why pretend they are just generic Objects?
Why not stuff them into

Foo array[10];

Then you can write

array[0].bar();

just like you wish.


: you can't just say 'array[0].bar'. Instead you have to write

: ((Foo)array[0]).bar();

: This gets worse if 'array' contains Foo and Bar objects and both have a
: "bar" method. Then this becomes:

: if (array[0] instanceof Foo) {
: ((Foo)array[0]).bar();
: } else {
: ((Bar)array[0]).bar();
: }

If Foo and Bar are derived from the same class which provides "bar()", or
if they both implement an interface that has bar, then, as above, you can
select a type for the array that is more specific than Object (and more
appropriate), and then the above is not needed.


: Thus, it is often required in Java to do the type checking by hand.

I wonder why UNIVERSAL.pm provides isa() and can()? Perhaps it's because
you have to do these same kind of checks in perl on occasion?


: Therefore I never quite understood how SUN can claim that Java has
: polymorphism at all.

Perhaps because it does?
 
T

Tassilo v. Parseval

Also sprach Malcolm Dew-Jones:
Tassilo v. Parseval ([email protected]) wrote:
: Also sprach Eric Schwartz:


: >> As for sum types, they are subtly different. Values of a sum type are
: >> tagged. This can take several forms but again in the example of a java.
: >> Incase you cant tell this is the language I use most. If you have a base
: >> class that extends a superclass1 and a superclass2. You can initialise a
: >> variable as the base class, and then say:
: >>
: >> if (instanceOf(superclass1)) { do something }
: >> else if (instanceOf(superclass2)) { do something else }
: >
: > But that's crappy OO programming. You should do
: >
: > object.method()
: >
: > instead, and let inheritance take care of what gets done, no?

: No, not in Java. Due to broken-by-design method dispatch, you will
: constantly be checking the type and then do a typecast. If you have a
: class "Foo" with a method "bar" and you stuff 10 Foo objects into

: Object array[10];

If they are Foo objects, then why pretend they are just generic Objects?
Why not stuff them into

Foo array[10];

Then you can write

array[0].bar();

just like you wish.

Too bad that you sometimes have no choice. Just look at some of the
classes in the Java API (like 'Collection' or so). They all cast their
objects down to the most generic class 'Object'.

Java simply is lacking things like C++ templates. Note that C++ would
become pretty unprogrammable if you didn't have them for the sake of
genericity and polymorphism.
: you can't just say 'array[0].bar'. Instead you have to write

: ((Foo)array[0]).bar();

: This gets worse if 'array' contains Foo and Bar objects and both have a
: "bar" method. Then this becomes:

: if (array[0] instanceof Foo) {
: ((Foo)array[0]).bar();
: } else {
: ((Bar)array[0]).bar();
: }

If Foo and Bar are derived from the same class which provides "bar()", or
if they both implement an interface that has bar, then, as above, you can
select a type for the array that is more specific than Object (and more
appropriate), and then the above is not needed.

Take this hierarchy:

Class1;
Class2 extends Class1;
Class3 extends Class2; // and possibly overrides Class1.method()

Say, that each of these classes is instantiatable. So I'd naturally
choose

Class1 array[10];

How exactly would that avoid typecasts? Sure, I can probably have each
of these three implement an interface and change the type of the array
to that of the common interface. However, do I want that? Certainly not.
It means I, the programmer, have to accept such a red-herring in order
to make polymorphism work as expected and convenient.
: Thus, it is often required in Java to do the type checking by hand.

I wonder why UNIVERSAL.pm provides isa() and can()? Perhaps it's because
you have to do these same kind of checks in perl on occasion?

Yes, occasionally. But this happens at runtime. In Java the thing wont
even compile. Also, please count the occurances of can() and isa() in
Perl code and compare the number to 'instanceof' and typecasts in Java
programs.

Often enough I had to program in Java and each time I got sick of these
(deliberate, I may add) limitations of this language. This will turn any
medium-sized program into something bloated with many auxiliary
interfaces and classes that wouldn't be there if Java chose a more
reasonable approach.
: Therefore I never quite understood how SUN can claim that Java has
: polymorphism at all.

Perhaps because it does?

Hardly to a visible extent.

Tassilo
 
J

John W. Kennedy

Tassilo said:
No, not in Java. Due to broken-by-design method dispatch, you will
constantly be checking the type and then do a typecast. If you have a
class "Foo" with a method "bar" and you stuff 10 Foo objects into

Object array[10];

you can't just say 'array[0].bar'.

Assuming that you are an adult, you declared it:
Foo array[10];
and then you can say:
array[0].bar();
Instead you have to write

((Foo)array[0]).bar();

This gets worse if 'array' contains Foo and Bar objects and both have a
"bar" method. Then this becomes:

if (array[0] instanceof Foo) {
((Foo)array[0]).bar();
} else {
((Bar)array[0]).bar();
}

Thus, it is often required in Java to do the type checking by hand.
Therefore I never quite understood how SUN can claim that Java has
polymorphism at all.

No, assuming that you are an adult, you declared
interface BarInterface {
void bar();
}
and you declared both classes Foo and Bar as:
implements BarInterface
and you declared the array as:
BarInterface array[10];
and then you can say:
array[0].bar();

--
John W. Kennedy
"But now is a new thing which is very old--
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor's sake."
-- Charles Williams. "Judgement at Chelmsford"
 
J

John W. Kennedy

Tassilo said:
Too bad that you sometimes have no choice. Just look at some of the
classes in the Java API (like 'Collection' or so). They all cast their
objects down to the most generic class 'Object'.

Which is why Java 1.5 includes generic types, so that you can declare a
collection as:
Collection said:
Take this hierarchy:

Class1;
Class2 extends Class1;
Class3 extends Class2; // and possibly overrides Class1.method()

Say, that each of these classes is instantiatable. So I'd naturally
choose

Class1 array[10];

How exactly would that avoid typecasts? Sure, I can probably have each
of these three implement an interface and change the type of the array
to that of the common interface. However, do I want that? Certainly not.
It means I, the programmer, have to accept such a red-herring in order
to make polymorphism work as expected and convenient.

Poor baby!

If you're too big a coward to tell your lies about Java in Java
newsgroups, then keep the Hell off the subject of Java in other groups.

--
John W. Kennedy
"But now is a new thing which is very old--
that the rich make themselves richer and not poorer,
which is the true Gospel, for the poor's sake."
-- Charles Williams. "Judgement at Chelmsford"
 
T

Tassilo v. Parseval

Also sprach John W. Kennedy:
Tassilo v. Parseval wrote:

Which is why Java 1.5 includes generic types, so that you can declare a
collection as:
Collection<Foo> fooset;

I am aware of that. Java 1.5 is still beta and so I don't see any reason
why I should withdraw my statement.
Take this hierarchy:

Class1;
Class2 extends Class1;
Class3 extends Class2; // and possibly overrides Class1.method()

Say, that each of these classes is instantiatable. So I'd naturally
choose

Class1 array[10];

How exactly would that avoid typecasts? Sure, I can probably have each
of these three implement an interface and change the type of the array
to that of the common interface. However, do I want that? Certainly not.
It means I, the programmer, have to accept such a red-herring in order
to make polymorphism work as expected and convenient.

Poor baby!

If you're too big a coward to tell your lies about Java in Java
newsgroups, then keep the Hell off the subject of Java in other groups.

I am not subscribed to any Java newsgroup, so I couldn't see the
discussion evolving from that. I am afraid you have to antagonize me
here in this group (or if you prefer: by mail. I'd be delighted).

Apart from that, everything I wrote in the above paragraph is the truth
for non-beta Javas. Or else show me how to do it without interfaces (I
said that you can use them and that I consider them a red-herring).

Tassilo
 
A

Aaron Sherman

Tassilo v. Parseval said:
Also sprach Malcolm Dew-Jones:
: > object.method()
: >
: > instead, and let inheritance take care of what gets done, no?
: No, not in Java. Due to broken-by-design method dispatch, you will
: constantly be checking the type and then do a typecast. If you have a
: class "Foo" with a method "bar" and you stuff 10 Foo objects into
: Object array[10];

If they are Foo objects, then why pretend they are just generic Objects?
Why not stuff them into
Too bad that you sometimes have no choice. Just look at some of the
classes in the Java API (like 'Collection' or so). They all cast their
objects down to the most generic class 'Object'.

I think you are misunderstanding Java.

The entire reason that your have to lug around vtables is so that
polymorphism will work as you expect. Otherwise, polymorphism is only
one-way any your life is most unpleasant.

Example:

class AJSClass1 {
public static void main(String[] args) {
AJSClass3 foo = new AJSClass3();
AJSClass2 bar = foo;
System.out.println(bar.hello());
}
}

class AJSClass2 {
public String hello() {
return "Hello";
}
}

class AJSClass3 extends AJSClass2 {
public String hello() {
return "World";
}
}

If that didn't print "World", we'd be in pretty sad shape (well, those
who use Java would be, I'm not one of those -- I had to go search
language references just to remember how to declare main ;-)
Java simply is lacking things like C++ templates. Note that C++ would
become pretty unprogrammable if you didn't have them for the sake of
genericity and polymorphism.

C++ does not use templates for what you describe above. C++ uses the
same vtable management (in general, though specifics of implementation
differ) as Java. Templates allow CODE to be polymorphic right along
with the objects that the code works on.
Yes, occasionally. But this happens at runtime. In Java the thing wont
even compile. Also, please count the occurances of can() and isa() in
Perl code and compare the number to 'instanceof' and typecasts in Java
programs.

The reason you use can() or isa() in Perl is (I would assume) much the
same reason that you would use the equivalents in Java: to know if an
object that you have been handed is capable of performing some task.

Now, in Java you have the option of using type-checking to tell you
that up-front if you have designed your class structure correctly. In
Perl, you have to do it manually, because Perl's types are too dynamic
to impose such restrictions (I think Perl 6 aims to allow such
restrictions, though).
Often enough I had to program in Java and each time I got sick of these
(deliberate, I may add) limitations of this language.

I think you got stuck with some bad documentation or poorly written
libraries.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top