in reply to Re^13: use fields; # damnit
in thread use fields; # damnit

You can't really try to successfully take all that into consideration on the same level. Rather, I would say that Perl has multiple distinct type systems layered on top of each other:

  1. The base type system, the one actually concerned with the representation of values, is strongly typed and completely uncircumventable. You can neither cast nor convert values into each other at this level, in any way, shape, or form.
  2. Context is a distinct typing system and quite strongly typed (think of "there is no list in scalar context", f.ex). However, it has a full set of conversion rules covering all axes, so in practive, that hardly matters.
  3. The high level type system, the level at which strings and numbers differ f.ex, is just about typeless. This layer is vague and always implicit, never declared, nowhere to be enforced.
  4. Finally, the type of an object is yet another fully disjoint typing system; in fact it is just metadata dangling off of a thing, only accessible via a reference. I am not sure how strongly typed this can be considered to be, but even if so that is ultimately meaningless since it is completely dynamic to the point that what it means that an object is of some type can completely change at any point. It also exists in a kind of vacuum, because the only time it ever matters is on method lookup. In all other circumstances it is completely inconsequential.

If we tally up, we find that we have two explicit typing systems which are both strong, and one which is barely definable and can hardly be called a typing system at all. Then we have another one dangling on the side of it all, nearly completely isolated and so ridiculously dynamic it doesn't even make sense to talk about whether it is strong or not.

So, yes, Perl as a whole defies classification.

If you scale back and look at the innate typing that's an explicit part of the language, however, you find that to be a strong one. That's why me or merlyn or chromatic will assert that Perl is strongly typed. Of course, noone will dispute that it is a strange example of strong typing. :-)

Makeshifts last the longest.

Replies are listed 'Best First'.
Re^15: use fields; # damnit
by stvn (Monsignor) on Aug 22, 2004 at 00:37 UTC
    So, yes, Perl as a whole defies classification

    Well at least we can agree on this. I like your breakdown, its a very interesting way of looking at it. However, I prefer to look at a language as having a single type system rather than several type systems layered upon one another. You (and chromatic and merlyn) say tomAto, and I will say tOmato. IMO, thats one of the things that makes perl so great, because there is TIMTOWTDI, there is also more than one way to look at it too.

    That's why me or merlyn or chromatic will assert that Perl is strongly typed.

    Funny, i find that sometimes I don't always agree with them either ;-)

    -stvn
