raptor has asked for the wisdom of the Perl Monks concerning the following question:
hi,
I was thinking isn't better if we have the ability to say :
sub ($self,$var,@arr) { }
Instead of something like this :
sub ()
{
my $self = shift;
my ($var,@arr) = @_;
...
}
this will save alot keystorokes ... yes I know this place is for prototipes.. but the vars are easly recognaized from prototypes ( /\$\w+/ ).
what U think ?
Re: sub ($self,$var,@arr) {}
by MeowChow (Vicar) on Feb 09, 2001 at 15:57 UTC
|
sub ($self, $var, @arr) {
...
}
## versus
sub {
my ($self, $var, @arr) = @_;
...
}
Total Savings = 6 keystrokes (not including spaces)
This wouldn't add new functionality, and saving a few keystrokes is less important, IMHO, than maintaining consistency.
Understanding what @_ is, how it works, and how to use it is a Good Thing; it takes some of the mystery out of parameter passing, and is conceptually related to many other important Perlisms that beginners often struggle with (eg. $_, local, aliases). Offering Perl beginners an easy way out by not learning about @_ would be doing them a disservice. @_ allows for many interesting possibilities that fixed parameter lists do not (for instance, "overloaded" subs). It would also be unfortunate if Perl's worth were diluted by encouraging people to code like it's just another scripting language. My gut feeling is that if you were to add such a syntax, newcomers to the language would use it almost exclusively, and @_ would evolve into an unusual, depricated construct of interest primarily to obfuscators.
And I don't want Perl to look any more like C, C++, or Java than it has to ;) Bad memories, you know?
That said, your suggestion is in keeping with the idea that TIMTOWTDI, and I don't see how it could break backwards-compatibility or be difficult to implement. It would also add some sanity, from an aesthetic perspective, to Perl's prototyping system.
So I don't quite know on which end of this issue I sit. Perhaps, I'll just offer the annoying cliche "if it ain't broke..." | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Perhaps raptor was hinting at the way C used to reference
parameters, K&R style, which is a little outdated:
int main (argc, argv)
int argc,
char *argv[]
{
return 0;
}
Still, I find it nice that Perl allows you to use the parameters
any way you wish, which is especially useful when you're
passing parameters using the HASH-style methods, such that you
really don't know how many parameters you are going to
receive, nor what type they are:
MyFunc ( -type => qw ( lemur llama lynx ),
-width => 150 );
It is interesting that CGI.pm uses parameters in a way
that is not unlike UNIX-style command-line arguments in
terms of the way they are parsed and processed.
The prototypes introduced in 5.6(?) go a long way towards
ensuring that your module is used properly, and detecting
errors in parameters vs. errors in the module:
sub MyFunc ($$\$)
{
my ($x, $y, $z) = @_;
# $x and $y are required, $z optional.
}
Although MeowChow doesn't "want Perl to look any more like ... C,C++
or Java",
that is no reason to not borrow methods and practices from
these languages that were implemented with solid reasoning.
The cliché "if it ain't broke" certainly hasn't been
heeded by the Perl developers, Larry Wall included, because
Perl 4.0 was hardly broken, and just when you think it couldn't
get any better, it did!
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
ok I think that
prototypes are GOOD thing, but current implementation doesn't help US alot :")
| [reply] [Watch: Dir/Any] |
Re: sub ($self,$var,@arr) {}
by mirod (Canon) on Feb 09, 2001 at 17:02 UTC
|
To expand on what MeowChow wrote, I have no objection if the current @_ mechanism is
also kept.
I like Perl's flexibility and here are some of the things you can do
with the current parameter passing mechanism:
- change the value of the argument being passed to the function:
my $v="toto";
change( $v);
print $v;
sub change { $_[0]="tata"; }
prints tata as $_[0] is aliased to $v. You can
actually even write the function
sub change { $sv=\$_[0]; $$sv="tata"; }
- write functions which accept variable arguments:
sub my_print
{ if(UNIVERSAL::isa($_[0], 'GLOB' ))
{ my( $fh, $text)= @_;
print $fh "my", $text;
}
else
{ print "my", $text; }
}
Here if( UNIVERSAL::isa($_[0], 'GLOB') returns true if
the first argument to the function is a filehandle stored
in a GLOB or a sub-classed GLOB (a trick I found on PM
BTW, thanks tye), so I can use the function as
my_print( "toto"); or as my_print( \*FH, "tata");
- have fun passing the arguments unchanged to some other
function:
#!/bin/perl -w
use strict;
my $s="toto";
my $n="3";
append( $s, "one");
append( $n, 1);
print "s: $s n: $n\n";
sub append
{ if( $_[1]=~ /^\d+$/) { &append_nb; }
else { &append_string; }
}
sub append_string
{ $_[0] .= $_[1]; }
sub append_nb
{ $_[0] += $_[1]; }
outputs: s: totoone n: 4
Here &append_nb calls the function with the current
@_, whatever is it, which is still aliased to the original
variables, and thus still modifies it.
I'll let you figure out how &append_string
is different from goto &append_string
| [reply] [Watch: Dir/Any] [d/l] [select] |
C-like Function Prototypes
by japhy (Canon) on Feb 09, 2001 at 20:12 UTC
|
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
|
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. | [reply] [Watch: Dir/Any] [d/l] |
|
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
#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
| [reply] [Watch: Dir/Any] [d/l] |
(jeffa) Re: sub ($self,$var,@arr) {}
by jeffa (Bishop) on Feb 09, 2001 at 19:58 UTC
|
And why are you passing @arr around like that.
my $foo = new Foo;
$foo->Bar($var, \@array);
sub Bar {
my $self = shift;
my ($var, $array_ref) = @_;
}
Get in the habit of passing references around, much
nicer to your RAM.
Jeff
R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
L-L--L-L--L-L--L-L--L-L--L-L--L-L--
| [reply] [Watch: Dir/Any] [d/l] |
|
sorry long way I wasn't here here is my answer.
just exapmle I'm not passing in this way..
And the people can use both ways, why not ..i.e.
sub mysub ($self)
{
my @rest = @_;
}
sub mysub ($self,$nextvar1,$nextvar2)
{
...
}
instead of :
sub mysub
{
my ($self,@rest) = @_;
}
OR
sub mysub
{
my $self = shift;
...some code .. $nextvar1 = shift;
...code ...
$nextvar2 = shift;
}
for me the first is much more clear... and can be used to document what the creator of this sub mostly expected like parameters..
with one RegEx U can extract a desc of methods and so on...
this is JMO
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: sub ($self,$var,@arr) {}
by extremely (Priest) on Feb 10, 2001 at 04:22 UTC
|
Something along this line is being discussed for perl6 but as you have discovered from other posts most perl types ho-hum it. =) It has the same potential issue as prototypes where the first scalar might cause an array to be cast into scalar form:
sub popntuple1 ($one, @two) {
return $one, \@two;
}
sub popntuple2 () {
my ($one, @two) = @_;
return $one, \@two)
}
my @a = ( 1, 2, 3, 4);
my @b = ( 6, 7, 8, 9);
($p, $t) = popntuple1(@a,@b);
($pp, $tt)=popntuple2(@a,@b);
If the scalar causes a cast, you get 4, (6,7,8,9)
otherwise you get 1, (2,3,4,6,7,8,9). And if it doesn't
cast, what did it save you?
--
$you = new YOU;
honk() if $you->love(perl) | [reply] [Watch: Dir/Any] [d/l] |
|
|