Как использовать оператор diamond в качестве аргумента вызова функции в скалярном контексте? - PullRequest
2 голосов
/ 17 марта 2011

Как я могу напрямую передать значение из оператора diamond в функцию (под)?

Я пытался:

#!/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(<>,<>,<>); #here

Но мне нужно вводить EOF, когда я вводю числадля каждого из аргументов функции.Он ведет себя как @array=<>.Я хочу, чтобы он вел себя как $var=<>.Таким образом, ввод должен выглядеть следующим образом:

Enter Numbers: 5 4 3

Ответы [ 4 ]

6 голосов
/ 17 марта 2011

Я покажу вам несколько лучших практик, пока помогу вам с вашим вопросом ...

#!/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);
5 голосов
/ 17 марта 2011

Голый оператор <> внутри списка аргументов функции всегда вызывается в контексте списка.Но есть много способов заставить скалярный контекст, который вам нужен:

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

Обратите внимание, что <> в скалярном контексте будет читать входные данные до следующего «разделителя записей».которая по умолчанию является новой строкой вашей системы, поэтому поведение кода по умолчанию заключается в чтении отдельных значений из каждой строки.Если (как следует из исходного поста) входные данные разделены пробелами и расположены в одной строке, то вам необходимо либо:

  1. установить разделитель записей в пробел ($/ = " ") перед вызовом <> или
  2. Использовать другую схему, например split, для разбора строки ввода на отдельные значения
# read a line of input and extract 3 whitespace-separated values
quadraticEq( split /\s+/, <>, 3 );

Для такой проблемы я бы почти всегдапереходите к # 2, но есть больше, чем один способ сделать это.

2 голосов
/ 17 марта 2011
quadraticEq(map scalar <>, 1..3);

См. Также perldoc -f readline .

2 голосов
/ 17 марта 2011

Обычно при передаче значений в подпрограммы Perl использует контекст списка, поэтому вы используете <> так же, как и

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

Что, очевидно, не то, что вы хотите!

Вы можете включить скалярный контекст с помощью ключевого слова scalar:

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

Или, прочитайте их все в переменные, чтобы люди знали, что вы собираетесь:

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

Кроме того, вы должны действительно проанализировать аргументы @_ перед их использованием. Это сделает вашу функцию более понятной. Пример:

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