Skip to content

Discussion: The standard way of writing generic functions #670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Hejsil opened this issue Jan 3, 2018 · 4 comments
Closed

Discussion: The standard way of writing generic functions #670

Hejsil opened this issue Jan 3, 2018 · 4 comments
Milestone

Comments

@Hejsil
Copy link
Contributor

Hejsil commented Jan 3, 2018

In Zig the compiler prevents you from passing structs (and other potentially big data) to procedures by values. This is good, cause then we avoid large copies. This does however have the side effect that all generic code have to pass &const T around, to ensure that the code is truly generic.

Now, let's say that I have some procedure for lessThan on strings ([]const u8). It would look something like this:

fn lessThan(lhs: []const u8, rhs: []const u8) -> bool { ... }

And I have a slice of strings ([][]const u8). I can't use my lessThan procedure for generic procedures like insertionSort, because it requires procedures of type fn(&const T, &const T) -> bool or fn(&const []const u8, &const []const u8) -> bool for strings specifically. This means, we have to write an ugly wrapper function whenever we wanna use "pass by value" procedures with generic procedures.

This might not be a problem, and we decide that this is indeed how it should be. I do however think this needs to be discussed before deciding on "the standard way" of writing generic procedures.

Let me kick the discussion of with one way of dealing with this. In Zig, we can actually write a user space procedure that can decide whether a type can be passed by value. With this a procedure can also be written to take a type, and return a type that can be passed to a procedure (see types.zig for implementation).

With these procedures insertionSort can now have this signature:

fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: Pass(T), rhs: Pass(T))->bool)

And now, insertionSort can take my lessThan procedure without any wrapper.

This solution does complicate the generic code a little, as one would have to call the getValue to use values passed with Pass.

@Hejsil
Copy link
Contributor Author

Hejsil commented Jan 3, 2018

Another interesting side note. If we ever get anonymous procedures, then one could write mem.lessThan like this:

const lessThan = fn (comptime T: type) -> fn ([]const T, []const T) -> bool {
    return fn ([]const T, []const T) -> bool { ... }
}

And now, we can can use mem.lessThan with insertionSort (if it has the signature from above):

insertionSort([]const u8, strs, mem.lessThan(u8));

@andrewrk andrewrk added this to the 0.2.0 milestone Jan 3, 2018
@andrewrk
Copy link
Member

andrewrk commented Jan 3, 2018

Related: #103

@andrewrk
Copy link
Member

andrewrk commented Jan 3, 2018

Also related: #386

@andrewrk
Copy link
Member

I believe this is resolved now that #733 has landed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants