diff --git a/documentation/coffee/array_comprehensions.coffee b/documentation/coffee/array_comprehensions.coffee index c272944e..3510e1fb 100644 --- a/documentation/coffee/array_comprehensions.coffee +++ b/documentation/coffee/array_comprehensions.coffee @@ -1,5 +1,7 @@ # Eat lunch. -lunch: this.eat(food) for food in ['toast', 'cheese', 'wine'] +lunch: eat(food) for food in ['toast', 'cheese', 'wine'] -# Zebra-stripe a table. -highlight(row) for row, i in table when i % 2 is 0 \ No newline at end of file +# Naive collision detection. +for roid in asteroids + for roid2 in asteroids when roid isnt roid2 + roid.explode() if roid.overlaps(roid2) \ No newline at end of file diff --git a/documentation/coffee/existence.coffee b/documentation/coffee/existence.coffee new file mode 100644 index 00000000..68dc0411 --- /dev/null +++ b/documentation/coffee/existence.coffee @@ -0,0 +1 @@ +solipsism: true if mind? and not world? \ No newline at end of file diff --git a/documentation/coffee/expressions_comprehension.coffee b/documentation/coffee/expressions_comprehension.coffee new file mode 100644 index 00000000..c608dd21 --- /dev/null +++ b/documentation/coffee/expressions_comprehension.coffee @@ -0,0 +1,3 @@ +# The first ten global properties. + +globals: (name for property, name in window)[0...10] \ No newline at end of file diff --git a/documentation/coffee/expressions_try.coffee b/documentation/coffee/expressions_try.coffee new file mode 100644 index 00000000..3fe3a7f4 --- /dev/null +++ b/documentation/coffee/expressions_try.coffee @@ -0,0 +1,6 @@ +alert( + try + nonexistent / undefined + catch error + "The error is: " + error +) \ No newline at end of file diff --git a/documentation/coffee/object_comprehensions.coffee b/documentation/coffee/object_comprehensions.coffee new file mode 100644 index 00000000..8b637082 --- /dev/null +++ b/documentation/coffee/object_comprehensions.coffee @@ -0,0 +1,3 @@ +years_old: {max: 10, ida: 9, tim: 11} + +ages: child + " is " + age for age, child in years_old \ No newline at end of file diff --git a/documentation/coffee/objects_and_arrays.coffee b/documentation/coffee/objects_and_arrays.coffee index ff10c6ed..f66a8a25 100644 --- a/documentation/coffee/objects_and_arrays.coffee +++ b/documentation/coffee/objects_and_arrays.coffee @@ -1,6 +1,13 @@ song: ["do", "re", "mi", "fa", "so"] + ages: { max: 10 ida: 9 tim: 11 -} \ No newline at end of file +} + +matrix: [ + 1, 0, 1 + 0, 0, 1 + 1, 1, 0 +] \ No newline at end of file diff --git a/documentation/coffee/range_comprehensions.coffee b/documentation/coffee/range_comprehensions.coffee new file mode 100644 index 00000000..d13a669a --- /dev/null +++ b/documentation/coffee/range_comprehensions.coffee @@ -0,0 +1,3 @@ +for i in [0...eggs.length] by 12 + dozen_eggs: eggs[i...i+12] + deliver(new egg_carton(dozen)) diff --git a/documentation/coffee/scope.coffee b/documentation/coffee/scope.coffee index 691072ab..b074dad2 100644 --- a/documentation/coffee/scope.coffee +++ b/documentation/coffee/scope.coffee @@ -1,5 +1,5 @@ num: 1 change_numbers: => - num: 2 - new_num: 3 + new_num: -1 + num: 10 new_num: change_numbers() \ No newline at end of file diff --git a/documentation/coffee/splices.coffee b/documentation/coffee/splices.coffee new file mode 100644 index 00000000..745237ae --- /dev/null +++ b/documentation/coffee/splices.coffee @@ -0,0 +1,5 @@ +numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +numbers[3..6]: [-3, -4, -5, -6] + + diff --git a/documentation/index.html.erb b/documentation/index.html.erb index 0e0232b9..13b24d49 100644 --- a/documentation/index.html.erb +++ b/documentation/index.html.erb @@ -63,7 +63,7 @@ output is quite readable — pretty-printed, with comments preserved intact.
- +Latest Version: 0.2.0 @@ -74,17 +74,18 @@
Mini Overview
Installation and Usage
- Punctuation Primer
+ Significant Whitespace
Functions and Invocation
Assignment
Objects and Arrays
Lexical Scoping and Variable Safety
Conditionals, Ternaries, and Conditional Assignment
+ The Existence Operator
Everything is an Expression
Aliases
While Loops
- Array Comprehensions
- Slicing Arrays with Ranges
+ Comprehensions (Arrays, Objects, and Ranges)
+ Array Slicing and Splicing with Ranges
Inheritance, and Calling Super from a Subclass
Embedded JavaScript
Switch/When/Else
@@ -225,22 +226,22 @@ coffee --print app/scripts/*.coffee > concatenation.js
- Punctuation Primer - You don't need to use semicolons ; to terminate expressions, ending - the line will do just as well. All other whitespace is - not significant. Instead of using curly braces { } - to delimit a block of code, use a period . to mark the end of a - block, for - functions, +
+ Significant Whitespace + CoffeeScript uses Python-style significant whitespace: You don't need to + use semicolons ; to terminate expressions, ending + the line will do just as well. Semicolons can still be used to fit + multiple expressions onto a single line. Instead of using curly braces + { } to delimit a block of code (like functions, if-statements, - switch, and try/catch. + switch, and try/catch), + use indentation.
Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. + function body. The empty function looks like this: =>
<%= code_for('functions', 'cube(5)') %> @@ -252,8 +253,8 @@ coffee --print app/scripts/*.coffee > concatenation.js <%= code_for('assignment', 'greeting') %>- Declarations of new variables are pushed up to the top of the current scope, - so that assignments may always be used within expressions. + Declarations of new variables are pushed up to the top of the nearest + lexical scope, so that assignment may always be used within expressions.
@@ -261,7 +262,8 @@ coffee --print app/scripts/*.coffee > concatenation.js Object and Array literals look very similar to their JavaScript cousins. When you spread out each assignment on a separate line, the commas are optional. In this way, assigning object properties looks the same as - assigning local variables. + assigning local variables, and can be moved around freely. You can mix + and match the two styles.
<%= code_for('objects_and_arrays', 'song.join(",")') %> @@ -273,25 +275,29 @@ coffee --print app/scripts/*.coffee > concatenation.js <%= code_for('scope', 'new_num') %>- Notice how the variables are declared with var the first time - they appear. The second reference of num, within the function, - is not redeclared because num is still in scope. As opposed - to the second occurrence of new_num, in the last line. + Notice how the all of the variable declarations have been pushed up to + the top of the closest scope, the first time they appear. + num is not redeclared within the inner function, because it's + already in scope; the new_num within the function, on the other hand, + should not be able to change the value of the external variable of the same name, and + therefore has a declaration of its own.
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult - to pollute the global namespace by accident. + to pollute the global namespace by accident. If you'd like to create + global variables, attach them as properties on window, + or on the exports object in CommonJS.
Conditionals, Ternaries, and Conditional Assignment If/else statements can be written without the use of parentheses and - curly brackets. As with functions and other block expressions, conditionals - are closed with periods. No period is necessary when using the single-line - postfix form, with the if at the end. + curly brackets. As with functions and other block expressions, + multi-line conditionals are delimited by indentation. There's also a handy + postfix form, with the if or unless at the end.
CoffeeScript will compile if statements using the ternary operator @@ -299,12 +305,22 @@ coffee --print app/scripts/*.coffee > concatenation.js
<%= code_for('conditionals') %>- The conditional assignment operators are available: ||=, + The conditional assignment operators are included: ||=, which only assigns a value to a variable if the variable's current value is falsy, and &&=, which only replaces the value of truthy variables.
++ The Existence Operator + It's a little difficult to check for the existence of a variable in + JavaScript. if (variable) ... comes close, but fails for zero, + the empty string, and false. The existence operator ? returns true unless + a variable is null or undefined, which makes it analogous + to nil? in Ruby. +
+ <%= code_for('existence') %> +Everything is an Expression (at least, as much as possible) You might have noticed how even though we don't add return statements @@ -316,14 +332,22 @@ coffee --print app/scripts/*.coffee > concatenation.js
<%= code_for('expressions', 'eldest') %>- The same mechanism is used to push down assignment through switch - statements, and if-elses (although the ternary operator is preferred). - Another part of manipulating assignment statements is - CoffeeScript's declaration of new variables at the top of the - current scope. This allows assignment to be used as a piece of an - expression. + Because variable declarations occur at the top of scope, assignment can + be used within expressions, even for variables that haven't been seen before:
<%= code_for('expressions_assignment', 'six') %> ++ Things that would otherwise be statements in JavaScript, when used + as part of an expression in CoffeeScript, are converted into expressions + by wrapping them in a closure. This lets you do useful things, like assign + the result of a comprehension to a variable: +
+ <%= code_for('expressions_comprehension', 'globals') %> ++ As well as silly things, like passing a try/catch statement directly + into a function call: +
+ <%= code_for('expressions_try', true) %>Aliases @@ -367,8 +391,8 @@ coffee --print app/scripts/*.coffee > concatenation.js each (forEach) style iterators, or...
-- Array Comprehensions +
+ Comprehensions (Arrays, Objects, and Ranges) For your looping needs, CoffeeScript provides array comprehensions similar to Python's. They replace (and compile into) for loops, with optional guard clauses and the value of the current array index. @@ -378,13 +402,19 @@ coffee --print app/scripts/*.coffee > concatenation.js
<%= code_for('array_comprehensions') %>- If you're not iterating over an actual array, you can use a range to - specify the start and end of an array comprehension: - coundown(i) for i in [10..1]. + If you know the start and end of your loop, or would like to step through + in fixed-size increments, you can use a range to specify the start and + end of your comprehension:
+ <%= code_for('range_comprehensions') %> ++ Comprehensions can also be used to iterate over the values and keys in + an object: +
+ <%= code_for('object_comprehensions', 'ages.join(", ")') %> -- Slicing Arrays with Ranges +
+ Array Slicing and Splicing with Ranges CoffeeScript borrows Ruby's range syntax for extracting slices of arrays. With two dots (3..5), the range @@ -393,6 +423,11 @@ coffee --print app/scripts/*.coffee > concatenation.js a range that excludes the end.
<%= code_for('slices', 'numbers_copy') %> ++ The same syntax can be used with assignment to replace a segment of an + array with new values (to splice it). +
+ <%= code_for('splices', 'numbers') %>Inheritance, and Calling Super from a Subclass diff --git a/documentation/js/array_comprehensions.js b/documentation/js/array_comprehensions.js index b35ed908..089b9fcf 100644 --- a/documentation/js/array_comprehensions.js +++ b/documentation/js/array_comprehensions.js @@ -1,5 +1,5 @@ (function(){ - var __a, __b, __c, __d, __e, __f, food, i, lunch, row; + var __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2; // Eat lunch. lunch = (function() { __a = ['toast', 'cheese', 'wine']; @@ -7,18 +7,28 @@ for (__b in __a) { if (__a.hasOwnProperty(__b)) { food = __a[__b]; - __d = this.eat(food); + __d = eat(food); __c.push(__d); } } return __c; })(); - // Zebra-stripe a table. - __e = table; - for (i in __e) { - if (__e.hasOwnProperty(i)) { - row = __e[i]; - i % 2 === 0 ? highlight(row) : null; + // Naive collision detection. + __e = asteroids; + for (__f in __e) { + if (__e.hasOwnProperty(__f)) { + roid = __e[__f]; + __h = asteroids; + for (__i in __h) { + if (__h.hasOwnProperty(__i)) { + roid2 = __h[__i]; + if (roid !== roid2) { + if (roid.overlaps(roid2)) { + roid.explode(); + } + } + } + } } } })(); \ No newline at end of file diff --git a/documentation/js/existence.js b/documentation/js/existence.js new file mode 100644 index 00000000..60e9e922 --- /dev/null +++ b/documentation/js/existence.js @@ -0,0 +1,6 @@ +(function(){ + var solipsism; + if ((typeof mind !== 'undefined' && mind !== null) && !(typeof world !== 'undefined' && world !== null)) { + solipsism = true; + } +})(); \ No newline at end of file diff --git a/documentation/js/expressions_comprehension.js b/documentation/js/expressions_comprehension.js new file mode 100644 index 00000000..5dea5cf0 --- /dev/null +++ b/documentation/js/expressions_comprehension.js @@ -0,0 +1,16 @@ +(function(){ + var __a, __b, __c, globals, name, property; + // The first ten global properties. + globals = ((function() { + __a = window; + __b = []; + for (name in __a) { + if (__a.hasOwnProperty(name)) { + property = __a[name]; + __c = name; + __b.push(__c); + } + } + return __b; + })()).slice(0, 10); +})(); \ No newline at end of file diff --git a/documentation/js/expressions_try.js b/documentation/js/expressions_try.js new file mode 100644 index 00000000..9c236f65 --- /dev/null +++ b/documentation/js/expressions_try.js @@ -0,0 +1,9 @@ +(function(){ + alert((function() { + try { + return nonexistent / undefined; + } catch (error) { + return "The error is: " + error; + } + })()); +})(); \ No newline at end of file diff --git a/documentation/js/object_comprehensions.js b/documentation/js/object_comprehensions.js new file mode 100644 index 00000000..757ad863 --- /dev/null +++ b/documentation/js/object_comprehensions.js @@ -0,0 +1,20 @@ +(function(){ + var __a, __b, __c, age, ages, child, years_old; + years_old = { + max: 10, + ida: 9, + tim: 11 + }; + ages = (function() { + __a = years_old; + __b = []; + for (child in __a) { + if (__a.hasOwnProperty(child)) { + age = __a[child]; + __c = child + " is " + age; + __b.push(__c); + } + } + return __b; + })(); +})(); \ No newline at end of file diff --git a/documentation/js/objects_and_arrays.js b/documentation/js/objects_and_arrays.js index cfd1011e..3c7de98f 100644 --- a/documentation/js/objects_and_arrays.js +++ b/documentation/js/objects_and_arrays.js @@ -1,9 +1,10 @@ (function(){ - var ages, song; + var ages, matrix, song; song = ["do", "re", "mi", "fa", "so"]; ages = { max: 10, ida: 9, tim: 11 }; + matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0]; })(); \ No newline at end of file diff --git a/documentation/js/range_comprehensions.js b/documentation/js/range_comprehensions.js new file mode 100644 index 00000000..7457b7f4 --- /dev/null +++ b/documentation/js/range_comprehensions.js @@ -0,0 +1,9 @@ +(function(){ + var __a, __b, __c, __d, __e, dozen_eggs, i; + __d = 0; + __e = eggs.length; + for (__c=0, i=__d; (__d <= __e ? i < __e : i > __e); (__d <= __e ? i += 12 : i -= 12), __c++) { + dozen_eggs = eggs.slice(i, i + 12); + deliver(new egg_carton(dozen)); + } +})(); \ No newline at end of file diff --git a/documentation/js/scope.js b/documentation/js/scope.js index 0590b247..3319f50c 100644 --- a/documentation/js/scope.js +++ b/documentation/js/scope.js @@ -3,8 +3,8 @@ num = 1; change_numbers = function change_numbers() { var new_num; - num = 2; - return new_num = 3; + new_num = -1; + return num = 10; }; new_num = change_numbers(); })(); \ No newline at end of file diff --git a/documentation/js/splices.js b/documentation/js/splices.js new file mode 100644 index 00000000..0192c5e5 --- /dev/null +++ b/documentation/js/splices.js @@ -0,0 +1,5 @@ +(function(){ + var numbers; + numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6])); +})(); \ No newline at end of file diff --git a/index.html b/index.html index 4294fbd7..11397c73 100644 --- a/index.html +++ b/index.html @@ -36,7 +36,7 @@ output is quite readable — pretty-printed, with comments preserved intact.
- +Latest Version: 0.2.0 @@ -47,17 +47,18 @@
Mini Overview
Installation and Usage
- Punctuation Primer
+ Significant Whitespace
Functions and Invocation
Assignment
Objects and Arrays
Lexical Scoping and Variable Safety
Conditionals, Ternaries, and Conditional Assignment
+ The Existence Operator
Everything is an Expression
Aliases
While Loops
- Array Comprehensions
- Slicing Arrays with Ranges
+ Comprehensions (Arrays, Objects, and Ranges)
+ Array Slicing and Splicing with Ranges
Inheritance, and Calling Super from a Subclass
Embedded JavaScript
Switch/When/Else
@@ -290,22 +291,22 @@ coffee --print app/scripts/*.coffee > concatenation.js
- Punctuation Primer - You don't need to use semicolons ; to terminate expressions, ending - the line will do just as well. All other whitespace is - not significant. Instead of using curly braces { } - to delimit a block of code, use a period . to mark the end of a - block, for - functions, +
+ Significant Whitespace + CoffeeScript uses Python-style significant whitespace: You don't need to + use semicolons ; to terminate expressions, ending + the line will do just as well. Semicolons can still be used to fit + multiple expressions onto a single line. Instead of using curly braces + { } to delimit a block of code (like functions, if-statements, - switch, and try/catch. + switch, and try/catch), + use indentation.
Functions and Invocation Functions are defined by a list of parameters, an arrow, and the - function body. The empty function looks like this: =>. + function body. The empty function looks like this: =>
square: x => x * x cube: x => square(x) * x @@ -341,8 +342,8 @@ greeting = "Hello CoffeeScript"; difficulty = 0.5; ;alert(greeting);'>run: greeting
- Declarations of new variables are pushed up to the top of the current scope, - so that assignments may always be used within expressions. + Declarations of new variables are pushed up to the top of the nearest + lexical scope, so that assignment may always be used within expressions.
@@ -350,28 +351,38 @@ difficulty = 0.5; Object and Array literals look very similar to their JavaScript cousins. When you spread out each assignment on a separate line, the commas are optional. In this way, assigning object properties looks the same as - assigning local variables. + assigning local variables, and can be moved around freely. You can mix + and match the two styles.
song: ["do", "re", "mi", "fa", "so"] + ages: { max: 10 ida: 9 tim: 11 } -
var ages, song; + +matrix: [ + 1, 0, 1 + 0, 0, 1 + 1, 1, 0 +] +
var ages, matrix, song; song = ["do", "re", "mi", "fa", "so"]; ages = { max: 10, ida: 9, tim: 11 }; -
@@ -382,46 +393,50 @@ ages = {
num: 1 change_numbers: => - num: 2 - new_num: 3 + new_num: -1 + num: 10 new_num: change_numbers()
var change_numbers, new_num, num; num = 1; change_numbers = function change_numbers() { var new_num; - num = 2; - return new_num = 3; + new_num = -1; + return num = 10; }; new_num = change_numbers();
- Notice how the variables are declared with var the first time - they appear. The second reference of num, within the function, - is not redeclared because num is still in scope. As opposed - to the second occurrence of new_num, in the last line. + Notice how the all of the variable declarations have been pushed up to + the top of the closest scope, the first time they appear. + num is not redeclared within the inner function, because it's + already in scope; the new_num within the function, on the other hand, + should not be able to change the value of the external variable of the same name, and + therefore has a declaration of its own.
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult - to pollute the global namespace by accident. + to pollute the global namespace by accident. If you'd like to create + global variables, attach them as properties on window, + or on the exports object in CommonJS.
Conditionals, Ternaries, and Conditional Assignment If/else statements can be written without the use of parentheses and - curly brackets. As with functions and other block expressions, conditionals - are closed with periods. No period is necessary when using the single-line - postfix form, with the if at the end. + curly brackets. As with functions and other block expressions, + multi-line conditionals are delimited by indentation. There's also a handy + postfix form, with the if or unless at the end.
CoffeeScript will compile if statements using the ternary operator
@@ -448,12 +463,27 @@ date = friday ? sue : jill;
expensive = expensive || do_the_math();
- The conditional assignment operators are available: ||=, + The conditional assignment operators are included: ||=, which only assigns a value to a variable if the variable's current value is falsy, and &&=, which only replaces the value of truthy variables.
++ The Existence Operator + It's a little difficult to check for the existence of a variable in + JavaScript. if (variable) ... comes close, but fails for zero, + the empty string, and false. The existence operator ? returns true unless + a variable is null or undefined, which makes it analogous + to nil? in Ruby. +
+solipsism: true if mind? and not world? +
var solipsism; +if ((typeof mind !== 'undefined' && mind !== null) && !(typeof world !== 'undefined' && world !== null)) { + solipsism = true; +} +
Everything is an Expression (at least, as much as possible)
You might have noticed how even though we don't add return statements
@@ -496,12 +526,8 @@ grade = function grade(student) {
eldest = 24 > 21 ? "Liz" : "Ike";
;alert(eldest);'>run: eldest
- The same mechanism is used to push down assignment through switch - statements, and if-elses (although the ternary operator is preferred). - Another part of manipulating assignment statements is - CoffeeScript's declaration of new variables at the top of the - current scope. This allows assignment to be used as a piece of an - expression. + Because variable declarations occur at the top of scope, assignment can + be used within expressions, even for variables that haven't been seen before:
six: (one: 1) + (two: 2) + (three: 3)
var one, six, three, two; @@ -509,6 +535,69 @@ six = (one =
+ Things that would otherwise be statements in JavaScript, when used + as part of an expression in CoffeeScript, are converted into expressions + by wrapping them in a closure. This lets you do useful things, like assign + the result of a comprehension to a variable: +
+# The first ten global properties. + +globals: (name for property, name in window)[0...10] +
var __a, __b, __c, globals, name, property; +// The first ten global properties. +globals = ((function() { + __a = window; + __b = []; + for (name in __a) { + if (__a.hasOwnProperty(name)) { + property = __a[name]; + __c = name; + __b.push(__c); + } + } + return __b; +})()).slice(0, 10); +
+ As well as silly things, like passing a try/catch statement directly + into a function call: +
+alert( + try + nonexistent / undefined + catch error + "The error is: " + error +) +
alert((function() { + try { + return nonexistent / undefined; + } catch (error) { + return "The error is: " + error; + } +})()); +
Aliases @@ -582,8 +671,8 @@ car.speed < speed_limit ? accelerate() : each (forEach) style iterators, or...
-- Array Comprehensions +
+ Comprehensions (Arrays, Objects, and Ranges) For your looping needs, CoffeeScript provides array comprehensions similar to Python's. They replace (and compile into) for loops, with optional guard clauses and the value of the current array index. @@ -592,11 +681,13 @@ car.speed < speed_limit ? accelerate() : each/forEach, map, or select/filter.
# Eat lunch. -lunch: this.eat(food) for food in ['toast', 'cheese', 'wine'] +lunch: eat(food) for food in ['toast', 'cheese', 'wine'] -# Zebra-stripe a table. -highlight(row) for row, i in table when i % 2 is 0 -
var __a, __b, __c, __d, __e, __f, food, i, lunch, row; +# Naive collision detection. +for roid in asteroids + for roid2 in asteroids when roid isnt roid2 + roid.explode() if roid.overlaps(roid2) +
var __a, __b, __c, __d, __e, __f, __g, __h, __i, __j, food, lunch, roid, roid2; // Eat lunch. lunch = (function() { __a = ['toast', 'cheese', 'wine']; @@ -604,29 +695,94 @@ lunch = (function() { for (__b in __a) { if (__a.hasOwnProperty(__b)) { food = __a[__b]; - __d = this.eat(food); + __d = eat(food); __c.push(__d); } } return __c; })(); -// Zebra-stripe a table. -__e = table; -for (i in __e) { - if (__e.hasOwnProperty(i)) { - row = __e[i]; - i % 2 === 0 ? highlight(row) : null; +// Naive collision detection. +__e = asteroids; +for (__f in __e) { + if (__e.hasOwnProperty(__f)) { + roid = __e[__f]; + __h = asteroids; + for (__i in __h) { + if (__h.hasOwnProperty(__i)) { + roid2 = __h[__i]; + if (roid !== roid2) { + if (roid.overlaps(roid2)) { + roid.explode(); + } + } + } + } } }
- If you're not iterating over an actual array, you can use a range to - specify the start and end of an array comprehension: - coundown(i) for i in [10..1]. + If you know the start and end of your loop, or would like to step through + in fixed-size increments, you can use a range to specify the start and + end of your comprehension:
+for i in [0...eggs.length] by 12 + dozen_eggs: eggs[i...i+12] + deliver(new egg_carton(dozen)) +
var __a, __b, __c, __d, __e, dozen_eggs, i; +__d = 0; +__e = eggs.length; +for (__c=0, i=__d; (__d <= __e ? i < __e : i > __e); (__d <= __e ? i += 12 : i -= 12), __c++) { + dozen_eggs = eggs.slice(i, i + 12); + deliver(new egg_carton(dozen)); +} +
+ Comprehensions can also be used to iterate over the values and keys in + an object: +
+years_old: {max: 10, ida: 9, tim: 11} -- Slicing Arrays with Ranges +ages: child + " is " + age for age, child in years_old +
var __a, __b, __c, age, ages, child, years_old; +years_old = { + max: 10, + ida: 9, + tim: 11 +}; +ages = (function() { + __a = years_old; + __b = []; + for (child in __a) { + if (__a.hasOwnProperty(child)) { + age = __a[child]; + __c = child + " is " + age; + __b.push(__c); + } + } + return __b; +})(); +
+ Array Slicing and Splicing with Ranges
CoffeeScript borrows Ruby's
range syntax
for extracting slices of arrays. With two dots (3..5), the range
@@ -649,6 +805,22 @@ numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
three_to_six = numbers.slice(3, 6 + 1);
numbers_copy = numbers.slice(0, numbers.length);
;alert(numbers_copy);'>run: numbers_copy
+
+ The same syntax can be used with assignment to replace a segment of an + array with new values (to splice it). +
+numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +numbers[3..6]: [-3, -4, -5, -6] + + +
var numbers; +numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; +numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6])); +
Inheritance, and Calling Super from a Subclass diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index f1c280bf..541c932e 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -19,7 +19,8 @@ token INDENT OUTDENT # Declare order of operations. prechigh - nonassoc UMINUS PARAM_SPLAT SPLAT NOT '!' '!!' '~' '++' '--' '?' + left '?' + nonassoc UMINUS PARAM_SPLAT SPLAT NOT '!' '!!' '~' '++' '--' left '*' '/' '%' left '+' '-' left '<<' '>>' '>>>' @@ -368,7 +369,7 @@ rule # An individual when. When: LEADING_WHEN Expression Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) } - | LEADING_WHEN Expression Block + | LEADING_WHEN Expression Block Terminator { result = IfNode.new(val[1], val[2], nil, {:statement => true}) } | Comment ;