3 ms·
To me the most convenient thing about it is the auto-declaring variables and proper loops. Whether the sugar is worth it or not comes down to taste. I used Pyth
by grayrest 15y ago
To me the most convenient thing about it is the auto-declaring variables and proper loops. Whether the sugar is worth it or not comes down to taste. I used Python as my primary language from 2001-2007 before switching to Javascript/Coffeescript full time so I'll provide a bit of commentary.
> Arrays could use a beard or the varied language syntax is going to cause ingrown pains
The whitespace magic only causes me a problem in a few situations.
Watch indent on wrapped if statement:
if foo is true or bar is false or
baz is null
doSomething() #Error
if foo is true or bar is false or
baz is null
doSomething() #ok
Explicitly returning objects is awkward:
foo: ->
if not ok then return
#lots of code here
return
x: 1 #ha ha
y: 2
foo: ->
if not ok then return
#lots of code here
return {
x: 1 #ok but ugly
y: 2}
I always want to use implicit call parens with property chaining but that doesn't work:
$('.doAllTheThings').filter 'span'
.data 'foo', true
.wrap '<div/>'
#produces filter('span'.data('foo' ...
$('.doAllTheThings').filter('span')
.data('foo', true)
.wrap('<div/>')
The result of assigning a comprehension threw me off for a while because I was thinking Python list comprehension instead of postfix loop:
foo = x + 1 for x in array
foo = (x + 1 for x in array) #what I expected
(foo = x + 1) for x in array #what happens
for x in array #same thing written the other way
foo = x + 1
Finally, the whitespace magic working well tends to depend on object/functional arguments coming last in the call list with the functional arg coming after the object.
These annoyances are relatively rare and are the sort of thing you just get used to if you use the language heavily. The upside is that for an appropriately designed API (the options object argument last convention in JS makes this fairly common), the object literal magic gives a feel like python kwargs:
animatedShow node, duration: 200, onComplete: -> fire 'doThing'
You can also do DSLish things fairly easily. I'm a fairly heavy YUI user. Compare:
YUI.add('myCoolModule', function(Y, name) {
Y.CoolModel = Y.Base.create('coolModel', Y.Model, [], {
aMethod: function(){return this.get('foo') === 1}
},{
ATTRS: {
foo: {value: 1},
bar: {value: 2, readOnly: true}
}
})
}, '1.0.0', { requires: ['app', 'model'] });
to:
YUI.module 'myCoolModule',
version: '1.0.0'
requires: ['app', 'model']
(Y) ->
Y.CoolModel = CoolModel
class CoolModel extends Y.Model
@ATTRS:
foo:
value: 1
bar:
value: 2
readOnly: true
aMethod: -> @get('foo') is 1
It requires a one word patch on Coffeescript (superclass name in generated output) and the addition of a tiny YUI.module to YUI.add shim but I think the result is a lot cleaner.
> It's also bizarre from a Python background
Python's auto-concatenation of runs of string literals is convenient but I don't know of another language that does the same thing.
> if foo.bar? then console.log foo.bar
The ? is an explicit existence check, while doing `if(foo.bar)` will fail if bar is an empty string or zero. I tend to write existence checks using the postfix form:
console.log foo.bar if foo.bar
This is a personal style that indicates that the normal control flow is to log but there's a simple guard on the operation. I'd use the if...then form if I expected the test to fail a significant fraction of the time (i.e. it's a branch instead of a guard). My other quirk is that I use &&/|| only for short circuiting but and/or only for boolean logic.
- nolanw 15y ago> Python's auto-concatenation of runs of string literals is convenient but I don't know of another language that does the same thing. The C preprocessor (in GCC and Clang at least) will concatenate adjacent literals, so add C, C++, and Objective-C to your list.
- thezilch 15y agoI'm not going to fight on most of the non-parenthetical aspects of the syntax -- it always sounds like a holy war, everyone is right, and everyone is wrong. I've not looked closely at the implementation, but Python concatenating adjacent strings might be a relic of C-based languages -- the same rule applies there and likely a standard of the language with CPython being the default underbelly of Python. Then your final (YUI) example, we have "random" commas. Again, the language syntax starts to trend towards generally inconsistent, and I have to enforce more style guides upon my team. NOTE: I work heavily with YUI as well, and my team -- Python stack -- too writes shims to support "kwargs"-like syntax, so I can't really consider coffeescript having an advantage. Quick pseudo comparison... YUI.module = function(name, func, kwargs){ kwargs = kwargs || {}; return YUI.add(name, function(Y){func(Y);}, kwargs.version, kwargs.details); }; YUI.module("myCoolModule", function(Y){ ... }, {"version": "1.0.0", "details": {"requires": ["app", "model"]});
- grayrest 15y agoThe random comma in the yui example can be eliminated fairly easily. It being there is due to Coffeescript not being able to support the following call style when I initially wrote the shim. YUI.module = function(o, f) { var name = o.name, ver = o.version; delete o.name; delete o.version; if(!name || !version) throw "Both `name` and `version` are required."; return YUI.add(name, f, ver, o); } YUI.module name: 'myCoolModule' version: 1.0 requires: ['app','model'] (Y) -> ... Ultimately CoffeeScript is syntax sugar for Javascript that you pay for with wrong line numbers when debugging. I think it's worth it, but I have friends who disagree. My coffeescript source is about 30% fewer lines of code than the equivalent javascript. Roughly half of that is entirely closing braces/parens but the other half is actual code reduction/simplification, mostly from loop comprehensions. I also use it for API design. My habit when doing the design is to write out code for how I'd like to use it. I always use coffeescript for this regardless of whether I'm implementing it in JS or CS because a bad api visually looks bad to me when I write it out and I bang at it until it looks right. I've been mocked for this process by a couple people who have asked for my input on their projects but I've never had someone not take my resulting recommendations.