Closed josher19 closed 14 years ago
First off, you win the prize for prettiest issue of the week:
I'll need more time to give you a more than superficial response, but at first glance:
All that aside, your suggestions go together hand in hand, and would make for an interesting branch of CoffeeScript, if you want to take a stab at implementing it. I'm sure there are plenty of interesting avenues you could take, if you decided to allow predefined helper functions and compile-time type checking.
Thanks for the lovely ticket.
I like the idea for a ??
and ??=
operator, since we already have ?
and it's a common anti-pattern.
I agree about the type-checking, it's not really in the spirit of the language. However, as pointed out in the issue, sometimes it is important an argument be of a specific type, and it's a pain having to run conversions on each one. Having a quick way to ensure the arguments are correct at runtime sure would be handy.
it would be neat if the pattern matching could work with the ||=
operator. I.e. you could set defaults for inbound arguments with one line:
[a,b,c] ||= [x,y,z]
compiling to
var __a, a, b, c; __a = [x, y, z]; a = a ? a : __a[0]; b = b ? b : __a[1]; c = c ? c : __a[2];
Getting all flavors of assignment to work with pattern matching is going to be a bit of a trick, but conditional assignment based on existence is now on master.
a ?= 5
Compiles to:
var a;
a = (a !== undefined && a !== null) ? a : 5;
Note that we don't have to do the string comparison on typeof === 'undefined'
for the existential assignment, because if it's not in scope we declare it at the top.
...
And finally, you can now use the existential operator infix as well:
result: attempt ? give_up
As for syntax that's a shortcut for this.
, what do y'all think about this:
Person: first, last =>
:name: first + last
Person::introduce: =>
print("Hello there, I'm " + :name)
Ah - nicely done with all these jash. I like how the :x mirrors the prototype ::
I'm unsure about the ambiguity of saving a property on the context. value: this.prop could exist as value: :prop which is very close to value::prop which could technically mean either of those statements, right?
Yeah, I think it's too fuzzy as well -- overloads the colon to the breaking point. Closing the ticket...
Using code>@</code wouldn't be fuzzy as it's not used for anything else :-D.
@jashkenas:
First, Thanks for the Award! I cut & pasted the text from a Gist and it was a real mess until I put it in the Markdown Previewer and fixed it up. From now on, I'm writing my text there first before posting to preview how it looks.
In theory, you could optimize
a ?= 5
To compile to:
var a;
if (typeof a !== 'undefined' && a !== null) a = 5;
or
var a;
if (a != null) a = 5;
and save the unnecessary assignment of:
a = a;
when a is undefined. Last time I checked (a long time ago) IE 6 died on a === undefined
, but null == undefined
on all browsers (that's == not ===).
I like the idea of the new infix existential operator:
result: attempt ? give_up
But it may look too close to ternary op ?:
in Javascript, which is why I suggested ??
I can see JavaScript coders mis-reading the code as:
result = attempt ? give_up : null;
instead of
result = (typeof attempt !== 'undefined' && attempt !== null) ? attempt : give_up;
@Tesco Although it may not be in the spirit of the language, sometimes type checking is needed, and that can be a real pain because of some of JavaScript's quirks. Example: instanceof does inhertitance
var tom = new Horse(); tom instanceof Object === true;
but does not do primitive types:
var str="This is a string"; str instanceof String
is false even though the constructor is true:
var str="This is a string"; str.constructor === String
So something to ease the pain of doing type checking would be great! Maybe I should just make isType
into an (optional) external CS or JS library?
@weepy: I agree, an @ would be nice:
Person: first, last =>
@name: [first, last].join(" ")
Person::introduce: =>
print("Hello there, I'm " + @name)
@josher:
Underscore.js already has a pretty nice isType
suite of checks, optimized for speed. If you'd like to contribute to those, I'd be glad to take the patches. They are:
isEqual, isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isDate, isRegExp isNaN, isNull, isUndefined
I have some suggestions for making CoffeeScript Classes even easier to use in a friendly, "Unfancy" way.
default ??
1.) Allow a "default" in function args or ?? in expressions as a shortcut. Existence (?) is great, but it can be even better if we can use it like the || operator.
// in javascript, all 4 would become:
which is much smarter way to do it than
Bug-prone CoffeeScript example:
See http://gist.github.com/274158 for more examples of common JavaScript class parameter shortcut bugs.
Better CoffeeScript example:
Best, "Unfancy" CoffeeScript example:
my
2) A quicker way set my class variables would be using "my": my: => this.attr: attr
becomes a one liner:
It would be nice to have in the compiler so it works well with default:
// for Horse example: Horse: my name, my speed default 45 =>
mustbe, force
3) One thing that gets newbies and sometimes veteran Javascript programmers is giving the wrong type of argument to a function or constructor. A common example is forgetting to convert user input in a textfield from a String ("42") to a Number (42). A "mustbe" (throw Error) or "force" (try to convert to new Class) clause, which ideally would be checked at compile time (against primitives, anyway) instead of while running, would be great!
Sample Javascript and tests for ArgTypeError and isType are in this Gist: http://gist.github.com/277078
Example Usage
4) Extended CoffeeScript examples using proposed new syntax additions: // See: http://gist.github.com/gists/274170
Note: without the "force Number" clause, the foal unexpectedly escapes:
instead of