CoffeeScriptとJavaScriptやPythonやRubyの文法の比較

PythonやRubyだとあんな感じで書くけど、CoffeeScriptだとどうかなーというのを思い浮かぶがままに書き下していく。

- JavaScriptも追加

#コメント

```py
# comment
```

```ruby
# comment
```

```js
// comment
```

```coffeescript
# comment
```

#複数行にまたがるコメント

Pythonには複数行コメントがないので文字列で代用する

```py
'''
comment
'''

"""
comment
"""
```

```ruby
=begin
comment
=end
```

```js
/*
comment
*/
```

```coffeescript
###
comment
###
```

#文字の埋め込み

```py
>>> width = 100
>>> "{0}px".format(width)
"100px"
>>> "%dpx" % width
"100px"
```

```ruby
width = 100
p "#{width}px"
# => 100px
```

```js
width = 100;
console.log("" + width + "px");
```

Rubyに似てる

```coffeescript
width = 100
console.log "#{width}px"
# 100px
```

#複数行にまたがる文字列

```py
>>> a = '''a
... b'''
"a\nb"
```

```ruby
a = 'a
b'
# => "a\nb"
```

```js
a = 'a\
      b';
// "a\n     b"
```

```coffeescript
a = 'a
b'
# "ab"
```

#連想配列

```py
d = {'a': 0, 'b': 2}
```

```ruby
d = {:a => 0, :b => 2}
```

```js
d = {a: 0, b: 2}
```

```coffeescript
d = a: 0, b: 2
d = {a: 0, b: 2} # もOK
# 複数行にまたがる場合は`,`を省略可
d =
  a: 0  # 途中にコメントも入れられる
  b: 2
d = {
  a: 0
  b: 2
}
```

#配列

```py
l = [1, 3, 5]
```

```ruby
l = [1, 3, 5]
```

```js
l = [1, 3, 5]
```

```coffeescript
l = [1, 3, 5]
#複数行にまたがる場合は`,`が省略可
l = [
  1
  3
  5
]
```

#連続した配列

```py
>>> range(5)
[0, 1, 2, 3, 4]
>>> range(5, 0, -1)
[5, 4, 3, 2, 1]
>>> range(2, 5)
[2, 3, 4]
```

```coffeescript
[0...5]
# [0, 1, 2, 3, 4]
[0..4]
# [0, 1, 2, 3, 4]

[4...-1]
# [4, 3, 2, 1, 0]
[4..0]
# [4, 3, 2, 1, 0]

[2...5]
# [2, 3, 4]
[2..4]
# [2, 3, 4]
```

#配列へのアクセス

```py
>>> l = range(10)
>>> l[1]
1
>>> l[2:4]
[2, 3]
>>> l[2:]
[2, 3, 4, 5, 6, 7, 8, 9]
>>> l[:4]
[0, 1, 2, 3]
>>> l[::3]
[0, 3, 6, 9]
>>> l[-1]
9
>>> l[3:6] = [6, 8, 9]
>>> l
[0, 1, 2, 6, 8, 9, 6, 7, 8, 9]
```

```coffeescript
l = [0...10]
l[1]
# 1
l[2...4]
# [2, 3]
l[2...]
# [2, 3, 4, 5, 6, 7, 8, 9]
l[...4]
# [0, 1, 2, 3]
i for i in l by 3
# [0, 3, 6, 9]
l[l.length-1]]
# 9
l[3...6] = [6, 8, 9]
# [0, 1, 2, 6, 8, 9, 6, 7, 8, 9]
```

#リスト内包表記

##単純な場合

```py
>>> l = ['a', 'b', 'c']
>>> [v for v in l]
['a', 'b', 'c']
>>> [(i, v) for i, v in enumerate(l)]
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> d = {'a': 0, 'b': 1, 'c': 2}
>>> [k for k in d]
['a', 'b', 'c']
>>> [(k, v) for k, v in d.items()]
[('a', 0), ('b', 1), ('c', 2)]
```

```coffeescript
l = ['a', 'b', 'c']
v for v in l
# ['a', 'b', 'c']
[v for v in l]
# [ ['a', 'b', 'c'] ]
[i, v] for i, v in l
# [[0, 'a'], [1, 'b'], [2, 'c']]
d = a: 0, b: 1, c: 2
k for k of d
# ['a', 'b', 'c']
[k, v] for k, v of d
# [['a', 0], ['b', 1], ['c', 2]]
```

