Skip to content
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

Proposal: Rename var to anytype for generics #4820

Closed
ikskuh opened this issue Mar 26, 2020 · 8 comments · Fixed by #5846
Closed

Proposal: Rename var to anytype for generics #4820

ikskuh opened this issue Mar 26, 2020 · 8 comments · Fixed by #5846
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ikskuh
Copy link
Contributor

ikskuh commented Mar 26, 2020

Introduce the keyword anytype to replace var in generic function declarations:

fn add2(input: anytype) @TypeOf(input) {
    return input + 2;
}

fn trueOrOne(comptime wantBool: bool) anytype {
    if(wantBool) {
        return true;
    } else {
        return @as(u32, 1);
    }
}

Benefits:

  • Remove confusion about what var means.
  • Prevent the word vararg which confuses with C lingo
  • Is much more precise than var in the place

Downsides:

  • Introduces a new keyword
  • Increases the stuff one must remember

Credits go to @fengb and @Qix- for proposing the idea in IRC 👍

@Qix-
Copy link
Contributor

Qix- commented Mar 26, 2020

junon = me :) Sounds good to me.

@andrewrk andrewrk added accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. labels Mar 26, 2020
@andrewrk andrewrk added this to the 0.7.0 milestone Mar 26, 2020
@nycex
Copy link
Contributor

nycex commented Mar 26, 2020

Isn't the type in anytype is redundant, couldn't it just be named any?

@andrewrk
Copy link
Member

The plan for this is the same for other keyword changes. zig fmt auto correcting code for 1 release cycle, remove legacy syntax in the next release cycle.

@andrewrk
Copy link
Member

Isn't the type in anytype is redundant, couldn't it just be named any?

The entire : foo syntax is redundant, we could even just have it so that you could omit the type and it would be any type. The counter-argument there was that it would encourage people to make generic functions even where generic functions are not appropriate.

@ikskuh
Copy link
Contributor Author

ikskuh commented Mar 26, 2020

Isn't the type in anytype is redundant, couldn't it just be named any?

I think any is too generic and anytype will communicate precisely what is arbitrary in this place. any could be any value as in the C++ type std::any which is a "union" over all types

@JesseRMeyer
Copy link

JesseRMeyer commented Mar 26, 2020

Isn't the type in anytype is redundant, couldn't it just be named any?

I think any is too generic and anytype will communicate precisely what is arbitrary in this place. any could be any value as in the C++ type std::any which is a "union" over all types

Is there any allowance in Zig's grammer where

name: specifier

does not mean 'The storage called name is of type specifier'? If not, then the structure of the : disambiguates the meaning.

@ghost
Copy link

ghost commented Mar 27, 2020

Benefits: ...
Downsides: Increases the stuff one must remember

Easier to remember two keywords that are not context dependent IMO, but I would still prefer var over anytype in case something like this was implemented, simply because var is shorter and less obtrusive.

// isBuffer and isLogger are type predicates: fn(type) bool
fn filterProcess(input: anytype(isBuffer), output: anytype(isBuffer)) anytype(isLogger) {
    // dostuff
}

// more readable imo
fn filterProcess(input: var(isBuffer), output: var(isBuffer)) var(isLogger) {
    // dostuff
}

Same if there was a way to make aliases (item 3) of the generic type parameter.

// not immediately obvious these "types" are just aliases of the generic type
fn filterProcess(input: Buffer, output: Buffer) Logger {
    // dostuff
}
// with var or anytype "wrapping" the alias: 
fn filterProcess(input: anytype(Buffer), output: anytype(Buffer)) anytype(Logger) {
    // dostuff
}

fn filterProcess(input: var(Buffer), output: var(Buffer)) var(Logger) {
    // dostuff
}

If there won't be any "upgrades" to the generic type parameter though, I think anytype will be better than var.

@benjaminmordaunt
Copy link

benjaminmordaunt commented Sep 1, 2020

As an aside, is there a sensible reason that the example code isn't able to coerce floating point types? In order to make the add2 function work as expected, we need:

fn add2(input: anytype) @TypeOf(input) {
    return input + @as(@TypeOf(input), 2);
}

This is clunky. Am I missing something here?

Also, I'm really not a fan of the @TypeOf(x) syntax in the return type, especially as I imagine this to be a fairly common pattern. Do we need a more concise syntax here to extract the type of an object? Such as @@x? This would also make type resolution more of a "first-class citizen" of the language.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants