Supply 和普通数组中具有空值的映射函数的行为不一致?

che*_*nyf 6 swift raku combine

最近在学习Swift的Combine框架。

用苹果的话来说:

组合框架为您的应用程序如何处理事件提供了一种声明性方法。您可以为给定的事件源创建单个处理链,而不是潜在地实现多个委托回调或完成处理程序闭包。链的每个部分都是一个组合运算符,它对从上一步接收到的元素执行不同的操作。

在Combine中,有一个函数叫做compactMap,它可以过滤nil值:

import Combine

let strings = ["a", "1.24", "3", "def", "45", "0.23"].publisher

strings
  .compactMap { Float($0) }
  .sink(receiveValue: {
    print($0)
  })
  .store(in: &subscriptions)
)
Run Code Online (Sandbox Code Playgroud)

Swift 中的紧凑映射

我在Raku中将上面的代码重写如下:

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
Run Code Online (Sandbox Code Playgroud)

但它也输出两个空括号。当在普通数组而不是 Supply 上使用映射时,具有空值的映射被过滤:

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
Run Code Online (Sandbox Code Playgroud)

具有Empty值的map函数的行为与 plain不一致吗?SupplyArray

p6s*_*eve 7

为什么不这样做...

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
Run Code Online (Sandbox Code Playgroud)

我同意,与常规 grep (不需要 .so)相比,似乎存在很小的差异(与故障处理相关)...

say @strings.grep(*.Num);
#(1.24 3 45 0.23)
Run Code Online (Sandbox Code Playgroud)