munificent / ui-as-code

Design work on improving Dart's syntax for UI code
BSD 3-Clause "New" or "Revised" License
121 stars 11 forks source link

Property Shorthand & Destructuring #6

Closed andresaraujo closed 6 years ago

andresaraujo commented 6 years ago

Hi @munificent I like the ideas on this repo,

Have you considered "property shorthand" and "destructuring"? I think these will benefit a lot when writing UI in Dart code:

Argument/Property shorthand ::

Inspired by reasonml

Why?

// Example 1 

greeting({String name}) => 'Hello ${name}';

main() {
  final name = 'Yoda';
  greeting(::name); // same as: greeting(name: name);
}
// Example 2,
// In a Map it will define a string key with the same name

save(String key, String description, bool isLocked) {
  final params = <String, dynamic>{
    ::key,
    ::description,
    "locked": isLocked
  };
  /* Same as:
  {
    "key": key,
    "description": description,
    "locked": isLocked
  }
  */
  // ...
}
// Example 3,

buildItem(String title, String subtitle, String iconUrl) {
  final style = getStyle(iconUrl);
  return Container(
    child: StockItem(::title, ::subtitle, ::iconUrl, ::style), 
    // same as SotckItem(title: title, subtitle: subtitle, iconUrl: iconUrl, style: style)
    //...
  );
}

Destructuring

Why

// Example 1 

main() {
  final someInts = Tuple2<int, int>(10, 20);
  final {item1, item2} = someInts;
}
// Example 2

build(context) {
  final {
    primaryColor,
    accentColor,
    buttonColor,
  } = Theme.of(context);

  //...
}
// Example 3

main() {
  final colors = getColors();

  for(final {key, value} in colors) {
    //...
  }
}
// Example 4

main() async {
  final {data, status} = await getResult(); // class Result { dynamic data, Status status }

  //...
}

Feel free to close this if its not in scope for this repo.

munificent commented 6 years ago

There are two separate features here, argument shorthands and destructuring. Destructuring has been discussed heavily for Dart, but is, I think, out of scope for the UI-as-code" work. There isn't a lot of local variable binding that I see in UI code, so destructuring wouldn't come into play much. I do think it's a very useful feature for other kinds of code.

The argument shorthand syntax is interesting. I haven't put too much thought into this, but I have two concerns with it, a pragmatic one and a squishier one:

  1. Pragmatically, most UI code that I've looked at does not pass variables as named parameters. Code like this is rare:
var child = Thing(...);
SomeWidget(child: thing);

Instead, UI code tends to build the entire thing in one big expression:

SomeWidget(child: Thing(...));

That means that I think this shorthand syntax would rarely be applicable. My goal is to focus on syntax that is useful in a large fraction of cases, and I don't think that's true here.

  1. My squishier concern is that this makes the name of a local variable significant in ways that it heretofore hasn't been. This syntax encourages you to name your local variable in a way that makes it easier to pass it as an argument, at the possible expense of choosing a name that helps clarify the code right there. If someone change:
var someUsefulName = Thing(...);
SomeWidget(child: someUsefulName);

To:

var child = Thing(...);
SomeWidget(::child);

I'd be sad that the code is less readable. I could certainly be wrong, but that leads me to think this wouldn't be a good fit for Dart. I do really appreciate the suggestion, though! I need to take a deeper look at ReasonML.