Clash of programming languages

trialgod

Lt. Commander
Registriert
Feb. 2008
Beiträge
1.547
Da anscheinend Interesse darin besteht sich gegenseitig zu zeigen wie "geil" doch die selber benutze Sprache ist und wie "scheiße" die von anderen genutzte, möchte ich hier einfach mal Real-World-Problems aufgreifen und zusammenfassen.

Und zwar werden Aufgaben erstellt und dann konkrete Lösungen des Problems anhand von Codeschnipseln der verschiedenen Sprachen vergleichbar gemacht.

Jetzt darf sich jeder beteiligen und spezielle Sachen rauspicken, wo er die eigene Sprache total überlegen findet. Er kann natürlich auch gleich Codeschnipsel für mehrere Sprachen liefern.

Regeln:
1. Jeder der eine Aufgabe eines Anderen mit eigenem Code beliefert darf eine eigene Aufgabe stellen.
2. Die Aufgabe sollte nicht zu komplex sein, da es hier sonst den Rahmen sprengt.
3. Sie sollte wenigstens irgendetwas darstellen, was man auch im Arbeitsalltag so antreffen könnte.

Das ganze ist natürlich auch als Spaß gemeint und sollte auch so behandelt werden.

Ebenfalls kann man sicher so noch was in der eigenen Sprache von anderen lernen.

Hier die erste Aufgabe:
Es gibt eine CSV-Datei aus externer Quelle. Diese beinhaltet ein riesiges SET an Adressdaten mit den typischen Feldern. (Id, Name, Vorname, Straße, Hausnummer, Plz, Ort, Land).
Die Sortierung dieser Daten erfolgt nach der Id. Das Land ist in einem 2 stelligen ISO Code angegeben.

Unsere Aufgabe ist es alle Adressen aus DE zu filtern und nach Ort, Nachname und Vorname zu sortieren.

Das Einlesen der CSV gehört nicht zur Aufgabe, da hier wohl jeder eine externe oder eigene Bibliothek hat, die dies übernimmt.

C#
Code:
// Das Einlesen könnte beispielsweise so aussehen
var csvReader = new csvReader<Address>("path/to/csv.csv");
List<Address> addresses = csvReader.ReadAllLines().ToList();

// Hier die eigentliche Aufgabe
List<Address> filteredAndsortedAddresses = 
    addresses
        .Where(a => a.Land == "DE")
        .OrderBy(a => a.Ort)
        .ThenBy(a => a.Nachname)
        .ThenBy(a => a.Vorname)
        .ToList();
 
Zuletzt bearbeitet:
Da .NET eh Opensource wird kann Java getrost sterben ;)
2 Jahre, dann läuft Android v15 CandyCrush auf .NET!

Und Apple ist eben Apple. Aber da beschwer ich mich nicht, objective c ist verdammt performant.
Willst du dass ich deine Hausaufgaben mache? Konkretisier das doch mal n bissl, das Beispiel ist sehr mager.

mfg,
Max
 
max_1234 schrieb:
Da .NET eh Opensource wird kann Java getrost sterben ;)
2 Jahre, dann läuft Android v15 CandyCrush auf .NET!

Und Apple ist eben Apple. Aber da beschwer ich mich nicht, objective c ist verdammt performant.
Willst du dass ich deine Hausaufgaben mache? Konkretisier das doch mal n bissl, das Beispiel ist sehr mager.

mfg,
Max

Was hat dieser gesamte Post mit dem Thread zutun?

Und Hausaufgaben? Du bist dir schon im Klaren, dass hier nicht nur 13 Jährige rumlaufen.

Ich präferiere .NET, versuche aber immer Open Minded zu bleiben und Sachen von Anderen zu adaptieren. So kann man was lernen. Und man kann Vor- und Nachteile bestimmter Sprachen herausheben.
 
Die Verwendung gibt der zahlende Kunde vor, und in dieser Programmiersprache, IDE oder sonstwas wird es dann gelöst. :cool_alt:

