Uma xícara de CoffeeScript

Uma xícara de CoffeeScript

Programador tem fama de gostar de café. Se você pertence a este distinto grupo e também gosta de JavaScript, então provavelmente gostará de CoffeeScript.

CoffeeScript é uma linda linguagem que traz o que há de melhor (sintaticamente falando) em outras linguagens como Python e Ruby, e pra completar, também é compilável para JavaScript.

O objetivo deste post é apenas apresentar uma breve introdução da linguagem e suas principais vantagens. Para uma completa referência de CoffeeScript – inclusive instruções de instalação –, recomendo que visite a documentação oficial, que recentemente traduzimos para o português: coffeescript.com.br.

Curiosidades

Adeus ; e {}‘s

Quem programa em Python ou Ruby, acaba detestando esse papo de ter que usar ; ao final das linhas. Outra coisa que também é chata – e sintaticamente feia – é usar {} para delimitar blocos de comando, nesse caso, CoffeeScript apenas considera a indentação do código (assim como em Python).

Objetos

Para definir um simples objeto, até o uso de , é opcional:

bandas =
    rock:
        nome: 'Creedence Clearwater Revival'
        ano: 1967
    funk:
        nome: James Brown
        ano: 1956

Mas se você quiser declarar tudo em uma única linha, deve-se utilizar , normalmente. O JavaScript equivalente ao código acima é:

bandas = {
    rock: {
        nome: 'Creedence Clearwater Revival',
        ano: 1967
    },
    funk: {
        nome: James Brown,
        ano: 1956
    }
};

Interpolação de strings

JavaScript não tem interpolação de strings, então CoffeeScript nos traz esse recurso super útil no estilo de Ruby, usando #{} dentro da string:

numero = 42
string = "O número #{ numero } dividido por 3 é #{ numero / 3 }."

Em JavaScript, precisaríamos realizar a concatenação de strings:

var numero, string;
numero = 42;
string = "O número " + numero + " dividido por 3 é " + (numero / 3) + ".";

Intervalos

Os intervalos (ranges) são expressões que retornam arrays com números sequenciais. Podemos utilizar intervalos para fazer iterações e fatiar (slice) arrays:

# definindo intervalos
sequenciaCrescente   = [0..10] # com .. inclui o último índice
sequenciaDecrescente = [7...3] # com ... exclui o último índice

bebidas = [ 'jack daniel’s', 'heineken', 'stella artois', 'martini', 'smirnoff ice' ]

# fatiamento de array
bebidasDeMacho  = bebidas[0..1]
bebidasDeMenina = bebidas[2..4]

O script acima gera a seguinte saída em JavaScript:

var sequencia, bebidas, bebidasDeMacho, bebidasDeMenina;

sequenciaCrescente   = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
sequenciaDecrescente = [7, 6, 5, 4];

bebidas = [ 'jack daniel’s', 'heineken', 'stella artois', 'martini', 'smirnoff ice' ];

bebidasDeMacho  = bebidas.slice(0, 2);
bebidasDeMenina = bebidas.slice(2, 5);

Compreensões de lista

Outra coisa trazida de Python, compreensões de lista são uma mão na roda. São expressões que executam determinadas ações em arrays, objetos e intervalos, e ainda retornam valores. Por exemplo, vamos percorrer um objeto e retornar strings:

nirvana =
    vocalista: 'Kurt Cobain'
    baixista: 'Krist Novoselic'
    baterista: 'Dave Grohl'

# iterando sobre chaves/valores do objeto
funcoes = for funcao, integrante of nirvana
    "#{integrante} é #{funcao}"

Perceba a diferença (quantidade de linhas e legibilidade) entre essas últimas 2 linhas do código acima e as 9 últimas linhas de JavaScript geradas abaixo:

var funcao, funcoes, integrante, nirvana;

nirvana = {
    vocalista: 'Kurt Cobain',
    baixista: 'Krist Novoselic',
    baterista: 'Dave Grohl'
};

funcoes = (function() {
    var _results;
    _results = [];
    for (funcao in nirvana) {
      age = yearsOld[funcao];
      _results.push("" + integrante + " é " + funcao);
    }
    return _results;
})();

Para fazer um for clássico, simplesmente utilizamos os intervalos. Podemos basicamente fazer de duas maneiras:

# forma mais clássica
for numero in [0...5]
    console.log numero

# forma mais elegante
console.log numero for numero in [0...5]

Operador existencial

Verificar a existência de variáveis em JavaScript é um pouco chato, pois precisa-se efetuar 2 testes. CoffeeScript tem um operador ? que torna essa tarefa muito simples:

rockBand = true if guitarra? and not sertanejoUniversitario?

rockBand será verdadeiro se existir guitarra e se não existir sertanejoUniversitario. A seguir, o JavaScript equivalente:

var rockBand;

if ((typeof guitarra !== "undefined" && guitarra !== null) && !(typeof sertanejoUniversitario !== "undefined" && sertanejoUniversitario !== null)) {
    rockBand = true;
}

Classes

Taí uma coisa que qualquer programador OO sente bastante falta em JavaScript: declarações de classes de maneira mais clara. Isso ocorre porque JavaScript é uma linguagem orientada a protótipos, e trabalhar com prototipação e herança prototipada é um pouco confuso pra quem vem da orientação à objetos. CoffeeScript oferece uma maneira simples de definição de classes e herança, inclusive com construtores mais simples.

class Animal
  constructor: (@nome) ->

  mover: (metros) ->
    alert @nome + " moveu-se #{metros}m."

class Cachorro extends Animal
  mover: ->
    alert "Au au!"
    super 5

class Gato extends Animal
  mover: ->
    alert "Miau!"
    super 45

toto = new Cachorro "Totó, o cachorro"
tom  = new Gato "Tom, o gato"

toto.mover()
tom.mover()

Quer adicionar propriedades ou métodos à sua classe (protótipo) em tempo de execução?

Animal::morrer = ->
  alert "#{@nome} morreu =("

Eu poderia continuar falando das N coisas legais de CoffeeScript – como herança, funções, splats, atribuições de troca, switchs, comparações em cadeia, etc –, mas simplesmente não há necessidade, visto que temos um ótimo e completo guia da linguagem aqui: coffeescript.com.br.

Por enquanto é isso

Haters Gonna Hate

CoffeeScript é um assunto muito polêmico. Eis um link que achei bem engraçado, trata-se da discussão sobre o commit que adiciona o CoffeeScript como padrão no Ruby on Rails. Salientando que esse foi um dos commits mais polêmicos da história do GitHub. Vale dar uma olhada, os nerds se atracaram num grande bate boca com imagens bastante divertidas.

#22