-1

In Perl, if I have:

no strict;
@ARY = (58, 90);

To operate on an element of the array, say it, the 2nd one, I would write (possibly as part of a larger expression):

$ARY[1]  # The most common way found in Perldoc's idioms.

Though, for some reason these also work:

@ARY[1]
@{ARY[1]}

Resulting all in the same object:

print (\$ARY[1]);
print (\@ARY[1]);
print (\@{ARY[1]});

Output:

SCALAR(0x9dbcdc)
SCALAR(0x9dbcdc)
SCALAR(0x9dbcdc)

What is the syntax rules that enable this sort of constructs? How far could one devise reliable program code with each of these constructs, or with a mix of all of them either? How interchangeable are these expressions? (always speaking in a non-strict context).

On a concern of justifying how I come into this question, I agree "use strict" as a better practice, still I'm interested at some knowledge on build-up non-strict expressions.

In an attemp to find myself some help to this uneasiness, I came to:

  • The notion on "no strict;" of not complaining about undeclared variables and quirk syntax.
  • The prefix dereference having higher precedence than subindex [] (perldsc § "Caveat on precedence").
  • The clarification on when to use @ instead of $ (perldata § "Slices").
  • The lack of "[]" (array subscript / slice) description among the Perl's operators (perlop), which lead me to think it is not an operator... (yet it has to be something else. But, what?).

For what I learned, none of these hints, put together, make me better understand my issue.

Thanks in advance.

g.cze
  • 38
  • 6
  • IMHO, the _knowledge_ for `strict` and `no strict` - is the same. The difference is only than the `strict` will help you write correct programs. Switch off the strict only when really needed. (in rare cases, partially, such `no strict 'refs'`; and such.) – clt60 Sep 08 '14 at 22:18
  • This isn't anything to do with dereferencing, nor anything to do with strict, as far as I can tell, and strict doesn't know or care about "quirk syntax". – hobbs Sep 09 '14 at 02:53

4 Answers4

4

Quotation from perlfaq4:

What is the difference between $array[1] and @array[1]?

The difference is the sigil, that special character in front of the array name. The $ sigil means "exactly one item", while the @ sigil means "zero or more items". The $ gets you a single scalar, while the @ gets you a list.

Please see: What is the difference between $array[1] and @array[1]?

Community
  • 1
  • 1
VladimirM
  • 817
  • 5
  • 7
2

@ARY[1] is indeed a slice, in fact a slice of only one member. The difference is it creates a list context:

@ar1[0] = qw( a b c );    # List context.
$ar2[0] = qw( a b c );    # Scalar context, the last value is returned.
print "<@ar1> <@ar2>\n";

Output:

<a> <c>

Besides using strict, turn warnings on, too. You'll get the following warning:

Scalar value @ar1[0] better written as $ar1[0]

In perlop, you can read that "Perl's prefix dereferencing operators are typed: $, @, %, and &." The standard syntax is SIGIL { ... }, but in the simple cases, the curly braces can be omitted.

See Can you use string as a HASH ref while "strict refs" in use? for some fun with no strict refs and its emulation under strict.

choroba
  • 231,213
  • 25
  • 204
  • 289
1

Extending choroba's answer, to check a particular context, you can use wantarray

sub context { return wantarray ? "LIST" : "SCALAR" }

print $ary1[0] = context(), "\n";
print @ary1[0] = context(), "\n";

Outputs:

SCALAR
LIST
Community
  • 1
  • 1
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • 1
    If you like `wantarray()` you may find `Contextual::Return` of interest, as it lets you detect more nuanced conditions http://search.cpan.org/~dconway/Contextual-Return-0.004007/lib/Contextual/Return.pm – Sobrique Sep 09 '14 at 10:15
  • @Sobrique. Looks pretty interesting. Thanks for sharing. `:)` – jaypal singh Sep 09 '14 at 16:53
1

Nothing you did requires no strict; other than to hide your error of doing

@ARY = (58, 90);

when you should have done

my @ARY = (58, 90);

The following returns a single element of the array. Since EXPR is to return a single index, it is evaluated in scalar context.

$array[EXPR]

e.g.

my @array = qw( a b c d );
my $index = 2;
my $ele = $array[$index];   # my $ele = 'c';

The following returns the elements identified by LIST. Since LIST is to return 0 or more elements, it must be evaluated in list context.

@array[LIST]

e.g.

my @array = qw( a b c d );
my @indexes ( 1, 2 );
my @slice = $array[@indexes];   # my @slice = qw( b c );

\( $ARY[$index]   )  # Returns a ref to the element returned by $ARY[$index]
\( @ARY[@indexes] )  # Returns refs to each element returned by @ARY[@indexes]

${foo}       # Weird way of writing $foo. Useful in literals, e.g. "${foo}bar"
@{foo}       # Weird way of writing @foo. Useful in literals, e.g. "@{foo}bar"
${foo}[...]  # Weird way of writing $foo[...].

Most people don't even know you can use these outside of string literals.

ikegami
  • 367,544
  • 15
  • 269
  • 518