Die perfekte oder gute Programmiersprache gibt es leider nicht.
 
@PHuV

Naja, die Programmiersprache in der sich am leichtesten DSLs definieren lassen (und mit der hoechsten Abstraktionsstufe) ist meiner Meinung nach die beste aller Sprachen.
Hat man genug dieser DSLs als offene APIs zur Verfuegung gestellt so steht diese einer Perfekten Programmiersprache in nichts nach.

Der zahlende Kunde der eine Programmiersprache vorgibt wird sich damit bloss selbst in den Fuss schiessen.
 
Zuletzt bearbeitet:
Der zahlende Kunde hat meist mehr als nur ein Softwareprojekt und daher ein berechtigtes Interesse, nicht die Anzahl der eingesetzten Programiersprachen und Frameworks zu maximieren. Daher kommt es schnell zu äußeren Zwängen. Ob er sich damit letztlich (irgendwann) in den Fuß schießt, ist nicht die Sorge der Architekten/Entwickler.
 
Um mal was zum eigentlichen Thema beizutragen, hier mein Ansatz in Scala zum Problem von trialgod.

Code:
// Das Einlesen könnte beispielsweise so aussehen
val addresses = csvReader.readAddresses

// Hier die eigentliche Aufgabe
val filteredSorted = addresses.filter(_.land == "DE").sortBy{ case Address(l,o,n,v) => (o,n,v) }

// oder alternativ, um näher an der Lösung von trialgod zu bleiben
val alternativ= addresses.filter(_.land == "DE").sortBy( a => (a.ort, a.nachname, a.vorname) )

Meine Aufgabe: eine möglichst simple Datenstruktur ähnlich einem Ringbuffer schreiben, die nichts können muss, außer:

- man soll beliebig viele Daten dranhängen können
- man soll die Anzahl der Elemente in der Struktur auslesen können
- es soll eine Methode oder Funktion next geben, die immer das nächste Element zurückgibt. Nach dem man das letzte Element mit next ausgelesen hat, sollte der nächste Aufruf von next wieder das erste Element liefern.

Pseudobeispiel:

Code:
r = new ring('A','B','C','D')
r.length // -> 4 
r.next // -> A
r.next // -> B
r.next // -> C
r.next // -> D
r.next // -> A


Wer das ganze immutable machen möchte: next darf dann bei einem bestimmten Objekt immer ein und das selbe Element zurückliefern (z.B. 'A'). Eine zusätzliche Methode 'proceed' soll in diesem Fall einen neuen Ring zurückliefern, auf welchem next dann das nächste Element zurückliefert ('B') usw..

Pseudobeispiel:

Code:
r = new ring('A','B','C','D')
r.length // -> 4 
r.next // -> A
r.next // -> A
r2 = r.proceed
r2.next // -> B
r2.proceed.next // -> C


edit: muss nicht unbedingt für String/Char sein, wobei generisch natürlich am coolsten wäre.
 
Zuletzt bearbeitet:
Sind wir hier nicht bei einem Enumerator? Den müsste es doch so ziemlich überall Built-In geben? (Steinigt mich wenn nicht, kenne nicht so viele Sprachen).

C#
Code:
var ring = new List<string> { "A", "B", "C", "D" };

IEnumerator<string> r1 = ring.GetEnumerator();
IEnumerator<string> r2 = ring.GetEnumerator();

r1.MoveNext();
r2.MoveNext();

Console.WriteLine(r1.Current); // -> A
Console.WriteLine(r2.Current); // -> A

r1.MoveNext();

Console.WriteLine(r1.Current); // -> B
Console.WriteLine(r2.Current); // -> A

Hier muss man sich nur noch einen Wrapper drumrum schreiben, der bei MoveNext() == false (also wenn kein weiteres Element vorhanden) einen neuen Enumerator nimmt.

Ist das gleiche, nur dass die Datenredundanz nicht vorhanden ist, also Daten und Abfrage gekapselt sind.

Hier mit Extension Method:
Code:
public static class EnumeratorExtensions
{
    public static T NextOrReset<T>(this IEnumerator<T> enumerator)
    {
        if (!enumerator.MoveNext())
        {
            enumerator.Reset();
            enumerator.MoveNext();
        }

        return enumerator.Current;
    }
}

Code:
var ring = new List<string> { "A", "B", "C", "D" };

IEnumerator<string> r1 = ring.GetEnumerator();
IEnumerator<string> r2 = ring.GetEnumerator();

Console.WriteLine(r1.NextOrReset()); // -> A
Console.WriteLine(r2.NextOrReset()); // -> A

Console.WriteLine(r1.NextOrReset()); // -> B
Console.WriteLine(r2.Current); // -> A

Console.WriteLine(r1.NextOrReset()); // -> C
Console.WriteLine(r1.NextOrReset()); // -> D
Console.WriteLine(r1.NextOrReset()); // -> A

Zeigt die Möglichkeiten ganz gut, kann man an der Stelle auch Anpassen wie man möchte.
 
Zuletzt bearbeitet:
Einen Enumerator, Iterator o.ä. zu verwenden liegt natürlich nahe. Was eigentlich angedacht war ist, dass man nachträglich noch Elemente an das Ende anhängen kann, sodass next trotzdem nahtlos ohne "reset" weiter funktioniert - das habe ich aber oben nicht erwähnt und ist von dem her natürlich nicht relevant für die Lösung.

Ich hätte mir lediglich etwas mehr Kapselung zur Konsistenzerhaltung erwünscht, wobei die Collection und der Enumerator isoliert und zusammen verwaltet werden. Wenn ring verändert wird, sollte der Enumerator meines bescheidenen .NET-Wissens nach eine Exception werfen... bei Java verfällt der Iterator dagegen in einen undefinierten Zustand, was noch schlimmer ist. Aber wenn du auf einen edit keine Lust mehr hast, ist es auch so akzeptiert :).

edit: meine Umsetzung von damals: wenn man eine Sprache mit effizienten Head- und Tail-Operationen auf Listen hat, kann man auch den Head nehmen (entspricht dann dem next) und nach dem Ausgeben wieder hinten an den Tail dranhängen. Ist sehr kurz und die Liste lässt sich nachträglich erweitern, denn der head (aka next) bleibt dabei unberührt.
 
Zuletzt bearbeitet:
carom schrieb:
Ich hätte mir lediglich etwas mehr Kapselung zur Konsistenzerhaltung erwünscht, wobei die Collection und der Enumerator isoliert und zusammen verwaltet werden. Wenn ring verändert wird, sollte der Enumerator meines bescheidenen .NET-Wissens nach eine Exception werfen... bei Java verfällt der Iterator dagegen in einen undefinierten Zustand, was noch schlimmer ist.

Ja das stimmt, der Iterator wirft dann eine Exception.

Übrigens wollte ich hier keinen "Aufgabe und Lösungen" Thread erstellen, sondern die Lösungen in den verschiedenen Programmiersprachen vergleichen ;)

Wenn ich Lust habe, passe ich meine Lösung oben noch einmal an.
 
Das CSV-Problem in Ruby, der natürlich allerbesten aller Sprachen!

Code:
# Datenmodell
class Person
	attr_accessor :iso, :vn, :nn, :ort
	def initialize val
		@iso,@vn,@nn,@ort = val
	end
end
CSV.read('data.csv').compact.map{|x| Person.new(x)}.keep_if{|x| x.iso == 'DE'}.sort_by{|x| [x.ort,x.nn,x.vn]}
 
Ruby ist Banane - es wird einfach zu oft grundlegend verändert als dass man es professionell nutzen könnte.
Bereits zwischen zwei minor Versionen können Inkompabilitäten auftreten. Von Rails fange ich gar nicht an, ist nur ein Webpage Baukasten mit Ruby Plugin Support :p
 
Zuletzt bearbeitet:
Zurück
Oben