Strawman proposal: value types in Dart

2,498 views
Skip to first unread message

Dominic Hamon

unread,
Aug 10, 2012, 12:01:02 PM8/10/12
to General Dart Discussion

Motivation

Currently, all objects in Dart are stored and passed by reference. This, presumably, stems from the tight integration Dart has with JavaScript, which does the same. However, for developers coming from non-script languages such as C/C++ and C# this can be a surprise. It can certainly be the root cause of subtle bugs. For instance:

void drawPoint(vec2 position) {
_projectionMatrix.transform(position);
_context.drawPoint(position);
}

Oops. Calling this apparently harmless method has just changed the value of the position passed in. The current solution requires an explicit copy to be taken:

void drawPoint(vec2 position) {
final vec2 drawPosition = new vec2.copy(position);
_projectionMatrix.transform(drawPosition);
_context.drawPoint(drawPosition);
}

This adds extra work and adds more objects that need to be tracked and garbage collected. Not only that, but even when typing out that example I made a mistake and passed position into transform instead of drawPosition. It’s far too easy to make this mistake and avoiding it adds cognitive load that shouldn’t be necessary.

Proposal

Passing reference types by value

By introducing the val keyword to method and function parameters, Dart will be able to support passing reference types (classes) by value. This has the nice side-effect of keeping the default as pass-by-reference and will be less surprising for those developers coming from JavaScript.

void drawPoint(val vec2 position) {
_projectionMatrix.transform(position);
_context.drawPoint(position);
}

The VM should be able to handle this natively by making an explicit copy, however it might be able to avoid the GC cost of the extra object by knowing this copy only needs to exist for the limited scope of this method. When converted to JavaScript, an explicit copy would need to be added. While this ends up in the same situation as no pass-by-value, it takes the onus and cognitive load off of the developer and into the tools.

User-defined value types

Dart does currently have value types, such as num, int, and double, but it is currently impossible to declare user-defined value types. As a precedence, consider C# that offers struct types alongside class types. C# passes primitive types and struct types by value and class types by reference. By introducing the struct keyword, Dart will allow a user to define a type that should be passed by value by default.

Passing value types by reference

In some cases, it is useful to be able to explicitly pass a value type (primitive or user-defined) by reference. Introducing the ref keyword to function and method parameters that cause a type that would normally be passed by value to be passed by reference instead will allow this.

void incIfTrue(bool predicate, ref int counter) {
if (predicate) {
                ++counter;
        }
}

Thoughts?
- dominic

Gilad Bracha

unread,
Aug 10, 2012, 12:11:36 PM8/10/12
to mi...@dartlang.org
We have considered the notion of value types in Dart, but from a rather different perspective.

A value type would be an object known to be deeply immutable: all final fields, all initialized to deeply immutable objects.  How you pass such an object is then immaterial - it can be optimized as desired..

The absence of pass by value is not due to the interactions with Javascript.  It's a core part of the object model. It's the same in Smalltalk, in Ruby, in Java etc. Object are passed by reference. The only difference wrt Java is that unlike Smalltalk & Ruby, some things are not objects (but there are no user defined value types).

