Skip to content
New issue

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

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

Already on GitHub? # to your account

Proposal: Anonymous function literals #20242

Closed
Darkfllame opened this issue Jun 9, 2024 · 5 comments
Closed

Proposal: Anonymous function literals #20242

Darkfllame opened this issue Jun 9, 2024 · 5 comments

Comments

@Darkfllame
Copy link

First off, I know that proposals are closed, but i think a lot of project could benefits from that.

A minor addition: ononymous function literals, basically they're syntax sugar for struct { fn inner(...){...}}.inner, as fn(...) {...}, this could be super useful especially in callback-based APIs like GLFW, SDL (in some points) or other zig libraries (i don't have example ;( ).

I really hope this feature is added to zig since it's really annoying typing the whole struct thing or making a whole new function just for a simple callback.

@expikr
Copy link
Contributor

expikr commented Jun 9, 2024

#1048

@nektro
Copy link
Contributor

nektro commented Jun 9, 2024

this is explicitly not proposing closures

@andrewrk andrewrk closed this as not planned Won't fix, can't repro, duplicate, stale Jun 9, 2024
@mlugg
Copy link
Member

mlugg commented Jun 9, 2024

Duplicate of #1717. The reason you don't have an example of a callback-based Zig API is because callbacks are a poor model in Zig: idiomatic APIs, such as std.mem.sort, prefer using a context struct so that arbitrary data can be passed to the callback.

@Darkfllame
Copy link
Author

The idea behind this request was the ability to generate functions with custom signatures are comptime, passing a anonymous function (not a closure) to a built-in function that will generate a custom functions. Can't really explain, but something on the line of:

fn GenFunc(comptime I: u32) fn(...) i32
// Maybe having the ability to have anytype as return type would be 
// sweet but it's been removed for a reason I guess.
{
  return @func(fn(args: switch(I) {
    1 => struct { a: i32 },
    else => struct {},
  }) i32 {
    return if (@hasField(@TypeOf(args), "a") args.a else I;
  });
}

const func1 = GenFunc(1);
const func2 = GenFunc(2);
const func10 = GenFunc(10);

pub fn main() void {
  // won't type std import because this is an example and i'm still lazy
  std.debug.print("func1(5)", .{func1(5)});      // 5
  std.debug.print("func1(12)", .{func1(12)});  // 12
  std.debug.print("func2()", .{func2()});          // 2
  std.debug.print("func10()", .{func10()});      // 10
}

And I'm honestly sure this could be actually kinda good for zig extern libraries, like, instead of having to write a ton of functions to be exported you just generate them via a comptime function and then export them.

I know that like this it could be pretty dumb and a "Why the hell would it need this very specific feature" and I would tell you, idk I would find it pretty epic, like imagine the ability to create functions at will, it would sure be unique to zig.

Also if you want I can propose other (useful) things like:

  • more clarity on the comptime-made types (I really don't know if I can set declarations in those)
  • a comptime allocator or something because the current way of allocating memory at comptime is through ++ and ** which I find not consistent with the rest of the language
  • remove @divFloor() since dividing an integer will floor it (at machine code level) and I find it just annoying, basically just @floor(a / b)
  • also I'd love to see a way to use the file system at comptime (and the return of non-literal import module names with that)

Little note here: Of course I don't want zig to be like c++ (feature bloated), I only want it to be better than today and these features I propose are small ones that can make development maybe easier for some (and for me). Now accept them or not, but I'd sure love to see them be implemented.

@mlugg
Copy link
Member

mlugg commented Jun 10, 2024

The goal behind your original proposal is irrelevant -- the fact remains that it is a duplicate of another issue which has been separately rejected.

In terms of the "function generation" idea, I'm pretty confident such a proposal would be quickly rejected -- similar ideas have been discussed before but aren't a good fit for Zig. And, FWIW, if you don't have significant open-source contributions to one or more Zig projects, proposals are unlikely to be taken that seriously -- using the language is the only way to figure out what features and designs would be a good fit for it.

Your list of random other proposals is the very definition of drive-by proposal, i.e. exactly what the "Zig is not accepting language proposals" warning is trying to avoid. But, to quickly respond to each one:

  • The error message you get when you try and include a declaration on a reified (@Type) type makes this situation very clear:
    foo.zig:2:9: error: reified structs must have no decls
        _ = @Type(.{ .Struct = .{
            ^~~~~
    
  • We hope for std.mem.Allocator to eventually be usable at comptime, either through FixedBufferAllocator or potentially a special "comptime allocator". This is currently not possible due to design complexities around reinterpreting memory at comptime.
  • "I just find it annoying" is a very poor justification. This suggestion shows you have failed to read the table of operators in the langref, which explains why @divFloor exists.
  • You can import arbitrary files at comptime using @embedFile. This is fairly restrictive by design; you shouldn't be doing directory traversals and referencing files in arbitrary places on the system at comptime.

A general piece of advice: as well as not having evidence of contributing to Zig projects (your own or others), proposals will be immediately rejected if they are not sufficiently detailed. None of the proposals you have brought forward have the level of rigor expected. A languge proposal should include:

  • The precise syntax and semantics being proposed
  • One or more real-world use cases; without these, there is no compelling reason to implement a proposal
  • A candid discussion of advantages and drawbacks to the proposal

For some examples of what a proposal should include, you can take a look at these examples:

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

No branches or pull requests

5 participants