setStrokeColor: Issue with my code, or with the libs?

228 views
Skip to first unread message

Dominic Hamon

unread,
Jan 25, 2012, 7:07:33 PM1/25/12
to General Dart Discussion
Here is code that works:

  /** Sets the rendering context stroke color based on the given color3. */
  void set _color(Color3 color) {
    int red = (color.x * 255).round().toInt();
    int green = (color.y * 255).round().toInt();
    int blue = (color.z * 255).round().toInt();

    final colorString = new StringBuffer("#");
    String redString = red.toRadixString(16);
    String greenString = green.toRadixString(16);
    String blueString = blue.toRadixString(16);

    colorString.add(redString);
    colorString.add(greenString);
    colorString.add(blueString);

    ctx.setStrokeColor(colorString.toString());
    ctx.setFillColor(colorString.toString());
  }

However, it is slow (6% of a frame). I would like to replace it with:

  /** Sets the rendering context stroke color based on the given color3. */
  void set _color(Color3 color) {
    int red = (color.x * 255).round().toInt();
    int green = (color.y * 255).round().toInt();
    int blue = (color.z * 255).round().toInt();

    ctx.setStrokeColor(red, green, blue);
    ctx.setFillColor(red, green, blue);
  }


Which compiles cleanly with dartc and frog with as many type safety warnings and errors enabled as I could find. When I run the frog version, I get an 'Unknown Type Exception' on the call to setStrokeColor. Am I doing something wrong, or is there an issue with the libs?

I have tried setting an alpha value, declaring red, green, and blue as 'var' and 'num', but nothing helps and I'm not sure where the type error is. Any help would be appreciated.

Dominic Hamon

unread,
Jan 25, 2012, 7:16:00 PM1/25/12
to General Dart Discussion
Exact error message: Uncaught TypeError: Type error

Bob Nystrom

unread,
Jan 25, 2012, 8:13:31 PM1/25/12
to Dominic Hamon, General Dart Discussion
That looks like a lib bug to me. I see this bug was closed but maybe it shouldn't be? Does it work if you just pass in some literals like ctx.setStrokeColor(1, 2, 3)?

- bob

Jim Hugunin

unread,
Jan 25, 2012, 9:04:59 PM1/25/12
to Bob Nystrom, Dominic Hamon, General Dart Discussion
This is a great question!  The answer is that this is an issue with your code, with our libraries and with the web standardization process in general.  First of all, here's how you can fix your code so that it will run in chrome or safari:
  void set _color(Color3 color) {
    ctx.setStrokeColor(color.x, color.y, color.z, 1);
    ctx.setFillColor(color.x, color.y, color.z, 1);
  }

You'll notice two key differences from your original code.  First, these methods expect floats rather than ints.  Second, they need to be called with 4 arguments including a non-optional alpha value.

If all you care about is getting your code running, you can stop reading now...

There are still some pretty nasty issues here:
  1. Your code will only work in webkit-based browsers.  For example, if you run this in firefox you'll get an error that setStrokeColor is not a method.  I'm not familiar with the history of this issue, but according to the latest version of the canvas draft spec, the mozilla folks are right - http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#colors-and-styles.  This issue of differing versions of the web standards is a big deal for web developers.  Our goals are to figure out how to shield you from as much of this as possible in dart; however, we are nowhere near achieving that goal yet.  The fact that canvas wouldn't have existed if some engineers hadn't just built and shipped the thing for the first time without paying any attention to the standards bodies only complicates this question further.
  2. Even in webkit, this is a very hard method for us to define correctly in dart.  If you go to the docs on MDN for CanvasRenderingContext2D, you'll see that this method has four overloads (two of which have one optional parameter).  It isn't clear to us how best to represent such a method in dart - which has no method overloading.  At the moment, the dart:dom library merges all four possible parameter signatures into one - using var and optional as needed to make things work.  The problem is that this can easily lead to situations where neither dart's static nor runtime type checks will catch an error like the one you just made.  This is very unfriendly to our developers.  We've talked about a lot of other options - for example, using setStrokeColor0, setStrokeColor1, setStrokeColor2, and setStrokeColor3 to represent the four different signatures; however, this seems unfriendly to developers in a different way.  We hope to come up with something really clever to resolve this dilemma in the dart:html library - but this particular problem hasn't been addressed yet and any good suggestions about how to proceed would be welcome.