At some point in the future, we may consider user defined value types along the lines I described above (I think there's a feature request for that). I don't expect us to ever seek to emulate system-programming languages directly by passing mutable objects by value.



- dominic

--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 



--
Cheers, Gilad

John McCutchan

unread,
Aug 10, 2012, 12:13:45 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 9:01 AM, Dominic Hamon <dom...@google.com> wrote:
As a developer coming from C/C++ to Dart, 'every object is passed by reference' was one of the biggest surprises. The semantics make it difficult to move code from a language that passes by value by default, for example, C/C++. It's important to note that many game developers will be coming from code bases written in C/C++. Looking at Dominic's proposal, I've been bitten by the vector example multiple times when moving code from my C++ engine to Dart. Has the Dart team considered adding a struct keyword that mirrors the C# semantics? If so, why was it not added?

--
John McCutchan <jo...@johnmccutchan.com>

Gilad Bracha

unread,
Aug 10, 2012, 12:38:56 PM8/10/12
to mi...@dartlang.org

As a developer coming from C/C++ to Dart, 'every object is passed by reference' was one of the biggest surprises.

Sorry to hear that, but  Dart is not at all focused on catering to C/C++ programmers, especially when that conflicts with catering to Javascript or Java programmers. C# is somewhere in the middle - it is after all a hybrid of Java and C++ at heart.

 
The semantics make it difficult to move code from a language that passes by value by default, for example, C/C++. It's important to note that many game developers will be coming from code bases written in C/C++. Looking at Dominic's proposal, I've been bitten by the vector example multiple times when moving code from my C++ engine to Dart. Has the Dart team considered adding a struct keyword that mirrors the C# semantics? If so, why was it not added?
 

Emulating C/C++ or even C# is a non-goal. We are not seeking to build a new systems programming language.  

Conceptually, passing a mutable object by value is an oxymoron. If something is mutable, it cannot be passed by  value; you are passing some other object, a copy, not the original.  It is best for copying to explicit.  It makes costs more explicit, and much more importantly, makes the semantics explicit - no hidden copying.  

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 

Supporting these features in that form is not particularly important in application programming, but is unattractive to Javascript or Java programmers, who are our main audiences.  

I'll add that value types as I described in my previous message can really be passed without risk of mutation, whereas structs contain mutable references which could lead to mutations in any case.


--
Cheers, Gilad

dominic

unread,
Aug 10, 2012, 12:53:19 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 9:38 AM, Gilad Bracha <gbr...@google.com> wrote:


As a developer coming from C/C++ to Dart, 'every object is passed by reference' was one of the biggest surprises.

Sorry to hear that, but  Dart is not at all focused on catering to C/C++ programmers, especially when that conflicts with catering to Javascript or Java programmers. C# is somewhere in the middle - it is after all a hybrid of Java and C++ at heart.

 
The semantics make it difficult to move code from a language that passes by value by default, for example, C/C++. It's important to note that many game developers will be coming from code bases written in C/C++. Looking at Dominic's proposal, I've been bitten by the vector example multiple times when moving code from my C++ engine to Dart. Has the Dart team considered adding a struct keyword that mirrors the C# semantics? If so, why was it not added?
 

Emulating C/C++ or even C# is a non-goal. We are not seeking to build a new systems programming language.

C/C++, and C# especially, are no longer constrained to the systems programming world. XNA and .NET have made C# wildly popular in the game dev arena and I know, from discussions with developers at the New Game Conf and Game Developers Conference, that they're trying to break into web development but are repeatedly surprised by these features of JavaScript. If we can find a way to add something to the language to help them without changing the default behaviour that developers coming from JS web development expect, then I think it will only benefit the language.
 
 

Conceptually, passing a mutable object by value is an oxymoron. If something is mutable, it cannot be passed by  value; you are passing some other object, a copy, not the original.  It is best for copying to explicit.  It makes costs more explicit, and much more importantly, makes the semantics explicit - no hidden copying.  

It's very interesting that you see the copying as hidden, whereas I see the reference passing as hidden. I do agree with your point - passing by value actually means passing a copy. However, I prefer (due to my background) to have control over that copying.
 

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 

My argument is that adding the optional parameter passing mode reduces cognitive load for some users. In my case, I have to remember to add an explicit copy when I want to pass by value. If, instead, I could do this at the API or type level then that load is reduced.
 

Supporting these features in that form is not particularly important in application programming, but is unattractive to Javascript or Java programmers, who are our main audiences.  

I'll add that value types as I described in my previous message can really be passed without risk of mutation, whereas structs contain mutable references which could lead to mutations in any case.

That's true, and complicates the notion of what it means to copy a complex user-defined value type. I'm a little unclear on what a deeply immutable object would be like to use. For example, if I had:

immutable class vec2 {
  num x, y;
}

as an example your deeply immutable type, would I be able to pass this an instance to a method, have that method alter the values x and y, but have the original instance left unchanged? Or does deeply immutable mean that methods wouldn't be able to change the values of x and y?
 


--
Cheers, Gilad

John McCutchan

unread,
Aug 10, 2012, 1:15:21 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 9:38 AM, Gilad Bracha <gbr...@google.com> wrote:
 
The semantics make it difficult to move code from a language that passes by value by default, for example, C/C++. It's important to note that many game developers will be coming from code bases written in C/C++. Looking at Dominic's proposal, I've been bitten by the vector example multiple times when moving code from my C++ engine to Dart. Has the Dart team considered adding a struct keyword that mirrors the C# semantics? If so, why was it not added?
 

Emulating C/C++ or even C# is a non-goal. We are not seeking to build a new systems programming language.  


No one has asked for Dart to emulate all of C/C++ or C#. The request is very narrow: Dart to support user defined value struct types whose instances are implicitly copied when passed to a function so that the callee's usage of the instance is side effect free from the perspective of the caller.

C/C++ and C# are as much application programming languages as they are systems languages. If we were to measure based on lines of code written, all three are hands down application languages. The vast majority of game _applications_ are written in C/C++. Again, the request is very narrow and not a general request for Dart to become a systems programming language.

Conceptually, passing a mutable object by value is an oxymoron. If something is mutable, it cannot be passed by  value; you are passing some other object, a copy, not the original.  It is best for copying to explicit.  It makes costs more explicit, and much more importantly, makes the semantics explicit - no hidden copying.  


Introducing struct types whose instances are always copied when passed to functions is not hidden copying- the programmer consciously chose to use a struct versus a class and therefore has explicitly requested that copies be made when passed. Similarly if a "val" keyword was added, the programmer has explicitly requested a copy be made.

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 


C# is a high level language and it offers both struct types and the ref keyword allowing the programmer to control parameter passing.

Thanks,
--
John McCutchan <jo...@johnmccutchan.com>

Christopher Wright

unread,
Aug 10, 2012, 1:20:13 PM8/10/12
to mi...@dartlang.org
Immutable objects give you all the safety of value types and more. They cost you in efficiency, mainly due to garbage collection, if the value is not conceptually globally immutable; and they are a bit harder to construct. Especially if you are building up one of these things progressively -- you probably end up using the builder pattern or something like that, with your builders having a constructor taking an existing object to base their fields off of. (If you just have a constructor, then adding a field will be...problematic at best, if you are creating objects of this type based on existing objects with some specific changes.)

I've seen people using a fine-grained const system to try to get deeply immutable views of objects that are otherwise mutable. The results were workable but not wonderful. It would not fit in with Dart in the slightest.

You could effectively write your own const system, though:

class Foo {
  var a, b;
  final ReadonlyFoo readonly;
  Foo() : readonly = new ReadonlyFoo(this);
}

class ReadonlyFoo {
  var _foo;
  ReadonlyFoo(this._foo);
  get a() => _foo.a;
  get b() => _foo.b;
}

If you want a Foo that is globally immutable (so it can't change out from under you), you could store foo.clone().readonly instead of foo.readonly.

Doing the same thing in a generic manner requires mirrors and noSuchMethod and the like, though, which is a bit of a performance drain.

Don Olmstead

unread,
Aug 10, 2012, 1:25:03 PM8/10/12
to mi...@dartlang.org
I'm going to echo John and Dominics sentiments here. I have seen a tremendous interest in Dart for game developers as it makes a lot more sense to build something like that in Dart than JavaScript. Having the C# style struct that's passed by value would be a great addition.

Honestly I think you're missing who your real audience here, people who have a C/C++/C# background and want to get into web programming but cringe at the thought of working in JavaScript.

Matthew Butler

unread,
Aug 10, 2012, 2:05:41 PM8/10/12
to mi...@dartlang.org
Just my $0.02CND, coming from Ruby, I much more prefer and expect pass by reference in a 'purely' object oriented language.

Gilad Bracha

unread,
Aug 10, 2012, 2:40:19 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 9:53 AM, dominic <domi...@google.com> wrote:


C/C++, and C# especially, are no longer constrained to the systems programming world.

Wrt C# I agree - but this feature comes from its C++ heritage. 
 
XNA and .NET have made C# wildly popular in the game dev arena and I know, from discussions with developers at the New Game Conf and Game Developers Conference, that they're trying to break into web development but are repeatedly surprised by these features of JavaScript. If we can find a way to add something to the language to help them without changing the default behaviour that developers coming from JS web development expect, then I think it will only benefit the language.

Adding a feature always comes with a cost.  The fact that some objects are passed by reference and some by value is something *everyone* using the language will need to know - they will encounter your code, for example, and need to understand it (or, more likely, be totally surprised).  


It's very interesting that you see the copying as hidden, whereas I see the reference passing as hidden.

Yes. Your mental model is different - but I'd much rather the C people learn the pass-by-reference idea than burden the Javascript, Java and Ruby developers with the mechanics of the C world.
 
I do agree with your point - passing by value actually means passing a copy. However, I prefer (due to my background) to have control over that copying.
 

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 

My argument is that adding the optional parameter passing mode reduces cognitive load for some users.

And, as I note above, it adds load for others. We believe there are more of them than there are of you. Otherwise, Dart might be totally different.
 
In my case, I have to remember to add an explicit copy when I want to pass by value. If, instead, I could do this at the API or type level then that load is reduced.
 

Supporting these features in that form is not particularly important in application programming, but is unattractive to Javascript or Java programmers, who are our main audiences.  

I'll add that value types as I described in my previous message can really be passed without risk of mutation, whereas structs contain mutable references which could lead to mutations in any case.

That's true, and complicates the notion of what it means to copy a complex user-defined value type. I'm a little unclear on what a deeply immutable object would be like to use. For example, if I had:

immutable class vec2 {
  num x, y;
}

as an example your deeply immutable type, would I be able to pass this an instance to a method, have that method alter the values x and y, but have the original instance left unchanged? Or does deeply immutable mean that methods wouldn't be able to change the values of x and y?

The latter.
 

--
Cheers, Gilad

Don Olmstead

unread,
Aug 10, 2012, 2:55:47 PM8/10/12
to mi...@dartlang.org
In C# struct is often used as an optimization strategy for lightweight data. A C# struct is honestly pretty different from a struct in C/C++. You can't inherit from it, and its created on the stack not the heap as a class is. In JavaScript you often get burnt by creating a bunch of garbage, which is why vector libraries do all the selfAdd stuff instead of using the more natural looking operators.

Would having a struct designation help in that scenario?

--

Gilad Bracha

unread,
Aug 10, 2012, 2:56:08 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 10:25 AM, Don Olmstead <don.j.o...@gmail.com> wrote:
I'm going to echo John and Dominics sentiments here. I have seen a tremendous interest in Dart for game developers as it makes a lot more sense to build something like that in Dart than JavaScript. Having the C# style struct that's passed by value would be a great addition.

Honestly I think you're missing who your real audience here, people who have a C/C++/C# background and want to get into web programming but cringe at the thought of working in JavaScript.

The question of audience is indeed crucial. We've made compromises between the Javascript and Java points of view for example, and they are certainly debatable. Here however, we have an easy choice because those two camps agree on this point.

I think games are an important domain for Dart, but the question remains how much the language should deviate from its core model. Contrary to what some have said, this is not a minor feature. It's huge conceptual shift.


On Fri, Aug 10, 2012 at 10:15 AM, John McCutchan <jo...@johnmccutchan.com> wrote:
On Fri, Aug 10, 2012 at 9:38 AM, Gilad Bracha <gbr...@google.com> wrote:
 
The semantics make it difficult to move code from a language that passes by value by default, for example, C/C++. It's important to note that many game developers will be coming from code bases written in C/C++. Looking at Dominic's proposal, I've been bitten by the vector example multiple times when moving code from my C++ engine to Dart. Has the Dart team considered adding a struct keyword that mirrors the C# semantics? If so, why was it not added?
 

Emulating C/C++ or even C# is a non-goal. We are not seeking to build a new systems programming language.  


No one has asked for Dart to emulate all of C/C++ or C#. The request is very narrow: Dart to support user defined value struct types whose instances are implicitly copied when passed to a function so that the callee's usage of the instance is side effect free from the perspective of the caller.

C/C++ and C# are as much application programming languages as they are systems languages. If we were to measure based on lines of code written, all three are hands down application languages. The vast majority of game _applications_ are written in C/C++. Again, the request is very narrow and not a general request for Dart to become a systems programming language.

Conceptually, passing a mutable object by value is an oxymoron. If something is mutable, it cannot be passed by  value; you are passing some other object, a copy, not the original.  It is best for copying to explicit.  It makes costs more explicit, and much more importantly, makes the semantics explicit - no hidden copying.  


Introducing struct types whose instances are always copied when passed to functions is not hidden copying- the programmer consciously chose to use a struct versus a class and therefore has explicitly requested that copies be made when passed. Similarly if a "val" keyword was added, the programmer has explicitly requested a copy be made.

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 


C# is a high level language and it offers both struct types and the ref keyword allowing the programmer to control parameter passing.

Thanks,
--
John McCutchan <jo...@johnmccutchan.com>

--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 

--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 



--
Cheers, Gilad

Don Olmstead

unread,
Aug 10, 2012, 3:59:54 PM8/10/12
to mi...@dartlang.org
The language isn't even M1 yet so now would be the time to do any huge conceptual shifts. If there is a way to get an actual optimization out of it, hence my question above, I would put this as worth any additional conceptual load.

As I stated I can see Dart having a huge audience from C/C++/C# devs. Personally I tried really hard to get into JavaScript but I just couldn't do it, so when Dart came around I tried it and was hooked. I see a lot of devs in similar situations where they know they need to target the web but JS is just too miserable to work with so they don't want to, and Dart is something they're very interested in using.

This is really an untapped market that Dart can fill. So when you look at language features I'd throw in C# as well for your comparisons. I know you worked on Java so that's gotta be close to your heart, but having experienced both languages there are quite a few instances where C# surpasses Java and the struct/class designation is an interesting one. Its a path for optimization that developers can leverage, and if it helps Dart perform better its worth taking the plunge.

It also had enums from day one. Just saying ;)

dominic

unread,
Aug 10, 2012, 5:12:50 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 11:40 AM, Gilad Bracha <gbr...@google.com> wrote:



On Fri, Aug 10, 2012 at 9:53 AM, dominic <domi...@google.com> wrote:


C/C++, and C# especially, are no longer constrained to the systems programming world.

Wrt C# I agree - but this feature comes from its C++ heritage. 

True, though there's no way in C++ to specify pass mode at the type level.
 
 
XNA and .NET have made C# wildly popular in the game dev arena and I know, from discussions with developers at the New Game Conf and Game Developers Conference, that they're trying to break into web development but are repeatedly surprised by these features of JavaScript. If we can find a way to add something to the language to help them without changing the default behaviour that developers coming from JS web development expect, then I think it will only benefit the language.

Adding a feature always comes with a cost.  The fact that some objects are passed by reference and some by value is something *everyone* using the language will need to know - they will encounter your code, for example, and need to understand it (or, more likely, be totally surprised).  

This already happens though, doesn't it? Am I wrong in thinking that primitive types like num, int, and double are already pass by value?
 


It's very interesting that you see the copying as hidden, whereas I see the reference passing as hidden.

Yes. Your mental model is different - but I'd much rather the C people learn the pass-by-reference idea than burden the Javascript, Java and Ruby developers with the mechanics of the C world.

Learning the idea isn't the problem. Being frustrated by it and having hard-to-discover bugs caused by it is. I'm sure Javascript and Java developers have made the same mistake and it's something that those developers have just learned to remember to think about. We have an opportunity to not have the issue in the first place.
 
 
I do agree with your point - passing by value actually means passing a copy. However, I prefer (due to my background) to have control over that copying.
 

The main pros of structs etc. are performance/optimization, but they come at a cost. Adding parameter passing modes adds complexity to the object model and cognitive load to the user.  Generally, this something that high level languages shy away from. 

My argument is that adding the optional parameter passing mode reduces cognitive load for some users.

And, as I note above, it adds load for others. We believe there are more of them than there are of you. Otherwise, Dart might be totally different.

I can't argue with that as I don't have the statistics or any way to prognosticate who the user-base will be. All I can do is represent a not-insignificant group of developers who want to use Dart instead of Javascript because it is better than Javascript.
 
 
In my case, I have to remember to add an explicit copy when I want to pass by value. If, instead, I could do this at the API or type level then that load is reduced.
 

Supporting these features in that form is not particularly important in application programming, but is unattractive to Javascript or Java programmers, who are our main audiences.  

I'll add that value types as I described in my previous message can really be passed without risk of mutation, whereas structs contain mutable references which could lead to mutations in any case.

That's true, and complicates the notion of what it means to copy a complex user-defined value type. I'm a little unclear on what a deeply immutable object would be like to use. For example, if I had:

immutable class vec2 {
  num x, y;
}

as an example your deeply immutable type, would I be able to pass this an instance to a method, have that method alter the values x and y, but have the original instance left unchanged? Or does deeply immutable mean that methods wouldn't be able to change the values of x and y?

The latter.

I'd like to see how this would work in practice with regards to something like a math library where some calls might take three parameters: two that should be immutable and one that should be mutable (an out parameter). It's unclear to me if the immutability is at the type level how this can work. Even if it's at the instance level, it makes it much more complicated to call a series of math methods some of which might mutate the instance, and some of which must not.

Make this explicit in the API and everything is much clearer, I think.

Given there's such a tight link between how an object is passed and it's (im)mutability, perhaps it's worth couching this in terms of mutability. Instead of pass-by-value and pass-by-reference, what we really want is deep immutability at the call level. Eg,

num dot(vec2 a, vec2 b) => a.x * b.x + a.y * b.y;
num dot(const vec2 a, const vec2 b) => a.x * b.x + a.y * b.y;

It doesn't matter really if these vec2 objects are passed by value or reference, it really matters that the method doesn't mutate them and this is clear in the API. In this example, I'm using const to signify deep immutability, ie, that if vec2 contained refs they too would be deeply immutable. I understand const has an existing meaning in Dart but I don't have a better keyword to suggest.

This should also allow tools to enforce correctness, and opens optimization opportunities in both the VM and JS compiler as assumptions can be made in the generated code.

Josh Gargus

unread,
Aug 10, 2012, 5:31:31 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 2:12 PM, dominic <domi...@google.com> wrote:
>
>
> On Fri, Aug 10, 2012 at 11:40 AM, Gilad Bracha <gbr...@google.com> wrote:
>>
>>
>> Adding a feature always comes with a cost. The fact that some objects are
>> passed by reference and some by value is something *everyone* using the
>> language will need to know - they will encounter your code, for example, and
>> need to understand it (or, more likely, be totally surprised).
>
>
> This already happens though, doesn't it? Am I wrong in thinking that
> primitive types like num, int, and double are already pass by value?
>

I don't know how the Dart implementation actually works (and it might
differ between the VM and dart2js), but it doesn't matter: since those
types are immutable, it is not possible to distinguish from Dart code
whether they are passed by value or reference.

