Function prototype

P

pavunkumar

Dear Friends,

How can I declare the prototype for a function in
Perl.

Thanks
 
P

pavunkumar

It is exceedingly likely that you do NOT want to declare a
prototype for a function.

What is it that you hope to accomplish by using a prototype?

See why Perl's prototypes are nearly always not what you are looking for:

http://www.perl.com/language/misc/fmproto.html

Dear Sir,

I want to write a function , that should accept specific
number of arguments .
example :

I have a function called "add" , I wrote definition for that adding
two numbers,which I am going to pass as a argument. In this case if I
pass more than two argument, compile has to say error. Actually it is
not saying . So How can I achieve this one.

Thanks.
 
W

Willem

pavunkumar wrote:
) I want to write a function , that should accept specific
) number of arguments .
) example :
)
) I have a function called "add" , I wrote definition for that adding
) two numbers,which I am going to pass as a argument. In this case if I
) pass more than two argument, compile has to say error. Actually it is
) not saying . So How can I achieve this one.

Rewrite the function 'add' so that it can add any number of arguments.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Ron Bergin

Dear Sir,

        I want to write a function , that should accept specific
number of arguments .
example :

I have a function called "add"  , I wrote definition for that adding
two numbers,which I am going to pass as a argument.  In this case if I
pass more than two argument, compile has to say error. Actually it is
not saying . So How can I achieve this one.

Thanks.

The args passed to the sub are in the @_ array. So, just check the
number of elements in the array then print your warning and exit the
sub if the count isn't what you want.
 
T

Ted Zlatanov

TJM> sub add {
TJM> die "add() must be called with exactly 2 arguments\n" unless @_ == 2;
TJM> ...


RB> The args passed to the sub are in the @_ array. So, just check the
RB> number of elements in the array then print your warning and exit the
RB> sub if the count isn't what you want.

He specifically asked for compile-time checks.

OP: look at `perldoc perlsub' to learn about prototypes. Here are some
examples from the documentation (you probably want the first example):

Declared as Called as

sub mylink ($$) mylink $old, $new
sub myvec ($$$) myvec $var, $offset, 1
sub myindex ($$;$) myindex &getstring, "substr"
sub mysyswrite ($$$;$) mysyswrite $buf, 0, length($buf) - $off, $off
sub myreverse (@) myreverse $a, $b, $c
sub myjoin ($@) myjoin ":", $a, $b, $c
sub mypop (\@) mypop @array
sub mysplice (\@$$@) mysplice @array, @array, 0, @pushme
sub mykeys (\%) mykeys %{$hashref}
sub myopen (*;$) myopen HANDLE, $name
sub mypipe (**) mypipe READHANDLE, WRITEHANDLE
sub mygrep (&@) mygrep { /foo/ } $a, $b, $c
sub myrand (;$) myrand 42
sub mytime () mytime

Prototypes have many flaws, but they *are* a Perl feature.

Ted
 
G

Graham Drabble

sub add {
die "add() must be called with exactly 2 arguments\n"
unless @_ == 2; ...

He does actually say he wants it done at compile time and your solution
works at run time.

I suspect that it's not possible to do what he wants but would love to
be proven wrong.
 
C

Charlton Wilbur

TZ> On Thu, 06 Aug 2009 08:48:04 -0500 Tad J McClellan


TJM> sub add { die "add() must be called with exactly 2 arguments\n"
TJM> unless @_ == 2; ...

TZ> On Thu, 6 Aug 2009 06:43:18 -0700 (PDT) Ron Bergin

RB> The args passed to the sub are in the @_ array. So, just check
RB> the number of elements in the array then print your warning and
RB> exit the sub if the count isn't what you want.

TZ> He specifically asked for compile-time checks.

And how do you propose that the compiler can check that?

If the compiler sees

my $sum = add(some_function());

how is it supposed to know that some_function() will return exactly two
elements in a list, for instance?

TZ> Prototypes have many flaws, but they *are* a Perl feature.

In this case, however, they're a poor attempt to work around a
fundamental miscomprehension of how Perl works. Better to fix the
miscomprehension than to patch over it with prototypes.

Charlton
 
P

Peter J. Holzer

TZ> On Thu, 06 Aug 2009 08:48:04 -0500 Tad J McClellan



TJM> sub add { die "add() must be called with exactly 2 arguments\n"
TJM> unless @_ == 2; ...

TZ> On Thu, 6 Aug 2009 06:43:18 -0700 (PDT) Ron Bergin

RB> The args passed to the sub are in the @_ array. So, just check
RB> the number of elements in the array then print your warning and
RB> exit the sub if the count isn't what you want.

TZ> He specifically asked for compile-time checks.

And how do you propose that the compiler can check that?

If the compiler sees

my $sum = add(some_function());

how is it supposed to know that some_function() will return exactly two
elements in a list, for instance?

With a suitable prototype in scope, it knows that some_function() will
return exactly one element, since it is called in scalar context.

Yes, that means that with a prototype

sub add($$);

this

my $sum = add(some_function());

cannot work, because the compiler will notice at compile time that add
has only one argument, not two, and will abort the compilation. This may
be a problem or it may be what the OP wants.

TZ> Prototypes have many flaws, but they *are* a Perl feature.

In this case, however, they're a poor attempt to work around a
fundamental miscomprehension of how Perl works. Better to fix the
miscomprehension than to patch over it with prototypes.

Prototypes are a part of "how Perl works". I'd call denying the
existence of prototypes a fundamental miscomprehension of how Perl
works.

hp
 
A

Alan Curry

With a suitable prototype in scope, it knows that some_function() will
return exactly one element, since it is called in scalar context.

Yes, that means that with a prototype

sub add($$);

this

my $sum = add(some_function());

cannot work, because the compiler will notice at compile time that add
has only one argument, not two, and will abort the compilation. This may
be a problem or it may be what the OP wants.

Once upon a time, I tried something like this, honestly expecting it to work:

sub foo ($$$$);

if($something) {
@args=($a, $b, $c, 0);
} else {
@args=($x, $y, $z, 1);
}

foo(@args);

It's easy to see at compile time that @args will always have the proper
number of elements to satisfy the prototype. But prototypes don't do that,
and furthermore there's nothing in perl that does do that, so you have to
live with run-time assertions. Oh well.
 
X

Xho Jingleheimerschmidt

Charlton said:
TZ> He specifically asked for compile-time checks.

And how do you propose that the compiler can check that?

The same way it does for built-ins.
If the compiler sees

my $sum = add(some_function());

how is it supposed to know that some_function() will return exactly two
elements in a list, for instance?

It isn't. It is supposed to know that some_function will return exactly
one element. That is because it will arrange for some_function to be
called in a scalar context.

What do you think "split some_function()" does?


Xho
 
T

Tim McDaniel

See why Perl's prototypes are nearly always not what you are looking
for:

http://www.perl.com/language/misc/fmproto.html

pavunkumar said:
I want to write a function , that should accept specific
number of arguments .

Perl's prototypes do not do that...

$ perl -e 'sub add($$) { return $_[0] + $_[1]; }; print add(3), "\n";'
Not enough arguments for main::add at -e line 1, near "3)"
Execution of -e aborted due to compilation errors.

$ perl -e 'sub add($$) { return $_[0] + $_[1]; }; print add(3,4,5), "\n";'
Too many arguments for main::add at -e line 1, near "5)"
Execution of -e aborted due to compilation errors.

Looks to me like they DID "accept specific numbers of arguments" in
those cases.

I love compile-time checking and I wish there was more.

I use Perl sub prototypes. I declare subs before use. I always call
with parens when calling my own functions. I only use a fixed number
of scalars (for example, ($$$$)) or some scalars followed by an
optional list (for example, ($$$@)) or explicit documentation that it
accepts a list (@). Where there's a scalar argument, by gum, I pass
in a scalar: if I code "sub add($$)", I expect "add(@two_elements)"
to die.

And a few programs where I used
sub my_chomp(;\$)
sub trim(;\$)
I coded them to chomp | trim a scalar variable in-place, but if no
scalar is provided, process $_. And a few more rare cases, but
nothing weird. For example, if I want a ref argument, I do it myself.

This catches, at compile time, almost every error that I make with
arguments, without the bother of coding a die (which wouldn't fire at
compile time anyway).
 
T

Ted Zlatanov

TZ> He specifically asked for compile-time checks.

CW> And how do you propose that the compiler can check that?

CW> If the compiler sees

CW> my $sum = add(some_function());

CW> how is it supposed to know that some_function() will return exactly two
CW> elements in a list, for instance?

The OP can read the documentation and decide for himself if prototypes
will work for him. Obviously they don't work for everyone, but for a
subset of Perl (especially the subset commonly found in production) they
may be suitable.

TZ> Prototypes have many flaws, but they *are* a Perl feature.

CW> In this case, however, they're a poor attempt to work around a
CW> fundamental miscomprehension of how Perl works. Better to fix the
CW> miscomprehension than to patch over it with prototypes.

While I don't feel quite so strongly, I agree prototypes usually don't
fully solve the problem of checking function parameters, and relying on
them is usually the wrong way to write good Perl. At least for version
5.x ;)

Ted
 
T

Ted Zlatanov

On Fri, 7 Aug 2009 02:11:12 +0000 (UTC) (e-mail address removed) (Alan Curry) wrote:

AC> Once upon a time, I tried something like this, honestly expecting it to work:

AC> sub foo ($$$$);

AC> if($something) {
AC> @args=($a, $b, $c, 0);
AC> } else {
AC> @args=($x, $y, $z, 1);
AC> }

AC> foo(@args);

AC> It's easy to see at compile time that @args will always have the proper
AC> number of elements to satisfy the prototype. But prototypes don't do that,
AC> and furthermore there's nothing in perl that does do that, so you have to
AC> live with run-time assertions. Oh well.

I present to you Yet Another Golden Rule of Perl (YAGRoP):

Nothing in Perl is easy at compile time. Everything in Perl is easy at
run time.

This, of course, compares favorably with Java, where the run time is
only good for generating exceptions, and C++, where the run time is only
good for catching exceptions :)

Ted
 
T

Tim McDaniel

Quoth (e-mail address removed):

If you have 5.10, you can use the '_' prototype character for that
behaviour.

Thanks. Alas that I have so little control over most systems I use;
perl -e 'print $]'
shows me versions between 5.5 and 5.10 depending on the systems.
There's no need for the '\': $_[0] is passed by reference.

Not if the actual argument is an expression. Then Perl creates a
temporary variable and passes a reference to that, so any assignments
to it are silently discarded after the sub ends. By contrast, a
prototype of \$ errors out if the argument is not a scalar variable
(expressions, even array elements, are forbidden) and if prototypes
are being checked.

$ perl -e 'sub t1(\$) { ${$_[0]} = 1;} my $v = -1; t1($v ); print $v, "\n"; '
1

$ perl -e 'sub t1(\$) { ${$_[0]} = 1;} my $v = -1; t1($v + 2); print $v, "\n"; '
Type of arg 1 to main::t1 must be scalar (not addition) at -e line 1, near "2)"
Execution of -e aborted due to compilation errors.

$ perl -e 'sub t2($) { $_[0] = 1; print $_[0], "\n";} my $v = -1; t2($v); print $v, "\n"; '
1
1

$ perl -e 'sub t2($) { $_[0] = 1; print $_[0], "\n";} my $v = -1; t2($v + 2); print $v, "\n"; '
1
-1

What are the conditions under which the prototype is not used?
I think they're
- a call lexically before the sub declaration
- old-style &name(...) call
- object method call
Is that right?
 
T

Tim McDaniel

As for "using Perl 5.005 in production": that's the default Perl on
Panix (my ISP) in its shell accounts. It's not production, and I
recally really don't have control. I can't even convince Panix to
install Perl 5.010.

Quoth (e-mail address removed):
There's no need for the '\': $_[0] is passed by reference.

Not if the actual argument is an expression. Then Perl creates a
temporary variable and passes a reference to that, so any assignments
to it are silently discarded after the sub ends.

Not true. Perl passes an alias to the result of the expression, so you
can perfectly well assign to $_[0] and change the variable passed:

I didn't SAY "variable"! I said "if ... expression", by which I meant
the general case of an expression, not a variable specifically.
(Yes, a variable is an expression, but variables like $v were treated
like expressions like $v+2, then Perl would not have pass-by-reference
semantics in any such situation, and I would not have written "if".)
~% perl -E'sub foo ($) { $_[0] = 2 } my $x; foo($x); say $x'
2

Of course. I showed much the same thing as an example.
~% perl -E'sub foo ($) { $_[0] = 2 } foo(1); say $x'
Modification of read-only value attempted at -e line 1.

And to repeat my previous example,

$ perl -e 'sub t2($) { $_[0] = 1; print $_[0], "\n";} my $v = -1; t2($v + 2); print $v, "\n"; '
1
-1
$ perl -e 'print $], "\n"'
5.010000

The argument is the expression "$v + 2", and like I wrote, Perl
silently discards the assignment after the sub ends. (That is, it's
assigning to a temporary variable.) The statement in "man perlsub",

In particular, if an element $_[0] is updated, the corresponding
argument is updated (or an error occurs if it is not updatable).

is false.
(the ($) prototype has no effect in any of these cases).

Right. It's my reflex.
Array and hash elements *are* allowed,

I swear I tested it ... Ah. It depends on *where* I test it. 5.005
says

$ perl -e 'sub t2(\$) { ${$_[0]} = 1; print ${$_[0]}, "\n";} my @v = (-1); t2($v[0]); print $v[0], "\n"; '
Type of arg 1 to main::t2 must be scalar (not array element) at -e line 1, near "])"
Execution of -e aborted due to compilation errors.

But it works in Perl 5.008 and later.
 
J

Jürgen Exner

pavunkumar said:
I want to write a function , that should accept specific
number of arguments .
example :

I have a function called "add" , I wrote definition for that adding
two numbers,which I am going to pass as a argument. In this case if I
pass more than two argument, compile has to say error. Actually it is
not saying . So How can I achieve this one.

Your requirement is uncommon in Perl. Usually people would write
functions to deal with an arbitrary number of arguments (in your example
of add just add them all) or include code in the function to check for
the correct number of arguments at runtime:
die "Wrong number of arguments in add" unless @_ == 2;

However, if you really really want to you can read up on prototypes in
"perldoc perlsub", section "Prototypes".

jue
 

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

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top