From 78d191cbf396d2ea32d920282934aa44f8ade4be Mon Sep 17 00:00:00 2001 From: Nic Gaffney Date: Mon, 20 Oct 2025 01:59:56 -0500 Subject: inital commit --- src/lib.zig | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 33 +++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/lib.zig create mode 100644 src/main.zig (limited to 'src') diff --git a/src/lib.zig b/src/lib.zig new file mode 100644 index 0000000..8e99ad3 --- /dev/null +++ b/src/lib.zig @@ -0,0 +1,73 @@ +const std = @import("std"); + +/// Compose two single argument functions +pub fn compose( + comptime outerFunc: anytype, + comptime innerFunc: anytype +) blk:{ + const outerFuncType = @TypeOf(outerFunc); + const outerFuncTypeInfo = @typeInfo(outerFuncType); + if(outerFuncTypeInfo != .@"fn") + @compileError("Expected function, found " ++ @typeName(outerFuncType)); + const innerFuncType = @TypeOf(innerFunc); + const innerFuncTypeInfo = @typeInfo(innerFuncType); + if(innerFuncTypeInfo != .@"fn") + @compileError("Expected function, found " ++ @typeName(innerFuncType)); + const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?; + const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?; + break :blk fn(in) out; +} { + const out = @typeInfo(@TypeOf(outerFunc)).@"fn".return_type.?; + const in = @typeInfo(@TypeOf(innerFunc)).@"fn".params[0].type.?; + return struct { + fn func(input: in) out { + return outerFunc(innerFunc(input)); + } + }.func; +} + +pub fn mapAlloc( + allocator: std.mem.Allocator, + func: anytype, + items: anytype, +) error{OutOfMemory}!blk:{ + const itemsType = @TypeOf(items); + const itemsTypeInfo = @typeInfo(itemsType); + const funcType = @TypeOf(func); + const funcTypeInfo = @typeInfo(funcType); + if(funcTypeInfo != .@"fn") + @compileError("Expected function, found " ++ @typeName(funcType)); + if(itemsTypeInfo != .array and itemsTypeInfo != .pointer) { + @compileError("Expected array or slice, found " ++ @typeName(itemsType)); + } + + break :blk []funcTypeInfo.@"fn".return_type.?; +} { + const funcType = @TypeOf(func); + const funcTypeInfo = @typeInfo(funcType); + var result = try allocator.alloc(funcTypeInfo.@"fn".return_type.?, items.len); + for(items, 0..) |item, i| + result[i] = func(item); + return result; +} + +pub fn map( + func: anytype, + items: anytype, + buffer: anytype, +) void { + const funcType = @TypeOf(func); + const bufferType = @TypeOf(buffer); + const itemsType = @TypeOf(items); + const funcTypeInfo = @typeInfo(funcType); + const bufferTypeInfo = @typeInfo(bufferType); + const itemsTypeInfo = @typeInfo(itemsType); + if(funcTypeInfo != .@"fn") + @compileError("Expected function, found " ++ @typeName(funcType)); + if(itemsTypeInfo != .array and itemsTypeInfo != .pointer) + @compileError("Expected array, found " ++ @typeName(itemsType)); + if(bufferTypeInfo != .array and bufferTypeInfo != .pointer) + @compileError("Expected array, found " ++ @typeName(bufferType)); + for (items, 0..) |item, i| + buffer.*[i] = func(item); +} diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..949c368 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,33 @@ +const std = @import("std"); +const func = @import("funcz"); + +fn iter(n: i32) i32 { + return n + 1; +} + +fn mul2(n: i32) i32 { + return n * 2; +} + +pub fn main() !void { + var gpa = std.heap.DebugAllocator(.{}){}; + const allocator = gpa.allocator(); + const iterThenMul2 = func.compose(mul2, iter); + var items = [_]i32{ 0, 1, 2, 3, 4 }; + const itemsSlice: []i32 = items[0..items.len]; + const newItems = try func.mapAlloc(allocator, iterThenMul2, itemsSlice); + defer allocator.free(newItems); + var buffer: [128]i32 = undefined; + func.map(iterThenMul2, itemsSlice, &buffer); + std.debug.print("compose(mul2, iter)(5) = {d}\n", .{ iterThenMul2(5) }); + std.debug.print("mapAlloc(allocator, compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}) = {{ ", .{}); + for(newItems) |item| { + std.debug.print("{d}, ", .{item}); + } + std.debug.print("}}\n", .{}); + std.debug.print("map(compose(mul2, iter), []i32{{ 0, 1, 2, 3, 4 }}, &buffer) = {{ ", .{}); + for(buffer[0..items.len]) |item| { + std.debug.print("{d}, ", .{item}); + } + std.debug.print("}}\n", .{}); +} -- cgit v1.2.3