I'm sorry for such a confusing runtime error, but I hope this clears things up and will let you be productive again - and maybe help us figure out the right solution going forwards.

Thanks - Jim

Justin Fagnani

unread,
Jan 25, 2012, 9:33:42 PM1/25/12
to Jim Hugunin, Bob Nystrom, Dominic Hamon, General Dart Discussion
On Wed, Jan 25, 2012 at 6:04 PM, Jim Hugunin <jim...@google.com> wrote:
This is a great question!  The answer is that this is an issue with your code, with our libraries and with the web standardization process in general.  First of all, here's how you can fix your code so that it will run in chrome or safari:
  void set _color(Color3 color) {
    ctx.setStrokeColor(color.x, color.y, color.z, 1);
    ctx.setFillColor(color.x, color.y, color.z, 1);
  }

You'll notice two key differences from your original code.  First, these methods expect floats rather than ints.  Second, they need to be called with 4 arguments including a non-optional alpha value.

If all you care about is getting your code running, you can stop reading now...

There are still some pretty nasty issues here:
  1. Your code will only work in webkit-based browsers.  For example, if you run this in firefox you'll get an error that setStrokeColor is not a method.  I'm not familiar with the history of this issue, but according to the latest version of the canvas draft spec, the mozilla folks are right - http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#colors-and-styles.  This issue of differing versions of the web standards is a big deal for web developers.  Our goals are to figure out how to shield you from as much of this as possible in dart; however, we are nowhere near achieving that goal yet.  The fact that canvas wouldn't have existed if some engineers hadn't just built and shipped the thing for the first time without paying any attention to the standards bodies only complicates this question further.
  2. Even in webkit, this is a very hard method for us to define correctly in dart.  If you go to the docs on MDN for CanvasRenderingContext2D, you'll see that this method has four overloads (two of which have one optional parameter).  It isn't clear to us how best to represent such a method in dart - which has no method overloading.  At the moment, the dart:dom library merges all four possible parameter signatures into one - using var and optional as needed to make things work.  The problem is that this can easily lead to situations where neither dart's static nor runtime type checks will catch an error like the one you just made.  This is very unfriendly to our developers.  We've talked about a lot of other options - for example, using setStrokeColor0, setStrokeColor1, setStrokeColor2, and setStrokeColor3 to represent the four different signatures; however, this seems unfriendly to developers in a different way.  We hope to come up with something really clever to resolve this dilemma in the dart:html library - but this particular problem hasn't been addressed yet and any good suggestions about how to proceed would be welcome.

I've been bitten by this one a few times already, and I would suggest that you don't try to emulate the DOM at all - in particular it seems bad to put the burden on the Canvas API to know of all the ways to represent a color. I'd suggest a single argument of type Color, which can have all sorts of named constructors to support hex, names, RGB, RGBA, etc. If you really wanted, you could "overload" the method to accept a string or Color and add rgb() and rgba() functions that return Color so that it looks like CSS.

I know that dart:dom is supposed to be as close to the normal DOM as possible, so maybe it still has untyped arguments and runtime errors. Yuck. At least dart:html would be sane.

Cheers,
  Justin

Don

unread,
Jan 25, 2012, 9:51:31 PM1/25/12
to General Dart Discussion
Perhaps a feature request I submitted a little while back could help
with the overloading issue: http://code.google.com/p/dart/issues/detail?id=956.

This is what the api might look like with interleaved params:

ctx.setStrokeColor(colorString, a);
might be:
ctx.setStrokeColorNamed(colorString)withAlpha(a);

ctx.setStrokeColor(grayLevel, a);
might be:
ctx.setStrokeColorWithGrayLevel(grayLevel)alpha(a);

ctx.setStrokeColor(r,g,b,a);
might be:
ctx.setStrokeColorWithRed(r)green(g)blue(b)alpha(a);

ctx.setStrokeColor(c, m, y, k, a);
might be:
ctx.setStrokeColorWithCyan(cyan)magenta(m)yellow(y)darkness(k)alpha(a);

Anyway, since under this proposal each method would have a unique
name, overloading wouldn't be an issue. More readable API to boot in
my opinion.

On Jan 25, 9:04 pm, Jim Hugunin <jim...@google.com> wrote:
> This is a great question!  The answer is that this is an issue with your
> code, with our libraries and with the web standardization process in
> general.  First of all, here's how you can fix your code so that it will
> run in chrome or safari:
>   void set _color(Color3 color) {
>     ctx.setStrokeColor(color.x, color.y, color.z, 1);
>     ctx.setFillColor(color.x, color.y, color.z, 1);
>   }
>
> You'll notice two key differences from your original code.  First, these
> methods expect floats rather than ints.  Second, they need to be called
> with 4 arguments including a non-optional alpha value.
>
> If all you care about is getting your code running, you can stop reading
> now...
>
> There are still some pretty nasty issues here:
>
>    1. Your code will only work in webkit-based browsers.  For example, if
>    you run this in firefox you'll get an error that setStrokeColor is not a
>    method.  I'm not familiar with the history of this issue, but according to
>    the latest version of the canvas draft spec, the mozilla folks are right -
>    http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canva....
>     This issue of differing versions of the web standards is a big deal for
>    web developers.  Our goals are to figure out how to shield you from as much
>    of this as possible in dart; however, we are nowhere near achieving that
>    goal yet.  The fact that canvas wouldn't have existed if some engineers
>    hadn't just built and shipped the thing for the first time without paying
>    any attention to the standards bodies only complicates this question
>    further.
>    2. Even in webkit, this is a very hard method for us to define correctly
>    in dart.  If you go to the docs on MDN for
> CanvasRenderingContext2D<https://developer.mozilla.org/en/DOM/CanvasRenderingContext2D>,
>    you'll see that this method has four overloads (two of which have one
>    optional parameter).  It isn't clear to us how best to represent such a
>    method in dart - which has no method overloading.  At the moment, the
>    dart:dom library merges all four possible parameter signatures into one -
>    using var and optional as needed to make things work.  The problem is that
>    this can easily lead to situations where neither dart's static nor runtime
>    type checks will catch an error like the one you just made.  This is very
>    unfriendly to our developers.  We've talked about a lot of other options -
>    for example, using setStrokeColor0, setStrokeColor1, setStrokeColor2, and
>    setStrokeColor3 to represent the four different signatures; however, this
>    seems unfriendly to developers in a different way.  We hope to come up with
>    something really clever to resolve this dilemma in the dart:html library -
>    but this particular problem hasn't been addressed yet and any good
>    suggestions about how to proceed would be welcome.
>
> I'm sorry for such a confusing runtime error, but I hope this clears things
> up and will let you be productive again - and maybe help us figure out the
> right solution going forwards.
>
> Thanks - Jim
>
>
>
>
>
>
>
> On Wed, Jan 25, 2012 at 5:13 PM, Bob Nystrom <rnyst...@google.com> wrote:
>
> > On Wed, Jan 25, 2012 at 4:16 PM, Dominic Hamon <domin...@google.com>wrote:
> > That looks like a lib bug to me. I see this bug<http://code.google.com/p/dart/issues/detail?id=150>was closed but maybe it shouldn't be? Does it work if you just pass in some

Bob Nystrom

unread,
Jan 25, 2012, 9:54:14 PM1/25/12
to Justin Fagnani, Jim Hugunin, Dominic Hamon, General Dart Discussion
On Wed, Jan 25, 2012 at 6:33 PM, Justin Fagnani <justin...@google.com> wrote:

I've been bitten by this one a few times already, and I would suggest that you don't try to emulate the DOM at all - in particular it seems bad to put the burden on the Canvas API to know of all the ways to represent a color. I'd suggest a single argument of type Color, which can have all sorts of named constructors to support hex, names, RGB, RGBA, etc.

I like this approach in general. I would be a bit concerned about the performance hit of having to constantly box/unbox Color objects in this specific case since the Canvas API is one of the few corners of the web where API performance can be a big deal.

One option would be:

set strokeColor(Color color) { ... }
set strokeColorText(String cssHex) { ... }
void setStrokeRgb(num r, num g, num b) { ... }

I don't like that the third one isn't a setter but... <shrug>.

- bob

Bob Nystrom

unread,
Jan 25, 2012, 9:58:23 PM1/25/12
to Don, General Dart Discussion
On Wed, Jan 25, 2012 at 6:51 PM, Don <dga...@gmail.com> wrote:
Perhaps a feature request I submitted a little while back could help
with the overloading issue: http://code.google.com/p/dart/issues/detail?id=956.

This is what the api might look like with interleaved params:

ctx.setStrokeColor(colorString,  a);
might be:
ctx.setStrokeColorNamed(colorString)withAlpha(a);

