1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
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));
}
switch (itemsTypeInfo) {
.pointer => |p| if(p.size != .many and p.size != .slice) @compileError("Expected pointer of size 'many' or 'slice', found " ++ @tagName(p)),
else =>{},
}
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));
switch (itemsTypeInfo) {
.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);
}
|