Gostaria de saber quais são as diferenças técnicas de implementação entre C # e Scala e como as duas soluções se comparam às idéias e preocupações de implementação expressas no email Peek Past lambda de Brian Goetz, enviado à lista de discussão do Project Lambda (JSR 335) ?
Do email:
Exploramos o caminho de "talvez lambdas devessem ser apenas instâncias de classe interna, isso seria realmente simples", mas finalmente chegamos à posição de "funções são uma direção melhor para o futuro da linguagem".
e ainda mais:
A visão lambdas-são-objetos do mundo entra em conflito com esse possível futuro. A visão lambdas-são-funções do mundo não existe, e preservar essa flexibilidade é um dos pontos a favor de não sobrecarregar as lambdas com a aparência de objeto.
Conclusão:
Lambdas-são-funções abre portas. Lambdas são objetos os fecha.
Preferimos ver aquelas portas abertas.
E algum comentário de uma pessoa no tópico do Reddit diz:
Na verdade, enviei um e-mail a Neal Gafter sobre isso e para meu entendimento limitado de sua explicação C # e o design atual do Java é bastante semelhante, pois os Delegados são na verdade objetos e não tipos de funções. Parece que ele acredita que Java deve aprender com as desvantagens das lambdas de C # e evitá-las (assim como o C # aprendeu com as desvantagens de Java e as evitou no início).
Por que a abordagem "Lambdas são funções" possibilita mais oportunidades no futuro do que "Lambdas são objetos"? Alguém pode explicar quais diferenças existem e como elas influenciam a forma como o código seria escrito?
Vendo que as coisas no Scala "simplesmente funcionam", continuo pensando que estou perdendo algo sobre as abordagens adotadas / propostas em C # / Java (8), provavelmente está relacionado a preocupações sobre compatibilidade com versões anteriores?
Respostas:
Eu acho que a discussão sobre objetos versus funções é um arenque vermelho. Se a pergunta for: "Um lambda é uma função ou um objeto?" a resposta deve ser sim .
Esse é o objetivo das funções de primeira classe: elas não são tratadas de maneira diferente de qualquer outro tipo. O Java já consegue ignorar principalmente as diferenças entre os tipos Object e primitivo (e Scala se sai melhor ainda), portanto, se um lambda é uma subclasse de Object ou se é um novo tipo primitivo ou algo mais não é realmente importante para a linguagem. O importante é que você pode colocar suas lambdas em coleções, passá-las para serem chamadas, chamá-las e fazer qualquer outra coisa que você queira fazer com um objeto ou método.
O Scala realiza isso usando um objeto wrapper que possui um método chamado
apply
que pode ser chamado justamente()
, fazendo com que pareça uma chamada de método. Isso funciona esplendidamente; Na maioria das vezes, você nem precisa se preocupar se possui um método ou está chamando a aplicação de um objeto de função.fonte
Pelo que entendi, é mais sobre como as lambdas são consideradas no nível do idioma principal. Como o email diz,
Eu acho que resume bem a sua pergunta. Se você declarar que "lambdas são objetos", então eles são apenas um objeto de uma classe específica e você está preso a isso. Por outro lado, se você declarar "lambdas são funções", semanticamente você terá um campo de jogo muito mais rico. O Java 1.7 pode compilá-los em objetos, para que sejam praticamente idênticos nesse ponto.
Mas o Java 1.8, ou 1.9, pode trazer mudanças na linguagem (como tipos estruturais reificados) do que permitir que funções sejam usadas de maneiras muito mais flexíveis. Se "lambdas fossem objetos", essas alterações não seriam compatíveis com versões anteriores e você teria que introduzir um novo conceito ainda mais, para não quebrar o código existente das pessoas. Mas, se
javac
apenas silenciosamente convertendo lambdas em objetos nos bastidores, o novojavac
pode convertê-los para o que quiser, desde que a semântica ainda seja válida.fonte
foreach
,map
,filter
às coleções.Principalmente, ele simplesmente não quer se comprometer muito cedo com alguma coisa. Não vejo nenhuma razão além do apagamento que ele apresentou, mas essa é realmente uma razão muito forte.
Considere estes métodos no Scala
Regex
:Seria mais simples se eles fossem simplesmente isso:
Infelizmente, isso não é possível, porque essas duas funções são idênticas sob apagamento. Mas tudo bem, essas funções fazem coisas um pouco diferentes; portanto, um nome diferente pode ser justo o suficiente.
No entanto, a
Match
é algo muito útil, mas na maioria das vezes você deseja a correspondênciaString
ou a lista de subgrupos. Gostaríamos de ter o seguinte:Não é possível, por causa do apagamento. Eu escolhi esse exemplo em particular porque estava diretamente envolvido com ele, mas já vi pelo menos meia dúzia de perguntas no Stack Overflow, onde as pessoas perguntam por que uma sobrecarga é ilegal, causada por esse problema exato.
E, então, considere que a correspondência de padrões do Scala e do Java
instanceof
são efetivamente inúteis por causa do apagamento.Eu acho que é justo adiar os tipos de função até que esse problema seja resolvido. Afinal, existem muitas linguagens na JVM, e não é como se o Java fosse uma linguagem em rápida evolução.
fonte