Na maioria das linguagens com caracteristicas funcionais esse exemplo do filtro e possivel em 1 linha de codigo. Passa ser mais importante entao a sintaxe da linguagem. Neste aspecto Ruby nao e das piores mas acho que poderia ser melhor.
editado: onde escrevi sintaxe queria dizer na verdade ‘expressividade’.
[quote=louds][quote=peczenyj]public class X {
public X doSomething() { /* statement */ return this; }
}
Como posso criar uma closure que retorne ela mesma? Faz sentido?
[/quote]
Usa o Y Combinator.[/quote]
Agora boiei tb.
Primeiro nao entendi porque uma funcao se daria ao trabalho de retornar ela mesma. Eu fico imaginando passar ou receber essa funcao e alguem precisar executa-la para que retorne a propria (digo ja enclosured).
Y Combinator eu sei apenas que e pra criar funcoes recursivas… mas como nao consegui entender o problema muito menos consegui ligar com a solucao.
Talvez fizesse mais sentido uma funcao (e nao uma closure) que retornasse ela mesma…
Alguém pode me dar um exemplo prático de, como closures poderia resolver um problema, o qual não o consegueriamos sem ele?
Só para eu entender onde realmente eu poderia empregá-lo…
Muita gente passa a vida inteira sem sentir a menor falta delas. Closures, da maneira que estamos nos referindo aqui é uma maneira de usar higher order procedures, que nos permitem ‘aumentar’ nosso poder de abstração e a expressividade dos nossos programas. Aqui tem um ótimo exemplo de como expressar derivadas usando high order procedures, é menos complicado do que parece.
Primeiro nao entendi porque uma funcao se daria ao trabalho de retornar ela mesma. Eu fico imaginando passar ou receber essa funcao e alguem precisar executa-la para que retorne a propria (digo ja enclosured).
Y Combinator eu sei apenas que e pra criar funcoes recursivas… mas como nao consegui entender o problema muito menos consegui ligar com a solucao.
Talvez fizesse mais sentido uma funcao (e nao uma closure) que retornasse ela mesma…[/quote]
O YC permite a função ter uma referencia a si própria, agora se ela vai se chamar recursivamente ou simplesmente retornar o valor é indiferente.
[quote=louds]
O YC permite a função ter uma referencia a si própria, agora se ela vai se chamar recursivamente ou simplesmente retornar o valor é indiferente.[/quote]
Louds, vc tem razao,
E pq ando lendo sobre cultura lisp onde closures sao implementadas na linguagem desde sempre pra trabalhar com funcoes anonimas.
Mas pensando melhor sobre nomenclatura em outras linguagens onde closures sao implementadas posteriormente, talvez seja melhor mesmo falar “retornar uma closure”, pra diferenciar de outro mecanismo utilizado ate entao pela linguagem para passar/retornar blocos de codigo (classes internas anonimas em Java). Parece que em lisp essa diferenciacao nao é importante do ponto de vista pro programador.
[quote=facholi]Alguém pode me dar um exemplo prático de, como closures poderia resolver um problema, o qual não o consegueriamos sem ele?
Só para eu entender onde realmente eu poderia empregá-lo…[/quote]
Da mesma forma que não existe problema que OO resola que não seja resolvido antes você não vai encontrar um exemplo destes. A questão é apenas a maneira como resolvemos.
[quote=cmoscoso][quote=louds]
O YC permite a função ter uma referencia a si própria, agora se ela vai se chamar recursivamente ou simplesmente retornar o valor é indiferente.[/quote]
Louds, vc tem razao,
E pq ando lendo sobre cultura lisp onde closures sao implementadas na linguagem desde sempre pra trabalhar com funcoes anonimas.
Mas pensando melhor sobre nomenclatura em outras linguagens onde closures sao implementadas posteriormente, talvez seja melhor mesmo falar “retornar uma closure”, pra diferenciar de outro mecanismo utilizado ate entao pela linguagem para passar/retornar blocos de codigo (classes internas anonimas em Java). Parece que em lisp essa diferenciacao nao é importante do ponto de vista pro programador.
O que vc acha?[/quote]
Acho que levará bastante tempo até a comunidade realizar o poder do que é possível com closures.
Vejo isso pelo .NET. As pessoas ainda estão explorando muito o C# 3.0.
O problema do Java é que ele ficou “institucionalizado” - é uma linguagem didática e comercial, como se fosse um Cobol moderno (sempre que quero chocar um Java-maníaco, digo para ele que “Java == COBOL”).
E é por isso que acabam se opondo às mudanças; como se sabe, é mais difícil fazer uma mudança que não destrua tudo que já foi feito - como foi o caso do “generics”, que tentou ser retrocompatível com os programas antigos e ficou extremamente difícil de entender - que uma mudança que destrua tudo (como é o caso de cada versão do C# que aparece).
A nova mudança (closures), que tem de ser retrocompatível com os programas antigos, também é difícil de entender, e fica um pouco abaixo das expectativas - se a Sun simplesmente fosse a única dona do Java, e ela se notabilizasse por destruir tudo que foi feito antes - o que não é bem o que a Sun faz; programas antigos em C que rodam em antigas máquinas Sparc continuam rodando nas novas de hoje em dia sem problemas - então ela poderia fazer algo mais simples, como o que apareceu no C# 3.0.
O Neal Gafter, embora não trabalhe mais para a Sun, compreende o que deve ser feito para não afetar os programas antigos, e é por isso que a parte de Closures é menos ambiciosa e mais complicada do que ela poderia ser.
Pro Louds:
Sera que os programadores nao explorarao o poder de closures em Java por falta de ambicao na implementacao (o thingol colocou como ‘a coisa certa’, ignorar compatibilidade retroativa) ou por que os proprios programadores nao conhecem tecnicas de programacao funcional?
Pro Thingol:
Deve ter sido mesmo um trabalho do cao pra implementar closures em Java mas vc acha mesmo que a interface ficou tao ruim ao ponto de ser pior pra entender do que todas aquelas regrinhas especificas do uso de classes internas, sintaxe fora do convencional para classes anonimas, ter que declarar variaveis final?
A minha opiniao é que sim, simplicidade na implementacao importa mas compatibilidade tb é importante ate certo ponto.
“Java == COBOL Moderno”, vc disse tudo aqui, eu tenho a mesma impressao mas… isso é necessariamente algo ruim?
[quote=sergiotaborda][Bruno Laturner]invoke em que ser chamado explicitamente?
Acho sacanagem ter que fazer soma.invoke(2,3) em vez de soma(2,3). Se closures são funções, ajam como tal.[/quote]
Segundo autor da fonte confiável, “Anonima” vou colocar aqui a resposta que achei plausível.
“Closure não será incorporado pela linguagem (pelo menos em Java 7) segundo palavras do próprio Mister M (Michael Nascimento) e mesmo na comunidade internacional, houve uma arrefecida desse tópico.”
Agora segundo, anonimo, ai vem a resposta !!!
A sua afirmação sobre uma forma de se declarar uma classe simplificada que possuirá apenas uma função não deixa de ser verdade no contexto de Java.A primeira utilização seria para contemplar um problema que a comunidade java reclama, a verborragia da linguagem.
Seria melhor fazer isso:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Teste{
public static void main(String[] args){
List<Endereco> l = new ArrayList<Endereco>();
l.add(new Endereco("Rua dos Batatais",327));
l.add(new Endereco("Rua das Cebolas",127));
Collections.sort(l,new Ordenador());
for (Endereco endereco : l) {
System.out.println(endereco.getRua());
}
}
}
ou isso (usando a notação proposta pelo Neal Gafter)?
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Teste{
public static void main(String[] args){
List<Endereco> l = new ArrayList<Endereco>();
l.add(new Endereco("Rua dos Batatais",327));
l.add(new Endereco("Rua das Cebolas",127));
int(Object, Object) funcao = (Object e1, Object e2){
return ((Endereco)o1).getNumero()-((Endereco)o2).getNumero();
};
Collections.sort(l,funcao);
for (Object o : l) {
System.out.println(((Endereco)o).getRua());
}
}
}
–Classe Endereco usada acima –
public class Endereco {
private String rua;
private int numero;
public Endereco(String string, int i) {
this.rua = string;
this.numero = i;
}
String getRua() {
return rua;
}
void setRua(String rua) {
this.rua = rua;
}
int getNumero() {
return numero;
}
void setNumero(int numero) {
this.numero = numero;
}
}
PS: haveria uma nova sobrecarga no Collections.sort, para aceitar uma “função”
Essa seria então a idéia inicial: Criar um açúcar sintático eliminando a regra de que tudo tem de ser uma classe em java(nesse contexto, “explodimos” uma das regras de Ouro em Java).
Isso é bom, por limpar a quantidade código digitada pelo desenvolvedor, mas essa seria a resposta mais simplória.
O uso de closures não é apenas isso. Ele é muito mais do que isso!
Se Java aceitar tal facilidade do jeito que foi concebida, e suportar o método invoke que utilizou no código abaixo nós teremos uma das qualidades mais interessantes que uma linguagem ofereceria: a injeção de código em lacunas a serem preenchidas pelos desenvolvedores.
Design patterns como o Template, não precisariam ser implementados da maneira que existe em muitos frameworks em Java (exemplo classico é o que Struts faz).
.NET caminhou para esse lado, ao suportar os métodos anônimos (anonymous methods) e que oferece atualmente o LinQ, que é uma maneira de acessa a camada de dados de maneira transparente.
Outro ponto, bem citado pelo Joel Spolsky e é bem verdade, está no seguinte link:
O que acontece é que as classes eliminadas neste caso são boilerplates em forma de classes (frequentemente anônimas) que não representam nenhuma entidade real do sistema e estão lá apenas por conta de limitações da linguagem. Ou seja, não ocorre nenhuma explosão da OO, e sim flexibilização da linguagem que acaba por abstrair a necessidade de criar-se uma classe específica para um trabalho.
Essa seria então a idéia inicial: Criar um açúcar sintático eliminando a regra de que tudo tem de ser uma classe em java(nesse contexto, “explodimos” uma das regras de Ouro em Java).
[/quote]
Essa regra de ouro eu não conheço. Nem tudo é objeto em java. int, long .etc não são objetos.[/quote]
Java é uma linguagem fortemente orientada a objetos e tipos. Todas as estruturas são objetos.
int,long etc… não são estruturas. Mas os primitivos são exceções ha regra introduzidos apenas por questões de performance e limitação (lembre-se que Java foi criado originalmente para setop boxes com ambientes limitados. isso fico enrraizado na linguagem e o objetvo continua válido ainda hoje. )
Por isso em java temos tipos primitivos e objetos. Objetos por principio e primitivos por questões tecnicas de performance , etc…
Agora, introduzindo um novo tipo chamado “função” ele seria primitivo ou objeto ?
O ponto é que Java tem as suas estruturas amarradas como objetos. Então ,sendo uma função uma estrutura ela deveria ser um objeto. Se ela não for ela será um primitivo. Mas ser um primitivo viola a regra de que apenas os primitivos são primitivos e o resto são objetos. Por outro lado estariamos confiando que uma função é um tipo especial de primitivo já que não ha promoção entre int e function, mas ha entre int e double, por exemplo. Então a escolha recai logicamente em que função tem que ser um objeto.
E é isso que os Function Types são. Objetos que implementam interfaces especiais. Primitivos continuam sendo primitivos e o resto são objetos.
Porderiamos abrir um terceiro tipo e java passaria a ter primitivos, objetos e funções.
Sendo que primitivo é uma exceção a objeto , função seria uma exceção a ambos. Isso trás vários problemas tecnicos e até fiolosoficos. A escolha de tornar função objetos é simples, clara e de acordo com a politica usada até agora. Até anotations são objetos. E repare que eles são completamente intropectivos ( não pdoe dar um new em annotation). function type segue o mesmo caminho.
Isso não é verdade. A distinção existe por pura incompetência dos designers da linguagem e máquina virtual. A CLR não possui qualquer forma de tipo primitivo
e tem performance na mesma categoria do Java. Alimentar um mito envolva desses erros é um enorme desserviço a todos aqui no GUJ.
Essa discussão de primitivo ou objeto é enraizada na ignorância da distinção entre ambos.
Não faz sentido argumentar em cima disso quando, fundamentalmente, deveriam questionar sobre
quais carregam semântica de value type/scalar ou reference type.
Pois está a distinção dos tipos em Java rotulados de primitivos por falha dos designers da linguagem.
Curiosamente, esta é uma exigência feita a mais de uma década para a Sun, suportar tipos escalares
arbitrários.
[quote=sergiotaborda]
O ponto é que Java tem as suas estruturas amarradas como objetos. Então ,sendo uma função uma estrutura ela deveria ser um objeto. Se ela não for ela será um primitivo. Mas ser um primitivo viola a regra de que apenas os primitivos são primitivos e o resto são objetos. Por outro lado estariamos confiando que uma função é um tipo especial de primitivo já que não ha promoção entre int e function, mas ha entre int e double, por exemplo. Então a escolha recai logicamente em que função tem que ser um objeto.
E é isso que os Function Types são. Objetos que implementam interfaces especiais. Primitivos continuam sendo primitivos e o resto são objetos.
Porderiamos abrir um terceiro tipo e java passaria a ter primitivos, objetos e funções.
Sendo que primitivo é uma exceção a objeto , função seria uma exceção a ambos. Isso trás vários problemas tecnicos e até fiolosoficos. A escolha de tornar função objetos é simples, clara e de acordo com a politica usada até agora. Até anotations são objetos. E repare que eles são completamente intropectivos ( não pdoe dar um new em annotation). function type segue o mesmo caminho. [/quote]
Seu questionamento é completamente descabido. Pois uma closure é isomorfa a um tipo por referência, a um objeto. Anotações são tipos comuns a linguagem e a questão
de poderem ser usadas para anotar membros é ortogonal, elas são apenas uma categoria particular de interfaces.
Sérgio, por favor, faça sua lição de casa antes de sair disseminando desinformação.
[quote=louds][quote=sergiotaborda]
Java é uma linguagem fortemente orientada a objetos e tipos. Todas as estruturas são objetos.
int,long etc… não são estruturas. Mas os primitivos são exceções ha regra introduzidos apenas por questões de performance e limitação (lembre-se que Java foi criado originalmente para setop boxes com ambientes limitados. isso fico enrraizado na linguagem e o objetvo continua válido ainda hoje. )
Por isso em java temos tipos primitivos e objetos. Objetos por principio e primitivos por questões tecnicas de performance , etc…
[/quote]
Isso não é verdade. A distinção existe por pura incompetência dos designers da linguagem e máquina virtual. A CLR não possui qualquer forma de tipo primitivo
[/quote]
Devo compreender das suas palavras que vc só usa Long, Integer, Boolean, Double , etc… nos seus programas ? e nunca long, int , boolean , double ?
Devo compreender das suas palavras que escreve ifs assim :
if (a.booleanValue()){
// do something
}
Vc quer descer em um nivel que não estava na mensagem que respondi.
[quote=louds]
Chame o que quiser. Mas quando vc faz :
Annotation x;
e usa reflection para obter x , x não é um tipo primitivo. Da mesma forma que function type também não é tipo primitivo. Esse era o ponto. A regra de ouro citada é exatamente essa “apenas os primitivos são primitivos”.
Que o mesmo que dizer que “em java tudo são objetos”. A exceção - sendo um erro ou não - é uma exceção à regra.