in reply to sub ($self,$var,@arr) {}

The prototypes found in C allow functions to behave differently, given different arguments:
int product (int x, int y) { return x * y; } char *product (char *company, int prodID) { /* magic to return name of product related to prodID in the given company */ }
Now, in Perl, we can do this ourselves in the function, by checking the contents of @_, since Perl doesn't differentiate between strings and numbers (or types of numbers) like C does. (But the practice of having a function do totally unrelated things is A Bad Thing, and lends itself to confusion.)

How would you C-ize this Perl function?
sub foo { die "foo() needs at least one argument" if !@_; (my($x,$), local($z)) = @_; $y ||= 10; $z ||= $x * $y; # ... }
Maybe something like
sub foo ( my($x) :req, my($y) ||= 10, local($z) ||= ($x * $y) ) { # ... }
I find that hideous. I really think I would find any type of variable-based prototyping in Perl pretty ugly.

japhy -- Perl and Regex Hacker

Replies are listed 'Best First'.
Re (tilly) 2: C-like Function Prototypes
by tilly (Archbishop) on Feb 09, 2001 at 22:01 UTC
    I don't think that C style dispatch on the type of parameters is being asked for. What is being asked for is done in a number of languages. For comparison here is a Ruby version of your function which differs only in the fact that Ruby was designed from the start using lexical scope and so does not have to support dynamic scope for backwards compatibility:
    def foo (x, y=10, z=nil) z = x * y if z.nil? # etc end
    which does not seem to me to be significantly uglier than Perl.

    But mixing Perl and typing is IMNSHO utterly broken. It is often said that Perl does not differentiate between strings, numbers, etc. This is only somewhat true. Perl allows a variable to contain any of them, and then your code differentiates between them. Mixing this existing type system with anything else doesn't work. On a similar note, it is very hard in Perl to write generic code which will continue to work if people pass in strings, references to arrays, etc. It can be done, but you are fighting the language.

    In Ruby this is trivial. In fact the above code is perfectly generic as long as x is some type that supports a * method. (Overloading in Perl is possible, but not so transparent.)

    Now I am not saying that the way that Ruby does it is right or better. I am just saying that it is possible to support prototyping very similar to what raptor asked for without it being ugly and broken. I am also saying that Perl's claim of not forcing types on variables isn't completely true. But what Perl loses in the ability to write generic code, it gains in the fact that you can transparently extract numbers from strings, work with them as numbers, and then use them as strings again without needing to do explicit conversions. And 3/2 in Perl is not 1.

    PS: Ruby does not have a concept like @_. The closest it has to that is the ability to declare a parameter with a * which will gather remaining arguments into an array. If Ruby did have @_ then the conflict between the two modes of passing arguments would become much worse. Not coincidentally, Ruby is also not list oriented...

    PPS: I am not trying to advocate Ruby, merely show by comparison with another language that the suggestion can work. However I don't think it would work well in Perl for a number of reasons. First is the confusion with the existing idea of prototypes. Second we have the conflict with the existing notion of @_. Thirdly there would be questions about pass by value versus pass by reference.

      ok... I wanted to write also this, but didn't done that ... but now will do :
      sub mysub (\$var1,$var2) { ..code.. $var1 = "Hello";#this changes $somvar later in the code }
      Later :
      mysub(my \$somvar,$echo) print $somevar
      instead of :
      sub mysub () { my (\$var1,$var2) = @_; } my $somvar = 12; my $refvar = \$somvar; mysub($refvar,$echo) print $somevar
      my 5c
Careful...
by McD (Chaplain) on Feb 09, 2001 at 22:05 UTC
    japhy writes:

    $y ||= 10;

    FWIW, be careful with that. Using ||= is one of my favorite ways to write fluent Perl, but it just got me burned a few days ago.

    The problem was that the $y I was initializing was a numeric value - but zero was an acceptable value.

    In that case, my ||= was overriding the supplied value of zero, which tested false against the operator. In the example here, providing an argument of 0 for $y will result in $y getting 10, not zero.

    Oops. :-)

    Peace,
    -McD

      #534987 in arturo's minor amplifications for the benefit of those who read the thread days later: For just those sorts of cases where false values are valid, $y =defined($y) ? $y : 10; (or whatever test makes sense).

      Philosophy can be made out of anything. Or less -- Jerry A. Fodor