我对 Raku 很陌生,我对函数式方法有疑问,尤其是 reduce。我最初有这样的方法:
sub standardab{
my $mittel = mittel(@_);
my $foo = 0;
for @_ {
$foo += ($_ - $mittel)**2;
}
$foo = sqrt($foo/(@_.elems));
}
Run Code Online (Sandbox Code Playgroud)
它工作正常。然后我开始使用reduce:
sub standardab{
my $mittel = mittel(@_);
my $foo = 0;
$foo = @_.reduce({$^a + ($^b-$mittel)**2});
$foo = sqrt($foo/(@_.elems));
}
Run Code Online (Sandbox Code Playgroud)
我的执行时间增加了一倍(我将其应用于大约 1000 个元素)并且解决方案相差 0.004(我猜是舍入误差)。如果我正在使用
.race.reduce(...)
Run Code Online (Sandbox Code Playgroud)
我的执行时间比原始顺序代码高 4 倍。有人能告诉我这是什么原因吗?我考虑了并行初始化时间,但是 - 正如我所说 - 我将它应用于 1000 个元素,如果我更改代码中的其他 for 循环以减少它会变得更慢!
谢谢你的帮助
我想提高我编写真正高性能代码的 Haskell 技能(来自 C/C++ 背景,这对我的自我很重要:D)。
所以我写了两个函数来通过莱布尼茨公式计算 Pi(它不是关于计算 pi,它只是一个例子):
calcPiStep k = (if even k then 4.0 else -4.0) / (2.0*fromIntegral k + 1.0)
calcPiN n = foldl (\p x -> p + calcPiStep x) 0.0 [0..n]
calcPiInf = toinf [0..] 0
where
toinf = \(x:xs) l -> do
let curr = l + calcPiStep x
curr:toinf xs curr
Run Code Online (Sandbox Code Playgroud)
calcPiInf 通过递归构造一个无限列表。带有 foldl 的 calcPiN 和带有 n 次迭代的 lambda。
我发现 calcPiInf 比 calcPiN 快,并且不会因为数字太大而导致堆栈溢出。 第一个问题:这仅仅是因为懒惰的评估吗?
其次我写了一个相应的C++程序:
using namespace std;
double calcPi(int …Run Code Online (Sandbox Code Playgroud) 所以我目前正在学习Rust,并且有一个关于如何实现非消耗迭代器的问题。我编写了一个堆栈:
struct Node<T>{
data:T,
next:Option<Box<Node<T>>>
}
pub struct Stack<T>{
first:Option<Box<Node<T>>>
}
impl<T> Stack<T>{
pub fn new() -> Self{
Self{first:None}
}
pub fn push(&mut self, element:T){
let old = self.first.take();
self.first = Some(Box::new(Node{data:element, next:old}));
}
pub fn pop(&mut self) -> Option<T>{
match self.first.take(){
None => None,
Some(node) =>{
self.first = node.next;
Some(node.data)
}
}
}
pub fn iter(self) -> StackIterator<T>{
StackIterator{
curr : self.first
}
}
}
pub struct StackIterator<T>{
curr : Option<Box<Node<T>>>
}
impl<T> Iterator for StackIterator<T>{
type Item = …Run Code Online (Sandbox Code Playgroud)