Cheers,
Josh

Matthew Butler

unread,
Aug 10, 2012, 7:40:08 PM8/10/12
to mi...@dartlang.org
...
Learning the idea isn't the problem. Being frustrated by it and having hard-to-discover bugs caused by it is. I'm sure Javascript and Java developers have made the same mistake and it's something that those developers have just learned to remember to think about. We have an opportunity to not have the issue in the first place.
...

This point in particular I wanted to respond to. No matter what path is taken, 'being frustrated' by behaviour is assured. Lets say we do add a 'val' parameter modifier to force pass by value instead of pass by reference as default. Then you will be frustrated by forgetting to use the 'val' parameter, just as you are by forgetting to use .copy(); We're no further ahead.

Lets say then because a small sub-set of users keeps forgetting 'val' and finds it inconvenient to learn or be frustrated by not remembering it, we change the entire language to be pass by value as a default. Now the larger target audience from Java and Javascript (and other languages such as Ruby, etc) are frustrated that the behaviour isn't what they expect or are accustomed to. 

So changing the Dart language to fit a small subset of C/C++ game devs who want to use dart to enter the web-programming is going to frustrate those already using Java (GWT), Ruby, JavaScript.... Particularly when C/C++ devs are familiar with pointers and pass-by-reference in the first place, and just need to adjust to always pass-by-reference instead of just when passing a pointer (or explicit reference).

As Gilad mentioned, the target audience for Dart is existing web developers. In particular those familiar with client side scripting with JavaScript, Coffee Script, and Java (as applets or more over GWT). While I am more than excited to have more game devs coming to this platform I still don't see their numbers overriding those of the target audience coming to dart.

Just my $0.02CDN
Matt 

Don Olmstead

unread,
Aug 10, 2012, 9:10:15 PM8/10/12
to mi...@dartlang.org
Hey Matthew,

I'm going to assume you haven't used C#, so let me explain a bit on differences between structs and classes in it. So a struct is allocated on the stack, while a class is allocated to the heap. When passed to a function/method a struct is passed by reference by default, this behavior can be modified if requested, and a class is passed by reference.

So a struct allows a potential speedup for some situations. Since my background is gamedev, and because 3D either through visualizations or games is whats really going to task the DartVM in the browser, a 3D vector would be declared as a struct. So if we look at this excellent presentation from Lilli Thompson, http://console-to-chrome.appspot.com/#37, we see this bit of code.

function add(vecA, vecB) {
    return new Vector(
        vecA.x + vecB.x,
        vecA.y + vecB.y,
        vecA.z + vecB.z,
    );
}

Which is obviously horrible in JS because its going to create an object in the heap. If you do this enough you'll pay for it later. So instead in JS you do this.

function addTo(vecA, vecB) {
    vecA.x = vecA.x + vecB.x;
    vecA.y = vecA.y + vecB.y;
    vecA.z = vecA.z + vecB.z;
}

Which is ugly. And its even uglier if you have a longer expression than just a + b. So the idea is if you have a struct type within Dart you could do

Vector3 x = (a * b) + c - (f * a);

And it wouldn't create a ton of garbage to deal with on the heap. Everything would be allocated to the stack and all the temporaries would be destroyed along with it. Now I don't know enough about the VM to know if something like this is possible currently but I'm curious. Its really cool that the designers hang out here for those of us interested in whats going on under the hood, so its great to be able to throw out ideas and see what they think.

Honestly there are a ton of potential optimizations that can be done to make 3D on the web a better experience. This is just one of them. While they're probably not as important for someone just making a web app, they are really important for showcasing what is now possible in a browser. Games have always been a great driving force in technology as a game is way more demanding on the hardware than most apps.

Dart is in a unique position to ditch a lot of the crap in JS to make the web perform better, the SIMD extensions John McCutchan created for float arrays are a great start, and structs could be another performance win.

--

Justin Fagnani

unread,
Aug 10, 2012, 9:37:40 PM8/10/12
to mi...@dartlang.org
On Fri, Aug 10, 2012 at 6:10 PM, Don Olmstead <don.j.o...@gmail.com> wrote:
Hey Matthew,

I'm going to assume you haven't used C#, so let me explain a bit on differences between structs and classes in it. So a struct is allocated on the stack, while a class is allocated to the heap. When passed to a function/method a struct is passed by reference by default, this behavior can be modified if requested, and a class is passed by reference.

So a struct allows a potential speedup for some situations. Since my background is gamedev, and because 3D either through visualizations or games is whats really going to task the DartVM in the browser, a 3D vector would be declared as a struct. So if we look at this excellent presentation from Lilli Thompson, http://console-to-chrome.appspot.com/#37, we see this bit of code.

function add(vecA, vecB) {
    return new Vector(
        vecA.x + vecB.x,
        vecA.y + vecB.y,
        vecA.z + vecB.z,
    );
}

Which is obviously horrible in JS because its going to create an object in the heap. If you do this enough you'll pay for it later. So instead in JS you do this.

function addTo(vecA, vecB) {
    vecA.x = vecA.x + vecB.x;
    vecA.y = vecA.y + vecB.y;
    vecA.z = vecA.z + vecB.z;
}

Which is ugly. And its even uglier if you have a longer expression than just a + b. So the idea is if you have a struct type within Dart you could do

Vector3 x = (a * b) + c - (f * a);

And it wouldn't create a ton of garbage to deal with on the heap.

