« first day (120 days earlier)      last day (2447 days later) » 

06:53
@EliahKagan so <> is magic :)
That answer has a stray apostrophe too
@EliahKagan nice!
@Zanna Actually, that does not do what I want.
ek@Io:~$ cat >a <<<ழ
ek@Io:~$ perl -wpe 'use open qw(:std :utf8); s/./sprintf " %d", ord $&/ge' a
 224 174 180
ek@Io:~$ perl -wpe 'use open qw(:std :utf8); s/./sprintf " %d", ord $&/ge' <a
 2996
07:14
But I don't think that SO answer was wrong (except in the one way I had said before). Instead, I believe the problem is that, even though the Perl interpreter acts on use directives at compile time, I had failed to realize that it would still apply only to invocations of open that appear in code that is scoped to it (i.e., in its lexical scope, and probably below it). I am still not 100% sure that's what's going wrong, but I think it is.
Perl scripts compile to bytecode before being run, as in many other interpreted languages (e.g., Python), but in Perl it is further from just an implementation detail or optimization than many others, because you can write code that runs during that phase. use has this effect, as do BEGIN blocks when -n or -p has not been passed. With -n or -p, BEGIN blocks have more awk-like semantics, I have heard. I've used BEGIN with -n and -p but I'm far from 100% on the details.
07:28
I know it is my above implementation, and not that answer, that is wrong in the way that matters, because I can write a more cumbersome one-liner that avoids using -p (or -n) and instead code a similar while (<>) loop myself. (I could code the exact equivalent while (<>) loop, too, which invokes print in a continue block, checks if it succeeded, and bails if it didn't. But in many situations it is not really necessary, and I consider this one of them.) When I do this, it works:
ek@Io:~$ perl -we 'use open qw(:std :utf8); while (<>) { s/./sprintf " %d", ord $&/ge; print }' a
 2996
@Zanna This is the approach I should have used there and there. I believe it is fully correct:
ek@Io:~$ perl '-Mopen qw(:std :utf8)' -wpe 's/./sprintf " %d", ord $&/ge' a
 2996
07:51
I mean using -M. Not making a file and pass it as a command-line argument; that's just for testing, since that's the functionality that was broken in my previous one-liner. Giving the text on standard input of course still works, too.
08:12
We've got a long way just by wondering what . matches :D
08:35
@Zanna The slightly more complicated task of grouping the code points by the lexeme in which they appear is, in my opinion, far more amusing.
#!/usr/bin/env perl

use strict;
use warnings;
use 5.010;
use open qw(:std :utf8);

sub ordinals {
    my $text = shift // $_;
    my $nums = join q{ }, map { ord } split //ms, $text;
    return "($nums)";
}

while (<>) {
    say join q{ }, map { ordinals } split /\X\K/msx;
}
ek@Io:~$ pl/lexemes <<<ழ்אx
(2996 3021) (1488) (120) (10)
I left the newline in for that, but arguably it would be more useful to chomp it off.
08:48
Yeah, that's better, because the -0 option can be passed to the Perl interpreter to control what character is taken to be the same record separator, so there is no actual lost opportunity.
So, with this modified code:
#!/usr/bin/env perl

use strict;
use warnings;
use 5.010;
use open qw(:std :utf8);

sub ordinals {
    my $text = shift // $_;
    my $nums = join q{ }, map { ord } split //ms, $text;
    return "($nums)";
}

while (<>) {
    chomp;
    say join q{ }, map { ordinals } split /\X\K/msx;
}
:D
ek@Io:~$ printf 'ழ்אx\n' | pl/lexemes
(2996 3021) (1488) (120)
ek@Io:~$ printf 'ழ்אx\0y \nz\0' | perl -0 pl/lexemes
(2996 3021) (1488) (120)
(121) (32) (10) (122)
ek@Io:~$ printf abecedarian | perl -0145 pl/lexemes
(97) (98)
(99)
(100) (97) (114) (105) (97) (110)
09:15
I want to say that this is something that is more compact in Perl than in Python! But actually I don't know, because I don't know how to match a lexeme in Python. Python's regex dialect does not suppport \X, which in Perl does that. That is, \X is doing the magic of matching the two-code-point sequence ழ் but also matching just single code points when they are displayed as a single symbol. I do not presume Python can't also do it easily and automatically, only that I don't know how.
@EliahKagan why does the last output have line breaks?
The reason they all have line breaks is that I used say, which appends a newline.
If I used print instead of say, and I didn't add a newline manually, and I didn't assign a newline to $\ beforehand (which print uses as the output record separator), then newlines would never appear in the output, for that script.
I'm glad I was able to edit that message. $` is also a special variable in Perl, and it's totally unrelated to $\. :)
haha I thought that's what you meant
-0 doesn't change the output record separator $/ (which is undef by default in Perl anyway), only the input record separator $\. The more intriguing question is why there is a newline in the output of that one-liner.
ek@Io:~$ cat a
ழ
ek@Io:~$ cat b
ழ்אx
ek@Io:~$ perl '-Mopen qw(:std :utf8)' -wpe 's/./sprintf " %d", ord $&/ge' a b
 2996
 2996 3021 1488 120
