Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.9k stars 540 forks source link

[doc] print join 1..9 #22399

Closed jidanni closed 1 month ago

jidanni commented 1 month ago

I wish somebody could make these all work the same way,

perl -wle 'print join 1,2..8;'
perl -wle 'print join (1,2..8);'
perl -wle 'print join (1,2..8)'
perl -wle 'print join (1..8)'
perl -wle 'print join (1..8,9)'
perl -wle 'print join (1,2..8,9)'
perl -wle 'print join 1,2..8,9'
perl -wle 'print join 1..8,9'
perl -wle 'print join 1,2..9'

Or on perldoc -f join say "beware of syntax...".

Anyway, sometimes one really does want to say

$ perl -wle 'print join 1,2..9'
213141516171819

But write it simpler. Alas:

$ perl -wle 'print join 1..9'
Use of uninitialized value $. in range (or flip) at -e line 1.
Grinnz commented 1 month ago

Most built in functions act similarly to using a $ prototype for each scalar argument they take. Thus join 1..8 interprets the 1..8 argument in scalar context, which means .. is the flipflop operator and not the range operator in this case. This is unlikely to be reasonably changeable.

jidanni commented 1 month ago

Well I'm just thinking one can roll

printf FORMAT, LIST

into just printf @bla

so the user cannot really know when such conveniences will work and when they won't, at least from doing perldoc -f ... . They need trial and error to see if they won't blow up.

(Not a workaround:)

$ perl -wle '@v=2..8; print join @v;'

$
Grinnz commented 1 month ago

True, it is inconsistent

mauke commented 1 month ago

This is documented.

perldoc perlfunc, first paragraph:

A unary operator generally provides scalar context to its argument, while a list operator may provide either scalar or list contexts for its arguments. If it does both, scalar arguments come first and list argument follow, and there can only ever be one such list argument. For instance, splice has three scalar arguments followed by a list, whereas gethostbyname has four scalar arguments.

perldoc -f join:

join EXPR,LIST

Thus the first argument is a scalar, followed by an arbitrary list expression.

You're right that the synopsis of printf isn't quite consistent about this, but its description mentions it prominently. perldoc -f printf:

printf FORMAT, LIST

[...] The FORMAT and the LIST are actually parsed as a single list. The first argument of the list will be interpreted as the printf format. This means that printf(@_) will use $_[0] as the format.

mauke commented 1 month ago

I wish somebody could make these all work the same way,

Changing the way join parses its arguments isn't really feasible. It would break 25+ years of established behavior.

That said, you can bypass the (implicit) prototype by using & with CORE::join:

$ perl -we 'use v5.16; say &CORE::join(1..9)'
213141516171819