Protótipo de Closures em Java está "feature-complete"

Mais um, em Javascript (copie todo o código, jogue num html e veja no browser):

<script type="text/javascript">
	var lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

	Array.prototype.select = function(selectorFunction) {
		var result = [];

		for (var i = 0; i < this.length; i++) {
			if (typeof selectorFunction == "function" && selectorFunction(this[i])) {
				result.push(this[i]);
			}
		}
		return result;
	}

	document.write(lista.select(function(e) {return e % 2 == 0}));
</script>

Porém, Javascript não tem suporte nativo para filtragem em Array, mas tem closure! Por isso, tive que adicionar um método select no Array.
Fica assim:

Java com closure -> 24 linhas
Javascript -> 11 linhas
Java com closure (apelando pra não considerar customização de ArrayList) -> 9 linhas
Scheme -> 3 linhas
Ruby -> 2 linhas

"

Acho melhor ter uma linguagem que tem várias maneiras de fazer coisas semelhantes de modo elegante do que ter uma linguagem que tenta fazer isso de modo deselegante. Ficou feinho e burocrático utilizar closures em java, e espero que o uso disso não seja abusado no futuro.

T+

Poderíamos migrar todos pra Scala e sermos felizes para sempre :slight_smile:

Toda vida que um recurso novo é adicionado a linguagem, a história se repete. Na época de Generics, muita gente torceu o nariz e no final todos viram que é bom.
Às vezes acho a comunidade mais exigente que o necessário, minha opinião. Vejo linguagens como C# agregarem muitos recursos durante sua evolução, e em Java é a maior ladainha pra colocar algo novo.

Porque em vez de ficar fazendo remendos eles não criam algo novo do zero? :?

[quote=tnaires]Toda vida que um recurso novo é adicionado a linguagem, a história se repete. Na época de Generics, muita gente torceu o nariz e no final todos viram que é bom.
Às vezes acho a comunidade mais exigente que o necessário, minha opinião. Vejo linguagens como C# agregarem muitos recursos durante sua evolução, e em Java é a maior ladainha pra colocar algo novo.[/quote]

Todos quem cara-pálida?

A implementação de generics em java é sebosa e não existe informação nenhuma sobre os genéricos em tempo de execução, obrigando a construção de gambiarras (como passar o Class<T> quando você já passou T em algum lugar, não haver T[]). Uma feature que adiciona um absurdo de complexidade acidental, sem adicionar quase nada em funcionalidades. E a falta de type-inference faz o código generico ser desnecessariamente feio.

E espero que na nova versão eles não façam mais a gente ficar passando Class<T>.

Mas a minha mensagem você entendeu. Eu só devia ter sido mais cuidadoso e ter falado “quase todos”. :stuck_out_tongue:

[EDITADO]
Então reescrevendo:
Na época de Generics, muita gente torceu o nariz e no final quase todos viram que foi melhor.
[/EDITADO]

O remendo é melhor que nada, mas não é o melhor.

Bom, pra mim o que interessa é que agora a consistência das minhas coleções pode ser verificada em tempo de compilação, além de não ter que ficar fazendo casts o tempo todo.
Mas veja só, eu falando que a comunidade é exigente, nem tinha reparado que há uns posts atrás nesse tópico eu tava reclamando da sintaxe de closures também :oops:

[quote=tnaires]Bom, pra mim o que interessa é que agora a consistência das minhas coleções pode ser verificada em tempo de compilação, além de não ter que ficar fazendo casts o tempo todo.
Mas veja só, eu falando que a comunidade é exigente, nem tinha reparado que há uns posts atrás nesse tópico eu tava reclamando da sintaxe de closures também :oops: [/quote]

O cast está lá, só que agora ele se esconde atrás de um <String> e mesmo com código “genérico” é possível causar ClassCastExceptions, simplesmente porque a implementação de genericos não existe, é uma coisa que está na imaginação dos programadores Java :slight_smile:

Todas as propostas de reificação que eu vi em java quebram a compatibilidade por completo do código genérico atual e eu duvido muito que eles tenham interesse em fazer isso. Eles deveriam fazer igual a MicOsoft, admitir que a implementação é chula e escrever tudo denovo. Ou esquecer Java e começar a dar mais valor a outras linguagens da JVM, como Scala.

Do jeito que a coisa tá indo com o Java, só um pensamento vem a minha cabeça:

“Eu não sei com que IDEs o Java 8 será programado, mas o Java 9 será com paus e pedras.”

Olá senhores,

Este recurso me lembra a execução de blocos de código que existe/existiam em clipper vrs. 5.x

Evidencia 1

CLS ? EVAL( { | nVar | nVar * nVar }, 6 )

Evidencia 2

aVar := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } bDouble := { | nVal | QOUT( TRANSFORM( ( nVal * 2 ), "@B 999")) } AEVAL( aVar, bDouble )

Evidencia 3

A := {'GARY HALL', 'FRED SMITH', 'TIM JONES'} B := { | X, Y | X > Y } asort(A, B)

Vou parar com as evidencias de utilização em clipper porque simples as formas de uso de blocos de códigos nesta linguagem deve beirar uma centena.

Me parece que na linguagem Ruby tem algo semelhante:

array = [1, 'hi', 3.14] array.each { |item| puts item }

Pois bem, este recurso já existe fazem uns 15 ou 16 anos :shock:

Causou grande repercussão na linguagem clipper na época, pelo fato dela ser procedural e este recurso permitir a construção de algoritimos mais “sofisticados” e aumentando bastante o poder das estruturas dinamicas da linguagem.

