Home > Software design >  Inconsistent behavior of map function with Empty value in Supply and plain Array?
Inconsistent behavior of map function with Empty value in Supply and plain Array?

Time:09-03

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)
)

compactMap in Swift

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)
  • Related