如何在 Zig 實現閉包與 Monads
一個有意思的探索,由於 Zig 目前原生並不支持閉包,因此需要一些小技巧來實現該功能。
fn bar(comptime x: usize) fn (usize) usize {
return struct {
pub fn foo(y: usize) usize {
var counter: usize = 0;
for (x..y) |i| {
if ((i % 2) == 0) {
counter += i * i;
}
}
return counter;
}
}.foo;
}
const std = @import("std");
pub fn main() void {
const f = bar(10);
std.debug.print("{any}\n", .{f(20)});
}
在上面中,有兩點需要注意:
-
用一個匿名的 struct 來包一下要返回的函數
-
閉包捕獲的變量
x
必須是 comptime 的,因爲函數本身就是 comptime 的,如果去掉,會報下面的錯誤:
main.zig:1:18: error: function with comptime-only return type 'fn (usize) usize' requires all parameters to be comptime
main.zig:1:18: note: use '*const fn (usize) usize' for a function pointer type
main.zig:1:8: note: param 'x' is required to be comptime
當有人在編程中使用術語 monad 時,通常指的是一個允許我們安全地進行鏈式調用的包裝器,一個用 Zig 實現的 Maybe monad 如下所以:
fn Maybe(comptime T: type) type {
return struct {
val: ?T,
pub fn apply(self: Maybe(T), fun: *const fn (T) ?T) Maybe(T) {
if (self.val != null) {
return Maybe(T){ .val = fun(self.val.?) };
}
return Maybe(T){ .val = null };
}
pub fn unwrapOr(self: anytype, default: T) T {
if (self.val != null) {
return self.val.?;
}
return default;
}
pub fn init(val: T) @This() {
return Maybe(T){ .val = val };
}
};
}
- 原文鏈接:Implementing Closures and Monads in Zig[1]
參考資料
[1]
Implementing Closures and Monads in Zig: https://zig.news/andrewgossage/implementing-closures-and-monads-in-zig-23kf
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/175kFqhgPlNEMkKQAKZBcg