ctx.setStrokeColor(grayLevel, a);
might be:
ctx.setStrokeColorWithGrayLevel(grayLevel)alpha(a);

ctx.setStrokeColor(r,g,b,a);
might be:
ctx.setStrokeColorWithRed(r)green(g)blue(b)alpha(a);

ctx.setStrokeColor(c, m, y, k, a);
might be:
ctx.setStrokeColorWithCyan(cyan)magenta(m)yellow(y)darkness(k)alpha(a);

Anyway, since under this proposal each method would have a unique
name, overloading wouldn't be an issue. More readable API to boot in
my opinion.

Personally, I wish keyword arguments worked the way you suggest in Dart (i.e. like keyword selectors in Smalltalk). That would let you do:

ctx.setStrokeColor(string: colorString, alpha: a);
ctx.setStrokeColor(gray: grayLevel, alpha: a);
ctx.setStrokeColor(r: r, g: g, b: b, a: a);

Like your proposal, each of those would be distinct methods with no overloading involved. I just think the syntax here is a bit less scary. I know others on the team aren't crazy about this, though. In cases where you do want a single method with a bunch of optional params, this leads to a combinatorial explosion of methods for each subset of options.

Still, a guy can dream...

- bob

Justin Fagnani

unread,
Jan 25, 2012, 10:01:59 PM1/25/12
to Bob Nystrom, Jim Hugunin, Dominic Hamon, General Dart Discussion
Yeah, I'd probably be willing to eat that - I would hope very small - hit to be able to have:

context.strokeColor = Color.WHITE;
context.strokeColor = "#bcf";
context.strokeColor = rgba(0, 0, 0, .2);
context.setShadow(5, 5, 5, Color.BLACK);

all work.



- bob


Don

unread,
Jan 26, 2012, 1:36:44 AM1/26/12
to General Dart Discussion
Like I mentioned on the feature request, I think the only difference
between what you and I are after is syntax, which doesn't bother me
much. I do worry about what's more surprising though - to find out
that syntax that looks like conventional named args actually makes
different method signatures, or a more foreign, but (in my opinion)
more explicit syntax that shows that you are creating unique methods
sigs.

I'd love either implementation, but that's sad to hear that other
people on the team aren't happy with it. This doesn't seem like a huge
leap to me, and I feel like the iOS migrants that you would be trying
to pull back to an open platform with Dart are already familiar (and
pretty happy) with this.
> *do* want a single method with a bunch of optional params, this leads to a

Peter Ahé

unread,
Jan 26, 2012, 3:13:54 AM1/26/12
to Bob Nystrom, Don, General Dart Discussion

Thinking out loud here...

I think you have three different set of arguments. What I mean is that
you'd probably want to overload this way:

setStrokeColor(String string, [num alpha = 1]) { ... }
setStrokeColor(num gray, [num alpha = 1]) { ... }
setStrokeColor(num r, num g, num b, [num a = 1]) { ... }

I don't even want to consider overloading based on types. But
overloading based on names of arguments is fine (it not really
overloading, the name of the method is just a little weirder). So
let's remove the types:

setStrokeColor(string, [alpha = 1]) { ... }
setStrokeColor(gray, [alpha = 1]) { ... }
setStrokeColor(r, g, b, [a = 1]) { ... }

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

You'd have to write:

setStrokeColor(r: 1, g: 2, b: 3);

So perhaps another overload is needed:

/** This is for compatibility with JavaScript. If [arg3 !== null ||
arg4 !== null], forward to [setStrokeColor:r:g:b:], otherwise, if
[arg1 is String], forward to [setStrokeColor:string:], otherwise
forward to [setStrokeColor:gray:]. */
setStrokeColor(arg1, [arg2, arg3, arg4]) { ... }

Cheers,
Peter

Vadim Tsushko

unread,
Jan 26, 2012, 7:13:16 AM1/26/12
to General Dart Discussion
+100
Required named arguments as part of function signature looks pretty
good for me.

On 26 янв, 14:13, Peter Ahé <a...@google.com> wrote:

Ladislav Thon

unread,
Jan 26, 2012, 7:30:19 AM1/26/12
to General Dart Discussion
+100
Required named arguments as part of function signature looks pretty
good for me.

Agreed! They would be great for designing APIs and nicely complement optional named arguments. Oh, and if they solve some nasty problem in dart:html, that's a nice side effect for me :-)

LT

Dominic Hamon