ek@Io:~$
The reason has to do with what . matches!
09:30
but I don't understand what it's splitting on in abecedarian... why does that produce three lines of output?
@EliahKagan it didn't match the terminal newline...?
ek@Io:~$ perl -wle 'print chr 0145'
e
oh! :)
awesome
I think you mean...
(97) (119)
(115) (111) (109)
(10)
hahaha ^_^
so 10 is a newline
Yeah. That's why the trailing (10) is what went away from the non-chomping version to the current, chomping version.
@Zanna Correct. Though in situations where there are non-terminal newlines, . in a Perl regex without any flags set won't match them, either:
ek@Io:~$ reply
0> "first\nsecond" =~ /(.*)/;
$res[0] = 'first'

1>
The only way that would happen, with that one-liner, is if the input record separator were made to be something other than a newline. Then non-terminal newlines could appear. This is why it is somewhat widely recommended always to use the s flag:
1> "first\nsecond" =~ /(.*)/s;
$res[1] = 'first
second'

2>
09:53
I'm so far behind I am wondering exactly what this operation is doing... For example I get...
2> "first\nsecond" =~ /(.*\n.*)/;
$res[2] = 'first
second'
but...
10> "first\nsecond" =~ /.....\n....../;
$res[10] = 1
for almost anything I enter I get 1 haha
@Zanna You're basically just checking if there was a match, there. The capture group in /(.*\n.*)/ is what makes it return the captured text.
7> "first\nsecond" =~ /(.....\n......)/;
$res[7] = 'first
second'

8> "first\nsecond" =~ /(.....)\n(......)/;
$res[8] = [
  'first',
  'second'
]
oh!
From perldoc perlop:
"m/PATTERN/msixpodualngc"
"/PATTERN/msixpodualngc"
        Searches a string for a pattern match, and in scalar context
        returns true if it succeeds, false if it fails. If no string is
        specified via the "=~" or "!~" operator, the $_ string is
        searched. (The string specified with "=~" need not be an
        lvalue--it may be the result of an expression evaluation, but
        remember the "=~" binds rather tightly.) See also perlre.