O problema é que fazer a manutenção em algoritimos construidos com este recurso do tipo “sedutor” era dramático, porque o desenvolvedor geralmente aplicava isto como solução para tudo. Posso estar errado (e quero estar) mas muitos vão esquecer da OOP e aplicar isto na primeira dificuldade que aparecer.

Talvez este recurso se encaixe bem em linguagens como Ruby porque as propostas estão (IMO) bastante relacionadas, mas isto não diminui os possíveis problemas que podem ser causados por ele.

P.S. Com certeza isso irá fazer com que novos livros ou capitulos de livros sobre melhores práticas sejam editados enchendo ainda mais os bolsos de alguns.

flw

E o que já está implementado? Fica pra lá?

Não, faz a mesma coisa que um espremedor com a laranja

[quote=fantomas]Olá senhores,

Este recurso me lembra a execução de blocos de código que existe/existiam em clipper vrs. 5.x

Evidencia 1

CLS ? EVAL( { | nVar | nVar * nVar }, 6 )

Evidencia 2

aVar := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } bDouble := { | nVal | QOUT( TRANSFORM( ( nVal * 2 ), "@B 999")) } AEVAL( aVar, bDouble )

Evidencia 3

A := {'GARY HALL', 'FRED SMITH', 'TIM JONES'} B := { | X, Y | X > Y } asort(A, B)

Vou parar com as evidencias de utilização em clipper porque simples as formas de uso de blocos de códigos nesta linguagem deve beirar uma centena.

Me parece que na linguagem Ruby tem algo semelhante:

array = [1, 'hi', 3.14] array.each { |item| puts item }

Pois bem, este recurso já existe fazem uns 15 ou 16 anos :shock:

Causou grande repercussão na linguagem clipper na época, pelo fato dela ser procedural e este recurso permitir a construção de algoritimos mais “sofisticados” e aumentando bastante o poder das estruturas dinamicas da linguagem.

O problema é que fazer a manutenção em algoritimos construidos com este recurso do tipo “sedutor” era dramático, porque o desenvolvedor geralmente aplicava isto como solução para tudo. Posso estar errado (e quero estar) mas muitos vão esquecer da OOP e aplicar isto na primeira dificuldade que aparecer.

Talvez este recurso se encaixe bem em linguagens como Ruby porque as propostas estão (IMO) bastante relacionadas, mas isto não diminui os possíveis problemas que podem ser causados por ele.

P.S. Com certeza isso irá fazer com que novos livros ou capitulos de livros sobre melhores práticas sejam editados enchendo ainda mais os bolsos de alguns.

flw[/quote]

Closure não é somente passagem de função de um lugar para outro! Uma função com suporte a closure captura o contexto onde foi criado. Coisa que em linguagens procedurais não acontecia (como: VB, Clipper, C) por uma razão simples: só haviam dois contextos, o local (dentro da função) e o global. E os dois eram sempre acessados onde quer que a função fosse executada.

Em linguagem OO, existe também o contexto do objeto. E com isso, não basta criar uma função e executá-lo por aí, é necessário que esta tenha a referência do objeto que a criou. Essa obtenção de referência, é o closure!

Veja mais em http://pt.wikipedia.org/wiki/Closure .

[quote=Maurício Linhares]
A implementação de generics em java é sebosa e não existe informação nenhuma sobre os genéricos em tempo de execução, obrigando a construção de gambiarras (como passar o Class<T> quando você já passou T em algum lugar, não haver T[]). Uma feature que adiciona um absurdo de complexidade acidental, sem adicionar quase nada em funcionalidades. E a falta de type-inference faz o código generico ser desnecessariamente feio.[/quote]

O motivo para não haver T[] é que arrays no java são covariant:

Object[] numbers = new Long[1]; numbers[0] = "ops..."; //vai ter problemas em tempo de execução...!

Para resolver esse problema use LIST, pois é invariant (só aceita mesmo tipo) e se haver algo errado nem deixa compilar.

Ou seja, isso pelo menos garante mais qualidade pro código. Eu não sei como conseguem implementar em outras linguagens estáticas o T[], a não ser que as arrays desde o começo fossem invriants, pq do contrário é improvável que admitam covariants em generics.

Hmmm…

[quote=renato3110]Closure não é somente passagem de função de um lugar para outro! Uma função com suporte a closure captura o contexto onde foi criado. Coisa que em linguagens procedurais não acontecia (como: VB, Clipper, C) por uma razão simples: só haviam dois contextos, o local (dentro da função) e o global. E os dois eram sempre acessados onde quer que a função fosse executada.

Em linguagem OO, existe também o contexto do objeto. E com isso, não basta criar uma função e executá-lo por aí, é necessário que esta tenha a referência do objeto que a criou. Essa obtenção de referência, é o closure!

Veja mais em http://pt.wikipedia.org/wiki/Closure .[/quote]

Valeu pelo esclarecimento…

Só quiz deixar claro que:

a) A idéia na minha opinião não é nova, como disse ela dever ter uns 15 anos e provavelmente o Turbo Pascal também já tinha coisa parecida (e melhor) 4 ou 5 anos antes disso, ou seja, 20 anos se não for mais rsrsrsrs.

b) Pelo fato do clipper ser procedural e java ser orientado a objetos e +15 anos terem se passado desde quando a ideia apareceu é claro que alguma coisa diferente tinha que ter.

c) Os códigos feitos com code blocks se transformaram em um inferno em termos de manutenção e conceito, e com os “closures”, na minha opinião, não será diferente. Diria que será pior porque além dos BOLOVO teremos os closures para atormentar ainda mais :frowning: .

[]'s

Mas não fui eu quem disse aquilo :smiley: