开发者

How do I use the diamond operator as a function call argument in scalar context?

How can I directly pass a value from the diamond operator to a function (sub)?

I have tried:

#!/usr/bin/perl
use Math::Complex;

#quadraticEq - quadratic equation with parameters a ,b ,c
sub quadraticEq {
    print "\nx1= ", 
      ($_[1]*$_[1]-sqrt($_[1]*$_[1]-4*$_[0]*$_[2]))/(2*$_[0]),
      "\nx2= ",
      ($_[1]*$_[1]+sqrt($_[1]*$_[1]-4*$_[0]*$_[2]))/(2*$_[0]);
}

print 'Enter Numbers:';
quadraticEq(<>,<开发者_StackOverflow>,<>); #here

But I need to enter EOF when I enter numbers for each of the function arguments. It behaves as @array=<>. I want it to behave like $var=<>. So the input should look like this:

Enter Numbers: 5 4 3


I'm going to show you a couple of best practices while I help you with your question...

#!/usr/bin/perl

use strict;     # strict/warnings helps detect lots of bugs and logic issues,
use warnings;   # so always use them

use Math::Complex; # WHITESPACE IS YOUR FRIEND

#quadraticEq - quadratic equation with parameters a ,b ,c

sub quadraticEq{
    # Shift out your subroutine variables one at a time, or assign them to a list.
    my ($a, $b, $c) = @_;

    print "\nx1= ", 
      ($b*$b-sqrt($b*$b-4*$a*$c))/(2*$a), # You're wrong on your formula btw
      "\nx2= ",
      ($b*$b+sqrt($b*$b-4*$a*$c))/(2*$a);
}

print 'Enter Numbers: ';

# Perl only supports reading in a line at a time, so... if you want all your
# inputs on one line, read one line.
# EDIT: That's not strictly true, since you can change the input record separator,
# but it's just simpler this way, trust me.

my $line = <>;

# Then you can split the line on whitespace using split.
my @coefficients = split /\s+/, $line;

# You should check that you have at least three coefficients and that they
# are all defined!

quadraticEq(@coefficients);


A naked <> operator inside a list of function arguments is always called in list context. But there are many ways to force the scalar context that you want:

quadraticEq(scalar <>, scalar <>, scalar <>);
quadraticEq("" . <>, "" . <>, "" . <>);
quadraticEq(0 + <>, 0 + <>, 0 + <>);  # if you want to evaluate as numbers anyway

Note that <> in scalar context will read from the input up to the next "record separator". which by default is your system's newline, so the default behavior of the code above is to read separate values from each line. If (as the original post suggests) the inputs are space separated and all on one line, then you will need to either:

  1. Set the record separator to a space ($/ = " ") before calling <>, or
  2. Use a different scheme, like split to parse a line of input into separate values
# read a line of input and extract 3 whitespace-separated values
quadraticEq( split /\s+/, <>, 3 );

For a problem like this, I would almost always go with #2, but There Is More Than One Way To Do It.


Generally, when passing values to subroutines, Perl uses list context, so what you're doing is using <> the same way as

my @args = (<>, <>, <>);

Which, obviously, isn't what you want!

You can force scalar context with the scalar keyword:

my @args = ( scalar <>, scalar <>, scalar <>); # read one

Or, read them all into variables, so that people know what you intend:

my $first = <>;
my $second = <>;
my $third = <>;

On an aside, you should really parse the arguments out of @_ before using them. It'll make your function supremely more understandable. An example:

sub quadratic2 {
    my ($a, $b, $c) = @_;
    ... # now use the actual symbols instead of array indexes
}


quadraticEq(map scalar <>, 1..3);

See also perldoc -f readline.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