aboutsummaryrefslogtreecommitdiff
path: root/src/map.zig
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2025-10-21 00:09:07 -0500
committerNic Gaffney <gaffney_nic@protonmail.com>2025-10-21 00:09:07 -0500
commitc034b4a1291a803028eef8b0950a7090ea54b047 (patch)
tree987040745c887299e69f2c3014c44ea829d89bb3 /src/map.zig
parentb4588b2064c3afde9497084caef6e83246b32501 (diff)
downloadfuncz-c034b4a1291a803028eef8b0950a7090ea54b047.tar.gz
Currying, Combinators, and organization
Diffstat (limited to 'src/map.zig')
-rw-r--r--src/map.zig62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/map.zig b/src/map.zig
new file mode 100644
index 0000000..c532f9e
--- /dev/null
+++ b/src/map.zig
@@ -0,0 +1,62 @@
+const std = @import("std");
+const typeVerify = @import("util.zig").typeVerify;
+
+/// ```zig
+/// (fn (Allocator, fn (fn (a) b, []a, *[]b) void)
+/// ```
+/// Map a function onto a list of values, using a buffer
+/// Type signature: `(a -> b) -> [a] -> [b]`
+/// `func` is of type `a -> b`, where `items` is of type `[a]` and `buffer` is a pointer to a value of type `[b]`.
+/// Haskell equivalent: `map func items`
+pub fn map(
+ comptime func: anytype,
+ items: []typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?,
+ buffer: *[]typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".return_type.?,
+) void {
+ _=typeVerify(@TypeOf(func), .{ .@"fn" });
+ // const itemsInfo = typeVerify(@TypeOf(items), .{ .pointer, .array });
+ // const bufferInfo = typeVerify(@TypeOf(buffer), .{ .pointer });
+ // const bufferChildInfo = typeVerify(bufferInfo.pointer.child, .{ .pointer, .array });
+ // switch (itemsInfo) {
+ // .pointer => |p| if(p.size != .many and p.size != .slice)
+ // @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
+ // else =>{},
+ // }
+ // switch (bufferChildInfo) {
+ // .pointer => |p| if(p.size != .many and p.size != .slice)
+ // @compileError("Expected pointer of size 'many' or 'slice', found '" ++ @tagName(p.size) ++ "'"),
+ // else =>{},
+ // }
+ for (items, 0..) |item, i|
+ buffer.*[i] = func(item);
+}
+
+/// ```zig
+/// (fn (Allocator, fn (fn (a) b, []a) error{OutOfMemory}![]b)
+/// ```
+/// Map a function onto a list of values, allocating space for the new slice
+/// Type signature: `(a -> b) -> [a] -> [b]`
+/// `func` is of type `a -> b`, where `items` is of type `[a]`.
+/// `map` will return a slice of type `[b]`
+/// Haskell equivalent: `map func items`
+pub fn mapAlloc(
+ allocator: std.mem.Allocator,
+ func: anytype,
+ items: anytype,
+) error{OutOfMemory}!blk:{
+ const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
+ const itemsInfo = typeVerify(@TypeOf(items), .{ .array, .pointer });
+ switch (itemsInfo) {
+ .pointer => |p| if(p.size != .many and p.size != .slice)
+ @compileError("Expected pointer of size 'many' or 'slice', found " ++ @tagName(p)),
+ else =>{},
+ }
+
+ break :blk []funcInfo.@"fn".return_type.?;
+} {
+ const funcInfo = typeVerify(@TypeOf(func), .{ .@"fn" });
+ var result = try allocator.alloc(funcInfo.@"fn".return_type.?, items.len);
+ for(items, 0..) |item, i|
+ result[i] = func(item);
+ return result;
+}