Side Effects may include… being wrong!

side-effects

Yesterday, I wrote a post about Side Effects. My post was based on observed behaviour, as opposed to the mechanics of the Dart VM. I am happy to report that my last post was wrong. Yes I was wrong, and yes I am extremely happy about it! I received a number of comments indicating that no, Dart is a pass-by-value for everything. Additionally I received a number of comments indicating that Dart is actually always a pass-by-reference. In fact, both are correct… sort of.

The fact that the responses I received also go to show that the terminology and mechanics are actually somewhat skewed based on experiences. First, strictly speaking, Dart is considered a Pass-by-value language. Where the value is always a reference to an object. Something I didn’t specifically mention in my last post, that everything in Dart is an object. Event ‘primative’ types like int, num, bool etc. That’s why we can do something like 5.toString(); in Dart and it will work. This may sound like a pass-by-reference, however it’s actually a lesser-known Call-by-sharing.

So what’s the difference between call-by-reference and call-by-sharing? Simply put, in call-by-sharing each object referenced is passed as a value. The reference itself isn’t passed, rather a value of the reference is copied to the destination. Initially this wasn’t clear to me either, why split the hairs? But as it turns out there’s one huge area where it makes a difference. If a reference was passed directly, we could change the entire instance of the original value. Which we cannot do in Dart. We can update the contents of an instance, but we can’t make a new instance altogether. Consider the following code:

void reassignOne(List arg) {
  arg = new List.from([100, 200, 300]);
  print('In call: $arg');
}

void main() {
  List list = [1, 2, 3];
  print(list);
  reassignOne(list);
  print(list);
}

If Dart was a true pass-by-reference language, then calling reassignOne with list would totally change list on the outside of the function. But because Dart is a pass-by-value, where all values are a reference to an Object, we can modify the list we pass (such as appending a new value) which will have side-effects outside of the function. However we cannot assign an entirely new reference and access that outside of the function.

So do my observations from the previous post indicate that ‘primative’ types are passed by value directly (as opposed to a reference to their object?) Because their objects are entirely immutable. When an immutable object reference is passed it really is no different than pass-as-value. In addition to num, bool, int, double, Symbol some other types in Dart are immutable such as DateTime and Interval.

I want to thank everyone who corrected my previous post. I don’t mind being wrong, as it’s always a new opportunity to learn! Particular thanks go to Googlers +Lasse R.H. Nielsen and +Justin Fagnani on providing links and details on the differences with Dart’s pass-by-value or call-by-sharing.

This entry was posted in Dart and tagged , . Bookmark the permalink.

Have Something To Add?

Loading Facebook Comments ...
Loading Disqus Comments ...