unread,
Jan 26, 2012, 10:09:19 AM1/26/12
to Jim Hugunin, Bob Nystrom, General Dart Discussion
On Wed, Jan 25, 2012 at 6:04 PM, Jim Hugunin <jim...@google.com> wrote:
This is a great question!  The answer is that this is an issue with your code, with our libraries and with the web standardization process in general.  First of all, here's how you can fix your code so that it will run in chrome or safari:
  void set _color(Color3 color) {
    ctx.setStrokeColor(color.x, color.y, color.z, 1);
    ctx.setFillColor(color.x, color.y, color.z, 1);
  }

You'll notice two key differences from your original code.  First, these methods expect floats rather than ints.  Second, they need to be called with 4 arguments including a non-optional alpha value.

If all you care about is getting your code running, you can stop reading now...

There are still some pretty nasty issues here:
  1. Your code will only work in webkit-based browsers.  For example, if you run this in firefox you'll get an error that setStrokeColor is not a method.  I'm not familiar with the history of this issue, but according to the latest version of the canvas draft spec, the mozilla folks are right - http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#colors-and-styles.  This issue of differing versions of the web standards is a big deal for web developers.  Our goals are to figure out how to shield you from as much of this as possible in dart; however, we are nowhere near achieving that goal yet.  The fact that canvas wouldn't have existed if some engineers hadn't just built and shipped the thing for the first time without paying any attention to the standards bodies only complicates this question further.
I'm not going to worry about this. Not only do I have every confidence that those working on Dart will figure it out, my opinion is that  as a developer I shouldn't have to worry about this. The API should be the best API for developers, and shouldn't necessarily match the underlying per-browser implementation.

In fact, I'd prefer the notion of a Color that can be initialized using doubles or Strings using named constructors, and then passed around where necessary. Bob mentioned that this add some overhead in a critical code path, but I don't imagine the current conditional-heavy implementation is that much faster. Either way, focus should be on the API first and performance second.

Don

unread,
Jan 26, 2012, 12:36:17 PM1/26/12
to General Dart Discussion
I like this too. I still think that keyword signatures by default are
superior for avoiding aberrations like these, and allow for
readability, which I think is much more important than 'writeability'.
A few extra words typed go a long way to save millions of developer's
the time it takes to understand the api. That said though, I agree
that since it would clash with the regular style, I think these
nonoptional named args as part of method signature work fine.

On Jan 26, 3:13 am, Peter Ahé <a...@google.com> wrote:

Don

unread,
Jan 26, 2012, 12:43:07 PM1/26/12
to General Dart Discussion
I think you really have to step back and consider that the performance
hit could be OK for you in some cases, but not for others. A method
like this gets called a lot, and I don't think the object performance
would be acceptable to impose on people. There's also the possibility
of more mistakes and ultimately even more verbosity when you force
objects to be created a certain way before a method that accepts them
will work the way you expect.