##リスト内包表記を使ったフィルタリング

```py
>>> [i for i in range(10) if i % 3 == 0]
[0, 3, 6, 9]
```

```coffeescript
i for i in [0...10] when i % 3 is 0
# [0, 3, 6, 9]
```

##CoffeeScriptのリスト内包表記はもっといろいろできる

```py
>>> for i in range(5)
...     print i
0
1
2
3
4
```

```coffeescript
console.log i for i in [0...5]
# 0
# 1
# 2
# 3
# 4
```

#関数

```py
def func(arg, *args):
    pass
```

```ruby
def func(arg, *args)
end
```

```js
var func = function(arg) {
  var args = 2 <= arguments.length ? Array.prototype.slice.call(arguments, 1) : []
}
```

```coffeescript
func = (arg, args...) ->
```

#関数呼び出し

 Pythonは関数呼び出しに()が必須

```py
>>> def foo(): return 'foo'
>>> foo
<function __main.foo>
>>> foo()
'foo'
```

Rubyは不要

```ruby
def foo
  'foo'
end
p foo
# => foo
def bar(x)
  x
end
p bar 'bar'
# => bar
```

JavaScriptはインスタンス生成時は不要。普通の呼び出し時は必須

```js
var foo = function() {return 'foo'};
console.log(typeof foo);
// 'function'
console.log(foo());
// 'foo'
f = new foo;
console.log(f.construoctor === foo);
// true
```

CoffeeScriptは引数が渡されない場合は()が必要、引数ありの場合は不要

```coffeescript
foo = -> 'foo'
console.log typeof foo
# 'function'
console.log foo()
# foo
bar = (x) -> x
console.log foo 'bar'
# bar
```

#関数の戻り値

PythonとJavaScriptは`return`必須。無ければPythonなら`None`が、JavaScriptなら`undefined`が返る。

```py
>>> def bar(): 'bar'
>>> bar() is None
True
```

```js
var bar = function() { 'bar' };
console.log(bar === undefined);
// true
```

RubyとCoffeeScriptは最後の文が`return`される。

```ruby
def bar
  'bar'
end
bar
# => 'bar'
```

```coffeescript
bar = -> 'bar'
bar()
# 'bar'
```

#クラス

```py
>>> class Klass(object):
...     def __init__(self, name):
...         self.name = name
>>> k = Klass('hoge')
>>> k.name
"hoge"
```

```ruby
class Klass
  attr "name"
  def initialize(name)
    @name = name
  end
end
k = Klass.new 'hoge'
p k.name
# => hoge
```

```js
function Klass(name) {
  this.name = name;
}
var k = new Klass('hoge');
console.log(k.name);
// hoge
```

```coffeescript
class Klass
  constructor: (name) ->
    @name = name
k = new Klass 'hoge'
console.log k.name
# hoge
```

##継承

```py
>>> class Parent(object):
...     def foo(self):
...         print 'parent'
>>> class Child(Parent):
...     def foo(self):
...         super(Child, self).foo()
...         print 'child'
>>> c = Child()
>>> c.foo()
parent
child
```

```ruby
class Parent
  def foo
    p 'parent'
  end
end
class Child < Parent
  def foo
    super
    p 'child'
  end
end
c = Child.new
c.foo
# => parent
# => child
```

```js
function Parent() {}
Parent.prototype.foo = function () { console.log('parent'); };
function Child() {}
Child.prototype = new Parent;
Child.prototype.foo = function () {
  Parent.prototype.foo.call(this);
  console.log('child');
}
var c = new Child;
c.foo();
// parent
// child
```

```coffeescript
class Parent
  foo: ->
    console.log 'parent'
class Child extend 
  foo: ->
    super
    console.log 'child'
c = new Child
c.foo()
# parent
# child
```

#Mixin

```ruby
module Fooable
  def foo
    p 'foo'
  end
end
class Klass
  include Fooable
end
k = Klass.new
k.foo
# => 'foo
```

```coffeescript
# https://gist.github.com/993415
class Mixin
  augment: (t) ->
    (t[n] = m unless n == 'augment' or !this[n].prototype?) for n, m of this
class Fooable extends Mixin
  foo: ->
    console.log 'foo'
class Klass
  constructor: ->
    Fooable::augment @
k = new Klass
k.foo()
# foo
```