Scala parece que deixou o Groovy para trás como a grande vedete das linguagens criadas para a JVM. Tem até gente dizendo que a Sun deveria declarar que Java 8 vai ser Scala e ponto final.
Mas alguém aqui já brincou pelo menos com Scala? O que é legal nela? O que não é tão legal? Eu pergunto do ponto de vista prático mesmo, não “a nível de pureza sintática.”
Sim, já fiz até um protótipo de quão mais limpa, legível e poderosa a JSR-310 se fosse implementada em Scala.
O que tem de bom em Scala?
[list]Não ter primitivos[/list]
[list]Operadores serem métodos[/list]
[list]Inferência de tipos[/list]
[list]Generics com covariância e contravariância na declaração e não no uso[/list]
[list]Implicit conversions[/list]
[list]Suporte a closures e functions[/list]
[list]Suporte a object[/list]
[list]Suporte a structural types[/list]
[list]Existential types[/list]
[list]Pattern matching[/list]
[list]Suporte a definição de visibilidade muito mais refinado[/list]
[list]Self-types[/list]
[list]A API[/list]
[list]Ter sido desenhada pra gerar bytecode (isso alguns discordariam)[/list]
[list]Interoperabilidade limpa com Java[/list]
E mais algumas coisas que eu esqueci. O que tem de ruim? Falta de doc, suporte inferior ao Java nas IDEs e não estar todo mundo usando
Scala é bem legal, porém o sistema de tipos é incrivelmente complexo. Apesar de ser um ótimo exercício teórico, ter virtual types e generic types na mesma linguagem é muito perigoso do ponto de vista de uniformidade e simplicidade. Apesar de ter casos que um resolve que o outro não e vice-versa, deveriam ter escolhido apenas um dos dois.
Se generics já tem algumas sutilezas, virtual types com path dependant types são bem complicados de explicar. Sem falar que produzir um compilador que gere mensagens de erro úteis é incrivelmente dificil (basta ver que nhaca que o compilador do scala vomita nesse caso).
Porém, no entanto, acho que o maior problema de Scala é a plataforma no qual executa, não a linguagem em sí.
Vocês podem dar uma palhinha de como ficam os generics em Scala? No Java eu já acho que tem umas coisas piradas, ainda mais quando mistura com autoboxing…
A sintaxe me pareceu incrivelmente enrolada e complexa. Java ganhou o mainstream porque a sintaxe era bem fácil. Basicamente fez com que OO fosse acessível para meros mortais.
E agora então com Ruby, fica ainda mais complicado ter que fazer um closure assim:
object Timer
{
def oncePerSecond(callback: () => unit): unit =
{
while (true)
{
callback()
Thread.sleep(1000)
}
}
def timeFlies(): unit =
{ Console.println("Time flies when you're having fun(ctionally)..."); }
def main(args: Array[String]): unit =
{
oncePerSecond(timeFlies)
}
}
Ao invés de assim:
def oncePerSecond
while 1 do
yield
sleep 1
end
end
def timeFlies
puts "Time flies when you're having fun(ctionally)..."
end
oncePerSecond { timeFlies }
Acho que o pessoal deveria se inspirar no Ruby e fazer linguagens com uma sintaxe parecida… E que rodem sem problemas dentro da JVM como a Scala…
Acho também que poderiam haver outros projetos competindo com o JRuby. Não precisa ser 100% compatível com o Ruby. Precisa ter uma sintaxe parecida, as sacadas mais importantes (closures, tudo é objeto, tudo é expressão, alias, operadores são métodos, etc) e rodar bonito dentro da JVM. Não sei se foi essa a intenção do Scala, mas a sintaxe ficou intimidadora… Talvez se removesse os tipos ou deixásse-os opcionais como ActionScript ficaria mais legível?
Em Scala, generics são especificados usando colchetes ao invés do par menor/maior:
class List[+T] {
def elements : Iterator[T] {
// logica para gerar o iterator
}
}
O legal é a declaração da covariância/contravariância junto com o tipo genérico. Ao invés de fazer como em Java, onde em todo lugar que você usa uma Collection, você normalmente declara como: Collection<? extends String>, em Scala você tem a opção de fazer isso na definição do tipo genérico, uma vez só.
def oncePerSecond(callback : => unit) =
while (true) {
callback
Thread.sleep(1000)
}
def timeFlies() = println("Time flies when you're having fun(ctionally)...")
oncePerSecond(timeFlies)
Os tipos só são requeridos quando não podem ser inferidos, as chaves podem ser suprimidas quando o método tem apenas uma expressão e para rodar como script, não é necessário um object.
Existencial types existem porque Scala não possui wildcards e da necessidade de operar sobre membros com argumentos genéricos. Eles preferiram adotar que o tipo tenha variância em vez de usar wildcards, não que seja ruim, mas se perde um pouco de expressividade quando a variância fica no tipo genérico em sí.
A utilidade de tipos existenciais é quando vc quer criar algo como:
void copy_1(<List><?> a, List<?> b) { a.set(0, g.get(0)); } // não compila
def copy_1[T](<List><T> a, List<T> b) for some {type T} { a.set(0, g.get(0)); } // agora compila
Eu também sou um dos que gostaram do Scala. Algo que me atraiu muito nele é o fato do pessoal já estar brincando com Scala + frameworks Java. O post que o Sérgio colocou uns tópicos atrás usando Menta + Scala mostra como a interoperabilidade entre Scala e código java existente é boa.
Particularmente, não sou um dos que vestiram a camisa do Ruby ou Rails (sem um motivo especial), mas era fato que java tava dando no saco. Neste caso, juntar um bom framework web (em IMHO, Wicket, por exemplo) e Scala, é simplesmente ótimo!
Resumindo, gostei do Scala e principalmente pelo fato de eu poder considerar e optar por um framework java em uma decisão de arquitetura sem necessariamente me amarrar a linguagem java e seus efeitos colaterais… rsrs…
Começo a desconfiar que Ruby dá um pau no Scala. Se eu estiver enganado por favor se manifestem.
Scala não tem metaprogramação.
Scala não tem continue nem break.
Scala não tem suporte a regex no nível da linguagem. (parece tão ruim quanto Java)
Scala é distribuído em jars, assim como Java. (Se uma biblioteca está com algum bug, vc tem que baixar o source, modificar e gerar o jar novamente. Com Ruby vc faz isso em um segundo!)
Scala não possui nenhum livro e nenhum suporte. (ok, isso vai mudar em breve)
A sintaxe de Scala é mais complexa e enrolada que a sintaxe de Ruby.