'Why does command after if False produce an empty list in Perl 6 REPL?
If the condition of if is False, instead of empty output, REPL gives () (an empty List?)
> put 1 if True
1
> put 1 if False
() # ← What is this?
What does () mean?
Solution 1:[1]
In earlier versions of this endlessly edited answer I wrote that "The REPL isn't doing anything special". But of course I was wrong. The REPL evaluates a line of code. If it generates output, it displays that output and that's it. If it doesn't, it says the value of the last statement. See JJ's answer.
The () you get means an empty list.
In earlier versions of this answer I agreed with you that it was an empty List. But of course I was wrong. In this instance it's a subtype of List. See Brad's answer.)
Arguably I'd best just delete this answer. :)
The following is what remains of possible value to this answer until someone else explains what else I've got wrong...
What Raku is doing
A statement evaluates to a value.
A statement can be just an expression.
An expression can be just a literal value:
> 42
42
A literal list of values evaluates to a List:
> 42, 99
(1 99)
An empty list is displayed as (). This can mean either an empty List:
> ()
() # <-- empty `List`
> List.new
() # <-- empty `List`
> 'aa' ~~ m:g/b/
() # <-- empty `List`
or an empty list that's a sub-type of List, but which reuses the same stringification, e.g. a Slip:
> Empty
() # <-- empty `Slip`
> Slip.new
() # <-- empty `Slip`
Statements can also evaluate to a single value:
> if True { 42 }
42
or a list:
> if True { 42, 99 }
(42 99)
Some statements evaluate to an empty list. Your question is one such example:
> if False {}
()
As Brad points out, that's an empty Slip, specifically the Empty instance.
Solution 2:[2]
Actually your question is incorrect.
What you really get back is an empty Slip.
Specifically, you get back a specific instance of it that is called Empty.
So it does in fact give you an Empty output.
TLDR; It returns Empty because it has to return something, and an empty Slip is more useful in list operations than any other "empty" value.
What Slip does is insert itself into the outer listy value.
say (1, 2, 3, (4, 5)).perl;
# (1, 2, 3, (4, 5))
say (1, 2, 3, (4, 5).Slip).perl;
# (1, 2, 3, 4, 5)
The reason for the existence of Slip is that Perl 6 doesn't flatten values by default.
sub return-list () { 4, 5 }
say (1, 2, 3, return-list()).perl;
# (1, 2, 3, (4, 5))
(Before the official release it used to flatten values in some cases, and it was both confusing and difficult to work-around)
So the feature of Slip was introduced for instances where you really did want it to flatten.
sub return-slip () { slip 4, 5 }
say (1, 2, 3, return-slip()).perl;
# (1, 2, 3, 4, 5)
Note that it only does one level of flattening.
sub return-structured-slip () {
slip 4, (5,)
}
say (1, 2, 3, return-structured-slip()).perl;
# (1, 2, 3, 4, (5,))
This is really useful to do a grep as a part of map code.
say (0..10).map: { $_, $_² if .is-prime }
# ((2 4) (3 9) (5 25) (7 49))
It can also be used for leaving off values when calling a routine.
my $a;
my $b = 1;
say(
( $a.perl if $a ),
( $b.perl if $b ),
)
One useful feature of singular Empty, is that you can match against it.
multi sub foo ($_){.say}
multi sub foo (Empty){ say 'Hello, World' }
foo Empty; # Hello, World
foo (1 if 0); # Hello, World
Note that it is possible to get an empty Slip that is not the singular value Empty. In which case it will not match.
|()
().Slip
Solution 3:[3]
It is returned value empty Slip (Empty). Try
say {put 1 if False}() ~~ Empty
You can use that … if False return Empty with List:
dd (2..100).map: { $_² if .is-prime }
Similarly, … with Nil and Nil andthen … return Empty.
Solution 4:[4]
All answers so far are excellent, explaining what's going on under the hood. But I'll try to answer your question directly.
If the condition of if is False, instead of empty output, REPL gives () (an empty List?)
The key to this is that you're working on the REPL. The REPL prints the output of a block if there's some; if there's no output, it prints whatever the expression returns. Let's then deal with your two options as blocks; what is inside the parentheses is what you would actually type in the REPL:
say (put 1 if True).^name # OUTPUT: «1?Bool?»
That's right. The REPL will see the output, 1, and print that. The block result, True in this case since that's what put returns, is dropped by the REPL. What happens in the second case?
say (put 1 if False).^name # OUTPUT: «Slip?»
In this case, there's no output. The REPL would take (put 1 if False) as an expression, and prints () which, in this case, is a Slip. As indicated in @raiph answer, that's what if False {} returns, so that's what you get in your REPL.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | wamba |
| Solution 4 |