On Jan 26, 10:09 am, Dominic Hamon <domin...@google.com> wrote:
> On Wed, Jan 25, 2012 at 6:04 PM, Jim Hugunin <jim...@google.com> wrote:
> > This is a great question!  The answer is that this is an issue with your
> > code, with our libraries and with the web standardization process in
> > general.  First of all, here's how you can fix your code so that it will
> > run in chrome or safari:
> >   void set _color(Color3 color) {
> >     ctx.setStrokeColor(color.x, color.y, color.z, 1);
> >     ctx.setFillColor(color.x, color.y, color.z, 1);
> >   }
>
> > You'll notice two key differences from your original code.  First, these
> > methods expect floats rather than ints.  Second, they need to be called
> > with 4 arguments including a non-optional alpha value.
>
> > If all you care about is getting your code running, you can stop reading
> > now...
>
> > There are still some pretty nasty issues here:
>
> >    1. Your code will only work in webkit-based browsers.  For example, if
> >    you run this in firefox you'll get an error that setStrokeColor is not a
> >    method.  I'm not familiar with the history of this issue, but according to
> >    the latest version of the canvas draft spec, the mozilla folks are right -
> >    http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canva....
> >     This issue of differing versions of the web standards is a big deal for
> >    web developers.  Our goals are to figure out how to shield you from as much
> >    of this as possible in dart; however, we are nowhere near achieving that
> >    goal yet.  The fact that canvas wouldn't have existed if some engineers
> >    hadn't just built and shipped the thing for the first time without paying
> >    any attention to the standards bodies only complicates this question
> >    further.
>
> > I'm not going to worry about this. Not only do I have every confidence
>
> that those working on Dart will figure it out, my opinion is that  as a
> developer I shouldn't have to worry about this. The API should be the best
> API for developers, and shouldn't necessarily match the underlying
> per-browser implementation.
>
> In fact, I'd prefer the notion of a Color that can be initialized using
> doubles or Strings using named constructors, and then passed around where
> necessary. Bob mentioned that this add some overhead in a critical code
> path, but I don't imagine the current conditional-heavy implementation is
> that much faster. Either way, focus should be on the API first and
> performance second.
>
>
>
>
>
>
>
>
>
> >    1. Even in webkit, this is a very hard method for us to define
> >    correctly in dart.  If you go to the docs on MDN for
> >    CanvasRenderingContext2D<https://developer.mozilla.org/en/DOM/CanvasRenderingContext2D>,
> >    you'll see that this method has four overloads (two of which have one
> >    optional parameter).  It isn't clear to us how best to represent such a
> >    method in dart - which has no method overloading.  At the moment, the
> >    dart:dom library merges all four possible parameter signatures into one -
> >    using var and optional as needed to make things work.  The problem is that
> >    this can easily lead to situations where neither dart's static nor runtime
> >    type checks will catch an error like the one you just made.  This is very
> >    unfriendly to our developers.  We've talked about a lot of other options -
> >    for example, using setStrokeColor0, setStrokeColor1, setStrokeColor2, and
> >    setStrokeColor3 to represent the four different signatures; however, this
> >    seems unfriendly to developers in a different way.  We hope to come up with
> >    something really clever to resolve this dilemma in the dart:html library -
> >    but this particular problem hasn't been addressed yet and any good
> >    suggestions about how to proceed would be welcome.
>
> > I'm sorry for such a confusing runtime error, but I hope this clears
> > things up and will let you be productive again - and maybe help us figure
> > out the right solution going forwards.
>
> > Thanks - Jim
>
> > On Wed, Jan 25, 2012 at 5:13 PM, Bob Nystrom <rnyst...@google.com> wrote:
>
> >> On Wed, Jan 25, 2012 at 4:16 PM, Dominic Hamon <domin...@google.com>wrote:
> >> That looks like a lib bug to me. I see this bug<http://code.google.com/p/dart/issues/detail?id=150>was closed but maybe it shouldn't be? Does it work if you just pass in some

Dominic Hamon

unread,
Jan 26, 2012, 12:51:39 PM1/26/12
to Don, General Dart Discussion
I didn't say to not deal with the performance issue, I said it should be secondary to a clear and simple API. I fail to see how introducing the notion of a Color object will increase verbosity when currently anyone using these libraries has to create their own, and all of those have to conform to a particular API already. I'm suggesting taking what is now a wrapper to the Dart API and merging it into the Dart API.

Of course, if Dart is going to continue to be focused on web programming only and there are no expectations that it will ever spread outside of that realm, then maybe staying close to the existing HTML API makes sense. It's also possible that there's an alternative API to Canvas out there that would allow an increase in performance. If, for example, the implementation handles the Color object as a native object and passes it directly through the pipeline to the GPU without any processing.

Justin Fagnani

unread,
Jan 26, 2012, 12:58:47 PM1/26/12
to Don, General Dart Discussion
On Thu, Jan 26, 2012 at 9:43 AM, Don <dga...@gmail.com> wrote:
I think you really have to step back and consider that the performance
hit could be OK for you in some cases, but not for others. A method
like this gets called a lot, and I don't think the object performance
would be acceptable to impose on people.

Any assertion about performance that results in a worse API should really be backed up by measurements.

In this case, the generated code for setStrokeColor() has enough conditionals that I question whether unboxing a Color object would lead to any performance hit at all, or rather might be an improvement.

I still contend that the Canvas API should not have to know all the ways to represent color. An API that exposes Color internals is fragile - what happens if CYMK is eventually supported, does context suddenly grow a new variation of all the methods that accept colors? It's also an ugly, more complex, and therefore harder to learn API.

If dart:html is analogous to jQuery for DOM, shouldn't it also strive to be more like three.js or Raphael for graphics? three.js has a Color object and uses it extensively in methods, while Raphael only accepts single strings to represent colors.

Cheers,
  Justin

Bob Nystrom

unread,
Jan 26, 2012, 2:47:38 PM1/26/12
to Peter Ahé, Don, General Dart Discussion
On Thu, Jan 26, 2012 at 12:13 AM, Peter Ahé <a...@google.com> wrote:

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

I can't tell you how much I would love this. One nice thing about it is that it might also let us unify it with named constructors and not need to have those a special-case feature of constructors:

new List(from: [1, 2, 3]);
new List(length: 123);

I wonder if this could also lead to better performance? We have cases where we have a named optional parameter and then the body of the method immediately checks that and branches. If that parameter was part of the method name, that branching would go away and the inline cache at the callsite could jump straight to the appropriate code?

- bob

Dominic Hamon

unread,
Jan 26, 2012, 2:52:33 PM1/26/12
to Bob Nystrom, Peter Ahé, Don, General Dart Discussion
On Thu, Jan 26, 2012 at 11:47 AM, Bob Nystrom <rnys...@google.com> wrote:


On Thu, Jan 26, 2012 at 12:13 AM, Peter Ahé <a...@google.com> wrote:

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

I can't tell you how much I would love this. One nice thing about it is that it might also let us unify it with named constructors and not need to have those a special-case feature of constructors:

new List(from: [1, 2, 3]);
new List(length: 123);

I'm not a language guru by any means, but how is this different to overloading, which, it has been stated, Dart will not support?

I really like this construct and if this means I get my overloaded constructors without having to name them, that makes me happy.

Peter Ahé

unread,
Jan 26, 2012, 3:21:38 PM1/26/12
to Dominic Hamon, Bob Nystrom, Don, General Dart Discussion


On Thursday, January 26, 2012, Dominic Hamon wrote:

On Thu, Jan 26, 2012 at 11:47 AM, Bob Nystrom <rnys...@google.com> wrote:


On Thu, Jan 26, 2012 at 12:13 AM, Peter Ahé <a...@google.com> wrote:

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

I can't tell you how much I would love this. One nice thing about it is that it might also let us unify it with named constructors and not need to have those a special-case feature of constructors:

new List(from: [1, 2, 3]);
new List(length: 123);

I'm not a language guru by any means, but how is this different to overloading, which, it has been stated, Dart will not support?

I really like this construct and if this means I get my overloaded constructors without having to name them, that makes me happy.
 

It isn't overloading because required names are part of the method names (although it is pretty subtle).

Similarly, Dart doesn't have operator overloading. It has methods with funky syntax. We just call it operator overloading so people sorta intuitively know what it is. So we'd probably call this overloading too if we were to add it to the language :-)

Cheers,
Peter

Justin Fagnani

unread,
Jan 26, 2012, 3:21:26 PM1/26/12
to Dominic Hamon, Bob Nystrom, Peter Ahé, Don, General Dart Discussion
On Thu, Jan 26, 2012 at 11:52 AM, Dominic Hamon <domi...@google.com> wrote:

On Thu, Jan 26, 2012 at 11:47 AM, Bob Nystrom <rnys...@google.com> wrote:


On Thu, Jan 26, 2012 at 12:13 AM, Peter Ahé <a...@google.com> wrote:

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

I can't tell you how much I would love this. One nice thing about it is that it might also let us unify it with named constructors and not need to have those a special-case feature of constructors:

new List(from: [1, 2, 3]);
new List(length: 123);

I'm not a language guru by any means, but how is this different to overloading, which, it has been stated, Dart will not support?

Dart won't support overloading based on types, since types are not allowed to change how a program executes, but making paramater _names_ part of the method signature means that you get "overloading" without overloading.

Peter is proposing a syntax that lets a developer indicate when a named parameter is required and part of the signature. This would allow you to have two functions with the same name, but different required named parameters.

I like it too Bob, but I still say that the Canvas API shouldn't have to be concerned with the many representations of Color. The issues seem mostly orthogonal to me.

Cheers,
  Justin

Peter Ahé

unread,
Jan 26, 2012, 3:24:26 PM1/26/12
to Dominic Hamon, Bob Nystrom, Don, General Dart Discussion


On Thursday, January 26, 2012, Dominic Hamon wrote:

On Thu, Jan 26, 2012 at 11:47 AM, Bob Nystrom <rnys...@google.com> wrote:


On Thu, Jan 26, 2012 at 12:13 AM, Peter Ahé <a...@google.com> wrote:

