3

Please could you explain this apparently inconsistent behaviour to me:

use strict;
my @a;

print "a" x 2; # this prints: aa
@a = "a" x 2; print @a; # this prints: aa

print ("a") x 2; # this prints: a
@a = ("a") x 2; print @a; # this prints: aa

Shouldn't the last one print a single 'a'?

Edit: Ok so now this is kind of making more sense to me: "Binary "x" is the repetition operator...In list context, if the left operand is enclosed in parentheses or is a list formed by qw/STRING/, it repeats the list." perlop

This is as clear as mud to me (binary x - why use the word binary? Is there a denary X?) But anyway: @a = ("a") x 2 # seems to be in list context, in that we have an array at the beginning - an array is not a list, but it contains a list, so I think we probably have a list context, (not an array context although they might be synonymous).

i suppose the "left operand" is ("a"). (It's either that or @a). perlop doesn't say what an operand actually is, querying perldoc.perl.org gives "No matches found", and googling gives "In computer programming, an operand is a term used to describe any object that is capable of being manipulated." Like an array for instance.

So the left operand might be enclosed in brackets so maybe it should "repeat the list". The list is either: ("a") x 2 or it is: ("a")

If we repeated ("a") x 2 we would get ("a") x 2 ("a") x 2. This doesn't seem right.

If we type: print $a[1] we will get a single 'a', so "it repeats the list" means Perl turns ("a") x 2 into ("a", "a") so we effectively get @a=("a", "a")

However, print ("a") x 2 does not get turned into ("a", "a"). That's because print is a "list operator" with a high precedence. So there we effectively get: (print ("a")) x 2

An array is a term so it also has a high precedence, but @a=stuff involves the assignation operator = which has a relatively low precedence. So it's quite different from print.

Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
Literat
  • 869
  • 7
  • 14
  • Some letters, you just shouldn't alternate in succession like that. – corsiKa Feb 20 '11 at 06:02
  • i don't understand what you mean – Literat Feb 20 '11 at 06:14
  • @DanD man, I have been enjoying answering your other question and since you are asking good questions, I and others will keep answering you. However, perhaps its time for a nice glass of wine and curl up with the perldocs (perldoc.perl.org or `perldoc` at your command line.) brian d foy has a wonderful post on perlmonks he calls the 'documentation documentation', which I link to in my profile: http://www.perlmonks.org/?node_id=408254 – Joel Berger Feb 20 '11 at 15:37
  • @DanD man, I don't mean to discourage you, rereading my above it seems that it could be taken the wrong way. I actually mean you seem to enjoy the intricacies and the documentation is very interesting for people like me (who ask similar questions). Keep asking here when you finds something strange. I've asked several http://stackoverflow.com/questions/4865447/demystifying-the-perl-glob and especially this one http://stackoverflow.com/questions/4045467/perl-match-outside-if-doesnt-reset-1-on-loop which I would count as finding my first bug in `perl` if it wasn't found by stumbling on the fix. – Joel Berger Feb 20 '11 at 15:46
  • A few months ago i had a really hard time with local, our and my. Looking in perldoc and googling didn't really help, in the end I just gave up. However, i have now asked 3 questions on here, and each time it was explained to me and i deepened my understanding. So, i now feel that i can go back and dig up my questions about my local, and our, and i will get tailor made responses and explanations. Reading perldoc also seems more possible now - even if some code is very condensed and hard to understand then i can ask here. – Literat Feb 22 '11 at 01:10
  • Many of those kind of questions have already been asked here (another nice thing about SO!). Try this one perhaps http://stackoverflow.com/questions/129607/what-is-the-difference-between-my-and-local-in-perl – Joel Berger Feb 22 '11 at 03:00
  • And from in that question I see this: http://perl.plover.com/local.html reading it right now, I can't think of seven uses of `local` off hand ... – Joel Berger Feb 22 '11 at 03:03
  • ... Although isn't a lexical filehandle better than a `local`ized filehandle glob? Someone? @tchrist would know. – Joel Berger Feb 22 '11 at 03:14

3 Answers3

7

add use warnings; in your script, then you will get warnings like

print (...) interpreted as function .
Useless use of repeat (x) in void context .

Do it like print (("a") x 2); # this prints: aa

As you mentioned in comments, how to format your code, i would say see Perltidy.

Perltidy is a Perl script which indents and reformats Perl scripts to make them easier to read. If you write Perl scripts, or spend much time reading them, you will probably find it useful.

Some more information about Perltidy:

You can download perltidy and run it with its defaults, or customise it to use your preferred bracing style, indentation width etc.

Customisation is easy and there are a huge number of options. The defaults are usually a fine starting place.

Perltidy can also be used to generate colourised HTML output of your code.

Perltidy comes with a sensible set of defaults; but they may not be right for you. Fortunately you can use tidyview as a graphical user interface to preview perltidy’s changes to your code and see which options suit you best. You can download tidyview from CPAN.

Note: Always add use strict and use warnings at the begining of your scripts.

Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
  • Ok perltidy i should try that. Thanks. But also, what i meant was when i posted my question it was all in black font and then someone (or something) came in here and changed it into different colours. i was just wondering how such a thing is possible. print+("a")x2 i never thought of that one... – Literat Feb 22 '11 at 01:13
  • see [editing help page](http://stackoverflow.com/editing-help), you will get information about , Markdown turns plain text formatting into fancy HTML formatting. – Nikhil Jain Feb 22 '11 at 06:20
4

I think the reason that you are getting strange behavior is because the print command for perl is to expect a list. Quoting from the relevant documentation:

Also be careful not to follow the print keyword with a left parenthesis unless you want the corresponding right parenthesis to terminate the arguments to the print; put parentheses around all the arguments.

Putting parentheses makes it act like a function. Consider if you perform this test case:

x("y") x 2;

sub x {
    my $y = shift;
    print "1: $y\n"; #result 1: y
    my $y = shift;
    print "2: $y\n"; #result 2:
}

When written as a function call, your results are consistent for a function being evaluated to its arguments rather than an assignment being evaluated after the following operations.

Jeff Ferland
  • 17,832
  • 7
  • 46
  • 76
3

You are being bitten by a common Perl parsing gotcha. Your third statement print ("a") x 2 is parsed as:

(print ("a")) x 2;

You can add another set of parentheses to fix the parsing:

print (("a") x 2);  # prints aa
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • i see. Why isn't the 4th line done in the same way i.e. why isn't `@a = ("a") x 2;` parsed as `(@a = ("a")) x 2;` (also please could you explain how you format code properly) – Literat Feb 20 '11 at 06:10
  • @DanD man - 4th line could not be parsed as you wrote due to operator precedence (see [perlop](http://perldoc.perl.org/perlop.html#Operator-Precedence-and-Associativity) for the table). – bvr Feb 20 '11 at 07:46
  • @DanD, there's a rule in Perl that "if it looks like a function call, it's a function call". That is, when you have a function name followed by optional whitespace and a left paren, the corresponding right paren terminates the arguments to that function. This is documented in [perlop](http://perldoc.perl.org/perlop.html#Terms-and-List-Operators-%28Leftward%29). – cjm Feb 20 '11 at 08:22
  • All the answers were useful but I'm going to put a big green tick by yours since you said "common Perl parsing gotcha" which makes me feel like i'm not the only one who's making mistakes. – Literat Feb 22 '11 at 02:58