【发布时间】:2021-07-24 13:35:30
【问题描述】:
在 APL 中有幂运算符 ⍣,如果将其应用于函数 f,则会叠加在 f 的应用上。如何在 Raku 中实现该运算符?
例如,f 的这个定义:
sub f(Int:D $i){ $i + 1 }
命令say (f ⍣ 4)(10); 应该等同于say f(f(f(f(10))));。
我下面的实现是针对一个有一个参数的函数。
问题
-
应该如何扩展或替换它以更好地处理多个(或任何)签名?
-
如何定义新的幂运算符的“高优先级”?
-
有没有更好的方法来定义
f ⍣ 0的“身份函数”结果?
参考链接
这里是 APL 的 ⍣ 的描述:
"Power Operator".
(⍣ 是“两点星”,或者更正式的"Apl Functional Symbol Star Diaeresis"。)
尝试
这是一个实现的尝试:
sub infix:<⍣>( &func, Int:D $times where $times >= 0 ) {
if $times == 0 {
sub func2($d) {$d}
} else {
sub func2($d) {
my $res = &func($d);
for 2..$times -> $t { $res = &func($res) }
$res
}
}
}
sub plus1(Int:D $i){ $i + 1 }
say 'Using (&plus1 ⍣ 0) over 4 :';
say (&plus1 ⍣ 0)(4);
say 'Using (&plus1 ⍣ 10) over 4 :';
say (&plus1 ⍣ 10)(4);
# Using (&plus1 ⍣ 0) over 4 :
# 4
# Using (&plus1 ⍣ 10) over 4 :
# 14
(我关注了这个教程页面:https://docs.raku.org/language/optut。)
测试
定义由 Brad Gilbert's answer 通过以下所有测试。
use Test;
sub infix:<⍣> ( &func, UInt $repeat ) is tighter( &[∘] ) { [∘] &func xx $repeat }
proto plus1(|) {*}
multi plus1(Int:D $i){ $i + 1 }
multi plus1(Bool:D $b){ $b.Int + 1 }
multi plus1(Int:D $i, Bool:D $b){ $i + $b.Int + 1 }
multi plus1(Int:D $i, Int:D $j){ $i + $j + 1 }
multi plus1(@j){ ([+] @j) + 1}
multi plus1(Int:D $i, @j){ plus1($i) + plus1(@j) - 1 }
multi plus1(%h){ ([+] %h.values) + 1 }
plan 9;
is plus1([1, 3, 5, 3]), 13, 'plus1([1, 3, 5, 3])';
is plus1(3, [1, 3, 5, 3]), 16, 'plus1(3, [1, 3, 5, 3])';
is plus1(3, True), 5, 'plus1(3, True)';
is (&plus1 ⍣ 0)(4), 4, '(&plus1 ⍣ 0)(4)';
is (&plus1 ⍣ 10)(4), 14, '(&plus1 ⍣ 10)(4)';
is (&plus1 ⍣ 10)([1, 3, 5, 3]), 22, '(&plus1 ⍣ 10)([1, 3, 5, 3])';
is (&plus1 ⍣ 3)(4, True), 8, '(&plus1 ⍣ 3)(4, True)';
is (&plus1 ⍣ 3)(3, [1, 3, 5, 3]), 18, '(&plus1 ⍣ 3)(3, [1, 3, 5, 3])';
is (&plus1 ⍣ 3)({a => 1, b => 3, c => 5}), 12, '(&plus1 ⍣ 3)({a => 1, b => 3, c => 5})';
done-testing;
【问题讨论】:
-
注意
([+] @j)可以写成[+]( @j )(]和(之间没有空格)。您也可以完全不使用括号1 + [+] @j或[+] 1, |@j
标签: raku infix-notation apl