Re^15: use fields; # damnit
by BrowserUk (Patriarch) on Aug 21, 2004 at 23:27 UTC

    It's interesting to compare tha various definitions of both what "strongly typed" means, and how Perl typing system is characterised by various people with the "industry standard definitions" of that term.

    Personally, I find it a stretch to consider a language that has only one type (plus two conglomorates) as strongly typed. I find there to be very little difference between "one type" and "no types".

    Assembler has no types--just memory and pointers to memory. Any pointer can point to memory containing anything. And any piece of memory (regardless of what it contains) can be treated as anything, including a pointer to anything.

    Perl has only one type: Scalars, plus two conglorates: hashes of scalars and arrays of scalars. And a scalar be used to contain any type of data: characters, integers, reals, strings, and references to anything. Often it contains many of these simulataneously.

    Whilst I can't fault your four levels of type definition, using the phrase "a strongly typed language" to describe Perl, given the industry accepted definition of that phrase, is something of a stretch.

    Of course, I'm not necessarially agreeing with that particular definition entirely, and I totally disagree that (all) langauges traditionally defined as being "strongly typed" actually meet that definition. More to the point, even those that do meet that definition rarely, if ever, deliver the kinds of benefits that "management" have been led to expect of them, by such definitions.

    Ultimately, I think that contextual typing is the most powerful (and maybe revolutionary) concept in perl. It won't really come to fruition until perl 6 hits the streets with it's enhanced contextual information, but it will be very interesting to see how things evolve once it does.

    The very idea that I can be passed some entity and assign it to a local variable defined as some type and the entity itself (or rather the author of the entity) can decide to give me the appropriate representation of that entity to fit my requirements--or raise an exception if it doesn't know how to convert itself to my requirements is just so powerful.

    Rather than me, the user of the entity trying to decide how to perform the conversion to the type I need, context moves that responsibility back to the author of the entity where it belongs.

    I'm not yet sure that this idea will be taken to it's full potential even with Perl 6. If I try to assign a scalar given to me to a variable defined as  my int  $x; (on a 32-bit platform) and the scalar contains '5e10', what will P6 do? Will the enhance want function notice the discrepancy?

    What if I try my Animal $beast = new Dog( ... );? I could see the possibility of want detecting the caller context as Animal and allowing the author of the Dog module to provide a return of the Animal instance (reference) that underlies the Dog instance regardless of whether Dog inherits from Animal or is composed from Animal and one or more other Classes. I guess you could do this now by providing a Dog::getAnimal method.

    Perl already has this kind of context awarness to a certain level. If you use a reference in a scalar context, it gives you a textual representation of the reference. If you use [cpna://overload], you can tweak this to provide a more meaningful representation without the need to call an asString() method explicitly.

    Finding uses for such an extension of the context information isn't at all hard. For example: A Dog in a Dog context might sort according to its bred, but in an Animal context it might sort according to it's genus (Is that the right term?).

    And yes. I rambled. And no, I'm not critiquing your post. Just adding my rambling thoughts to the mix.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

      Well, Perl has one simple and two composite data types, but the composite data types are indeed data types in their own right, the way classes are data types in Java.

      Again, as I said in conclusion — Perl is certainly a less than ordinary example of a strongly typed language. But by the letter of the definition, that is what it is. :-) Funny thought, I know.

      As for your ramblings, I'd stipulate that what you really want to look into is Perl6's object system with its traits model. Extensive contextual polymorphy like what you describe sounds more dangerous than advisable to me. I like contextuality in Perl5, I'm not sure it is really necessary, and I sometimes wonder if we couldn't have done just as well without it. As well, overloading mechanisms are considered easily abusable for a reason. I used to be a huge fan; nowadays, I'm not so sure. Just to confirm my worries, I've only recently had some run-ins with overloading (in Class::DBI) that reminded me very pointedly that it's a mixed blessing at best. I do believe that a language should provide such deep hooks; but they're not really for use in application programming.

      Makeshifts last the longest.

        ...you really want to look into is Perl6's object system with its traits model.

        I have had several passes at thinking through how they are going to work, including this one. I like the concept a lot--all the power of MI without the nightmare that MI usually is in practice. And without the "everything inherits from everything" imposssibly deep inheritance trees that usually result.

        I like contextuality in Perl5, I'm not sure it is really necessary, and I sometimes wonder if we couldn't have done just as well without it...

        Your not the first person who's expressed that opinion here. S'funny, but I still see context awareness as (one of) the major, new (to me) contributions that Perl has given to programming. I'm completely happy to see it not only persist, but be extended. The overloading thing is an orthoganal issue here--it's just one way of using it. Powerful, but orthoganal.

        What really started (ressurected) this thought process was a recent p6i post. Basically, Dan noted that in Parrot, the same mechanism that is used to provide for Multi-method dispath (that I think is destined to become very important in P6), means that calls to a subroutine, and returns from a subroutine, are essentially identical. Which, he goes on to suggest means that as well as MMD, we could have MMR (multi-method return) and all that is required is some HLL syntax to make use of this.

        Whilst the thread goes on to discuss various more or less humerous uses for this, the thought crossed my mind that actually no HLL construct is required. All it would need is for an under-the-covers use of the enhanced wantarray to determine the return context and use that to MMR the appropriate representation of the thing being returned.

        In effect, simply extending the current contextual awarness that allows me to write:

        my $thing = 3.5; print $array[ $thing ]; my $test = 'Some text' . $thing;

        all without having to perform casts or any other machinations.

        Extending this context awareness to user defined datatypes (objects) could allow the author of the class to (for example), add subroutines to his class (by some well known naming convention perhaps) along the lines of:

        sub ^asText { my $self = shift; return sprintf "...", $self.attr1, $self.attr2... } sub ^asAnimal { my $self = shift; return $self.Animal; }

        Then, whenever an object returns itself, the appropriate value is returned with the compiler determining which method is called to provide the result. If no method is provided for the context into which the value is being returned, then an exception is raised. If the return context is just scalar, then the base reference is returned.

        It would remove the need for every method to test the return context and do the right thing. It allows new type conversions to be added later by the provision of a single new method. Everything else remains the same, but if any existing method is called in a context of the new type, it does the right thing.

        I'm probably moving in directions that even TheDamian has the sense to steer clear of, but then I don't have the responsibility to see all the possible outcomes. Still, the idea seems immensely useful to me. But then it would, wouldn't it :)


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon