http://www.perlmonks.org?node_id=160235

Okay, I have to ask this. What on Earth is so great about strong typing that I have to have it? Is $x a float? Is it a double? Who the heck cares? (internally in Perl, if it's a number and it's not an integer, then it's a double). Sure, I don't want to stuff a float into an int and lose precision, but in Perl, you'll just automatically get the right type of number when you're done.

The 'C' language has weak typing. Sure, I can type int x;, but nothing later will stop me from trying to stuff a double in there, aside from the possible segfault or my wanting to know why four plus seven equals two hundred and thirteen. All typing in C really does is ensure that you've allocated enough memory (though a good compiler will let you know if you've screwed up if you turn on warnings).

Java, on the other hand, has strong typing. I can assign a float to a double and Java has no problem with that. If, however, I assign a double to a float, Java will fail at compile time unless I explicitly downcast the double to a float, thereby letting Java know that I really wasn't too concerned about precision in that assignment. However, if you had a type system that shields you from worrying about the exact details, is this level of nit-pickyness warranted?

What about Perl? Perl has the catch-all scalar. What's wrong with that? In my opinion, nothing, so long as you realize that there is a trade off and you accept it. That scalar's value can be a string, an integer, a double (yes, there's more, but I'm keeping this simple). Do you really care which? Sure, you need to know if your "value" of PI turns out to be an integer, but does it matter what you have with the following?

for ( my $i = 0; $i < 10; $i++ ) { # do stuff }

Yes, that's a C-style for loop and many people consider them heresy in Perl, but I used a familiar example in case someone wants to show this to someone unfamiliar with Perl.

In the above, admittedly trivial, example, if the purpose of the loop is to ensure that a particular activity occurred exactly 10 times, you probably wouldn't care what type $i is. Well, you would if you used $i != 10 for the exit condition, but you wouldn't do that anyway, right? But actually, what if you needed to? In Perl, a number is an integer if being an integer is enough. Once you add that .01 to the variable, it internally converts to a double and isn't going back. In fact, you wouldn't want it to go back in most instances. Perl knows what you wanted and handles it for you.

The interesting thing about Perl, though, is that it's "primitive typing mechanism" is actually very sophisticated. It only seems primitive on the surface. If you can stomach it -- and be warned, it's a rough ride -- read PerlGuts Illustrated. One of the quotes in there that really struck me was "the internal relationship between the Perl data types is really object oriented ... Perl uses multiple inheritance with [scalars] acting as some kind of virtual base class."

Whoa! What's up with that? And what does it mean to me? Well, what are the benefits of object-oriented programming? We get a clean, easy-to-use API. We get information hiding -- when was the last time you worried about whether or not the scalar had the ROK flag set properly? My favorite, though, is polymorphism. We call the "methods" on our "objects" and we don't worry about which method gets called. For example, in real life, what happens if you add 10 apples and 20 apples? You get 29 apples (I ate one). You don't get compiler warnings or segfaults. You just get a short exercise in how hungry Ovid is. However, try to add 10 and 20 apples with Perl:

$ perl -e 'print "10 apples"+"20 apples"' 30

Wow. Clearly, the plus operator has some deep magic assigned to it, but once you realize that you're basically making a method call and you don't care what type (hah!) of object you have, then you're doing okay.

Frankly, the more I think about this, the primary benefit of strong typing is generating compiler optimizations -- and if you needed lightning fast speed you wouldn't be using Perl anyway -- and catching stupid programmer mistakes like trying to add a string to a double. We lose the "catch stupid programmer mistakes" with Perl, but by not burdening us with the "benefits" of a strong type system, we can develop so much faster that we find and fix our stupid programmer mistakes before others even write the stupid programmer mistake.

I have never missed Perl's lack of strong typing (but it will be a nice option in Perl6), but the sort of applications that I work on generally don't require it. I'm wondering if any monks can share problems they have had because of Perl's type system. A counter-point would be nice to hear.

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: Griping about Typing
by Dominus (Parson) on Apr 18, 2002 at 19:03 UTC
    Says ovid:
    I'm wondering if any monks can share problems they have had because of Perl's type system. A counter-point would be nice to hear.
    A lot of folks, you among them, advise everyone to "always use strict". use strict includes use strict 'refs'. use strict 'refs' is there to detect, at run time, that the programmer has accidentally used a string in a place that expected a reference. That is nothing more than a type error. Therefore you, yourself, have provided the counterpoint.

    Frankly, the more I think abou this, the primary benefit of strong typing is generating compiler optimizations -- and if you needed lightning fast speed you wouldn't be using Perl anyway...
    I think you are confusing speed of programs written in Perl with the speed of Perl itself. People who write programs in Perl are often advised to forget about micro-optimizing, because the gains won't be large compared to the run time of the program. But that has northing to do with whether Perl itself shouldn't try to execute all programs as quickly as possible. I had this same discussion with a guy who wanted to know why the speed of Perl's internal hashing function was of any concern. The answer is that although it probably doesn't matter if any particular program is one percent faster or slower, every Perl program uses hashes, and if you can put a micro-optimization into Perl itself that will make every program one percent faster, you should do it.

    It's not even clear that speedup benefits of better type analysis would be so small as one percent. To add two machine integers takes only a few clock cycles. To add two PVIVs requires some tests, a function call or two, a switch, perhaps some memory allocation... I don't know how long it takes, but it might easily be a thousand times as long. There could be a substantial speed benefit if Perl could figure out that you weren't ever going to be storing anything but an integer in that scalar variable.

    we can develop so much faster that we find and fix our stupid programmer mistakes before others even write the stupid programmer mistake.
    That begs the question. You started by asking what the benefits of type checking are, but here you've implicitly assumed that they won't be very great.

    Earlier, you said:

    In the above, admittedly trivial, example, if the purpose of the loop is to ensure that a particular activity occurred exactly 10 times, you probably wouldn't care what type $i is.
    But you might care, if this were the innermost loop of your program, and if Perl could have gotten a 20% speed increase for the entire program by using a machine integer for the loop variable, which would have reduce the loop scaffold code to three machine instructions.

    It's easy to say "If you want C, you know where to find it", but the point here is that flexibly-typed data can coexist with strictly-typed data so that you don't have to sacrifice anything; you get the flexibility by default but still retain the option to get terrific speed in the parts of the program that need it. Common Lisp does this.

    I have never missed Perl's lack of strong typing
    Paul Graham calls that the 'blub problem'. Sure you don't miss it. TRS-80 BASIC programmers don't miss recursion; that doesn't mean it wouldn't be a benefit to them. C programmers will harangue you at length about how they don't miss automatic memory management; that doesn't mean it wouldn't be a benefit to them. It usually just means they're ignorant.

    --
    Mark Dominus
    Perl Paraphernalia

      I have never missed Perl's lack of strong typing.

      Yuck. I totally blew it on that one by not putting in the proper context. It's about as intelligent as saying "I've never missed not having a third eye." (how many negatives can I pack into one sentence?) I suppose I should have prefaced that statement by pointing out that I have worked with languages with stronger typing mechanisms, so I might be able to make a justification for stating that I am not totally unfamiliar with them, but the typing mechanisms for those other languages fall prey to the same arguments you put forward in your article about typing. Thus, I'm hard-pressed to sound intelligent about saying that I don't miss the broken and cumbersome type mechanisms of those other languages.

      ...if you can put a micro-optimization into Perl itself that will make every program one percent faster, you should do it.

      And following my comments regarding whether or not I care about a loop control variable being typed:

      But you might care, if this were the innermost loop of your program, and if Perl could have gotten a 20% speed increase for the entire program by using a machine integer for the loop variable, which would have reduce the loop scaffold code to three machine instructions.

      Thank you! That was exactly the sort of rebuttal that I was looking for. I hadn't given much thought (well, duh) to the speed of an individual program vis-a-vis the speed of Perl itself.

      I am curious, though, about the potential merits of my drawing an analogy between Perl's type system and the benefits of object oriented programming. The obvious trade off is performance. An optional strong typing mechanism to take advantage of performance, when needed, could coexist nicely with the OO-like behavior of the classic Perl variables. In fact, one OO behavior that I didn't mention, but that chromatic once pointed out to me, was tie. With tie, I can subclass the variable objects which seems to improve the analogy.

      The only reason that I came up with this is because I got rather tired of the "Perl's not typed" arguments. Frankly, I prefer to avoid language wars because they aren't terribly productive, but I was looking for a good way of explaining that Perl is not only typed -- around data structures instead of data types (is that equivocating?) -- but that its type mechanism has benefits that even OO afficionados could love.

      Side note: now that I stop to think about it, I think one might reasonably make the argument that C is not typed. If you take away the compiler warnings, the only thing (I think) that C really does is ensure that the amount of memory that a programmer asks for is allocated. After that, it will cheerfully try to stuff your float into the int. So, barring the warnings in the compiler, there's nothing built in to C to really support typing. Hmm... stuff for me to think about.

      Time passes... now that I've thought about it, the ability to cast data types within the program shows (amongst other examples) there is some typing being done. /me was stupid.

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      I don't think it's a matter of ignorance rather a matter of flexibility. If they could co-exist, I would have no problem with it. As far as 'blub', I know Paul a bit and in my experience he is a really brilliant guy but he is certainly TOOWTDIAIM (There Only One Way To Do It And It's Mine.) so I'll take that comment with a little bit of salt :)

      If type casting could be done without losing anything, great. I'm sure I would make good use for it as I have everything in Perl I've seen so far but if it were not an option, I'd find something else to program in.
Re: Griping about Typing
by robin (Chaplain) on Apr 18, 2002 at 16:48 UTC
    Dominus has a very nice article/talk on the subject of strong typing and Perl, which argues that strong typing is a good thing when automatic type inference is available. He gives some lovely examples of the power of ML-style strong typing.

    If your dislike of strong typing is based on languages like C and Pascal, it's well worth checking out a modern system such as O'Caml - which incidentally has a compiler that produces exceedingly efficient code, rivalling C.

    Sadly, Dominus concludes that adding this kind of type system to Perl would be like trying to "make a hot fudge sundae with mashed potatoes instead of ice cream".

Re: Griping about Typing
by FoxtrotUniform (Prior) on Apr 18, 2002 at 16:29 UTC
      What on Earth is so great about strong typing that I have to have it?

    I've usually been told "strong typing: good!" with no rationale. Occasionally, I'm told "strong typing helps prevent programmer error", with no explanation of how it prevents errors. (Okay, so it stops me from adding a string and an int. If I was adding strings and ints and expecting to get something useful, I have deeper problems than weak typing.)

    It occurs to me that a C-like "suggested typing" system encodes some information about a variable's domain. For instance, declaring int foo; says some things about foo: it measures a discrete value, for one. Chances are, the more information you give the person reading your code, the better; on the other hand, I can't think of any situation where this would be more useful than a proper variable name (my $line_count;).

    About the only advantage I can see in a stronger typing system than Perl's is the ability to align data in memory very precisely, which is useful when you're talking directly to hardware. I don't know of anyone doing that in Perl, though, and it doesn't require a strongly typed language: C does it rather well.

    --
    :wq

      You wrote:
      Occasionally, I'm told "strong typing helps prevent programmer error", with no explanation of how it prevents errors. (Okay, so it stops me from adding a string and an int. If I was adding strings and ints and expecting to get something useful, I have deeper problems than weak typing.)
      Please consider this C code:
      char name[] = "miguel"; int st_len = 0, namel; namel = strlen(name); st_len += name;
      See my error (actually a typo)? See how gcc warnings (which are kinda weak strong typing) save my time?
Re: Griping about Typing
by broquaint (Abbot) on Apr 18, 2002 at 16:55 UTC
    What on Earth is so great about strong typing that I have to have it?
    There is nothing so great about strong typing that you have to have it. That said, it can be wonderfully useful when done, and done correctly (see. Dominus' great article about strong typing).

    If it is done correctly, then if you ever have a type error then something is seriously wrong in your code, period. The reason you might want strong typing in your 'compiler' is to produce faster and slimmer code. The thing executing the strongly typed code will never have to guess whether it's dealing with an float or a double as it will be the right type.

    With that said, there aren't a great deal of advantages to the programmer with strongly typed code. They'll never get unexpected results due to mathematical imprecisions between type casts. Subsequently code will execute as you expect it to, not how the thing executing it guesses it should be executed.
    HTH

    _________
    broquaint

Re: Griping about Typing
by tadman (Prior) on Apr 18, 2002 at 19:07 UTC
    Typeless programming is great most of the time, but it can be a burning irritation as well. When the variables you are working with are malleable, like scalars, then you really don't care because of DWIM. When these scalars are actually object references, things can go all dark and blurry.
    my $bork = Bork->new(); my $x = $bork->bork()->bork();
    Quick quiz: What type of thing is $x anyway? What methods can you call on it? One of the great things about C++ and other strongly typed languages is that you have to prepare a holder for the thing you are requesting. It would be a lot more like:
    Bork bork = new Bork(); Chef x = bork->bork()->bork();
    No ambiguity there. Either you get a 'Chef', or you get a compile-time error.

    With the coming Apocalypse, I only hope that there will be some sort of optional type checking mechanism that can backpropagate the request into the function itself, just like wantarray. Here's an idea:
    my Bork:$bork = Bork->new(); my Chef:$x = $bork->bork()->bork();
    Maybe the bork method would be able to return a number of different things, including a 'Chef', based on some sort of if (wanta('Chef')) { ... } type check.

    Sure, you can say name your variables properly according to type, perhaps using the so-called Hungarian notation, but this can get quickly out of hand. You can also check the return types explicitly in some sort of paranoid gesture, but these are run-time errors and not compile time, which is really tough to test in comparison.

    Strict type checking, please, but only on request.
      You can already document your intent
      my $bork = Bork->new(); my Chef $x = $bork->bork->bork;
      Only trouble is (gee whizz!) I'm dreaming my life away.

      Ahem, back at the plot, the trouble is that perl will silently ignore your careful predeclaration and assign to $x even if ! $bork->bork->bork->isa('Chef'), which is a shame. use strict 'declarations' anyone? Implementation left as an exercise to the interested reader obviously. Me and C don't get on.

        Okay, can anyone explain how that works? It actually parses, though the class is completely ignored, provided it is defined somewhere. Here's a quick example:
        #!/usr/bin/perl -w use strict; use CGI; use LWP; my CGI $cgi = new CGI(); # Works my XYZ $cgi = new CGI(); # "No such class XYZ ..." my LWP $cgi = new CGI(); # Works, strangely enough
        Nothing in the docs about that, at least under my.
Re: Griping about Typing
by talexb (Chancellor) on Apr 18, 2002 at 21:13 UTC
    Having programmed in C for about 15 years, five of which I also used Pasal (ugh), I fall strongly on the "weak typing" side of this argument.

    Strong typing strikes me as 'training wheels' for beginner programmers who may need guidance not to do Stupid Things. Once one moves from Pascal to C or Perl, the training wheels come off, and all manner of bizarre and odd things are possible. This includes trying to add incompatible types: C will give you a compile time warning but may try to do what you are asking, with unpredictable results. Perl will probably go ahead and give you something weird and trust that you know what you're doing.

    That last bit is important. Perl trusts that you know what you're doing. It assumes if you really want to add "10 apples" and "20 apples", it will do its best to give you what it thinks is the answer. And that's the reason that I really enjoy Perl -- it gives me the same amount of freedom as C to do what I think is correct.

    And I truly hope that Damian and Larry (and whoever else we can persuade) will allow stricter typing in Perl 6, but as just an option. Please.

    Although Damian can be so darn persuasive. :)

    --t. alex

    "Nyahhh (munch, munch) What's up, Doc?" --Bugs Bunny

    ps Fascinating thread.

Re: Griping about Typing
by darksym (Beadle) on Apr 18, 2002 at 16:48 UTC
    Well it's good to have this as an option in Perl 6, but Perl 5's typing is quite excellent as-is. Rarely have I ever had to worry about these details. The biggest typing problem in Perl 5 is constants. Perl 6's constant attribute will be a much desired feature to me. My real fear is that Perl 6 could be abused when people start making things strong for no reason (especially C-programmers). KISS applies here. Perl shouldn't read like C... It should read like Perl. Also, the addition of attributes could potentially make for a sticky situation if attributes are abused to do the job that was really meant for an object. (Can this happen?)
Re: Griping about Typing
by pdcawley (Hermit) on Apr 19, 2002 at 06:58 UTC
    Strong typing can be useful at runtime too. For instance, here's a semi strong typing thing implemented with objects.
    package Quantity; overload '+' => add, ... ; sub new { my $proto = shift; my $quantity = shift; my $unit = shift; bless {quantity => $quantity, unit => $unit}, ref($proto)||$proto; } sub add { my $self = shift; my $target = shift; croak "Oi! You can't add $$self{unit}s to $$target{unit}s!" unless $$self{unit} eq $$target{unit}; $self->new($self->{quantity + $target->{quantity}, $self->{unit}); }
    Ooh looky, useful strong typing:
    $a = Quantity->new(10, 'apple'); $b = Quantity->new(20, 'orange'); ... $c = $a + $b; # dies "Oi! you can't add apples to oranges!"
    Note that the above example can be (and has been) useful extended to do dimensional analysis (is this a valid calculation), derived units (metres / seconds -> m/sec). Further possible extensions include upcasting (10 oranges + 20 apples = 30 fruit) and deferred calculations (10 EUR + 10 USD = new Sum(10 EUR, 10 USD), we'll worry about completing the calculation when we know what units we want the answer in, however 10 EUR * 10 USD = die "Meaningless calculation, don't be so bloody silly!")

    Strong typing does have it's uses. And not just in the 'making the compiler go quickly' sense. Replacing your dimensionless numbers with strongly typed quantities can be a really powerful tool for helping to track down calculation errors (no more pesky mile/kilometre confusion whilst doing calculations in orbital mechanics mister rocket scientist...). And that's even before you take into account the possible benefits of deferred calculation that can be easily hung on the side of such a system.

Re: Griping about Typing
by maverick (Curate) on Apr 19, 2002 at 14:47 UTC
    Perhaps all things can peacefully co-exist when you apply the rule of 'right tool for the job'...

    Pro - "Gimme my $foo!!!!"

    How much memory is consumed by the standard $foo? Let's assume it's 20bytes (since I really don't know), so for my little

    for (my $i=0; $i < 10; $i++) {
    I'm wasting 19 bytes...assuming that $i could be a short.

    Ram is cheap; processors are powerful. For my Perl app on a server, who cares that $foo took up 20 bytes? That trade is worth my time to not have to go through the reasoning process for a strong typed variable...

    • what am I gonna store? and integer.
    • only positives? ya.
    • what's the biggest value? 10
    ah! unsigned short foo;

    And those 19 wasted bytes are worth it to be able to stay focused on the larger goal.

    Here's another problem with strong typing...what is the maximum value you can put in an unsigned int?

    The correct answer is: depends. Depends on what kind of hardware you're using. ick! On a x86 and int is 4 bytes, or is it 2? I forget. It could be 3.5 on a SPARC for all I know...and that leads to major portability issues.

    Con -- "Hey, where's the SIMM slot on this Palm III?"

    Consider this scenerio. I've got my (slightly dusty) Palm III or some other such hand held device. Even if there is a Perl intepreter for it, I would be very hesitant to use it. Why? My Palm has 8meg of memory, for apps and run time execution. If I have $foo,$baz,$bar,$qux and they are all unsigned short counters of some sort, I've wasted 76 bytes. Can I afford to do that on a Palm that has 2 meg of free space? I don't think that I can.

    I guess you can sum it up by saying, that your choice of tool must be driven by your requirements and environment. Sometimes strong typing is a must...sometimes it isn't and just gets in the way.

    All things have their place. :)
    /me sits in lotus position; "Ohhhhmmmmm...."

    /\/\averick
    OmG! They killed tilly! You *bleep*!!

Re: Griping about Typing
by bsb (Priest) on Apr 13, 2003 at 11:56 UTC
    There's an interesting sounding Python specializing compiler which produces code optimized to the runtime values of your variables. Then if the inferred restrictions are broken it will fallback to a non-optimized version.

    Pysco