Recently, I have been learning Swift's Combine framework.
In Apple's words, "The Combine framework provides a declarative approach for how your app processes events. Rather than potentially implementing multiple delegate callbacks or completion handler closures, you can create a single processing chain for a given event source. Each part of the chain is a Combine operator that performs a distinct action on the elements received from the previous step."
In Combine, There is a function called compactMap
, which can filter nil values:
import Combine
let strings = ["a", "1.24", "3", "def", "45", "0.23"].publisher
strings
.compactMap { Float($0) }
.sink(receiveValue: {
print($0)
})
.store(in: &subscriptions)
)
I rewrite the above code in Raku as the following:
my @strings = ["a", "1.24", "3", "def", "45", "0.23"];
my Supply $supply = Supply.from-list(@strings);
my Supply $compact = $supply.map(-> $value {
try { Num($value) }
if $! { Empty } else { Num($value) }
}); # .grep(Num);
$compact.tap(
&say,
done => { say 'finished' },
quit => { say 'done' }
);
# () <--
# 1.24
# 3
# () <--
# 45
# 0.23
But it also output two empty parentheses. When use map on plain Array instead of on a Supply, the map with Empty value got filtered:
my @strings = ["a", "1.24", "3", "def", "45", "0.23"];
my @compacted = @strings.map(-> $value {
try { Num($value) }
if $! { Empty } else { Num($value) }
});
.say for @compacted;
# 1.24
# 3
# 45
# 0.23
Is the behavior of map
function with Empty value in Supply
and plain Array
inconsistent?
CodePudding user response:
Why not do it like this...
my @strings = ["a", "1.24", "3", "def", "45", "0.23"];
my $supply = Supply.from-list(@strings);
my $compact = $supply.grep(*.Num.so);
$compact.tap(&say);
# 1.24
# 3
# 45
# 0.23
I agree that there seems to be a small divergence (related to Failure handling) vs. regular grep (no .so needed)...
say @strings.grep(*.Num);
#(1.24 3 45 0.23)