mboost-dp1

Sun
- Forside
- ⟨
- Forum
- ⟨
- Nyheder
Det var da godt nok en afskyelig syntaks. Hvorfor er det at JCP ikke bare har valgt at dublikere C#?
Det virker så latterligt at man vælger sådan en dårlig syntaks, fuld af støj, og strong-typed argumenter, som slet ikke burde være nødvendige, da man allerede ved hvad typerne skal være.
Fjolser, alle sammen.
Hvis man ikke kan se pointen med closures og lambda, så må det være fordi man ikke forstår dem, eller aldrig har brugt dem.
Det giver så meget mere elegant kode, som er nemmere at forstå, maintaine, og har færre chancer for fejl.
Det virker så latterligt at man vælger sådan en dårlig syntaks, fuld af støj, og strong-typed argumenter, som slet ikke burde være nødvendige, da man allerede ved hvad typerne skal være.
Kritikken følger i kølvandet på de mange års debat, der har været hidtil, om hvordan closures bør implementeres i Java.Og om Java overhovedet skulle have closures, fordi visse personligheder foretrak det som et purt sprog, og mente at flere features gjorde sproget dårligere.
Fjolser, alle sammen.
Hvis man ikke kan se pointen med closures og lambda, så må det være fordi man ikke forstår dem, eller aldrig har brugt dem.
Det giver så meget mere elegant kode, som er nemmere at forstå, maintaine, og har færre chancer for fejl.
Er der forresten nogen som ved om Java 7 så får et yield[1] statement?
Ellers bliver det meget klodset at skulle implementere sine egne extensions med en lambda selector, og retunere en brugbar iterator.
[1] http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80).aspx
Ellers bliver det meget klodset at skulle implementere sine egne extensions med en lambda selector, og retunere en brugbar iterator.
[1] http://msdn.microsoft.com/en-us/library/9k7k7cf0(VS.80).aspx
Jeg har kun ét ord til jer: Scala
http://www.scala-lang.org/
Scala er til dem, som ikke gider skrive kode som:
ArrayList<String> lst = new ArrayList<String>();
Det er lidt ligesom at høre en Rasmus Seebach sang...
http://www.scala-lang.org/
Scala er til dem, som ikke gider skrive kode som:
ArrayList<String> lst = new ArrayList<String>();
Det er lidt ligesom at høre en Rasmus Seebach sang...
Windcape (1) skrev:Det var da godt nok en afskyelig syntaks. Hvorfor er det at JCP ikke bare har valgt at duplikere C#?
Det siger du jo altid når nogen snakker om java...
Jeg synes det ser fornuftigt nok ud, men jeg har ikke kigget nærmere på de mere komplicerede udtryk...
class CountingSorter {
/* @Shared ? */ int count = 0;
void sort(List<String> data) {
// Field 'count' is in scope, so the lambda expression may use it
Collections.sort(data,
#(String a, String b) { CountingSorter.this.count++; return a.length()-b.length(); });
}
}
Hvis folk gerne vil udenom version2
Og hvem er det der har så meget jord i hovedet at de tager David Heinemeier Hansson seriøst at any rate? Hans meninger kan jo kortes ned til smuk kode >>>>>> performance.
Windcape (1) skrev:Det virker så latterligt at man vælger sådan en dårlig syntaks, fuld af støj, og strong-typed argumenter, som slet ikke burde være nødvendige, da man allerede ved hvad typerne skal være.
Nu er det ikke alle som synes fuldt infererede typer er fedt i modsætning til manifest (ikke "strong-typed") typning. Men i C# kan du så i det mindste selv vælge.
Windcape (1) skrev:Fjolser, alle sammen.
Hvis man ikke kan se pointen med closures og lambda, så må det være fordi man ikke forstår dem, eller aldrig har brugt dem.
Det giver så meget mere elegant kode, som er nemmere at forstå, maintaine, og har færre chancer for fejl.
Det må så være din mening; jeg tror der er mange der ikke er enige i det (omend jeg selv er), så at kalde dem for fjolser er måske lidt i overkanten. Det er ikke alle der kan lide at blande forskellige paradigmer i samme sprog.
Måske fordi det faktisk ret tit giver mening?onetreehell (4) skrev:Det siger du jo altid når nogen snakker om java...
Men Haskell eller Scala er også et bud, men nu er C#s fordel jo bare at det minder meget om Java, og er strong-typed, så det ville netop give mening.
Din kode kan skrives så simpelt her i C#:onetreehell (4) skrev:Jeg synes det ser fornuftigt nok ud, men jeg har ikke kigget nærmere på de mere komplicerede udtryk..
int count = 0;
var sorted = data.OrderBy(x => { count++; return x.Length; })
Og så har du performance fordelene af at du faktisk får en iterator tilbage, samt ikke modificere dit nuværende dataset.
Begge dele er mere typisk for funktionel programmering, og sikre bedre og mindre fejlfyldt kode.
Mit bud er at det er fordi typer er en noget mere kompliceret størrelse i Java i forhold til C# på grund af de noget mere udtryksfulde generics. I Java kan generiske argumenttyper være infereret, mens de i C# ligger fast givet objektets type. Det vil sige at man ikke har en konkret type at tildele funktionen på samme måde som i C#. Hurtigt Java 5 eksempel (uden lambda):Windcape (1) skrev:Det var da godt nok en afskyelig syntaks. Hvorfor er det at JCP ikke bare har valgt at dublikere C#?
Det virker så latterligt at man vælger sådan en dårlig syntaks, fuld af støj, og strong-typed argumenter, som slet ikke burde være nødvendige, da man allerede ved hvad typerne skal være.
E <E> m(E a1, E a2) {
...
}
...
String s;
Integer i;
m(s,i); //<-- Her skal typen for E infereres ud fra String og Integer
Typen af E bliver noget i retningen af [m = Comparable<m> & Serializable], altså en rekursiv type for returværdien.
Jeg ved ikke hvordan man kunne bygge det sammen med de infererede funktionstyper, som du foreslår, men jeg kan garantere at det ikke er trivielt at løfte den nuværende inferens til at omfatte funktioner.
#9
Men compileren kan jo godt håndtere metode overloads, så det virker jo lidt underligt?
I dit eksempel burde følgende virke:
Hvor at tilsvarende i C# er det ikke nødvendigt med type-angivelse på metoderne.
Men hvis det var overloads, ville det jo virke, det er lidt underligt.
Men compileren kan jo godt håndtere metode overloads, så det virker jo lidt underligt?
I dit eksempel burde følgende virke:
m.<String>("foo", "bar");
m.<Integer>(42, 1337);
Hvor at tilsvarende i C# er det ikke nødvendigt med type-angivelse på metoderne.
Men hvis det var overloads, ville det jo virke, det er lidt underligt.
Hmm, det har ikke så meget med overloads at gøre.Windcape (10) skrev:Men compileren kan jo godt håndtere metode overloads, så det virker jo lidt underligt?
Windcape (10) skrev:I dit eksempel burde følgende virke:
Ja, det gør det bestemt også, men
m("foo", 42)
virker også. Og det virker også uden at du skal fortælle compileren explicit hvad E er. Det infereres fra typen af de konkrete argumenter.
Jeg mener bare at hvis du også skal til at inferere hvad typen af de konkrete argumenter er, så bliver det lidt indviklet. Hvis man så fylder inferens af funktionstyper ind over også, så tror jeg at man har nået en kompleksitet på type-inferensen som man gerne vil undgå.
Windcape (12) skrev:Hvordan kan det virke at give 2 forskellige typer, når begge parameter skal have samme type?
Fordi både String og Integer extender Comparable<E>, og derfor kan anses som samme type.
Hvilket mathiass også skrev:
mathiass (9) skrev:Typen af E bliver noget i retningen af [m = Comparable<m> & Serializable], altså en rekursiv type for returværdien.
Windcape (12) skrev:Hvordan kan det virke at give 2 forskellige typer, når begge parameter skal have samme type?
Det har de da også! De har faktisk flere fælles typer. Blandt andet har de begge to typen Objekt, men som skrevet i #9, så har de altså også en mere præcis type, som dog er rekursiv.
Windcape (12) skrev:Jeg vidste godt generics i Java var dårligt implementeret, men så dårligt?
Det er bestemt ikke dårligt implementeret. Det kan bare mere end C#. Mit eksempel type-checker kun, hvis body af metoden virker for enhver tildeling af konkret type for E, så der er ingenting galt med type-systemet som sådan. Jeg er også overbevist om at det godt kan lade sig gøre at tilføje funktionstyper (uden sub-type relation) til det, men prisen for det som du kalder lidt pænere syntax vil skulle betales med at mange programmører nok vil have svært ved at forstå hvad der foregår når de ikke skriver typen.
#14
Men i C# skulle det gøres ved hjælp af en constraint.
eller bedre
Hvor vi her sikre at vi faktisk kan sammenligne de 2 typer.
Det kan dog også gøres ved at angive det direkte:
Java bliver det første hvor man altid skal angive typer på alting.
Men i C# skulle det gøres ved hjælp af en constraint.
T m<T>(T a1, T a2)
where T : IComparable
eller bedre
T m<T>(T a1, T a2)
where T : IComparable<T>
Hvor vi her sikre at vi faktisk kan sammenligne de 2 typer.
Det kan dog også gøres ved at angive det direkte:
m<IComparable>("foo", 42);
Det fungere da ellers fint for samtlige andre sprog der har lambda understøttelse.mathiass (14) skrev:men prisen for det som du kalder lidt pænere syntax vil skulle betales med at mange programmører nok vil have svært ved at forstå hvad der foregår når de ikke skriver typen.
Java bliver det første hvor man altid skal angive typer på alting.
#15: Nej, det er ikke det samme. Hvis du skriver sådan, så lægger du dig fast på at typen skal extende IComparable. Det gør jeg ikke i mit Java eksempel, det viser sig bare at være tilfældet i den kaldende kode. Dit C# eksempel ser sådan ud i Java:
I Java vil T også i dette tilfælde blive infereret til den mest præcise type i den kaldende kode, så for et konkret kald til m vil typen af T være mere præcis end at den bare extender Comparable<T>.
T <T extends Comparable<T>> m(T a1, T a2) {
...
}
I Java vil T også i dette tilfælde blive infereret til den mest præcise type i den kaldende kode, så for et konkret kald til m vil typen af T være mere præcis end at den bare extender Comparable<T>.
#16
Men jeg kan stadigvæk ikke se hvorfor man skal angive typer, til f.eks. eksemplet fra #4
Fordi her ved vi jo allerede at typen af a og b vil være String, og så burde det jo ikke være nødvendigt at type-angive.
Men jeg kan stadigvæk ikke se hvorfor man skal angive typer, til f.eks. eksemplet fra #4
void Sort(List<String> data) {
final int count = 0;
Collections.sort(data, #(String a, String b) {
count++;
return a.length() - b.length();
});
}
Fordi her ved vi jo allerede at typen af a og b vil være String, og så burde det jo ikke være nødvendigt at type-angive.
#17: Selvfølgelig kan du altid finde special-cases hvor typen er åbenlys at inferere, men hvis du ikke behandler det generelle tilfælde, så vil sproget have en type-inferens som kan fejle i nogle tilfælde, så du selv skal skrive en korrekt type. Det er altså noget bras.
Det fungere da ellers fint for samtlige andre sprog der har lambda understøttelse.Jeg siger egentlig heller ikke at jeg er imod det. Jeg siger bare at jeg ikke lige kan se hvordan det kan laves på en fornuftig måde, og det tror jeg faktisk heller ikke at du kan.
Java bliver det første hvor man altid skal angive typer på alting.
Jeg vil påstå at alle de funktionelle sprog som du nævner har en kompleksitet i deres type-inferens som ville være meget uheldig at indføre i et sprog som Java. Det er også sprog der type-mæssigt er fundamentalt forskellige fra Java på rigtig mange måde.
Det eneste som giver mening at sammenligne med er C# og min indvending er også bare at generiske typer er meget mere komplicerede i Java end i C# og derfor lader den løsning sig ikke bare overføre.
Det eneste som giver mening at sammenligne med er C# og min indvending er også bare at generiske typer er meget mere komplicerede i Java end i C# og derfor lader den løsning sig ikke bare overføre.
#21: Nej, jeg tror ikke rigtigt at du forstår hvad jeg skriver. Jeg forstår ikke rigtig hvorfor du taler om implementation. Der er tale om to forskellige generics koncepter. Microsoft har lavet en fin løsning i C#, men den lader sig ikke umiddelbart overføre, som jeg ser det.
Jeg mener bestemt ikke at Java's generics skal laves om.
Jeg mener bestemt ikke at Java's generics skal laves om.
#23
Rent teoretisk kan de jo have nok så fine koncepter, men pragmatisk set gør de det samme.
Jeg har aldrig oplevet noget specielt ved Java's generics, udover at det er et hack oven på sproget, så der mangler en helt masse features.
Hvad er argumentet for ikke at gøre det ligesom i C#? Jeg kan virkelig ikke se det.
Derudover kommer checked exceptions til at se virkelig virkelig grimt ud i closures. Det virker somon at JCP bare har besluttet sig for at de skulle have disse her features, og slet ikke tænkt ind hvordan man designer det bedst ind i selve syntaksen og sproget.
Ligesom man gjorde med generics (type-boxing sucks!)
Rent teoretisk kan de jo have nok så fine koncepter, men pragmatisk set gør de det samme.
Jeg har aldrig oplevet noget specielt ved Java's generics, udover at det er et hack oven på sproget, så der mangler en helt masse features.
Hvad er argumentet for ikke at gøre det ligesom i C#? Jeg kan virkelig ikke se det.
Derudover kommer checked exceptions til at se virkelig virkelig grimt ud i closures. Det virker somon at JCP bare har besluttet sig for at de skulle have disse her features, og slet ikke tænkt ind hvordan man designer det bedst ind i selve syntaksen og sproget.
Ligesom man gjorde med generics (type-boxing sucks!)
Hmm, nej de gør ej. To ret store forskelle er manglen på runtime information i Java og på wildcards i C#. Det sidste definerer et subtype-forhold i Javas generics, som gør det noget mere udtryksfuldt end C#.Windcape (24) skrev:Rent teoretisk kan de jo have nok så fine koncepter, men pragmatisk set gør de det samme.
Min holdning til checked exceptions er at det fundamentalt set var en dårlig ide. Men nu har vi det, og så må nye features også virke med det. Man kan jo lade være med at bruge det.
#24
Der hvor det hele står og falder i denne diskussion er jo at C#'s generics ikke er lige så udtryksfulde som javas.
Om du som individ nogensinde har haft brug for dette skal jeg ikke kunne udtale mig om, jeg ved at jeg personligt aldrig har(men har haft implementeret en delmængde af en Javakompiler i Java og har i den forbindelse læst op på generics i mange flere detaljer end noget menneske nogensinde burde tvinges til!)
Som sådan kan man (som tidligere udtalt) på nuværende tidspunkt i Java "overlade mere til compiler/runtime" end man kan i C#.
At du så syntes det havde været bedre at Java havde implementeret på samme måde som C# er så hvad det er. Personligt er jeg glad for at verden ikke er generisk :-D
Der hvor det hele står og falder i denne diskussion er jo at C#'s generics ikke er lige så udtryksfulde som javas.
Om du som individ nogensinde har haft brug for dette skal jeg ikke kunne udtale mig om, jeg ved at jeg personligt aldrig har(men har haft implementeret en delmængde af en Javakompiler i Java og har i den forbindelse læst op på generics i mange flere detaljer end noget menneske nogensinde burde tvinges til!)
Som sådan kan man (som tidligere udtalt) på nuværende tidspunkt i Java "overlade mere til compiler/runtime" end man kan i C#.
At du så syntes det havde været bedre at Java havde implementeret på samme måde som C# er så hvad det er. Personligt er jeg glad for at verden ikke er generisk :-D
@Arne: Hvad er din egen mening?
#27: Vi kan vist hurtigt blive enige om, at den praktiske implementation af generics i Java er fejlbarlig, men arbejdsbyrden i fuldstændigt at omskrive JVM (eller hvad ellers måtte være nødvendigt for at opnå den ideelle understøttelse) er formentligt for stor til at vurderes ønskelig at gennemføre.
Ærligt talt ved jeg snart ikke, hvad jeg selv skal sige... Jeg kan ikke se, hvordan closures er kompatibelt med OOP i sin reneste form (som Java nu engang forsøger at lægge sig op ad), men der må siges at være gode argumenter for deres indførsel alligevel. Dog kan jeg, som mange andre herinde, overhovedet ikke forstå, hvorfor vi er endt med netop Straw-Man, for den virker da yderst gyselig. Så vidt jeg kan se, er forslaget her:
http://mail.openjdk.java.net/pipermail/lambda-dev/...
EDIT: Ignorer linket; det fremgår også af kildeartiklen.
Kender nogen årsagen til valget?
#27: Vi kan vist hurtigt blive enige om, at den praktiske implementation af generics i Java er fejlbarlig, men arbejdsbyrden i fuldstændigt at omskrive JVM (eller hvad ellers måtte være nødvendigt for at opnå den ideelle understøttelse) er formentligt for stor til at vurderes ønskelig at gennemføre.
Ærligt talt ved jeg snart ikke, hvad jeg selv skal sige... Jeg kan ikke se, hvordan closures er kompatibelt med OOP i sin reneste form (som Java nu engang forsøger at lægge sig op ad), men der må siges at være gode argumenter for deres indførsel alligevel. Dog kan jeg, som mange andre herinde, overhovedet ikke forstå, hvorfor vi er endt med netop Straw-Man, for den virker da yderst gyselig. Så vidt jeg kan se, er forslaget her:
http://mail.openjdk.java.net/pipermail/lambda-dev/...
EDIT: Ignorer linket; det fremgår også af kildeartiklen.
Kender nogen årsagen til valget?
Det er de vel heller ikke. Det er for at få mere funktionel programmering ind i et allerede multi-paradigm sprog.krainert (30) skrev:Jeg kan ikke se, hvordan closures er kompatibelt med OOP i sin reneste form
Forsøgte. Det er vist endeligt ved at komme videre.krainert (30) skrev:som Java nu engang forsøger at lægge sig op ad
Det giver slet ikke mening at tvinge folk til at skrive kode som:
List<User> adults = new List<User>();
for (User user : users)
{
if (user.getAge() > 18) { adults.Add(user); }
}
I stedet for
var adults = users.Where(user => user.Age > 18);
Både fordi at det sidste er mere clean-code, men også fordi det er bedre performance.
Hvis jeg kigger på http://java.sun.com/docs/books/tutorial/extra/gene...mathiass (31) skrev:Windcape (26) skrev:dynamic?
Øh, nej. dynamic er mangel på en type og tilhørende mangel på typecheck. Det har intet med wildcards at gøre.
Så kan jeg ikke se noget jeg ikke kan i C# 4.0
Kan du præcisere hvad du mener?
Jeg mener at dynamic ikke er en type i almindelig forstand, fordi 1)den bliver ikke checket af type-checkeren og 2)der er ingen garanti for at brugen af den ikke resulterer i en typefejl på runtime. Den adskiller sig i øvrigt fra wildcards på begge måder.Windcape (33) skrev:Hvis jeg kigger på http://java.sun.com/docs/books/tutorial/extra/gene...mathiass (31) skrev:Windcape (26) skrev:dynamic?
Øh, nej. dynamic er mangel på en type og tilhørende mangel på typecheck. Det har intet med wildcards at gøre.
Så kan jeg ikke se noget jeg ikke kan i C# 4.0
Kan du præcisere hvad du mener?
Det er ikke så relevant i forhold til Java sproget. Lambda'er vil også blive omskrevet til (formodentlig) en "anonym" klasse i byte code og køre som sådan på JVM'en.Ildhesten (35) skrev:#30 Så vidt jeg husker laver compileren type erasure sådan at JVM'en ikke skal bekymre sig om generics. Så det argument holder vist ikke
Jeg vil gerne have du forklare hvad du mener Wildcards er så.mathiass (36) skrev:Den adskiller sig i øvrigt fra wildcards på begge måder.
Fordi sådan som jeg læser det, er det det samme som at bruge object eller dynamic som type.
Derudover så ved compileren godt hvilken type et dynamisk variabel har.
dynamic test = "foo";
typeof(test) // System.String
test = 42;
typeof(test) // System.Int32
Fordi det retunere en iterator, så det er først når du bruger det aktuelle resultat at der bliver selected data.mathiass (38) skrev:Hvorfor skulle lambda-funktioner i sig selv dog give bedre performance end en for-løkke?
Men det er så også fordi at C# har rigtige iterators. Det har Java ikke.
Nej, det gør compileren bestemt ikke. typeof gør at runtime systemet giver dig den dynamiske type på runtime.Windcape (39) skrev:Derudover så ved compileren godt hvilken type et dynamisk variabel har.
dynamic test = "foo";
typeof(test) // System.String
test = 42;
typeof(test) // System.Int32
#40: Jeg synes ikke at vi skal åbne en diskussion mere, men det giver altså ikke bedre performance at lave arbejdet på et andet tidspunkt, og det har slet ikke noget med lambda-udtryk at gøre ud over at det LINQ library som du tale om benytter sig af lambda-utryk i sit interface.
Du har selv linket til en fremragende ressource som fortæller om wildcards, så jeg synes at du skal prøve at læse den. Jeg kan give dig et par eksempler på forskellen på ? og Object.Windcape (39) skrev:Jeg vil gerne have du forklare hvad du mener Wildcards er så.
Følgende type checker:
Collection<?> c = new ArrayList<String>();
Dette gør ikke:
Collection<Object> c = new ArrayList<String>();
Og heller ikke:
Collection<?> c = new ArrayList<String>();
c.add(new Object());
Prøv at sammenligne med add-metoden på Collection som tager noget af den generiske type og tænk over hvorfor den er type-sikker med wildcards.
Forskellen på dynamic og ? kan nok bedst beskrives ved at dynamic ikke type-checkes overhovedet mens ? behandles som ukendt på en sikker måde af compileren.
Man kan desuden lave bounds (? extends C) på wildcards, så compileren behandler typen som noget ukendt som man dog ved extender C. Der er et par gode eksempler på anvendelse af det på siden, som du har linket til.
#47: Kan man det? Så jeg kan skrive:
Og dermed tilføje ting af en hvilken som helst (inkompatibel) type til min stringlist gennem objectlist referencen?
Jeg har ikke lige en C# compiler tilgængelig her, men det lyder ikke særlig smart, hvis det passer. Wildcards er lige præcis en type-sikker måde at håndtere subtyping for generics får den slags typefejl på runtime.
List<string> stringlist = new List<string>();
List<object> objectlist = stringlist;
Og dermed tilføje ting af en hvilken som helst (inkompatibel) type til min stringlist gennem objectlist referencen?
Jeg har ikke lige en C# compiler tilgængelig her, men det lyder ikke særlig smart, hvis det passer. Wildcards er lige præcis en type-sikker måde at håndtere subtyping for generics får den slags typefejl på runtime.
#48
Jeg checkede lige, og nej, det kan ikke gøres implicit fra object til string.
Jeg forstår virkelig ikke ideen med at tillade at man tilføjer sådanne typer. Wildcards virker jo totalt meningsløse, og bare er et eksempel på hvordan Java's generics faktisk bare er dumt box-in / box-out af typer.
Jeg checkede lige, og nej, det kan ikke gøres implicit fra object til string.
Men hvorfor vil du overhovedet tilbyde muligheden?mathiass (48) skrev:Wildcards er lige præcis en type-sikker måde at håndtere subtyping for generics får den slags typefejl på runtime.
Jeg forstår virkelig ikke ideen med at tillade at man tilføjer sådanne typer. Wildcards virker jo totalt meningsløse, og bare er et eksempel på hvordan Java's generics faktisk bare er dumt box-in / box-out af typer.
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.