So 1 means it did match. I get nothing if I look for something that was not in the input
@EliahKagan I copied the later version to easily check that I understood your joke correctly, and then I used that command to find out what character 10 represents (I don't like guessing)
10:39
@Zanna You can also use something like...
ek@Io:~$ perl -wE 'use open qw(:std :utf8); say join "e", map { join "", map { chr } /(\d+)/g } <>' <<'EOF'
(97) (98)
(99)
(100) (97) (114) (105) (97) (110)
EOF
abecedarian
You can change join "e" to join "\n" or whatever you need.
neat
ek@Io:~$ perl -wE 'use open qw(:std :utf8); say join "\n", map { join "", map { chr } /(\d+)/g } <>' <<'EOF'
(2996 3021) (1488) (120)
(2996 3021) (1488) (120)
EOF
ழ்אx
ழ்אx
ek@Io:~$
ek@Io:~$ perl -wE 'use open qw(:std :utf8); say join "\0", map { join "", map { chr } /(\d+)/g } <>' <<'EOF' | xargs -0
(2996 3021) (1488) (120)
(121) (32) (10) (122)
EOF
ழ்אx y
z

ek@Io:~$
(That seems like the most readable of all easy ways to view the result of reversing the middle of those examples.)
this is very cool stuff. I was going to say you could use it to send silly messages in code and decode them, but maybe that script is taking decoded messages and encoding them...
You'll notice that <> has a different effect here, because it appears in list context rather than scalar context, so it reads to the end of input rather than reading a single line of input. I used <> once in list context, rather than letting the interpreter automatically evaluate it repeatedly in scalar context through the implied while (<>) of -p or -n, so that it wouldn't produce any output until the input was done.
at this point I have only a very foggy idea of what any of the elements are doing. Hopefully, I will learn
10:52
What an expression means can differ depending whether it appears in void, scalar, or list context. I do not know of other languages that work this way. It seems to be a source of many bugs, but I guess it is also handy. The idea is that human language works this way, supposedly.
With here documents, as shown above, it doesn't matter that much, nor would it if you were reading from a file or redirecting stdin, or redirecting stdout, but otherwise you'd get partial output before you were done entering input. This way, you don't:
ek@Io:~$ perl -wE 'use open qw(:std :utf8); say join "e", map { join "", map { chr } /(\d+)/g } <>'
(97) (98)
(99)
(100) (97) (114) (105) (97) (110)
abecedarian
ek@Io:~$
(I pressed Ctrl+D after the third line of parenthesized numerals.)
Also, this avoided having to guess and possibly be wrong about whether or not the record separator should appear at the end.
ek@Io:~$ perl '-Mopen qw(:std :utf8)' -wnE 'BEGIN { $\ = "e" } print join "", map { chr } /(\d+)/g' <<'EOF'
(97) (98)
(99)
(100) (97) (114) (105) (97) (110)
EOF
abecedariane
hmm not sure I got all that... but I have to go afk for a while :S
I'll reread when I get back :)
I've removed the prompt so it's easier to see where the output actually ends. Similarly, when it is entered while perl runs, instead of beforehand as a shell here document:
ek@Io:~$ perl '-Mopen qw(:std :utf8)' -wnE 'BEGIN { $\ = "e" } print join "", map { chr } /(\d+)/g'
(97) (98)
abe(99)
ce(100) (97) (114) (105) (97) (110)
dariane
Anyway this must be horribly confusing, since I realize that, in addition to neither saying much of anything about void/scalar/list context before and not linking to anything on it, I also never actually said specifically what -n and -p do, even though that was the one thing you had actually wanted to know! :)
When you get back, feel free to ping me -- if I'm around, I might say some stuff that is way less confusing.
 
2 hours later…
13:10
@EliahKagan afaik, a scalar is a quantity that only has magnitude (unlike a vector, which has both magnitude and directions), a void is a place with no particles, and a list is what you take with you when you go shopping for groceries
@EliahKagan well, to be honest, I am in the happy situation of knowing nothing about Perl and therefore appreciating being told anything at all about it.
13:33
ok I'll wear the hat, on the understanding that the "white fur trim" is 100% faux
14:11
@Zanna In Perl, you would have to take an array with you when you go shopping for groceries (or you could take a scalar that is a reference to an array), because lists are ephemeral.
hahaha
for example: In Perl, for and foreach mean the same thing. There are two forms of the for loop, but you can use either keyword for either one. It's common, but not universal, to just use for for both of them, which is what I prefer. I am about to describe the "foreach" style loop. This is the same style of "for" loop as Bourne-style shells all have. It is exactly the same for loop we discussed earlier. There we had:
for my $i (1..5) { say $i }
And other ways, like:
say for (1..5)
In all of these cases, the items that are actually being looped over -- that get bound to the loop variable (which is $_ if not declared explicitly) -- are in a list. In those loops, (1.. 5) is a list. You can also write stuff like:
for my $item (1, 8, 'foo', 23) { say $item }
And:
say for (15..20, 1..5);
This creates an array called @vals and initialized it with the a list of numbers from 1 to 10. It is thus an array of those numbers. (1..10) is a list @vals is an array.
my @vals = (1..10);
In general, Perl uses eager evaluation, but lists can be evaluated (or, well, used) lazily. To observe this, notice first that you can bail out of a for loop before iterating through each item. One way to do so is with last, which is like break in most other languages. Here's a contrived example:
for my $i (1..10) { last if $i > 5; print "$i\n" }
That does not show that lists can be evaluated lazily. This, however, does:
for my $i (1..1000000000000) { last if $i > 5; print "$i\n" }
That works just fine, while, in contrast, this causes the Perl interpreter to quit immediately with an out-of-memory error:
my @vals = (1..1000000000000);
When you write multiple values and separate them with commas, that usually makes a list. Ranges make a list. Arrays, when you actually use them, frequently make a list. Sorry about this imprecise description. What I am talking about is this:
0> my @vals = (10..14);
$res[0] = [
  10,
  11,
  12,
  13,
  14
]

1> my @morevals = (1..3, @vals, 17, 21);
$res[1] = [
  1,
  2,
  3,
  10,
  11,
  12,
  13,
  14,
  17,
  21
]
(1..3, @vals, 17, 21) is not a list that contains the array @vals. It is a list that contains all the element of the array @vals, as well as some other elements. This list is used to initialize the second array @morevals.
This is quite dissimilar to many languages. In most languages, arrays are not automatically expanded like that.
The @ sigil means "array." The $ sigil means "scalar." Conceptually, arrays are plural, while scalars are singular. @x and $x are completely separate. Both can exist at once, or either, or neither. The elements of arrays are scalars.
As that blog post about arrays and lists says, arrays can be multidimensional... but what this actually means is that you have an array of references to arrays. Those references are themselves actually scalars. There is no special language construct for a multidimensional array. Furthermore, you can have an array where some of its elements are references to other arrays and some are not. That's usually a bad idea, but you can do it.
14:49
@EliahKagan ah... so it just became an array because you assigned it to a variable
Yes. You can also do things like:
[10, 20, 30]
(sorry for my absence, my parents asked me to do something)
That's an array, even if you don't assign it to a variable.
No problem.
so square brackets make an array (while in Python, they make a list, iirc)
The [ ] make it a list literal. They do not have the same meaning as ( ), which are really just doing grouping. (You can make lists without the enclosing parentheses, in some situations where it would not be ambiguous.)
@Zanna Yes. Though you can make an array in Perl without the square brackets, as you've seen. Also, the same words mean different things for different languages. Lists in Python are like arrays in Perl. So really the [ ] notation has a more similar meaning in the two languages than might be immediately apparent just by listening to people talk about it.
14:57
I remember that lists in Python aren't immutable, so I see how they are more like arrays in Perl. I wonder how people manage to learn so many languages...
@EliahKagan I guess I would have expected it to print 6\n and then quit
Yeah, the choice of last is a bit weird. (The word, I mean.)
You can assign an array to an array. That copies all the elements. It does not alias the arrays; if you then modify one of the arrays, the other is not modified.
0> my @original = qw(foo bar baz quux);
$res[0] = [
  'foo',
  'bar',
  'baz',
  'quux'
]

1> my @copy = @original;
$res[1] = [
  'foo',
  'bar',
  'baz',
  'quux'
]

2> push @copy, 'foobar';
$res[2] = 5

3>  @copy
$res[3] = [
  'foo',
  'bar',
  'baz',
  'quux',
  'foobar'
]

4> @original
$res[4] = [
  'foo',
  'bar',
  'baz',
  'quux'
]
@EliahKagan so @vals was expanded when (or before) assigning @morevals, so we don't need @vals any more to use @morevals?
Correct.
In contrast, in Python, assigning a list to a variable just binds the variable to the same list as before:
>>> original = ['foo', 'bar', 'baz', 'quux']
>>> copy = original
>>> copy.append('foobar')
>>> copy
['foo', 'bar', 'baz', 'quux', 'foobar']
>>> original
['foo', 'bar', 'baz', 'quux', 'foobar']
In Perl, assigning one array to another is an example of using the right-hand-side array in list context. Arrays can also be used in scalar context. For example, you can assign the list to a scalar variable. This does not do what most people (who haven't done it in Perl yet) expect.
0> my @vals = (7..12);
$res[0] = [
  7,
  8,
  9,
  10,
  11,
  12
]

1> my $n = @vals;
$res[1] = 6
@EliahKagan oh! That's not what I'd expect. When I make a copy of something I guess I most often do so to modify the copy without changing the original
@EliahKagan it counted the elements...
@Zanna Well it's a copy of the variable, which in Python stores a reference to the actual object. The objects referenced by the original and copy variables in that Python example are the same object. It is not actually a copy of the list. There are ways to do that. In Python, for lists, the idiomatic ("Pythonic") way is to slice the array... but include all of it:
>>> original = ['foo', 'bar', 'baz', 'quux']
>>> copy = original[:]
>>> copy.append('foobar')
>>> copy
['foo', 'bar', 'baz', 'quux', 'foobar']
>>> original
['foo', 'bar', 'baz', 'quux']
15:11
makes sense. Sorry for sidetracking
When the number to the left of the : is omitted, it's 0. When the number to the right is omitted, it is the length of the list. If you omit both, you slice the whole list. Anyway, that's Python. Arrays in Perl also allow slicing, and it is basically the same way -- by indexing them with a range -- but there is no need, in Perl, to use slicing to copy the elements.
@Zanna Right. In scalar context, the array becomes its size (i.e., its number of elements). You might say it's not really counting them, because arrays in Perl know their own size; obtaining the size of an n-element array is an O(1) operation, not an O(n) operation.
Notice that there are other situations where scalar context applies, besides assignment to a scalar variable:
0> my @vals = (7..12);
$res[0] = [
  7,
  8,
  9,
  10,
  11,
  12
]

1> @vals + 3;
$res[1] = 9
Similarly, there are other situations where list context applies, besides assignment to an array:
2> join '; ', @vals;
$res[2] = '7; 8; 9; 10; 11; 12'
You can force scalar context with the built-in scalar function (really, I think it is technically a named unary operator):
0> my @vals = (3..7);
$res[0] = [
  3,
  4,
  5,
  6,
  7
]

1> @vals;
$res[1] = [
  3,
  4,
  5,
  6,
  7
]

2> scalar @vals;
$res[2] = 5
Using an array in scalar context -- with or without scalar -- is actually the typical and idiomatic way to take the size of an array in Perl!
However, ranges in Perl contain their upper bound, so if the purpose is to write a range of indices, then the actual size may not really be what you want. For example, this would be a mistake if I used it for any purpose besides to demonstrate this sort of mistake:
4> for my $i (0..@vals) { print "$i: $vals[$i]\n" }
0: 3
1: 4
2: 5
3: 6
4: 7
Use of uninitialized value in concatenation (.) or string at reply input line 1.
5:
$res[3] = ''
Instead, I should use the highest index as my upper bound. I could obtain this by subtracting 1 from the size, but I don't need to, because Perl provides syntax for this:
5> for my $i (0..$#vals) { print "$i: $vals[$i]\n" }
0: 3
1: 4
2: 5
3: 6
4: 7
$res[4] = ''
That last index should be -1 for an empty array, because:
7> [0..0];
$res[6] = [
  0
]

8> [0..-1];
$res[7] = []
And it is:
9> my @empty;
10> $#empty;
$res[8] = -1
When you declare an array variable but don't initialize or otherwise assign to it, it is the default value for an array, which is the empty array. This has the same effect as if you had initialized it with an empty list.
In contrast, the default value of a scalar variable is undef:
11> my $x;
$res[9] = undef
The built-in readline function for reading from files, which you can call explicitly but which is more commonly used because it's what things like <>, <<>>, <STDIN>, and <$f> use, behaves differently depending on whether it is used in a scalar or list context. This reads one line:
12> my $line = <>;
foobar
$res[10] = 'foobar
'
15:31
@EliahKagan oh hmm. That seems smart.
In contrast, this reads to end-of-input (I pressed Ctrl+D after typing quux and pressing Enter) and puts each line into a separate element of the array:
13> my @lines = <>;
foo
bar
baz
quux
$res[11] = [
  'foo
',
  'bar
',
  'baz
',
  'quux
'
]
@Zanna How so?
I'm not disagreeing. I'm not sure specifically what you mean, though.
Because the items looped over by a for loop are supplied as a list, writing for (<>) causes <> to be evaluated in list context, which causes all input to be read into memory before any of it is used. Sometimes this is fine; occasionally it is exactly what you require; but often it is preferable to read and operate on one line at a time instead.
17> for (<>) { chomp; say "$_ squared is ", $_ * $_ }
2
9
55
91
6
2 squared is 4
9 squared is 81
55 squared is 3025
91 squared is 8281
6 squared is 36
$res[15] = ''

18> while (<>) { chomp; say "$_ squared is ", $_ * $_ }
2
2 squared is 4
9
9 squared is 81
55
55 squared is 3025
91
91 squared is 8281
6
6 squared is 36
$res[16] = ''
@EliahKagan well, I said I want to add 3, and I didn't have to say what I mean by add 3.
15:47
@Zanna One of the reasons this can happen is that the meaning of + is not ambiguous. The + symbol in Perl is not also being used to indicate string concatenation, for example. In Python:
>>> a = [10, 20, 30]
>>> b = [77, 88, 99]
>>> a + b
[10, 20, 30, 77, 88, 99]
>>> 'foo' + 'bar'
'foobar'
Perl does not use + this way. For concatenation, Perl uses the separate . operator.
@EliahKagan for is not doing anything special there. <> appears in list context, so it reads all available lines. But while is doing something special. <> is evaluated in scalar context, and that's not special -- the condition for while or if is always evaluated in scalar context -- but there is something special going on in that while loop. There are actually two special things going on.
The result of <> (in scalar context) is checked to see if it is defined (in the sense of not being undef) rather than if it is true, and it is automatically assigned to $_. A for loop binds list elements to a loop variable automatically, but a while loop does not... and nonetheless while (<>) works to read lines of input one at a time and place each one in $_. This is special behavior.
From perldoc perlsyn: Actually, although it's worth reading, that doesn't really contain a highly accessible explanation.
@EliahKagan that makes sense :)
@EliahKagan so while is patient :)
You can undefine variables, in the sense of giving them their default value, which is undef for scalars and is the zero-element array for arrays (there are other kinds of variables in Perl besides scalars and arrays but I've hardly talked about them thus far). To do this, use the undef operator. Note that, when you're using use strict; (which should be virtually always), applying undef to something to "undefine" it does not have the same effect as removing it as a variable.
0> my $s = 'some text';
$res[0] = 'some text'

1> undef $s;
$res[1] = undef

2> $s;
$res[2] = undef

3> $t;
Global symbol "$t" requires explicit package name (did you forget to declare "my $t"?) at reply input line 1.
BEGIN not safe after errors--compilation aborted at reply input line 7.
(reply has use strict; enabled automatically, as does the Perl rename command. When you write actual script files, you have to write use strict; to get it--which you should. Constructs like perl -e do not automatically turn on use strict;.)
But applying undef to a variable does have the effect of causing it to be as though the variable had been declared without ever having been given a value.
The undef operator also returns the undef value. And you can omit the argument to undef. This is useful because it gives you the undef value. (When you use undef by itself as an expression, that isn't an undef literal: there is no undef literal. But it returns undef, so calling it without an operand gives you the same power as if there were an undef literal.)
undef is not just for scalars: you can make arrays empty with it:
0> my @values = (1..5);
$res[0] = [
  1,
  2,
  3,
  4,
  5
]

1> undef @values;
$res[1] = undef

2> @values;
3>
Note that it returns undef, which is a scalar, but it does not set its array operand to undef. An array cannot have the value undef, but it can have a single element that is undef. Such an array is quite defined, evaluates to true when used as a boolean, etc. It is rarely if ever what you would want. undef does the right thing, though, when given an array operand. It empties it out.
To check if a scalar is defined, you can use the defined operator. This checks if it is not undef. It still gives an error if you use it on an undeclared variable with use strict;. It also should not be used on arrays.
3> my $x = 'foobar';
$res[2] = 'foobar'

4> defined $x;
$res[3] = 1

5> undef $x;
$res[4] = undef

6> defined $x;
$res[5] = ''

7> my $y;
$res[6] = undef

8> defined $y;
$res[7] = ''
But:
0> my @values;
1> defined @values;
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at reply input line 1.

2> defined $z;
Global symbol "$z" requires explicit package name (did you forget to declare "my $z"?) at reply input line 1.
BEGIN not safe after errors--compilation aborted at reply input line 7.
Here, I pressed Ctrl+D without typing anything else first:
3> my $line = <>;
$res[0] = undef
16:10
I have to go afk again. If you continue, I'll definitely read and er reply later :D
In Perl, numbers are true, except 0, which is false, and strings are true, except the empty string and the string '0', which are false. Note that even a string consisting of a single null character is true.
4> 1 or 'it was false';
$res[1] = 1

5> 0 or 'it was false';
$res[2] = 'it was false'

6> 'x' or 'it was false';
$res[3] = 'x'

7> '' or 'it was false';
$res[4] = 'it was false'

8> '0' or 'it was false';
$res[5] = 'it was false'

9> '0.' or 'it was false';
$res[6] = '0.'

10> '0.0' or 'it was false';
$res[7] = '0.0'

11> '-1' or 'it was false';
$res[8] = '-1'

12> ' ' or 'it was false';
$res[9] = ' '

13> "\0" or 'it was false';
$res[10] = ''
One way to demonstrate that these rules would not work properly for while (<>) if it were really testing <> for truth is to set the input record separator $/ to the numeral 0 (not to be confused with the null character):
15> print "[$_]\n" while (<>);
1200345
[120]
[0]
[345
]
$res[12] = ''
(I pressed Enter after 1200345, then I pressed Ctrl+D at the beginning of the line after it showed me [0], since it was waiting for another 0 to end the record. Pressing Ctrl+D flushed the buffer and gave it one more iteration where there was text to read before end-of-input.)
One of the values $_ takes on in that loop is 0, as shown by [0]. There, [ ] have nothing to do with arrays; I just had to use some characters in print to show where the strings ended.
Even though the string consisting of a single 0 character is taken to be false, that while loop nonetheless kept reading. That is one way to demonstrate that while treats readline expressions specially. When you return, if I'm still here, I'll show an example of what while is usually doing and how this is different.

« first day (120 days earlier)      last day (2447 days later) »