aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2025-10-28 20:02:47 -0500
committerNic Gaffney <gaffney_nic@protonmail.com>2025-10-28 20:02:47 -0500
commit99c32737fe07bf7dc6094a1326be418ffd00e36f (patch)
treebc8549038f85586ef4b9724f51ab850193f36d68
parent96e8c19ebdc7c168a1bd243ce1793b2df1480939 (diff)
downloadfuncz-99c32737fe07bf7dc6094a1326be418ffd00e36f.tar.gz
filter implemented
-rw-r--r--src/compose.zig1
-rw-r--r--src/curry.zig1
-rw-r--r--src/example.zig13
-rw-r--r--src/filter.zig22
-rw-r--r--src/fold.zig6
-rw-r--r--src/map.zig2
-rw-r--r--src/root.zig1
7 files changed, 37 insertions, 9 deletions
diff --git a/src/compose.zig b/src/compose.zig
index 61ebb20..442b21b 100644
--- a/src/compose.zig
+++ b/src/compose.zig
@@ -7,7 +7,6 @@ const typeVerify = @import("util.zig").typeVerify;
/// Function composition
/// Type signature: (a -> b) -> (b -> c) -> (a -> c)
/// `outerFunc` and `innerFunc` are functions of types `b -> c` and `a -> b` respectively
-/// Haskell equivalent: `outerFunc . innerFunc`
pub fn compose(
comptime outerFunc: anytype,
comptime innerFunc: anytype
diff --git a/src/curry.zig b/src/curry.zig
index d196155..73976c2 100644
--- a/src/curry.zig
+++ b/src/curry.zig
@@ -7,7 +7,6 @@ const std = @import("std");
/// Type signature: (a -> b -> ... -> n -> r) -> a -> b -> ... -> n -> r
/// Transforms a function taking multiple arguments into a sequence of functions each taking a single argument
/// `func` is a function of type `(a, b, ..., n) -> r`
-/// Haskell equivalent: automatic currying (all functions are curried by default)
pub fn curry(func: anytype) curryTypeGetter(@TypeOf(func), @TypeOf(func), .{}) {
return curryHelper(func, .{});
}
diff --git a/src/example.zig b/src/example.zig
index 6622726..e20eb31 100644
--- a/src/example.zig
+++ b/src/example.zig
@@ -18,6 +18,10 @@ fn addThenMultiply(n: i32, m: i32, q: i32) i32 {
return (n + m) * q;
}
+fn isEven(n: i32) bool {
+ return (@mod(n, 2) == 0);
+}
+
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _=gpa.deinit();
@@ -28,13 +32,14 @@ pub fn main() !void {
const iterThenMul2 = func.compose(mul2, iter);
const composed = iterThenMul2(5);
// Map
- var items = [_]i32{ 0, 1, 2, 3, 4 };
+ var items = [_]i32{ 0, 1, 2, 3, 4, 5 };
const itemsSlice: []i32 = items[0..items.len];
var buffer: [16]i32 = undefined;
var buffSlice: []i32 = buffer[0..16];
func.map(iterThenMul2, itemsSlice, &buffSlice);
const bufferAlloc = try func.mapAlloc(allocator, iterThenMul2, itemsSlice);
defer allocator.free(bufferAlloc);
+ const filtered = func.filter(isEven, itemsSlice);
std.debug.print("curry(add)(4)(5) = {any}\n", .{ curriedAddResult });
std.debug.print("compose(mul2, iter)(5) = {d}\n", .{ composed });
@@ -45,6 +50,12 @@ pub fn main() !void {
}
std.debug.print("}}\n", .{});
+ std.debug.print("filter(isEven, bufferAlloc) = {{ ", .{});
+ for(filtered) |item| {
+ std.debug.print("{d}, ", .{item});
+ }
+ std.debug.print("}}\n", .{});
+
std.debug.print("mapAlloc(allocator, compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}) = {{ ", .{});
for(bufferAlloc) |item| {
std.debug.print("{d}, ", .{item});
diff --git a/src/filter.zig b/src/filter.zig
new file mode 100644
index 0000000..b9e2167
--- /dev/null
+++ b/src/filter.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+const typeVerify = @import("util.zig").typeVerify;
+
+/// ```zig
+/// (fn (fn (fn (a) bool, []a) []a)
+/// ```
+/// Filters a slice, only keeping items give `true` when passed into `func`
+/// Type signature: `(a -> bool) -> [a] -> [a]`
+/// `func` is of type `a -> bool`, where `items` is of type `[a]`
+pub fn filter(
+ func: anytype,
+ items: []typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?,
+) []typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.? {
+ var output = items;
+ var i: u32 = 0;
+ for (items) |it|
+ if (func(it)) {
+ output[i] = it;
+ i = i + 1;
+ };
+ return output[0..i];
+}
diff --git a/src/fold.zig b/src/fold.zig
index 6b910d3..ddaf0a9 100644
--- a/src/fold.zig
+++ b/src/fold.zig
@@ -2,12 +2,11 @@ const std = @import("std");
const typeVerify = @import("util.zig").typeVerify;
/// ```zig
-/// (fn (fn (fn (b, a) b, b, []a) void)
+/// (fn (fn (fn (b, a) b, b, []a) b)
/// ```
/// Folds a list of items over a function with the accumulator as the first arg
/// Type signature: `(b -> a -> b) -> b -> [a] -> b`
/// `func` is of type `b -> a -> b`, where `items` is of type `[a]` and `accumulator` is of type `b`.
-/// Haskell equivalent: `foldl func accumulator items`
pub fn foldl(
comptime func: anytype,
accumulator: (typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[0].type.?),
@@ -20,12 +19,11 @@ pub fn foldl(
}
/// ```zig
-/// (fn (fn (fn (a, b) b, b, []a) void)
+/// (fn (fn (fn (a, b) b, b, []a) b)
/// ```
/// Folds a list of items over a function with the accumulator as the second arg
/// Type signature: `(a -> b -> b) -> b -> [a] -> b`
/// `func` is of type `a -> b -> b`, where `items` is of type `[a]` and `accumulator` is of type `b`.
-/// Haskell equivalent: `foldr func accumulator items`
pub fn foldr(
comptime func: anytype,
accumulator: (typeVerify(@TypeOf(func), .{ .@"fn" }).@"fn".params[1].type.?),
diff --git a/src/map.zig b/src/map.zig
index b04366d..e0d713d 100644
--- a/src/map.zig
+++ b/src/map.zig
@@ -7,7 +7,6 @@ const typeVerify = @import("util.zig").typeVerify;
/// 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.?,
@@ -28,7 +27,6 @@ pub fn map(
/// 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,
diff --git a/src/root.zig b/src/root.zig
index 20c6a20..9c24261 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -6,4 +6,5 @@ pub const foldl = @import("fold.zig").foldl;
pub const foldr = @import("fold.zig").foldr;
pub const foldl1 = @import("fold.zig").foldl1;
pub const foldr1 = @import("fold.zig").foldr1;
+pub const filter = @import("filter.zig").filter;
pub const combinators = @import("combinators.zig");