coffee-script 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'coffee-script'
3
- s.version = '0.1.6' # Keep version in sync with coffee-script.rb
4
- s.date = '2009-12-27'
3
+ s.version = '0.2.0' # Keep version in sync with coffee-script.rb
4
+ s.date = '2010-1-5'
5
5
 
6
6
  s.homepage = "http://jashkenas.github.com/coffee-script/"
7
7
  s.summary = "The CoffeeScript Compiler"
@@ -22,5 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.require_paths = ['lib']
23
23
  s.executables = ['coffee']
24
24
 
25
- s.files = Dir['bin/*', 'examples/*', 'lib/**/*', 'coffee-script.gemspec', 'LICENSE', 'README']
25
+ s.files = Dir['bin/*', 'examples/*', 'lib/**/*', 'coffee-script.gemspec', 'LICENSE', 'README', 'package.json']
26
26
  end
data/examples/code.coffee CHANGED
@@ -1,16 +1,16 @@
1
1
  # Functions:
2
- square: x => x * x.
2
+ square: x => x * x
3
3
 
4
- sum: x, y => x + y.
4
+ sum: x, y => x + y
5
5
 
6
- odd: x => x % 2 is 0.
6
+ odd: x => x % 2 is 0
7
7
 
8
- even: x => x % 2 isnt 0.
8
+ even: x => x % 2 isnt 0
9
9
 
10
10
  run_loop: =>
11
- fire_events( e => e.stopPropagation(). )
11
+ fire_events(e => e.stopPropagation())
12
12
  listen()
13
- wait().
13
+ wait()
14
14
 
15
15
  # Objects:
16
16
  dense_object_literal: {one: 1, two: 2, three: 3}
@@ -22,14 +22,14 @@ spaced_out_multiline_object: {
22
22
  three: new Idea()
23
23
 
24
24
  inner_obj: {
25
- freedom: => _.freedom().
25
+ freedom: => _.freedom()
26
26
  }
27
27
  }
28
28
 
29
29
  # Arrays:
30
- stooges : [{moe: 45}, {curly: 43}, {larry: 46}]
30
+ stooges: [{moe: 45}, {curly: 43}, {larry: 46}]
31
31
 
32
- exponents : [x => x., x => x * x., x => x * x * x.]
32
+ exponents: [(x => x), (x => x * x), (x => x * x * x)]
33
33
 
34
34
  empty: []
35
35
 
@@ -45,9 +45,9 @@ if submarine.shields_up
45
45
  else if submarine.sinking
46
46
  abandon_ship()
47
47
  else
48
- run_away().
48
+ run_away()
49
49
 
50
- eldest: if 25 > 21 then liz else marge.
50
+ eldest: if 25 > 21 then liz else marge
51
51
 
52
52
  decoration: medal_of_honor if war_hero
53
53
 
@@ -58,8 +58,8 @@ race: =>
58
58
  run()
59
59
  walk()
60
60
  crawl()
61
- if tired then return sleep().
62
- race().
61
+ if tired then return sleep()
62
+ race()
63
63
 
64
64
  # Conditional assignment:
65
65
  good ||= evil
@@ -81,54 +81,54 @@ try
81
81
  dogs_and_cats_living_together()
82
82
  throw "up"
83
83
  catch error
84
- print( error )
84
+ print(error)
85
85
  finally
86
- clean_up().
86
+ clean_up()
87
87
 
88
- try all_hell_breaks_loose() catch error print(error) finally clean_up().
88
+ try all_hell_breaks_loose() catch error then print(error) finally clean_up()
89
89
 
90
90
  # While loops, break and continue.
91
91
  while demand > supply
92
92
  sell()
93
- restock().
93
+ restock()
94
94
 
95
- while supply > demand then buy().
95
+ while supply > demand then buy()
96
96
 
97
97
  while true
98
98
  break if broken
99
- continue if continuing.
99
+ continue if continuing
100
100
 
101
101
  # Unary operators.
102
102
  !!true
103
103
 
104
104
  # Lexical scoping.
105
- a: 5
105
+ v_1: 5
106
106
  change_a_and_set_b: =>
107
- a: 10
108
- b: 15.
109
- b: 20
107
+ v_1: 10
108
+ v_2: 15
109
+ v_2: 20
110
110
 
111
111
  # Array comprehensions.
112
- supper: food.capitalize() for food in ['toast', 'cheese', 'wine'].
112
+ supper: food.capitalize() for food in ['toast', 'cheese', 'wine']
113
113
 
114
- drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] if even(i).
114
+ drink(bottle) for bottle, i in ['soda', 'wine', 'lemonade'] when even(i)
115
115
 
116
116
  # Switch statements ("else" serves as a default).
117
117
  activity: switch day
118
- when "Tuesday" then eat_breakfast()
119
- when "Sunday" then go_to_church()
120
- when "Saturday" then go_to_the_park()
121
- when "Wednesday"
122
- if day is bingo_day
123
- go_to_bingo()
124
- else
125
- eat_breakfast()
126
- go_to_work()
127
- eat_dinner().
128
- else go_to_work().
118
+ when "Tuesday" then eat_breakfast()
119
+ when "Sunday" then go_to_church()
120
+ when "Saturday" then go_to_the_park()
121
+ when "Wednesday"
122
+ if day is bingo_day
123
+ go_to_bingo()
124
+ else
125
+ eat_breakfast()
126
+ go_to_work()
127
+ eat_dinner()
128
+ else go_to_work()
129
129
 
130
130
  # Semicolons can optionally be used instead of newlines.
131
- wednesday: => eat_breakfast(); go_to_work(); eat_dinner(); .
131
+ wednesday: => eat_breakfast(); go_to_work(); eat_dinner()
132
132
 
133
133
  # Array slice literals.
134
134
  zero_to_nine: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
@@ -140,21 +140,21 @@ sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
140
140
  aliquam erat volutpat. Ut wisi enim ad."
141
141
 
142
142
  # Inheritance and calling super.
143
- Animal: => .
143
+ Animal: =>
144
144
  Animal.prototype.move: meters =>
145
- alert(this.name + " moved " + meters + "m.").
145
+ alert(this.name + " moved " + meters + "m.")
146
146
 
147
- Snake: name => this.name: name.
147
+ Snake: name => this.name: name
148
148
  Snake extends Animal
149
149
  Snake.prototype.move: =>
150
150
  alert('Slithering...')
151
- super(5).
151
+ super(5)
152
152
 
153
- Horse: name => this.name: name.
153
+ Horse: name => this.name: name
154
154
  Horse extends Animal
155
155
  Horse.prototype.move: =>
156
156
  alert('Galloping...')
157
- super(45).
157
+ super(45)
158
158
 
159
159
  sam: new Snake("Sammy the Snake")
160
160
  tom: new Horse("Tommy the Horse")
@@ -1,7 +1,7 @@
1
1
  # Document Model
2
2
  dc.model.Document: dc.Model.extend({
3
3
 
4
- constructor: attributes => this.base(attributes).
4
+ constructor: attributes => this.base(attributes)
5
5
 
6
6
  # For display, show either the highlighted search results, or the summary,
7
7
  # if no highlights are available.
@@ -9,22 +9,22 @@ dc.model.Document: dc.Model.extend({
9
9
  # version of the summary has all runs of whitespace squeezed out.
10
10
  displaySummary: =>
11
11
  text: this.get('highlight') or this.get('summary') or ''
12
- text and text.replace(/\s+/g, ' ').
12
+ text and text.replace(/\s+/g, ' ')
13
13
 
14
14
  # Return a list of the document's metadata. Think about caching this on the
15
15
  # document by binding to Metadata, instead of on-the-fly.
16
16
  metadata: =>
17
17
  docId: this.id
18
- _.select(Metadata.models()
19
- meta => _.any(meta.get('instances')
20
- instance => instance.document_id is docId.).).
18
+ _.select(Metadata.models(), (meta =>
19
+ _.any(meta.get('instances'), instance =>
20
+ instance.document_id is docId)))
21
21
 
22
22
  bookmark: pageNumber =>
23
23
  bookmark: new dc.model.Bookmark({title: this.get('title'), page_number: pageNumber, document_id: this.id})
24
- Bookmarks.create(bookmark).
24
+ Bookmarks.create(bookmark)
25
25
 
26
26
  # Inspect.
27
- toString: => 'Document ' + this.id + ' "' + this.get('title') + '"'.
27
+ toString: => 'Document ' + this.id + ' "' + this.get('title') + '"'
28
28
 
29
29
  })
30
30
 
@@ -37,31 +37,31 @@ dc.model.DocumentSet: dc.model.RESTfulSet.extend({
37
37
 
38
38
  constructor: options =>
39
39
  this.base(options)
40
- _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText').
40
+ _.bindAll(this, 'downloadSelectedViewers', 'downloadSelectedPDF', 'downloadSelectedFullText')
41
41
 
42
- selected: => _.select(this.models(), m => m.get('selected').).
42
+ selected: => _.select(this.models(), m => m.get('selected'))
43
43
 
44
- selectedIds: => _.pluck(this.selected(), 'id').
44
+ selectedIds: => _.pluck(this.selected(), 'id')
45
45
 
46
- countSelected: => this.selected().length.
46
+ countSelected: => this.selected().length
47
47
 
48
48
  downloadSelectedViewers: =>
49
- dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip').
49
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_viewer.zip')
50
50
 
51
51
  downloadSelectedPDF: =>
52
- if this.countSelected() <= 1 then return window.open(this.selected()[0].get('pdf_url')).
53
- dc.app.download('/download/' + this.selectedIds().join('/') + '/document_pdfs.zip').
52
+ if this.countSelected() <= 1 then return window.open(this.selected()[0].get('pdf_url'))
53
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_pdfs.zip')
54
54
 
55
55
  downloadSelectedFullText: =>
56
- if this.countSelected() <= 1 then return window.open(this.selected()[0].get('full_text_url')).
57
- dc.app.download('/download/' + this.selectedIds().join('/') + '/document_text.zip').
56
+ if this.countSelected() <= 1 then return window.open(this.selected()[0].get('full_text_url'))
57
+ dc.app.download('/download/' + this.selectedIds().join('/') + '/document_text.zip')
58
58
 
59
59
  # We override "_onModelEvent" to fire selection changed events when documents
60
60
  # change their selected state.
61
61
  _onModelEvent: e, model =>
62
62
  this.base(e, model)
63
63
  fire: e == dc.Model.CHANGED and model.hasChanged('selected')
64
- if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this))..
64
+ if fire then _.defer(_(this.fire).bind(this, this.SELECTION_CHANGED, this))
65
65
 
66
66
  })
67
67
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
4
4
 
5
- ['toast', 'wine', 'cheese'].each( food => print(food.capitalize()). )
5
+ ['toast', 'wine', 'cheese'].each(food => print(food.capitalize()))
6
6
 
7
7
 
8
8
 
@@ -14,10 +14,10 @@
14
14
  # end
15
15
 
16
16
  LotteryTicket: {
17
- get_picks: => this.picks.
18
- set_picks: nums => this.picks: nums.
19
- get_purchase: => this.purchase.
20
- set_purchase: amount => this.purchase: amount.
17
+ get_picks: => this.picks
18
+ set_picks: nums => this.picks: nums
19
+ get_purchase: => this.purchase
20
+ set_purchase: amount => this.purchase: amount
21
21
  }
22
22
 
23
23
 
