dart-lang / language

Design of the Dart language
Other
2.66k stars 205 forks source link

Proposal: argument passed by reference #426

Open duzenko opened 5 years ago

duzenko commented 5 years ago

There is a workaround for local variables (wrap in class) but it's not clear how to handle class fields. Amount of code to do routine stuff like copy values and check for changes is overwhelming comparing to languages like C++, C#, Delphi, Swift. It's just annoying to write and maintain.

// model

class DateRange {
    DateTime start, end;
    ...
}

// utility

/// returns false if not changed
bool editDate(ref DateTime date) {
    ...
}

// view

DateRange range;
...
btn1.onPressed = () {
  if(editDate(range.start))
      save();
};
btn2.onPressed = () {
  if(editDate(range.end))
      save();
};

Compare to

btn1.onPressed = () {
  final out = editDate(range.start);
  if(out != null && out != range.start) {
      range.start = out;
      save();
  }
};

This is two lines vs. five. And in our business logic it's a very common thing.

lrhn commented 5 years ago

A "reference" (as in pass-by-reference) here should be any LValue, anything you can assign to.

It's not just a variable. Dart (non-local) variables are symmetric with getters/setters, so you should be able to pass a getter/setter pair as well. (But what if it's just a setter, can we use it as a ref parameter?).

We also allow assignment to o1[o2] expressions, if there is a declared []= operator, so they should probably also be allowed as reference parameters.

So, the possible reference arguments would be non-final local variables, getter/setter pairs and []/[]= operator pairs.

Capturing a reference to a local variable can definitely keep the variable alive past the run-time of the function, but that's not new, any closure capturing the variable will do that.

flyingtime commented 5 years ago

dart need on key word like c# out parameter modifier,like 'out' or 'ref' key word:

int initializeInMethod;
OutArgExample(out initializeInMethod);
Console.WriteLine(initializeInMethod);     // value is now 44

void OutArgExample(out int number)
{
    number = 44;
}
anggaaryas commented 3 years ago

@lrhn hi, may i ask something. why List() is pass by reference?

like listB = listA

is there any other type that use pass by reference like this?

lrhn commented 3 years ago

Dart treats all types the same, List is not special in any way.

All Dart parameters are technically passed by value. The catch is that all Dart's expressible values are really object references. So, you pass the list object by passing a reference to it "by value".

A language like C# has both value types (structs) and reference types (objects). The value of a value type is itself. When you pass a value type as argument, or store it in a variable, you copy the value itself. The "value of an object" is a reference to that object. That's why objects can preserve their identity when you pass around references to it, you're not copying the object, you're copying the object reference. (In other words, objects are not expressible (can be value of an expression) or denotable (can be denoted by an identifier) values, only references to objects are). When you do o.foo(), you implicitly dereference the object reference stored in o and access it's foo member

Java is the same, it has primitive values (int) and reference values/objects (Integer). In Java, all primitive values are immutable, but they stand out by not being subtypes of Object.

In Dart, all values implement Object and all expressible/denotable "values" (what we really store in variables) are actually object references — to objects which have an identity of their own. It's just such an overhead to always say that, so we usually just talk about "storing the string in the variable", even if it's really "storing a reference to the string object in the variable".

If the object is mutable, then it is detectable that it's the same object. If it's immutable, then it's harder to see whether it's the same object or just objects with similar behavior, unless you use identical to check the identity (which answers the question: "do these references point to the same object?").

This is also sometimes called "call by object reference". (And I should probably just have lead with that link, since it's awesome.)

anggaaryas commented 3 years ago

whoa, i never tried that all Object is same behaviour like List . It suprise me. thank you for explanation