4

I came across with these two lines, and though I've been trying to figure out what they do, I'm still in doubt about their meaning in the code. The piece of code I am talking about is:

my $mapped_from = ($num_phones_in == 60)? = $1 : $2;
my $mapped_to = ($num_phones_out == 48)? = $2 : $3;

I don't really understand what a variable between parentheses followed by a question mark do ()?. And also I don't know what those two numbers with dollar sign (as variables) separated by colon mean.

To give you more details about the code, in this part I'm working with a file that look like this:

ah X /
au u aU

Where the columns have 60, 48 and 39 lines respectively. I would really appreciate if someone could give me a clue since I am a bit lost.

ilkkachu
  • 138,973
  • Further to @Fox’s comment, it’s called a ternary operator - https://en.m.wikipedia.org/wiki/%3F:? – Guy Jan 27 '18 at 11:50

3 Answers3

14
my $mapped_from = ($num_phones_in == 60)? = $1 : $2;

That's a syntax error. The test ? val_true : val_false is the "ternary operator", an inline form of an if-else statement. If test is true, it evaluates to the val_true part, and if test is false, it evaluates to the val_false part. The question mark has nothing to do with the parenthesis. But = $1 isn't a valid expression.

Without the extra =, ($num_phones_in == 60)? $1 : $2; would check if $num_phones_in is sixty, and return $1 or $2 accordingly.

$1 and $2 (etc.) are variables that refer to the contents of the capture groups in the previous regex. If you did "afoob" =~ /a(.*)b/, then $1 would contain foo. See Variables related to regular expressions in perlvar.

ilkkachu
  • 138,973
  • Thanks for such a great explanation!!! yes, I've already checked that the extra equals symbol = has to be removed in order to continue with the script without any error. And I'd not heard about "ternary operator" but I will definitely read a bit more about it :D – little_mice Jan 27 '18 at 12:57
6

The ? : is called a ternary operator, and is said to be one of the most abused operators in any modern language. (Nested ternary operators, particularly.) These two lines are equivalent:

$value = ($a > 9) ? 10 : 0;

if ($a > 9) { $value = 10 } else { $value = 0 };

The $1 and $2 you also ask about are the result of bracketed matches in the most recent Regular Expression. For example,

$a = 'Hello world. 1+2 is 3';
$a =~ /(\w+).*?(\d+)/;
print "1=$1, 2=$2\n";.   # "1=Hello, 2=1"
ilkkachu
  • 138,973
Chris Davies
  • 116,213
  • 16
  • 160
  • 287
1

DIY

Meta-answer: find out for yourself.

Perl has the very nifty debug mode. You can enter it thusly:

perl -de1

(This is just a handy shortcut for -d (debug mode) and -e 1 (execute the statement "1"), which is a trivial no-op with the benefit of minimal amount of characters to type).

Then you are prompted with a debugger where you can enter perl code which will be executed immediately. Try this:

$num_phones_in = 10;
my $mapped_from = ($num_phones_in == 60)? = $1 : $2;

You will get a syntax error straight away. The second = needs to go away. And for good readability, either remove all space for the ?: operator, or add spaces, whatever you want. Perl does not care, but your colleagues will.

my $mapped_from = ($num_phones_in == 60)?$1:$2;
my $mapped_from = ($num_phones_in == 60) ? $1 : $2;
AnoE
  • 575