@@ -33,8 +33,8 @@ LotteryTicket: {
33
33
 
34
34
  WishScanner: {
35
35
  scan_for_a_wish: =>
36
- wish: this.read().detect( thought => thought.index('wish: ') is 0. )
37
- wish.replace('wish: ', '').
36
+ wish: this.read().detect(thought => thought.index('wish: ') is 0)
37
+ wish.replace('wish: ', '')
38
38
  }
39
39
 
40
40
 
@@ -79,28 +79,28 @@ Creature : {
79
79
 
80
80
  # This method applies a hit taken during a fight.
81
81
  hit: damage =>
82
- p_up: Math.rand( this.charisma )
82
+ p_up: Math.rand(this.charisma)
83
83
  if p_up % 9 is 7
84
84
  this.life += p_up / 4
85
- puts( "[" + this.name + " magick powers up " + p_up + "!]" ).
85
+ puts("[" + this.name + " magick powers up " + p_up + "!]")
86
86
  this.life -= damage
87
- if this.life <= 0 then puts( "[" + this.name + " has died.]" )..
87
+ if this.life <= 0 then puts("[" + this.name + " has died.]")
88
88
 
89
89
  # This method takes one turn in a fight.
90
90
  fight: enemy, weapon =>
91
- if this.life <= 0 then return puts( "[" + this.name + "is too dead to fight!]" ).
91
+ if this.life <= 0 then return puts("[" + this.name + "is too dead to fight!]")
92
92
 
93
93
  # Attack the opponent.
94
- your_hit: Math.rand( this.strength + weapon )
95
- puts( "[You hit with " + your_hit + "points of damage!]" )
96
- enemy.hit( your_hit )
94
+ your_hit: Math.rand(this.strength + weapon)
95
+ puts("[You hit with " + your_hit + "points of damage!]")
96
+ enemy.hit(your_hit)
97
97
 
98
98
  # Retaliation.
99
- puts( enemy )
99
+ puts(enemy)
100
100
  if enemy.life > 0
101
- enemy_hit: Math.rand( enemy.strength + enemy.weapon )
102
- puts( "[Your enemy hit with " + enemy_hit + "points of damage!]" )
103
- this.hit( enemy_hit )..
101
+ enemy_hit: Math.rand(enemy.strength + enemy.weapon)
102
+ puts("[Your enemy hit with " + enemy_hit + "points of damage!]")
103
+ this.hit(enemy_hit)
104
104
 
105
105
  }
106
106
 
@@ -123,12 +123,12 @@ Creature : {
123
123
  # Get evil idea and swap in code words
124
124
  print("Enter your new idea: ")
125
125
  idea: gets()
126
- code_words.each( real, code => idea.replace(real, code). )
126
+ code_words.each(real, code => idea.replace(real, code))
127
127
 
128
128
  # Save the jibberish to a new file
129
129
  print("File encoded. Please enter a name for this idea: ")
130
130
  idea_name: gets().strip()
131
- File.open("idea-" + idea_name + '.txt', 'w', file => file.write(idea). )
131
+ File.open("idea-" + idea_name + '.txt', 'w', file => file.write(idea))
132
132
 
133
133
 
134
134
 
@@ -149,5 +149,5 @@ wipe_mutterings_from: sentence =>
149
149
  while sentence.indexOf('(') >= 0
150
150
  open: sentence.indexOf('(') - 1
151
151
  close: sentence.indexOf(')') + 1
152
- sentence: sentence[0..open] + sentence[close..sentence.length].
153
- sentence.
152
+ sentence: sentence[0..open] + sentence[close..sentence.length]
153
+ sentence
@@ -1,107 +1,126 @@
1
- # Underscore.js
2
- # (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
3
- # Underscore is freely distributable under the terms of the MIT license.
4
- # Portions of Underscore are inspired by or borrowed from Prototype.js,
5
- # Oliver Steele's Functional, and John Resig's Micro-Templating.
6
- # For all details and documentation:
7
- # http://documentcloud.github.com/underscore/
8
-
9
- # ------------------------- Baseline setup ---------------------------------
10
-
11
- # Establish the root object, "window" in the browser, or "global" on the server.
12
- root: this
13
-
14
- # Save the previous value of the "_" variable.
15
- previousUnderscore: root._
16
-
17
- # If Underscore is called as a function, it returns a wrapped object that
18
- # can be used OO-style. This wrapper holds altered versions of all the
19
- # underscore functions. Wrapped objects may be chained.
20
- wrapper: obj => this._wrapped: obj.
21
-
22
- # Establish the object that gets thrown to break out of a loop iteration.
23
- breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration.
24
-
25
- # Create a safe reference to the Underscore object for reference below.
26
- _: root._: obj => new wrapper(obj).
27
-
28
- # Export the Underscore object for CommonJS.
29
- if typeof(exports) != 'undefined' then exports._: _.
30
-
31
- # Create quick reference variables for speed access to core prototypes.
32
- slice: Array.prototype.slice
33
- unshift: Array.prototype.unshift
34
- toString: Object.prototype.toString
35
- hasOwnProperty: Object.prototype.hasOwnProperty
36
- propertyIsEnumerable: Object.prototype.propertyIsEnumerable
37
-
38
- # Current version.
39
- _.VERSION: '0.5.1'
40
-
41
- # ------------------------ Collection Functions: ---------------------------
42
-
43
- # The cornerstone, an each implementation.
44
- # Handles objects implementing forEach, arrays, and raw objects.
45
- _.each: obj, iterator, context =>
46
- index: 0
47
- try
48
- return obj.forEach(iterator, context) if obj.forEach
49
- return iterator.call(context, item, i, obj) for item, i in obj. if _.isArray(obj) or _.isArguments(obj)
50
- iterator.call(context, obj[key], key, obj) for key in _.keys(obj).
51
- catch e
52
- throw e if e isnt breaker.
53
- obj.
54
-
55
- # Return the results of applying the iterator to each element. Use JavaScript
56
- # 1.6's version of map, if possible.
57
- _.map: obj, iterator, context =>
58
- return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
59
- results: []
60
- mapper: value, index, list => results.push(iterator.call(context, value, index, list)).
61
- _.each(obj, mapper)
62
- results.
63
-
64
- # Reduce builds up a single result from a list of values. Also known as
65
- # inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
66
- _.reduce: obj, memo, iterator, context =>
67
- return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
68
- reducer: value, index, list => memo: iterator.call(context, memo, value, index, list).
69
- _.each(obj, reducer)
70
- memo.
71
-
72
- # The right-associative version of reduce, also known as foldr. Uses
73
- # JavaScript 1.8's version of reduceRight, if available.
74
- _.reduceRight: obj, memo, iterator, context =>
75
- return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
76
- reversed: _.clone(_.toArray(obj)).reverse()
77
- reverser: value, index => memo: iterator.call(context, memo, value, index, obj).
78
- _.each(reversed, reverser)
79
- memo.
1
+
2
+ # Underscore.coffee
3
+ # (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
4
+ # Underscore is freely distributable under the terms of the MIT license.
5
+ # Portions of Underscore are inspired by or borrowed from Prototype.js,
6
+ # Oliver Steele's Functional, and John Resig's Micro-Templating.
7
+ # For all details and documentation:
8
+ # http://documentcloud.github.com/underscore/
9
+
10
+
11
+ # ------------------------- Baseline setup ---------------------------------
12
+
13
+ # Establish the root object, "window" in the browser, or "global" on the server.
14
+ root: this
15
+
16
+
17
+ # Save the previous value of the "_" variable.
18
+ previousUnderscore: root._
19
+
20
+
21
+ # If Underscore is called as a function, it returns a wrapped object that
22
+ # can be used OO-style. This wrapper holds altered versions of all the
23
+ # underscore functions. Wrapped objects may be chained.
24
+ wrapper: obj =>
25
+ this._wrapped: obj
26
+ this
27
+
28
+
29
+ # Establish the object that gets thrown to break out of a loop iteration.
30
+ breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
31
+
32
+
33
+ # Create a safe reference to the Underscore object for reference below.
34
+ _: root._: obj => new wrapper(obj)
35
+
36
+
37
+ # Export the Underscore object for CommonJS.
38
+ if typeof(exports) != 'undefined' then exports._: _
39
+
40
+
41
+ # Create quick reference variables for speed access to core prototypes.
42
+ slice: Array.prototype.slice
43
+ unshift: Array.prototype.unshift
44
+ toString: Object.prototype.toString
45
+ hasOwnProperty: Object.prototype.hasOwnProperty
46
+ propertyIsEnumerable: Object.prototype.propertyIsEnumerable
47
+
48
+
49
+ # Current version.
50
+ _.VERSION: '0.5.3'
51
+
52
+
53
+ # ------------------------ Collection Functions: ---------------------------
54
+
55
+ # The cornerstone, an each implementation.
56
+ # Handles objects implementing forEach, arrays, and raw objects.
57
+ _.each: obj, iterator, context =>
58
+ index: 0
59
+ try
60
+ return obj.forEach(iterator, context) if obj.forEach
61
+ if _.isArray(obj) or _.isArguments(obj)
62
+ return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
63
+ iterator.call(context, val, key, obj) for val, key in obj
64
+ catch e
65
+ throw e if e isnt breaker
66
+ obj
67
+
68
+
69
+ # Return the results of applying the iterator to each element. Use JavaScript
70
+ # 1.6's version of map, if possible.
71
+ _.map: obj, iterator, context =>
72
+ return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
73
+ results: []
74
+ _.each(obj) value, index, list =>
75
+ results.push(iterator.call(context, value, index, list))
76
+ results
77
+
78
+
79
+ # Reduce builds up a single result from a list of values. Also known as
80
+ # inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
81
+ _.reduce: obj, memo, iterator, context =>
82
+ return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
83
+ _.each(obj) value, index, list =>
84
+ memo: iterator.call(context, memo, value, index, list)
85
+ memo
86
+
87
+
88
+ # The right-associative version of reduce, also known as foldr. Uses
89
+ # JavaScript 1.8's version of reduceRight, if available.
90
+ _.reduceRight: obj, memo, iterator, context =>
91
+ return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
92
+ _.each(_.clone(_.toArray(obj)).reverse()) value, index =>
93
+ memo: iterator.call(context, memo, value, index, obj)
94
+ memo
95
+
80
96
 
81
97
  # Return the first value which passes a truth test.
82
98
  _.detect: obj, iterator, context =>
83
99
  result: null
84
- _.each(obj, (value, index, list =>
100
+ _.each(obj) value, index, list =>
85
101
  if iterator.call(context, value, index, list)
86
102
  result: value
87
- _.breakLoop()..))
88
- result.
103
+ _.breakLoop()
104
+ result
105
+
89
106
 
90
107
  # Return all the elements that pass a truth test. Use JavaScript 1.6's
91
108
  # filter(), if it exists.
92
109
  _.select: obj, iterator, context =>
93
- if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context).
110
+ if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
94
111
  results: []
95
- _.each(obj, (value, index, list =>
96
- results.push(value) if iterator.call(context, value, index, list).))
97
- results.
112
+ _.each(obj) value, index, list =>
113
+ results.push(value) if iterator.call(context, value, index, list)
114
+ results
115
+
98
116
 
99
117
  # Return all the elements for which a truth test fails.
100
118
  _.reject: obj, iterator, context =>
101
119
  results: []
102
- _.each(obj, (value, index, list =>
103
- results.push(value) if not iterator.call(context, value, index, list).))
104
- results.
120
+ _.each(obj) value, index, list =>
121
+ results.push(value) if not iterator.call(context, value, index, list)
122
+ results
123
+
105
124
 
106
125
  # Determine whether all of the elements match a truth test. Delegate to
107
126
  # JavaScript 1.6's every(), if it is present.
@@ -109,9 +128,10 @@ _.reduceRight: obj, memo, iterator, context =>
109
128
  iterator ||= _.identity
110
129
  return obj.every(iterator, context) if obj and _.isFunction(obj.every)
111
130
  result: true
112
- _.each(obj, (value, index, list =>
113
- _.breakLoop() unless result: result and iterator.call(context, value, index, list).))
114
- result.
131
+ _.each(obj) value, index, list =>
132
+ _.breakLoop() unless (result: result and iterator.call(context, value, index, list))
133
+ result
134
+
115
135
 
116
136
  # Determine if at least one element in the object matches a truth test. Use
117
137
  # JavaScript 1.6's some(), if it exists.
@@ -119,193 +139,193 @@ _.reduceRight: obj, memo, iterator, context =>
119
139
  iterator ||= _.identity
120
140
  return obj.some(iterator, context) if obj and _.isFunction(obj.some)
121
141
  result: false
122
- _.each(obj, (value, index, list =>
123
- _.breakLoop() if (result: iterator.call(context, value, index, list)).))
124
- result.
142
+ _.each(obj) value, index, list =>
143
+ _.breakLoop() if (result: iterator.call(context, value, index, list))
144
+ result
145
+
125
146
 
126
147
  # Determine if a given value is included in the array or object,
127
148
  # based on '==='.
128
149
  _.include: obj, target =>
129
150
  return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
130
- found: false
131
- _.each(obj, (value =>
132
- _.breakLoop() if (found: value is target).))
133
- found.
151
+ for val in obj
152
+ return true if val is target
153
+ false
154
+
134
155
 
135
156
  # Invoke a method with arguments on every item in a collection.
136
157
  _.invoke: obj, method =>
137
158
  args: _.rest(arguments, 2)
138
- _.map(obj, (value =>
139
- (if method then value[method] else value.).apply(value, args).)).
159
+ (if method then val[method] else val).apply(val, args) for val in obj
160
+
140
161
 
141
162
  # Convenience version of a common use case of map: fetching a property.
142
163
  _.pluck: obj, key =>
143
- _.map(obj, (value => value[key].)).
164
+ _.map(obj, (val => val[key]))
165
+
144
166
 
145
167
  # Return the maximum item or (item-based computation).
146
168
  _.max: obj, iterator, context =>
147
- return Math.max.apply(Math, obj) if !iterator and _.isArray(obj)
169
+ return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
148
170
  result: {computed: -Infinity}
149
- _.each(obj, (value, index, list =>
150
- computed: if iterator then iterator.call(context, value, index, list) else value.
151
- computed >= result.computed and (result: {value: value, computed: computed}).))
152
- result.value.
153
- #
154
- # # Return the minimum element (or element-based computation).
155
- # _.min = function(obj, iterator, context) {
156
- # if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
157
- # var result = {computed : Infinity};
158
- # _.each(obj, function(value, index, list) {
159
- # var computed = iterator ? iterator.call(context, value, index, list) : value;
160
- # computed < result.computed && (result = {value : value, computed : computed});
161
- # });
162
- # return result.value;
163
- # };
164
- #
165
- # # Sort the object's values by a criteria produced by an iterator.
166
- # _.sortBy = function(obj, iterator, context) {
167
- # return _.pluck(_.map(obj, function(value, index, list) {
168
- # return {
169
- # value : value,
170
- # criteria : iterator.call(context, value, index, list)
171
- # };
172
- # }).sort(function(left, right) {
173
- # var a = left.criteria, b = right.criteria;
174
- # return a < b ? -1 : a > b ? 1 : 0;
175
- # }), 'value');
176
- # };
177
- #
178
- # # Use a comparator function to figure out at what index an object should
179
- # # be inserted so as to maintain order. Uses binary search.
180
- # _.sortedIndex = function(array, obj, iterator) {
181
- # iterator = iterator || _.identity;
182
- # var low = 0, high = array.length;
183
- # while (low < high) {
184
- # var mid = (low + high) >> 1;
185
- # iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
186
- # }
187
- # return low;
188
- # };
189
- #
190
- # # Convert anything iterable into a real, live array.
191
- # _.toArray = function(iterable) {
192
- # if (!iterable) return [];
193
- # if (iterable.toArray) return iterable.toArray();
194
- # if (_.isArray(iterable)) return iterable;
195
- # if (_.isArguments(iterable)) return slice.call(iterable);
196
- # return _.map(iterable, function(val){ return val; });
197
- # };
198
- #
199
- # # Return the number of elements in an object.
200
- # _.size = function(obj) {
201
- # return _.toArray(obj).length;
202
- # };
203
- #
204
- # /*-------------------------- Array Functions: ------------------------------*/
205
- #
206
- # # Get the first element of an array. Passing "n" will return the first N
207
- # # values in the array. Aliased as "head". The "guard" check allows it to work
208
- # # with _.map.
209
- # _.first = function(array, n, guard) {
210
- # return n && !guard ? slice.call(array, 0, n) : array[0];
211
- # };
212
- #
213
- # # Returns everything but the first entry of the array. Aliased as "tail".
214
- # # Especially useful on the arguments object. Passing an "index" will return
215
- # # the rest of the values in the array from that index onward. The "guard"
216
- # //check allows it to work with _.map.
217
- # _.rest = function(array, index, guard) {
218
- # return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
219
- # };
220
- #
221
- # # Get the last element of an array.
222
- # _.last = function(array) {
223
- # return array[array.length - 1];
224
- # };
225
- #
226
- # # Trim out all falsy values from an array.
227
- # _.compact = function(array) {
228
- # return _.select(array, function(value){ return !!value; });
229
- # };
230
- #
231
- # # Return a completely flattened version of an array.
232
- # _.flatten = function(array) {
233
- # return _.reduce(array, [], function(memo, value) {
234
- # if (_.isArray(value)) return memo.concat(_.flatten(value));
235
- # memo.push(value);
236
- # return memo;
237
- # });
238
- # };
239
- #
240
- # # Return a version of the array that does not contain the specified value(s).
241
- # _.without = function(array) {
242
- # var values = _.rest(arguments);
243
- # return _.select(array, function(value){ return !_.include(values, value); });
244
- # };
245
- #
246
- # # Produce a duplicate-free version of the array. If the array has already
247
- # # been sorted, you have the option of using a faster algorithm.
248
- # _.uniq = function(array, isSorted) {
249
- # return _.reduce(array, [], function(memo, el, i) {
250
- # if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
251
- # return memo;
252
- # });
253
- # };
254
- #
255
- # # Produce an array that contains every item shared between all the
256
- # # passed-in arrays.
257
- # _.intersect = function(array) {
258
- # var rest = _.rest(arguments);
259
- # return _.select(_.uniq(array), function(item) {
260
- # return _.all(rest, function(other) {
261
- # return _.indexOf(other, item) >= 0;
262
- # });
263
- # });
264
- # };
265
- #
266
- # # Zip together multiple lists into a single array -- elements that share
267
- # # an index go together.
268
- # _.zip = function() {
269
- # var args = _.toArray(arguments);
270
- # var length = _.max(_.pluck(args, 'length'));
271
- # var results = new Array(length);
272
- # for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
273
- # return results;
274
- # };
275
- #
276
- # # If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
277
- # # we need this function. Return the position of the first occurence of an
278
- # # item in an array, or -1 if the item is not included in the array.
279
- # _.indexOf = function(array, item) {
280
- # if (array.indexOf) return array.indexOf(item);
281
- # for (var i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
282
- # return -1;
283
- # };
284
- #
285
- # # Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
286
- # # if possible.
287
- # _.lastIndexOf = function(array, item) {
288
- # if (array.lastIndexOf) return array.lastIndexOf(item);
289
- # var i = array.length;
290
- # while (i--) if (array[i] === item) return i;
291
- # return -1;
292
- # };
293
- #
294
- # # Generate an integer Array containing an arithmetic progression. A port of
295
- # # the native Python range() function. See:
296
- # # http://docs.python.org/library/functions.html#range
297
- # _.range = function(start, stop, step) {
298
- # var a = _.toArray(arguments);
299
- # var solo = a.length <= 1;
300
- # var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
301
- # var len = Math.ceil((stop - start) / step);
302
- # if (len <= 0) return [];
303
- # var range = new Array(len);
304
- # for (var i = start, idx = 0; true; i += step) {
305
- # if ((step > 0 ? i - stop : stop - i) >= 0) return range;
306
- # range[idx++] = i;
307
- # }
308
- # };
171
+ _.each(obj) value, index, list =>
172
+ computed: if iterator then iterator.call(context, value, index, list) else value
173
+ computed >= result.computed and (result: {value: value, computed: computed})
174
+ result.value
175
+
176
+
177
+ # Return the minimum element (or element-based computation).
178
+ _.min: obj, iterator, context =>
179
+ return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
180
+ result: {computed: Infinity}
181
+ _.each(obj) value, index, list =>
182
+ computed: if iterator then iterator.call(context, value, index, list) else value
183
+ computed < result.computed and (result: {value: value, computed: computed})
184
+ result.value
185
+
186
+
187
+ # Sort the object's values by a criteria produced by an iterator.
188
+ _.sortBy: obj, iterator, context =>
189
+ _.pluck(((_.map(obj) value, index, list =>
190
+ {value: value, criteria: iterator.call(context, value, index, list)}
191
+ ).sort() left, right =>
192
+ a: left.criteria; b: right.criteria
193
+ if a < b then -1 else if a > b then 1 else 0
194
+ ), 'value')
195
+
196
+
197
+ # Use a comparator function to figure out at what index an object should
198
+ # be inserted so as to maintain order. Uses binary search.
199
+ _.sortedIndex: array, obj, iterator =>
200
+ iterator ||= _.identity
201
+ low: 0; high: array.length
202
+ while low < high
203
+ mid: (low + high) >> 1
204
+ if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid
205
+ low
206
+
207
+
208
+ # Convert anything iterable into a real, live array.
209
+ _.toArray: iterable =>
210
+ return [] if (!iterable)
211
+ return iterable.toArray() if (iterable.toArray)
212
+ return iterable if (_.isArray(iterable))
213
+ return slice.call(iterable) if (_.isArguments(iterable))
214
+ _.values(iterable)
215
+
216
+
217
+ # Return the number of elements in an object.
218
+ _.size: obj => _.toArray(obj).length
219
+
220
+
221
+ # -------------------------- Array Functions: ------------------------------
222
+
223
+ # Get the first element of an array. Passing "n" will return the first N
224
+ # values in the array. Aliased as "head". The "guard" check allows it to work
225
+ # with _.map.
226
+ _.first: array, n, guard =>
227
+ if n and not guard then slice.call(array, 0, n) else array[0]
228
+
229
+
230
+ # Returns everything but the first entry of the array. Aliased as "tail".
231
+ # Especially useful on the arguments object. Passing an "index" will return
232
+ # the rest of the values in the array from that index onward. The "guard"
233
+ # check allows it to work with _.map.
234
+ _.rest: array, index, guard =>
235
+ slice.call(array, if _.isUndefined(index) or guard then 1 else index)
236
+
237
+
238
+ # Get the last element of an array.
239
+ _.last: array => array[array.length - 1]
240
+
241
+
242
+ # Trim out all falsy values from an array.
243
+ _.compact: array => array[i] for i in [0...array.length] when array[i]
244
+
245
+
246
+ # Return a completely flattened version of an array.
247
+ _.flatten: array =>
248
+ _.reduce(array, []) memo, value =>
249
+ return memo.concat(_.flatten(value)) if _.isArray(value)
250
+ memo.push(value)
251
+ memo
252
+
253
+
254
+ # Return a version of the array that does not contain the specified value(s).
255
+ _.without: array =>
256
+ values: _.rest(arguments)
257
+ val for val in _.toArray(array) when not _.include(values, val)
258
+
259
+
260
+ # Produce a duplicate-free version of the array. If the array has already
261
+ # been sorted, you have the option of using a faster algorithm.
262
+ _.uniq: array, isSorted =>
263
+ memo: []
264
+ for el, i in _.toArray(array)
265
+ memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
266
+ memo
267
+
268
+
269
+ # Produce an array that contains every item shared between all the
270
+ # passed-in arrays.
271
+ _.intersect: array =>
272
+ rest: _.rest(arguments)
273
+ _.select(_.uniq(array)) item =>
274
+ _.all(rest) other =>
275
+ _.indexOf(other, item) >= 0
276
+
277
+
278
+ # Zip together multiple lists into a single array -- elements that share
279
+ # an index go together.
280
+ _.zip: =>
281
+ args: _.toArray(arguments)
282
+ length: _.max(_.pluck(args, 'length'))
283
+ results: new Array(length)
284
+ for i in [0...length]
285
+ results[i]: _.pluck(args, String(i))
286
+ results
287
+
288
+
289
+ # If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
290
+ # we need this function. Return the position of the first occurence of an
291
+ # item in an array, or -1 if the item is not included in the array.
292
+ _.indexOf: array, item =>
293
+ return array.indexOf(item) if array.indexOf
294
+ i: 0; l: array.length
295
+ while l - i
296
+ if array[i] is item then return i else i++
297
+ -1
298
+
299
+
300
+ # Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
301
+ # if possible.
302
+ _.lastIndexOf: array, item =>
303
+ return array.lastIndexOf(item) if array.lastIndexOf
304
+ i: array.length
305
+ while i
306
+ if array[i] is item then return i else i--
307
+ -1
308
+
309
+
310
+ # Generate an integer Array containing an arithmetic progression. A port of
311
+ # the native Python range() function. See:
312
+ # http://docs.python.org/library/functions.html#range
313
+ _.range: start, stop, step =>
314
+ a: _.toArray(arguments)
315
+ solo: a.length <= 1
316
+ i: start: if solo then 0 else a[0];
317
+ stop: if solo then a[0] else a[1];
318
+ step: a[2] or 1
319
+ len: Math.ceil((stop - start) / step)
320
+ return [] if len <= 0
321
+ range: new Array(len)
322
+ idx: 0
323
+ while true
324
+ return range if (if step > 0 then i - stop else stop - i) >= 0
325
+ range[idx]: i
326
+ idx++
327
+ i+= step
328
+
309
329
 
310
330
  # ----------------------- Function Functions: -----------------------------
311
331
 
@@ -313,34 +333,36 @@ _.reduceRight: obj, memo, iterator, context =>
313
333
  # optionally). Binding with arguments is also known as 'curry'.
314
334
  _.bind: func, obj =>
315
335
  args: _.rest(arguments, 2)
316
- => func.apply(obj or root, args.concat(_.toArray(arguments)))..
317
-
318
- # # Bind all of an object's methods to that object. Useful for ensuring that
319
- # # all callbacks defined on an object belong to it.
320
- # _.bindAll = function(obj) {
321
- # var funcs = _.rest(arguments);
322
- # if (funcs.length == 0) funcs = _.functions(obj);
323
- # _.each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
324
- # return obj;
325
- # };
326
- #
327
- # # Delays a function for the given number of milliseconds, and then calls
328
- # # it with the arguments supplied.
329
- # _.delay = function(func, wait) {
330
- # var args = _.rest(arguments, 2);
331
- # return setTimeout(function(){ return func.apply(func, args); }, wait);
332
- # };
336
+ => func.apply(obj or root, args.concat(_.toArray(arguments)))
337
+
338
+
339
+ # Bind all of an object's methods to that object. Useful for ensuring that
340
+ # all callbacks defined on an object belong to it.
341
+ _.bindAll: obj =>
342
+ funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
343
+ _.each(funcs, (f => obj[f]: _.bind(obj[f], obj)))
344
+ obj
345
+
346
+
347
+ # Delays a function for the given number of milliseconds, and then calls
348
+ # it with the arguments supplied.
349
+ _.delay: func, wait =>
350
+ args: _.rest(arguments, 2)
351
+ setTimeout((=> func.apply(func, args)), wait)
352
+
333
353
 
334
354
  # Defers a function, scheduling it to run after the current call stack has
335
355
  # cleared.
336
356
  _.defer: func =>
337
- _.delay.apply(_, [func, 1].concat(_.rest(arguments))).
357
+ _.delay.apply(_, [func, 1].concat(_.rest(arguments)))
358
+
338
359
 
339
360
  # Returns the first function passed as an argument to the second,
340
361
  # allowing you to adjust arguments, run code before and after, and
341
362
  # conditionally execute the original function.
342
363
  _.wrap: func, wrapper =>
343
- => wrapper.apply(wrapper, [func].concat(_.toArray(arguments)))..
364
+ => wrapper.apply(wrapper, [func].concat(_.toArray(arguments)))
365
+
344
366
 
345
367
  # Returns a function that is the composition of a list of functions, each
346
368
  # consuming the return value of the function that follows.
@@ -348,40 +370,48 @@ _.reduceRight: obj, memo, iterator, context =>
348
370
  funcs: _.toArray(arguments)
349
371
  =>
350
372
  args: _.toArray(arguments)
351
- args: [funcs[i]].apply(this, args) for i in [(funcs.length - 1)..0].
352
- args[0]..
353
-
354
- # /* ------------------------- Object Functions: ---------------------------- */
355
- #
356
- # # Retrieve the names of an object's properties.
357
- # _.keys = function(obj) {
358
- # if(_.isArray(obj)) return _.range(0, obj.length);
359
- # var keys = [];
360
- # for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
361
- # return keys;
362
- # };
363
- #
364
- # # Retrieve the values of an object's properties.
365
- # _.values = function(obj) {
366
- # return _.map(obj, _.identity);
367
- # };
368
- #
369
- # # Return a sorted list of the function names available in Underscore.
370
- # _.functions = function(obj) {
371
- # return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
372
- # };
373
- #
374
- # # Extend a given object with all of the properties in a source object.
375
- # _.extend = function(destination, source) {
376
- # for (var property in source) destination[property] = source[property];
377
- # return destination;
378
- # };
379
- #
380
- # # Create a (shallow-cloned) duplicate of an object.
381
- # _.clone = function(obj) {
382
- # if (_.isArray(obj)) return obj.slice(0);
383
- # return _.extend({}, obj);
384
- # };
373
+ for i in [(funcs.length - 1)..0]
374
+ args: [funcs[i].apply(this, args)]
375
+ args[0]
376
+
377
+
378
+ # ------------------------- Object Functions: ----------------------------
379
+
380
+ # Retrieve the names of an object's properties.
381
+ _.keys: obj =>
382
+ return _.range(0, obj.length) if _.isArray(obj)
383
+ key for val, key in obj
384
+
385
+
386
+ # Retrieve the values of an object's properties.
387
+ _.values: obj =>
388
+ _.map(obj, _.identity)
389
+
390
+
391
+ # Return a sorted list of the function names available in Underscore.
392
+ _.functions: obj =>
393
+ _.select(_.keys(obj), key => _.isFunction(obj[key])).sort()
394
+
395
+
396
+ # Extend a given object with all of the properties in a source object.
397
+ _.extend: destination, source =>
398
+ for val, key in source
399
+ destination[key]: val
400
+ destination
401
+
402
+
403
+ # Create a (shallow-cloned) duplicate of an object.
404
+ _.clone: obj =>
405
+ return obj.slice(0) if _.isArray(obj)
406
+ _.extend({}, obj)
407
+
408
+
409
+ # Invokes interceptor with the obj, and then returns obj.
410
+ # The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
411
+ _.tap: obj, interceptor =>
412
+ interceptor(obj)
413
+ obj
414
+
385
415
 
386
416
  # Perform a deep comparison to check if two objects are equal.
387
417
  _.isEqual: a, b =>
@@ -402,10 +432,10 @@ _.reduceRight: obj, memo, iterator, context =>
402
432
  return true if _.isNaN(a) and _.isNaN(b)
403
433
  # Compare regular expressions.
404
434
  if _.isRegExp(a) and _.isRegExp(b)
405
- return a.source is b.source and \
406
- a.global is b.global and \
407
- a.ignoreCase is b.ignoreCase and \
408
- a.multiline is b.multiline.
435
+ return a.source is b.source and
436
+ a.global is b.global and
437
+ a.ignoreCase is b.ignoreCase and
438
+ a.multiline is b.multiline
409
439
  # If a is not an object by this point, we can't handle it.
410
440
  return false if atype isnt 'object'
411
441
  # Check for different array lengths before comparing contents.
@@ -416,42 +446,57 @@ _.reduceRight: obj, memo, iterator, context =>
416
446
  return false if aKeys.length isnt bKeys.length
417
447
  # Recursive comparison of contents.
418
448
  # for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
419
- return true.
449
+ return true
450
+
420
451
 
421
452
  # Is a given array or object empty?
422
- _.isEmpty: obj => _.keys(obj).length is 0.
453
+ _.isEmpty: obj => _.keys(obj).length is 0
454
+
423
455
 
424
456
  # Is a given value a DOM element?
425
- _.isElement: obj => !!(obj and obj.nodeType is 1).
457
+ _.isElement: obj => obj and obj.nodeType is 1
458
+
459
+
460
+ # Is a given value an array?
461
+ _.isArray: obj => !!(obj and obj.concat and obj.unshift)
462
+
426
463
 
427
464
  # Is a given variable an arguments object?
428
- _.isArguments: obj => obj and _.isNumber(obj.length) and !_.isArray(obj) and !propertyIsEnumerable.call(obj, 'length').
465
+ _.isArguments: obj => obj and _.isNumber(obj.length) and !_.isArray(obj) and !propertyIsEnumerable.call(obj, 'length')
466
+
467
+
468
+ # Is the given value a function?
469
+ _.isFunction: obj => !!(obj and obj.constructor and obj.call and obj.apply)
470
+
471
+
472
+ # Is the given value a string?
473
+ _.isString: obj => !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
474
+
475
+
476
+ # Is a given value a number?
477
+ _.isNumber: obj => toString.call(obj) is '[object Number]'
478
+
479
+
480
+ # Is a given value a Date?
481
+ _.isDate: obj => !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
482
+
483
+
484
+ # Is the given value a regular expression?
485
+ _.isRegExp: obj => !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
486
+
429
487
 
430
488
  # Is the given value NaN -- this one is interesting. NaN != NaN, and
431
489
  # isNaN(undefined) == true, so we make sure it's a number first.
432
- _.isNaN: obj => _.isNumber(obj) and isNaN(obj).
490
+ _.isNaN: obj => _.isNumber(obj) and window.isNaN(obj)
491
+
433
492
 
434
493
  # Is a given value equal to null?
435
- _.isNull: obj => obj is null.
494
+ _.isNull: obj => obj is null
495
+
436
496
 
437
497
  # Is a given variable undefined?
438
- _.isUndefined: obj => typeof obj is 'undefined'.
498
+ _.isUndefined: obj => typeof obj is 'undefined'
439
499
 
440
- # Invokes interceptor with the obj, and then returns obj.
441
- # The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
442
- _.tap: obj, interceptor =>
443
- interceptor(obj)
444
- obj.
445
-
446
- # # Define the isArray, isDate, isFunction, isNumber, isRegExp, and isString
447
- # # functions based on their toString identifiers.
448
- # var types = ['Array', 'Date', 'Function', 'Number', 'RegExp', 'String'];
449
- # for (var i=0, l=types.length; i<l; i++) {
450
- # (function() {
451
- # var identifier = '[object ' + types[i] + ']';
452
- # _['is' + types[i]] = function(obj) { return toString.call(obj) == identifier; };
453
- # })();
454
- # }
455
500
 
456
501
  # -------------------------- Utility Functions: --------------------------
457
502
 
@@ -459,39 +504,41 @@ _.reduceRight: obj, memo, iterator, context =>
459
504
  # previous owner. Returns a reference to the Underscore object.
460
505
  _.noConflict: =>
461
506
  root._: previousUnderscore
462
- this.
507
+ this
508
+
463
509
 
464
510
  # Keep the identity function around for default iterators.
465
- _.identity: value => value.
511
+ _.identity: value => value
512
+
466
513
 
467
514
  # Break out of the middle of an iteration.
468
- _.breakLoop: => throw breaker.
469
-
470
- # # Generate a unique integer id (unique within the entire client session).
471
- # # Useful for temporary DOM ids.
472
- # var idCounter = 0;
473
- # _.uniqueId = function(prefix) {
474
- # var id = idCounter++;
475
- # return prefix ? prefix + id : id;
476
- # };
477
- #
478
- # # JavaScript templating a-la ERB, pilfered from John Resig's
479
- # # "Secrets of the JavaScript Ninja", page 83.
480
- # _.template = function(str, data) {
481
- # var fn = new Function('obj',
482
- # 'var p=[],print=function(){p.push.apply(p,arguments);};' +
483
- # 'with(obj){p.push(\'' +
484
- # str
485
- # .replace(/[\r\t\n]/g, " ")
486
- # .split("<%").join("\t")
487
- # .replace(/((^|%>)[^\t]*)'/g, "$1\r")
488
- # .replace(/\t=(.*?)%>/g, "',$1,'")
489
- # .split("\t").join("');")
490
- # .split("%>").join("p.push('")
491
- # .split("\r").join("\\'")
492
- # + "');}return p.join('');");
493
- # return data ? fn(data) : fn;
494
- # };
515
+ _.breakLoop: => throw breaker
516
+
517
+
518
+ # Generate a unique integer id (unique within the entire client session).
519
+ # Useful for temporary DOM ids.
520
+ idCounter: 0
521
+ _.uniqueId: prefix =>
522
+ (prefix or '') + idCounter++
523
+
524
+
525
+ # JavaScript templating a-la ERB, pilfered from John Resig's
526
+ # "Secrets of the JavaScript Ninja", page 83.
527
+ _.template: str, data =>
528
+ `var fn = new Function('obj',
529
+ 'var p=[],print=function(){p.push.apply(p,arguments);};' +
530
+ 'with(obj){p.push(\'' +
531
+ str.
532
+ replace(/[\r\t\n]/g, " ").
533
+ split("<%").join("\t").
534
+ replace(/((^|%>)[^\t]*)'/g, "$1\r").
535
+ replace(/\t=(.*?)%>/g, "',$1,'").
536
+ split("\t").join("');").
537
+ split("%>").join("p.push('").
538
+ split("\r").join("\\'") +
539
+ "');}return p.join('');")`
540
+ if data then fn(data) else fn
541
+
495
542
 
496
543
  # ------------------------------- Aliases ----------------------------------
497
544
 
@@ -505,48 +552,42 @@ _.reduceRight: obj, memo, iterator, context =>
505
552
  _.tail: _.rest
506
553
  _.methods: _.functions
507
554
 
508
- # /*------------------------ Setup the OOP Wrapper: --------------------------*/
509
- #
510
- # # Helper function to continue chaining intermediate results.
511
- # var result = function(obj, chain) {
512
- # return chain ? _(obj).chain() : obj;
513
- # };
514
- #
515
- # # Add all of the Underscore functions to the wrapper object.
516
- # _.each(_.functions(_), function(name) {
517
- # var method = _[name];
518
- # wrapper.prototype[name] = function() {
519
- # unshift.call(arguments, this._wrapped);
520
- # return result(method.apply(_, arguments), this._chain);
521
- # };
522
- # });
523
- #
524
- # # Add all mutator Array functions to the wrapper.
525
- # _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
526
- # var method = Array.prototype[name];
527
- # wrapper.prototype[name] = function() {
528
- # method.apply(this._wrapped, arguments);
529
- # return result(this._wrapped, this._chain);
530
- # };
531
- # });
532
- #
533
- # # Add all accessor Array functions to the wrapper.
534
- # _.each(['concat', 'join', 'slice'], function(name) {
535
- # var method = Array.prototype[name];
536
- # wrapper.prototype[name] = function() {
537
- # return result(method.apply(this._wrapped, arguments), this._chain);
538
- # };
539
- # });
540
- #
541
- # # Start chaining a wrapped Underscore object.
542
- # wrapper.prototype.chain = function() {
543
- # this._chain = true;
544
- # return this;
545
- # };
546
- #
547
- # # Extracts the result from a wrapped and chained object.
548
- # wrapper.prototype.value = function() {
549
- # return this._wrapped;
550
- # };
551
- #
552
- # ()
555
+
556
+ # /*------------------------ Setup the OOP Wrapper: --------------------------*/
557
+
558
+ # Helper function to continue chaining intermediate results.
559
+ result: obj, chain =>
560
+ if chain then _(obj).chain() else obj
561
+
562
+
563
+ # Add all of the Underscore functions to the wrapper object.
564
+ _.each(_.functions(_)) name =>
565
+ method: _[name]
566
+ wrapper.prototype[name]: =>
567
+ unshift.call(arguments, this._wrapped)
568
+ result(method.apply(_, arguments), this._chain)
569
+
570
+
571
+ # Add all mutator Array functions to the wrapper.
572
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift']) name =>
573
+ method: Array.prototype[name]
574
+ wrapper.prototype[name]: =>
575
+ method.apply(this._wrapped, arguments)
576
+ result(this._wrapped, this._chain)
577
+
578
+
579
+ # Add all accessor Array functions to the wrapper.
580
+ _.each(['concat', 'join', 'slice']) name =>
581
+ method: Array.prototype[name]
582
+ wrapper.prototype[name]: =>
583
+ result(method.apply(this._wrapped, arguments), this._chain)
584
+
585
+
586
+ # Start chaining a wrapped Underscore object.
587
+ wrapper.prototype.chain: =>
588
+ this._chain: true
589
+ this
590
+
591
+
592
+ # Extracts the result from a wrapped and chained object.
593
+ wrapper.prototype.value: => this._wrapped