Skip to content

Allow functions as enum Constructor Parameter #2241

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
synchronisator opened this issue May 13, 2022 · 6 comments
Closed

Allow functions as enum Constructor Parameter #2241

synchronisator opened this issue May 13, 2022 · 6 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@synchronisator
Copy link

I have an enum representing a bunch of elements that are clickable by the user.
Every possible element is a value in this enum.
Via SharedPreferences the user can toggle if he want to see this element or not.

To solve this problem i had to make an extension for my enum.

enum Element {
  dot("/assets/dot.png"),
  slash("/assets/slash.png"),
  plus("/assets/plus.png"),
  minus("/assets/minus.png");

  final String assetPath;

  const Element(this.assetPath);
}

extension ElementIsShown on Element {
  bool isShown(SharedPrefsProvider sp){
    switch (this) {
      case Element.dot:
        return sp.isDotShown;
      case Element.slash:
        return sp.isSlashShown;
      case Element.plus:
        return sp.isPlusShown;
      case Element.minus:
        return sp.isMinusShown;
  }
}

It would be nice to get this via constructor like this:

enum Element {
  dot("/assets/dot.png", (sp) => sp.isDotShown),
  slash("/assets/slash.png", (sp) => sp.isSlashShown),
  plus("/assets/plus.png", (sp) => sp.isPlusShown),
  minus("/assets/minus.png", (sp) => sp.isMinusShown);

  final String assetPath;
  final bool Function(SharedPrefsProvider) _isShownFunction;

  const Element(this.assetPath, this._isShownFunction);

  bool isShown(SharedPrefsProvider sp){
    return _isShownFunction(sp);
  }
}

(The same for setting the value.)

@synchronisator synchronisator added the feature Proposed language feature that solves one or more problems label May 13, 2022
@lrhn
Copy link
Member

lrhn commented May 13, 2022

This would allow function literals in a constant scope. That sounds like #1048.

@mateusfccp
Copy link
Contributor

mateusfccp commented May 13, 2022

Just to add that it is possible to pass functions in enums constructors, as long as they are constant.

Example:

enum Element {
  dot("/assets/dot.png", isDotShown),
  slash("/assets/slash.png", isSlashShown),
  plus("/assets/plus.png", isPlusShown),
  minus("/assets/minus.png", isMinusShown);

  final String assetPath;
  final bool Function(SharedPrefsProvider) _isShownFunction;

  const Element(this.assetPath, this._isShownFunction);

  bool isShown(SharedPrefsProvider sp){
    return _isShownFunction(sp);
  }
  
  static bool isDotShown(SharedPrefsProvider sp) => sp.isDotShown;
  static bool isSlashShown(SharedPrefsProvider sp) => sp.isSlashShown;
  static bool isPlusShown(SharedPrefsProvider sp) => sp.isPlusShown;
  static bool isMinusShown(SharedPrefsProvider sp) => sp.isMinusShown;
}

However, this is not any better than an extension.

@jakemac53
Copy link
Contributor

However, this is not any better than an extension.

I would guess that this is more easily optimized than the extension, but that is only a guess :).

@Levi-Lesches
Copy link

Why not move the logic to SharedPrefsProvider? After all, the question of whether an element is being shown isn't really intrinsic to the element itself, but rather a question of the device's state (managed by the platform's SharedPreferences implementation).

enum Element {
  dot("/assets/dot.png"),
  slash("/assets/slash.png"),
  plus("/assets/plus.png"),
  minus("/assets/minus.png");

  final String assetPath;

  const Element(this.assetPath);
}

class SharedPrefsProvider {
  bool isShown(Element element) => prefs.getBool(element.path);
}

void main() {
  final sp = SharedPrefsProvider();
  final element = Element.plus;
  print("Is shown? ${sp.isShown(element)}");
}

If you don't have access to that class, you can simply make isShown an extension on SharedPrefsProvider.

@synchronisator
Copy link
Author

@Levi-Lesches This is a nice idea.
At the moment i generate my SharedPrefsProvider with a tool https://synchronisator.github.io/sharedprefprovidergenerator/
But the key could be part of the Element itself. yes.

That is a good solution for my example, but i think the general possibility to add a (constant) function to an enum would still be great. And the example of @mateusfccp shows that its possible, but not in a direct way.

Maybe the solution could be to add a static inside the consturctor. like:

  dot("/assets/dot.png", static (sp) => sp.isDotShown),

Thanks for all the suggestions.

@munificent
Copy link
Member

Closing this because it sounds like the specific request is already covered by #1048 and a good workaround was provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

6 participants