I'm not VM guy either, so I hope those who are excuse me if I'm totally off base, but I hope this is the kind of thing the VM can optimize given the extra information it has with Dart.

Consider a "value type" that's completely initialized in the initializer list and has an empty constructor:

class Vector3 {
  final double x, y, z;
  Vector3(this.x, this.y, this.z);
  operator +(Vector3 b) => new Vector3(x + b.x, y + b.y, z + b.z);
}

and a snippet like:

Vector3 foo() {
  Vector3 a, b;
  ...
  a = a + b;
  return a;
}

References to a and b never leak from foo(), and the original object store in a is never referenced after a is reassigned so the original a can be reused. The + operator and initializers can be inlined to give:

Vector3 foo() {
  Vector3 a, b;
  ...
  a.x = a.x + b.x;
  a.y = a.y + b.y;
  a.z = a.z + b.z;
  return a;
}

This might be possible in dart2js and the VM. There may be some, or many, things preventing this type of optimization, but it could be possible and it'd be interesting to see if Dart can eek out good performance without having to introduce new language concepts or have developers worry about heaps and stacks, or follow patterns like addTo().

-Justin

Ladislav Thon

unread,
Aug 12, 2012, 1:20:55 PM8/12/12
to mi...@dartlang.org
Few thoughts about this:

1. It's important. It would be a huge change. A lot of JavaScript and Java people could be confused.

2. Let's not forget that one of Dart major goals is compilation to efficient JavaScript.

3. Sometimes, value types would be really great. But as an application programmer, I almost never miss them. (I don't do games, though.)

4. On the other hand, I sorely miss the distinction between passing parameters by value and by reference. Here's the thing: in Dart, there are no value types, everything is a reference (well, we can say that the Smi class in Dart VM is a value type, but that's an implementation detail and it really doesn't matter for deeply immutable types). Also, parameters are always passed by value -- where the value is the value of the reference (i.e., the pointer). Wikipedia explains it rather nicely in http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value (apparently, it's also called passing by sharing). In my opinion, modern languages should either support returning multiple values, or true passing by reference. Maybe both. Dart does neither.

5. I don't like the C# way using the "ref" and "out" keywords. I like how Ada did it: for each parameter, I could say that it's "in", "out" or "in out". If it results in pass by reference or whatever is an implementation detail. (Semantics is the same as in C#, though: out = out, in out = ref.)

LT

Christopher Wright

unread,
Aug 13, 2012, 10:09:36 AM8/13/12
to mi...@dartlang.org
You can stack-allocate these values if they are fully constructed within the function (by a non-factory constructor) and if the value never escapes the current scope. That gets you most of the efficiency, though you might end up with one or two extra copies depending on how efficiently the compiler reuses stack space.

Escape analysis takes some additional effort, of course.

dominic

unread,
Aug 13, 2012, 11:28:45 AM8/13/12
to mi...@dartlang.org
On Sun, Aug 12, 2012 at 10:20 AM, Ladislav Thon <lad...@gmail.com> wrote:
Few thoughts about this:

1. It's important. It would be a huge change. A lot of JavaScript and Java people could be confused.

If they never use struct or val/ref paramater passing modes, they have no reason to be confused. Just as with types in Dart it's completely optional.
 

2. Let's not forget that one of Dart major goals is compilation to efficient JavaScript.

Right - and this gives even more information to the compiler in terms of how objects are being used.
 

3. Sometimes, value types would be really great. But as an application programmer, I almost never miss them. (I don't do games, though.) 

4. On the other hand, I sorely miss the distinction between passing parameters by value and by reference. Here's the thing: in Dart, there are no value types, everything is a reference (well, we can say that the Smi class in Dart VM is a value type, but that's an implementation detail and it really doesn't matter for deeply immutable types). Also, parameters are always passed by value -- where the value is the value of the reference (i.e., the pointer). Wikipedia explains it rather nicely in http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value (apparently, it's also called passing by sharing). In my opinion, modern languages should either support returning multiple values, or true passing by reference. Maybe both. Dart does neither.

5. I don't like the C# way using the "ref" and "out" keywords. I like how Ada did it: for each parameter, I could say that it's "in", "out" or "in out". If it results in pass by reference or whatever is an implementation detail. (Semantics is the same as in C#, though: out = out, in out = ref.)

LT

--

Christoph Husse

unread,
Aug 29, 2012, 6:35:16 AM8/29/12
to mi...@dartlang.org
This is a very interesting discussion. I have experienced quite the same. I am a C++/C# developer with a lot of experience also in Java. But when it comes to JavaScript I can only shake my head, since it is beyond me how anyone could write any decent program in this ... well how would one call it...

I really loved dart from the moment we meet ^^. And after two days of usage I have to say now that it really is quite similar to C#, more than to Java. And I am using it for game programming as well.

The idea of having value types is a little bit too far fetched. It causes a lot of confusion for the uninitiated ^^... Even in C#. Instead the idea above was quite good. 

Just add a "const" modifier for function arguments. It would basically solve the problem, by either forcing a deep copy, which I wouldn't prefer for performance reasons, or by inheriting the C++ way. Just disallow any methods than change the object. As a caller I can now be sure that the object doesn't change, and as a library writer I get assurance from the compiler that I adhere to this protocol. The "const" modifier is one of the wealth of things why C++ is a superior language, even though it has a lot of downsides too ^^. 

And in the end, when you don't use "const", you don't need to care. Passing something as a const parameter is no different from passing something the usual way from a caller's perspective. So only library writers need to care and they are usually quite more advanced than those who actually only consume libraries. You can really trust them with the const keyword...

Christoph Husse

unread,
Aug 29, 2012, 8:43:30 AM8/29/12
to mi...@dartlang.org
To clarify... The pro of a "const" modifier is that it is a compiler feature, not a runtime feature. Structs in contrast come with a significant overhead in VMs, since they make efficient GCs considerably more complex. Additionally, languages other than C++ are notoriously unsuited for struct/class differentiation. In C++ we have "." and "->" operators to designate what we do. In C# we only have "." and you can't see whether you are dealing with structs or ref types. This is the root of all evil that comes with structs. Either you need all the infrastructure C++ provides you, or you are better of with compiler aiding features, like "const" or maybe even something like "inline classes", where you can tell the VM to use the current class as allocator for the field and don't do memory allocation, thus GC, twice when lifetime is equivalent anyway (a common usage of structs). This way you get the performance benefit of value types without having them. It is all a compiler/VM infrastructure that checks if you use classes correctly so that it can optimize all overhead away...

Tom Yeh

unread,
Aug 29, 2012, 11:56:24 PM8/29/12
to mi...@dartlang.org
Don't do it. Simplicity and elegance are top priority. Easy to migrate from another languages shall never be one of the goals. Languages are something that will last for decades. A consistent philosophy is more important than anything else.

I wrote tons of code in C/C++ for 10 year, in Java for another 10 year. Pass-by-reference is never a limitation. It is only about how to get a job done.

Don Olmstead

unread,
Aug 30, 2012, 12:29:11 AM8/30/12
to mi...@dartlang.org
If you read Dart A Modern Web Language http://www.dartlang.org/slides/2012/06/io12/Dart-A-Modern-Web-Language.pdf you'll see that raw execution speed is a huge priority. By allowing value types to be defined by the programmer execution speed can be increased by avoiding heap allocations. Of course this is going to increase the cognitive load for the programmer, but tooling can help with that.

As an example there's guidelines for choosing struct or class in C#


By making these guidelines rules that produce errors or warnings by the tools then those of us who do require raw execution speed can tune our applications properly.


--

Seth Ladd

unread,
Aug 30, 2012, 6:34:15 AM8/30/12
to mi...@dartlang.org, Kathy Walrath
Hi Don,

We intend to provide some guidelines for when and how to use const. I know it's not value types, but I agree with you that by providing more justifications and guidance for what Dart does provide, like const, we can help our developers do the right thing.

Marcello Dias

unread,
Jan 17, 2014, 10:27:26 AM1/17/14
to mi...@dartlang.org

I think nobody cares of posting in very old threads here,since the language is envolving as were speaking.
I myself are used in Delphi to say when I want pass by value or when I want to pass by  reference.
I was very concerned about this change and even have complained out loud in one user forum.
 Although I´ll have to write more(explicit creation of objects for the parameters,in order to change them ) I really think that it is not
a source for introducing bugs,it can even increase readibility in some specific cases.
In fact I realize that 99% of times when I pass it by value ,I dont change it ,just use its value to change another thing.
Very different to game programming.I suppose.
Reply all
Reply to author
Forward
0 new messages