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

Add a "default" operator #1236

Closed
DartBot opened this issue Jan 19, 2012 · 20 comments
Closed

Add a "default" operator #1236

DartBot opened this issue Jan 19, 2012 · 20 comments
Assignees
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). type-enhancement A request for a change that isn't a bug

Comments

@DartBot
Copy link

DartBot commented Jan 19, 2012

This issue was originally filed by @seaneagan


Note: This is different than issue #41

The need to default a null value is quite common. Thus, many languages (see below) provide an operator which returns the LHS unless it is null, in which case it "defaults" to the RHS. This saves a temporary variable declaration when the LHS is an expression which needs to be evaluated, and is much shorter and less cryptic than the ternary expression which is otherwise needed. To illustrate, assume we want to assign a variable to an expression if it's not null, otherwise to a default value. Currently in Dart, this would look like:

var x = b.c();
a = x !== null ? x : d;

or possibly:

a = ((x) => x !== null ? x : d)(b.c())

With a "default" operator, which might be denoted "??", this would shorten to:

a = b.c() ?? d;

Prior art:

CoffeeScript http://coffeescript.org/#operators :

// might require Dart to replace ternary operator with if expression (see issue #55)
foo ? bar
foo ?= bar

Groovy "elvis" operator - http://groovy.codehaus.org/Operators :

foo ?: bar

C# "null-coalescing" operator - http://msdn.microsoft.com/en-us/library/ms173224.aspx :

foo ?? bar

EcmaScript strawman - http://wiki.ecmascript.org/doku.php?id=strawman:default_operator :

foo ?? bar
foo ??= bar

JavaScript:

// defaults for any falsey value :(
foo || bar

Ruby:

// defaults for any falsey value :(
foo || bar
foo ||= bar

@DartBot
Copy link
Author

DartBot commented Jan 19, 2012

This comment was originally written by @seaneagan


If extension methods are added, this extension method might do the trick as well:

T ifNull<T>(T defaultValue) => this === null ? this : defaultValue;

where T is the type of this

Then, we could write:

a = b.c().ifNull(d)

@DartBot
Copy link
Author

DartBot commented Jan 19, 2012

This comment was originally written by @seaneagan


Or if "self types" were supported, then this "ifNull" method could be defined on Object. Assuming "self" were used to denote a "self type" annotation, then it would look like:

self ifNull(self defaultValue) this === null ? this : defaultValue;

@DartBot
Copy link
Author

DartBot commented Jan 19, 2012

This comment was originally written by @seaneagan


Forgot the => :

self ifNull(self defaultValue) => this === null ? this : defaultValue;

@DartBot
Copy link
Author

DartBot commented Jan 19, 2012

This comment was originally written by @seaneagan


One more try, should be !== :

self ifNull(self defaultValue) => this !== null ? this : defaultValue;

@dgrove
Copy link
Contributor

dgrove commented Feb 2, 2012

Removed Type-Defect label.
Added Type-Enhancement, Area-Language, Triaged labels.

@gbracha
Copy link
Contributor

gbracha commented Feb 3, 2012

Set owner to @gbracha.
Added Accepted label.

@gbracha
Copy link
Contributor

gbracha commented May 23, 2012

Added this to the Later milestone.

@DartBot
Copy link
Author

DartBot commented Aug 7, 2012

This comment was originally written by sra...@gmail.com


+1 for this feature!

Porting (CoffeeScript) code to Dart it's a feature I sorely missed e.g. having to write something like:

  pager = Platform.environment['PAGER'];
  pager = pager == null ? 'less' : pager;

instead of this (C# '??' style syntax):

  pager = Platform.environment['PAGER'] ?? 'less';

is both verbose and wet (4 refs to the assigned variable instead
of just one).

@DartBot
Copy link
Author

DartBot commented Nov 10, 2012

This comment was originally written by emilioplatz...@gmail.com


More ideas in http://code.google.com/p/dart/issues/detail?id=6582

@gbracha
Copy link
Contributor

gbracha commented Nov 10, 2012

Issue #6582 has been merged into this issue.

@DartBot
Copy link
Author

DartBot commented Apr 17, 2013

This comment was originally written by @tomochikahara


I already resolve this problem by option.dart in http://pub.dartlang.org/packages/option

pager = new Option(Platform.environment['PAGER']).getOrElse('less');

I believe Option should be in Dart core library.

@DartBot
Copy link
Author

DartBot commented Apr 30, 2013

This comment was originally written by @seaneagan


The main disadvantages I see with Option are:

* have to explicitly specify a type argument if you want to retain the type information (unless the analyzer can infer it somehow ?), which is not DRY.

  • an extra object is created (probably not a deal breaker)

Using an | operator would make it slightly less verbose, and more familiar to JavaScripters:

pager = new Option<String>(Platform.environment['PAGER']) | 'less';

@DartBot
Copy link
Author

DartBot commented Apr 30, 2013

This comment was originally written by @seaneagan


Also the ??= shorthand form can't be supported by Option, so you have something like:

someFoo = new Option<Foo>(someFoo) | foo();

instead of:

someFoo ??= foo();

@kevmoo
Copy link
Member

kevmoo commented Apr 5, 2014

Issue #18045 has been merged into this issue.

@tfortes
Copy link

tfortes commented Apr 5, 2014

Sorry I missed this one when I filed my duplicate (18045), but mine had another operator suggestion too (verbatim from that bug):

Going one step further, we could also add the ??! operator that returns null if LHS is null, and RHS otherwise.

Element child = getChild();
Element parent = child ??! child.parent;

[The operator names are debatable of course]

@DartBot
Copy link
Author

DartBot commented Apr 5, 2014

This comment was originally written by @simonpai


I'd guess using ??! might be a little bit hard to read? If Dart is going introduce both operators, maybe we can use something like ?|| and ?&& to enhance symbol semantics? Just my 2 cents.

@DartBot
Copy link
Author

DartBot commented Apr 6, 2014

This comment was originally written by @seaneagan


@16: That particular example is what the safe-navigation operator (issue #41) is for:

Element child = getChild();
Element parent = child?.parent;

But maybe there are cases you want want to call a function only if the input is not null, but that's already pretty easy since you don't have to repeat the input, you can just use the null literal:

var result = input == null ? null : f(input);

@kasperl
Copy link

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl
Copy link

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@DartBot DartBot added Type-Enhancement area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). labels Aug 4, 2014
@sethladd
Copy link
Contributor

sethladd commented Jun 4, 2015

There is a null-aware operator DEP that was approved: dart-archive/dart_enhancement_proposals#9

Implementations are underway.

@sethladd sethladd closed this as completed Jun 4, 2015
@kevmoo kevmoo added type-enhancement A request for a change that isn't a bug and removed type-enhancement labels Mar 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

7 participants