I have previously argued that it would be horrible to make all
parameter names part of the API by default. However, I see no problem
when the method author explicitly do something to make parameter names
part of the API. We already have "optionally named arguments", perhaps
we should look at adding "required named arguments" (aka Smalltalk
keyword-sends). For example:

setStrokeColor(string:, [alpha = 1]) { ... }
setStrokeColor(gray:, [alpha = 1]) { ... }
setStrokeColor(r:, g:, b:, [a = 1]) { ... }

In this case, it would be an error to write:

setStrokeColor(1, 2, 3);

I can't tell you how much I would love this. One nice thing about it is that it might also let us unify it with named constructors and not need to have those a special-case feature of constructors:

new List(from: [1, 2, 3]);
new List(length: 123);

I'm not a language guru by any means, but how is this different to overloading, which, it has been stated, Dart will not support?

I really like this construct and if this means I get my overloaded constructors without having to name them, that makes me happy.
 

It isn't overloading because required names are part of the method names (although it is pretty subtle).

Similarly, Dart doesn't have operator overloading. It has methods with funky syntax. We just call it operator overloading so people sorta intuitively know what it is. So we'd probably call this overloading too if we were to add it to the language :-)

Cheers,
Peter
 
Message has been deleted

Don

unread,
Jan 26, 2012, 3:55:21 PM1/26/12
to General Dart Discussion
I actually definitely would support having direct counterparts to the
DOM methods *along* with others that take in Color objects. I'm not
sure how likely it would be that the VM compensates for the
performance issue, but as long as people have a choice between the
different options they can pick what feels more natural and fits
their
performance requirements.

Regardles, I think the named args as part of the method signature (aka
keyword method signatures), while technically orthogonal, would
definitely help the readability of this API regardless of how we
choose to package the parameters.


On Jan 26, 3:21 pm, Justin Fagnani <justinfagn...@google.com> wrote:
> On Thu, Jan 26, 2012 at 11:52 AM, Dominic Hamon <domin...@google.com> wrote:

Bob Nystrom

unread,
Jan 26, 2012, 4:13:00 PM1/26/12
to Peter Ahé, Dominic Hamon, Don, General Dart Discussion
On Thu, Jan 26, 2012 at 12:21 PM, Peter Ahé <a...@google.com> wrote:

It isn't overloading because required names are part of the method names (although it is pretty subtle).

Right. The difference between this and overloading based on the type of the arguments is that here it's static unambiguous at the callsite which method you're selecting. Consider:

foo(bar);

If Dart could overload on type, there's no way of telling statically (i.e. at compile time) which method you're selecting here. You need to know the type of bar at runtime. But with named arguments, the callsites directly include the names directly in the program text itself:

foo(a: bar);
foo(b: bar);

- bob

John Messerly

unread,
Jan 26, 2012, 4:35:33 PM1/26/12
to Ladislav Thon, General Dart Discussion
Yeah I like this idea too. I've used named/optional arguments for cases where I really just wanted the name to appear at the call site--for example, "new ListView(snapToItems: true, paginate: true)" instead of "new ListView(true, true)".

- John

Daniel James

unread,
Jan 26, 2012, 4:42:07 PM1/26/12
to Bob Nystrom, Peter Ahé, Dominic Hamon, Don, General Dart Discussion

What about:

var x = y ? foo : something_else;
x(a: bar);
x(b: bar);

The value of 'x' can be 'foo' or 'something_else' so the call can't be
known statically. Or would the version of 'foo' need to be specified
in the assignment?

Peter Ahé

unread,
Jan 26, 2012, 4:57:17 PM1/26/12
to Daniel James, Bob Nystrom, Dominic Hamon, Don, General Dart Discussion
Yes, you would have to specify the "version" of foo. This is because there really isn't a method named foo at a low level. Instead there are two methods, one named "foo:a:" and one named "foo:b:". Notice that the names include colons. Syntactically, this is messy.

So since the name is already captured, it should be fine to write:

var x = foo:a:;
x(1); // Argument name already provided. 

Cheers,
Peter 

Daniel James

unread,
Jan 26, 2012, 5:57:50 PM1/26/12
to Peter Ahé, Bob Nystrom, Dominic Hamon, Don, General Dart Discussion

Sure, especially in a ternary operator. Would you be able to specify
optional arguments in the same manner, even though they aren't
strictly part of the function name?

Reply all
Reply to author
Forward
0 new messages