PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Java LinkedList mit int?


darph
2005-05-18, 15:36:26
List visit = new LinkedList();
visit.add(fromNode);

fromNode ist ein int Wert.

Nur dummerweise meckert er jetzt, weil er denkt, fromNode wäre der Index in der Liste und wartet auf das dort einzufügende Objekt. Ich will nicht als zwischen int und Integer hin und her casten müssen.

Gibt's da eine elegantere Lösung?

ScottManDeath
2005-05-18, 16:14:49
AFAIK gibts in Java 1.5 generics, also dann LinkedList<int>.


Ausserdem soll der der 1.5 Compiler das boxen zwischen Integer<->int grösstenteils automatisch machen.

Senior Sanchez
2005-05-18, 16:32:52
List visit = new LinkedList();
visit.add(fromNode);

fromNode ist ein int Wert.

Nur dummerweise meckert er jetzt, weil er denkt, fromNode wäre der Index in der Liste und wartet auf das dort einzufügende Objekt. Ich will nicht als zwischen int und Integer hin und her casten müssen.

Gibt's da eine elegantere Lösung?

Wenn du kein 1.5 nutzen darfst, wirste um das boxen in Integer nicht rum kommen.

mfg

darph
2005-05-18, 16:34:55
Generics dürfen wir nicht verwenden.

Ich mach's jetzt mit einem Stack und wilder Typtransformation

visit.push(j = new Integer (fromNode));

HellHorse
2005-05-18, 20:01:36
AFAIK gibts in Java 1.5 generics, also dann LinkedList<int>.
nein, LinkedList<Integer>

Also entweder

List visit = new LinkedList();
visit.add(new Integer(fromNode));
int i = ((Integer) visit.get(0)).intValue();


oder sowas:
http://www.kataba.com/dynamics/api/com/kataba/coll/List_i.html

ScottManDeath
2005-05-18, 22:42:32
Aber die Richtung hat gestimmt ;)

Dann macht der Compiler das Boxen dann selbst.

Ok, wieder was gelernt. Kenn Java auch nur theoretisch ;), genauso theoretisch wie ich ADA kenne =)

Coda
2005-05-19, 01:43:06
nein, LinkedList<Integer>Erklärung für einen C++ Mensch?

HellHorse
2005-05-19, 09:18:44
Erklärung für einen C++ Mensch?
Generics sind keine Makros, die Klassen generieren.
Typparameter müssen Referenztypen sein.

Boba Fett
2005-05-19, 10:47:26
Erstell doch einfach eine Unterklasse von LinkedList, in der die Methoden add und get überschreiben werden, so in der Art (nicht getestet!):

class MyLinkedList extends LinkedList {
public void add(int value) {
add(new Integer(value));
}

public int get(int i) {
return ((Integer) visit.get(i)).intValue();
}
}

ScottManDeath
2005-05-19, 15:52:05
Generics sind keine Makros, die Klassen generieren.
Typparameter müssen Referenztypen sein.

OT:
Bei den .NET 2.0 generics wurde es etwas anders implementiert. Da gibt es für Werttypen ( int, float und eigene structs) jeweils eigene Klassen mit Code aus Performancegründen. Alle Referenztypen teilen sich eine Klasse, der Compiler sorgt nur dafür dass es typsicher bleibt.

HellHorse
2005-05-19, 16:55:10
class MyLinkedList extends LinkedList {
public int get(int i) {
return ((Integer) visit.get(i)).intValue();
}
}

gayt nicht

@ScottManDeath
noch mehr OT:
Ziel von generics war, dass sie auf einer unmodifizierten VM laufen. Dass sie nur in 1.5 verfügbar sind liegt an Sun und nicht an generics. Entwickelt und verfügbar waren sie schon lange. Du kannst problemlos eine Liste, die mit 1.2 serialisiert wurde in 1.5 einlesen.

certeum censeo:
primitive Typen müssen weg

ScottManDeath
2005-05-19, 21:10:18
@ScottManDeath
noch mehr OT:
Ziel von generics war, dass sie auf einer unmodifizierten VM laufen. Dass sie nur in 1.5 verfügbar sind liegt an Sun und nicht an generics. Entwickelt und verfügbar waren sie schon lange. Du kannst problemlos eine Liste, die mit 1.2 serialisiert wurde in 1.5 einlesen.


OT continues:

Das mit der unveränderten VM ist auch nicht so einfach, versuche doch mal eine 1.5 .class mit generics auf einer 1.4 VM auszuführen.... Binärkompatibel sind 1.4 und 1.5 Bytecode jedenfalls nicht.

Man musste die 1.5 VM sowieso für einige neue Features (z.b. enums, annotations) anpassen (durch neue Bytecodes), dann hätte man auch gleich Generics in einer flexibleren Art und Weise implementieren können....


certeum censeo:
primitive Typen müssen weg

Hab ich da jetzt die Ironie übersehen?:confused:

Coda
2005-05-19, 21:52:34
Mhm nein, er ist wohl nur ein Smalltalk Fan :D

darph
2005-05-19, 22:28:05
Hab ich bereits erwähnt, daß ich Java nich mag? :usad:

Naja egal, hab's ja jetzt

HellHorse
2005-05-19, 23:28:20
Return of the OT

Das mit der unveränderten VM ist auch nicht so einfach, versuche doch mal eine 1.5 .class mit generics auf einer 1.4 VM auszuführen....
Binärkompatibel sind 1.4 und 1.5 Bytecode jedenfalls nicht.
Hat nix mit generics zu tun. Ich kann eine (generic) Liste, die mit 1.5 serialisiert wurde in 1.4 einlesen und umgekehrt. Die Klasse wird ja nicht mitserialisiert. ;)

Man musste die 1.5 VM sowieso für einige neue Features (z.b. enums, annotations) anpassen (durch neue Bytecodes),
Ja schon, aber das hat nix mit generics zu tun. Obwohl ich mir bei enums nicht sicher bin, das ist ja nur ein weiters Compilermakro. Allerdings wird IIRC auch die Stringkonkatenation in 1.5 mit StringBuilder gemacht, den es in 1.4 nicht gab.

dann hätte man auch gleich Generics in einer flexibleren Art und Weise implementieren können....
Hätte wäre wenn. Wie schon gesagt, 1.5 war nie das Ziel von generics. Generics wurden von Unis zusammen mit Sun entwickelt. Das sieht man schon daran, dass eigens dafür ein Kalkül (featherweight Java) geschaffen wurde um die Typkorrektheit von generics (und Java) zu beweisen. Dabei fand man auch ein paar Bugs im existierenden Typsystem von Java, die im Zug von 1.5 gefixt wurde. Komischerweise hängt das Sun nicht an die grosse Glocke. Das Ganze gabs schon lange, wurde verzögert und endete dann schliesslich in 1.5.

Generics in Java haben eingentlich nur ein Problem. Sie arbeiten schlecht mit zwei Sachen zusammen, die in aus Java verbannt gehören.
- Arrays
- primitive Typen


Hab ich da jetzt die Ironie übersehen?:confused:
Das meine ich todernst.

Mhm nein, er ist wohl nur ein Smalltalk Fan :D
Und wie :D
Ist aber mit der Sig nicht wirklich schwer zu erraten. ;)


Hab ich bereits erwähnt, daß ich Java nich mag?
Verleihe deiner Meinung Ausdruck mit sowas wie:
- primitve Typen
- Arrays
- kein Metamodel
- kein Closures
- zuvieles, das kein Objekt ist
- zuviele Compilertricks
- unflexible C Syntax (für jede Kleinigkeit muss die Syntax erweitert werden)
- keine classextensions
- statisches Typsystem
- nicht in sich selbst implementiert
- ...

Coda
2005-05-20, 00:10:35
Und wie
Ist aber mit der Sig nicht wirklich schwer zu erraten. Ich wusste gar nicht dass das Smalltalk ist :)
Das war ein voller Schuß ins Blaue :D

Generics in Java haben eingentlich nur ein Problem. Sie arbeiten schlecht mit zwei Sachen zusammen, die in aus Java verbannt gehören.
- Arrays
- primitive TypenWas wäre der Ersatz von Arrays?

Worin speichert eigentlich eine "Integer" Klasse in Smalltalk seinen Wert, wenn es keine primitiven Typen gibt? Oder ist die Implementation versteckt?

Ich sehe auch den großen Vorteil nicht, vor allem nicht bei C++.

Boba Fett
2005-05-20, 08:59:56
Scheiß Cut'n'Paste. :) Hier noch mal richtig:

class MyLinkedList extends LinkedList {
public void add(int value) {
add(new Integer(value));
}

public int get(int i) {
return ((Integer) get(i)).intValue();
}
}

Viele Grüße,

Boba

HellHorse
2005-05-20, 09:17:14
Was wäre der Ersatz von Arrays?
Arrays anders implementiert, als normale Klassen mit einer variablen Anzahl Instanzvariablen.

sowas

public variable class Array<T> implements List<T>, Serializable, ....



Worin speichert eigentlich eine "Integer" Klasse in Smalltalk seinen Wert, wenn es keine primitiven Typen gibt? Oder ist die Implementation versteckt?
Der Wert ist das Objekt selbst (immediate object).

Ich sehe auch den großen Vorteil nicht
Du hast ein einheitliches System in dem alles ein firstclass object ist. Wie LISP.
Du kannst Integer, Float, Double, BigInteger, ... ploymorph behandeln. Es ist einfach eine Zahl.
Integer Overflows lassen sich verhindern.
Zahlen verstehen Methoden #factorial, #isPrim, #even, #odd, #isPowerOfTwo, #positive, #negated.
Du kannst deine eigenen Zahlen implementieren, die transparent mit anderen Zahlen zusammenarbeiten.

vor allem nicht bei C++.
:rolleyes:

HellHorse
2005-05-20, 09:22:44
public int get(int i) {
return ((Integer) get(i)).intValue();
}
}

Das geht aufgrund der inkompatiblen Signagur nicht, du musst die Methode umbenennen.

public int getInt(int i) {
return ((Integer) this.get(i)).intValue();
}

Boba Fett
2005-05-20, 10:45:13
Das geht aufgrund der inkompatiblen Signagur nicht, du musst die Methode umbenennen.


Ah, danke. Nächstes Mal probiere ich den Code lieber aus, bevor ich poste. :)

ScottManDeath
2005-05-20, 14:16:06
Return of the OT


Hat nix mit generics zu tun. Ich kann eine (generic) Liste, die mit 1.5 serialisiert wurde in 1.4 einlesen und umgekehrt. Die Klasse wird ja nicht mitserialisiert. ;)


Ja schon, aber das hat nix mit generics zu tun. Obwohl ich mir bei enums nicht sicher bin, das ist ja nur ein weiters Compilermakro. Allerdings wird IIRC auch die Stringkonkatenation in 1.5 mit StringBuilder gemacht, den es in 1.4 nicht gab.


Hätte wäre wenn. Wie schon gesagt, 1.5 war nie das Ziel von generics. Generics wurden von Unis zusammen mit Sun entwickelt. Das sieht man schon daran, dass eigens dafür ein Kalkül (featherweight Java) geschaffen wurde um die Typkorrektheit von generics (und Java) zu beweisen. Dabei fand man auch ein paar Bugs im existierenden Typsystem von Java, die im Zug von 1.5 gefixt wurde. Komischerweise hängt das Sun nicht an die grosse Glocke. Das Ganze gabs schon lange, wurde verzögert und endete dann schliesslich in 1.5.


Gut, einigen wir uns auf (im Vergleich zu .NET oder C++) anderen Zielstellungen bei Generics.

Generics in Java haben eingentlich nur ein Problem. Sie arbeiten schlecht mit zwei Sachen zusammen, die in aus Java verbannt gehören.
- Arrays
- primitive Typen


Unter .NET sind die Wertypen transparent zu nutzen. Mann kann z.B. 1.GetType() oder auch 4.ToString() machen, bei Bedarf wird der Wert entsprechend als Object (z.B. System.Int32) geboxt. Wo ist dabei das Problem? Werttypen haben den Vorteil dass sie auf dem Stack leben, sie also nicht durch den GC müssen. Angenommen int wäre ein Referenztyp, dann wäre man ja dauernd am Garbage Collecten. Wäre wohl nicht so performant.

Es stimmt schon dass Java hier nicht ganz sauber ist, es gibt float, int... aber keine eigenen benutzerdefinierten Werttypen.

Ist aber mit der Sig nicht wirklich schwer zu erraten. ;)

Was macht der Code? Ich (kann kein Smalltalk :() hab nicht die leiseste Ahnung was da geschieht.



- kein Metamodel


Wie meinst Du das?

- kein Closures

C# 2.0 hat das yield return Schlüsselwort. Damit kann man Closures im Zusammenhang mit Enumeratoren nutzen.
Unter C++ muss man der Funktion ein Kontext Objekt mitgeben in der dann lokale Variablen gespeichert werden. Nicht schön, aber möglich, falls es denn gebraucht wird.


- zuvieles, das kein Objekt ist

Hast Du ein Beispiel dafür, mir fällt keins ein?


- unflexible C Syntax (für jede Kleinigkeit muss die Syntax erweitert werden)

Jede Sprache hat eine feste Syntax. Wenn die Sprache erweitert wird ist, es natürlich dass man ab und an Spracherweiterungen einführen muss. Wie wird das in Smalltalk gelöst, wenn z.b. in 4 Jahren es Sprachsyntax für z.B. Threadprogrammierung gibt?


- keine classextensions


Wie meinst Du das?


- statisches Typsystem


Wo ist dabei das Problem? In 99% der Fälle ist der Typ bekannt zur Kompilierzeit. Wenn man den dynamischen Typ braucht, kann man einige Probleme auch durch besseres Klassendesign lösen.


- nicht in sich selbst implementiert


Wie meinst Du das?

Du kannst Integer, Float, Double, BigInteger, ... ploymorph behandeln. Es ist einfach eine Zahl.
Integer Overflows lassen sich verhindern.
Zahlen verstehen Methoden #factorial, #isPrim, #even, #odd, #isPowerOfTwo, #positive, #negated.
Du kannst deine eigenen Zahlen implementieren, die transparent mit anderen Zahlen zusammenarbeiten.


Mhmm ich mache eine Klasse und überlade die Operatoren? Kann damit meinen eigenen Typ (z.b. für Rationale Zahlen) transparent verwenden.

Bei Java wurde Operatorenüberladung weggelassen, wegen der möglichen missbräuchlichen Nutzung. Solange man sich an "Do it like the ints do it" hält, ist man in der Regel auf der sicheren Seite

HellHorse
2005-05-20, 20:55:43
The OT strikes back
Gut, einigen wir uns auf (im Vergleich zu .NET oder C++) anderen Zielstellungen bei Generics.
Gut, daruf wollte ich auch hinaus.


Unter .NET sind die Wertypen transparent zu nutzen. Mann kann z.B. 1.GetType() oder auch 4.ToString() machen, bei Bedarf wird der Wert entsprechend als Object (z.B. System.Int32) geboxt. Wo ist dabei das Problem?
Ok, kann man das in .NET machen?

public Number add(Number a, Number b) {
return a + b;
}
Wobei a und b bel. unterschiedliche Zahlen sein können (Float, Integer, Decimal, BigInteger, Rational, ...)
Falls ja, :up:
Für mich ist das Symbol dafür, was mit Zahlen unter Java einfach falsch ist.

Was anderes. Kannst du einen eigenen unknown boolean machen, der mit true und false zusammenarbeitet und auch mit if/else?

Werttypen haben den Vorteil dass sie auf dem Stack leben, sie also nicht durch den GC müssen. Angenommen int wäre ein Referenztyp, dann wäre man ja dauernd am Garbage Collecten. Wäre wohl nicht so performant.
Wie schon gesagt, boxen ist genzdebil. Immediate Objekte. Wenn du performance Bedenken hast, schau dir OpenCroquet an. Smalltalk, ohne JIT. Wenn du einen Eindruck bessen kriegen willst, das sich zusätzlich mit einem guten JIT machen lässt: VisualWorks oder SELF (OS X/PPC nicht Solaris/SPARC)

Es stimmt schon dass Java hier nicht ganz sauber ist, es gibt float, int... aber keine eigenen benutzerdefinierten Werttypen.
Besser gleich ganz weg mit dem Schiess.


Was macht der Code? Ich (kann kein Smalltalk :() hab nicht die leiseste Ahnung was da geschieht.
Dann wollen wir mal:
| senderClass behavior source |
Definiert drei temporäre Variablen, senderClass, behavior, source. Man könnte die auch weglassen, aber dann wird es ein wenig unübersichtlicher.
senderClass := thisContext client class.
Speichert die Klasse des Objektes, von dem aus die aktuelle Methode aufgrufen hat in der temporären Variable senderClass.
behavior := Behavior new superclass: senderClass; setFormat: senderClass format.
Generiert eine Subklasse von senderClass. Behavior ist die Basisklasse aller Klassen, new erzeugt eine Instanz davon, also eine neue Klasse.
source := thisContext method getSourceFor: thisContext selector in: thisContext receiver class.
Holt den source code (inkl Kommentare, newlines, ...) der aktuellen Methode ohne den Methodennamen zu nennen. thisContext receiver class ist das gleiche wie self class.
behavior compile: source.
Kompiliert den sourcecode der akuellen Methode zu der Klasse, die wir generiert haben. Fügt also die aktuelle Methode der neuen Klasse hinzu.
thisContext client primitiveChangeClassTo: behavior new
Ändert die Klasse des aufrufenden Objektes zu der neuen Klasse, die wir generiert haben. Der Grund warum wir eine neue Instanz der Klasse, die wir generiert haben erstellen müssen (behavior new) ist dass Smalltalk sicher sein will, dass sie Klasse auch instantierbar ist.

Das ist kein Pseudocode! Das läuft!
Mach das mal in irgend einer anderen Sprache.


Wie meinst Du das?
Metaklassen, Metametaklassen, ...

C# 2.0 hat das yield return Schlüsselwort. Damit kann man Closures im Zusammenhang mit Enumeratoren nutzen.
Das ist ein ganz hässlicher Hack. Der Compiler erzeugt einfach eine statemachine. Das sind nicht Closures.

Unter C++ muss man der Funktion ein Kontext Objekt mitgeben in der dann lokale Variablen gespeichert werden. Nicht schön, aber möglich, falls es denn gebraucht wird.
Genau, nicht schön und mühsam.


Hast Du ein Beispiel dafür, mir fällt keins ein?
null zum Beispiel
Der Stack, der Grabage Collector, Klassen, Methoden, ...


Jede Sprache hat eine feste Syntax. Wenn die Sprache erweitert wird ist, es natürlich dass man ab und an Spracherweiterungen einführen muss. Wie wird das in Smalltalk gelöst, wenn z.b. in 4 Jahren es Sprachsyntax für z.B. Threadprogrammierung gibt?
Danke das du fragst:

self synchronized: [
self foo.
self bar
]
Das sind 3 Zeilen Code was zu implementieren. Die bestehende Syntax ist machtig genug für sowas.

Das Problem bei Java/C++/C# ist, dass jeder Scheiss (for, if, class, while, import, static, ...) mit einem eigenen keyword, statt mit einem allgemeinen Sprachmechanismus (z.B. Methodenaufruf) implementiert ist. Der Idealfall hier ist sicher LISP als "programmierbare Programmiersprache" mit einer simplen extrem flexiblen Syntax.
Für so etwas banales wie for-each musste die Java-Syntax angepasst werden. Willst du ein for-each für Listen, das auch den Index zurückgibt musst die Syntax noch einmal anpassen.
Man kann z.B. Traits zu Smalltalk hinzufügen, ohne die Syntax, die VM, oder den Bytecode zu ändern.


Wie meinst Du das?
Die JVM ist nicht in Java implementiert. Ich kann die JVM nicht innerhalb der JVM laufen lassen und debuggen.


Wo ist dabei das Problem? In 99% der Fälle ist der Typ bekannt zur Kompilierzeit. Wenn man den dynamischen Typ braucht, kann man einige Probleme auch durch besseres Klassendesign lösen.
Ich verweise auf die Diskussion in 'Design Patterns' zum composite wo add, remove und Konsorten implementiert werden sollen.
Auch Proxies sind viel einfacher zu implementieren und closures und statische Typisierung sind ein Fall für sich.
Was ich gegen statische Typisierung habe ist nicht, dass es weniger mächtig als dynamische Typisierung ist, sondern dass es in der Praxis ein Mehraufwand mit sehr kleinem Nutzen ist.


Wie meinst Du das?
Ok, angenommen ich will eine Methode zu Stirng, Object, oder sonst einer bel. Klasse hinzufügen. Diese Methode soll aber wegen der Versionskontrolle nicht zu dem Paket gehören, in dem die modifizierte Klasse ist, sondern zu einem anderen. Ich mache einfach ein Protokoll *MeinPaket in der Klasse, füge meine Methode dort hinzu in gut ist. Wenn ich mich mutig fühle kann ich mit *MeinPaket-override, sogar Methoden mit eigenen erstetzen..



Mhmm ich mache eine Klasse und überlade die Operatoren? Kann damit meinen eigenen Typ (z.b. für Rationale Zahlen) transparent verwenden.
So kannst du zwar bel. Zahlen zu deinen hinzuzählen, du kannst aber deine Zahl z.B nicht zu 1 hinzuzählen. Ist also nur die Hälfte.

ScottManDeath
2005-05-20, 23:02:18
The OT strikes back

public Number add(Number a, Number b) {
return a + b;
}

Wobei a und b bel. unterschiedliche Zahlen sein können (Float, Integer, Decimal, BigInteger, Rational, ...)
Falls ja, :up:
Für mich ist das Symbol dafür, was mit Zahlen unter Java einfach falsch ist.



Unter C++ sieht das so aus

template <typename T>
T add(T a, T b)
{
return a + b; // solange a und b den + operator haben geht das
}

unter C# 2.0 muss man halt eine Klasse drumrumbauen

public class MyClass
{
public T Add<T>( T a, T b)
{
return a + b;
}
}


Was anderes. Kannst du einen eigenen unknown boolean machen, der mit true und false zusammenarbeitet und auch mit if/else?


Japs, muss ich nicht mal selbst machen, ist als Beispiel in der C# Doku dabei ;)

// direkt aus der Hilfe ;)
public struct DBBool
{
// The three possible DBBool values.
public static readonly DBBool Null = new DBBool(0);
public static readonly DBBool False = new DBBool(-1);
public static readonly DBBool True = new DBBool(1);
// Private field that stores –1, 0, 1 for False, Null, True.
sbyte value;
// Private instance constructor. The value parameter must be –1, 0, or 1.
DBBool(int value)
{
this.value = (sbyte)value;
}
// Properties to examine the value of a DBBool. Return true if this
// DBBool has the given value, false otherwise.
public bool IsNull { get { return value == 0; } }
public bool IsFalse { get { return value < 0; } }
public bool IsTrue { get { return value > 0; } }
// Implicit conversion from bool to DBBool. Maps true to DBBool.True and
// false to DBBool.False.
public static implicit operator DBBool(bool x)
{
return x? True: False;
}
// Explicit conversion from DBBool to bool. Throws an exception if the
// given DBBool is Null, otherwise returns true or false.
public static explicit operator bool(DBBool x)
{
if (x.value == 0) throw new InvalidOperationException();
return x.value > 0;
}
// Equality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static DBBool operator ==(DBBool x, DBBool y)
{
if (x.value == 0 || y.value == 0) return Null;
return x.value == y.value? True: False;
}
// Inequality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static DBBool operator !=(DBBool x, DBBool y)
{
if (x.value == 0 || y.value == 0) return Null;
return x.value != y.value? True: False;
}
// Logical negation operator. Returns True if the operand is False, Null
// if the operand is Null, or False if the operand is True.
public static DBBool operator !(DBBool x)
{
return new DBBool(-x.value);
}
// Logical AND operator. Returns False if either operand is False,
// otherwise Null if either operand is Null, otherwise True.
public static DBBool operator &(DBBool x, DBBool y)
{
return new DBBool(x.value < y.value? x.value: y.value);
}
// Logical OR operator. Returns True if either operand is True, otherwise
// Null if either operand is Null, otherwise False.
public static DBBool operator |(DBBool x, DBBool y)
{
return new DBBool(x.value > y.value? x.value: y.value);
}
// Definitely true operator. Returns true if the operand is True, false
// otherwise.
public static bool operator true(DBBool x)
{
return x.value > 0;
}
// Definitely false operator. Returns true if the operand is False, false
// otherwise.
public static bool operator false(DBBool x)
{
return x.value < 0;
}
public override bool Equals(object obj)
{
if (!(obj is DBBool)) return false;
return value == ((DBBool)obj).value;
}
public override int GetHashCode()
{
return value;
}
public override string ToString()
{
if (value > 0) return "DBBool.True";
if (value < 0) return "DBBool.False";
return "DBBool.Null";
}
}


Nutzt man dann so:

DBBool is_true = DBBool.True;
DBBool is_false = DBBool.False;
DBBool is_null = DBBool.Null;
if(is_true) Console.WriteLine("is_true is true");
else Console.WriteLine("is_true is false");
if(!is_true)Console.WriteLine("!is_true is true");
else Console.WriteLine("!is_true is false");
if(is_false) Console.WriteLine("is_false is true");
else Console.WriteLine("is_false is false");
if(!is_false)Console.WriteLine("!is_false is true");
else Console.WriteLine("!is_false is false");
if(is_null) Console.WriteLine("is_null is true");
else Console.WriteLine("is_null is false");
if(!is_null)Console.WriteLine("!is_null is true");
else Console.WriteLine("!is_null is false");
/* output:
is_true is true
!is_true is false
is_false is false
!is_false is true
is_null is false
!is_null is false
*/


Metaklassen, Metametaklassen, ...

null zum Beispiel
Der Stack, der Grabage Collector, Klassen, Methoden, ...


Mhmm, warum sollte man darauf Zugriff haben wollen (Stack, GC)
Führt IMHO zu hässlichem, unverständlichem Code der schwer zu verstehen und zu warten ist. Ausserdem sind diese Dinge ein paar Abstraktionebenen zu tief IMHO.

Mittels Reflection kann man in .NET und Java auf Klassen und Methoden zugreifen, um z.B. dynamische neue Instanzen erstellen. Wenn man es braucht kann mit den Klassen für CodeDocumentObject auch dynamisch neue Typen erstellen, compilieren und Instanzen erstellen.


Das Problem bei Java/C++/C# ist, dass jeder Scheiss (for, if, class, while, import, static, ...) mit einem eigenen keyword, statt mit einem allgemeinen Sprachmechanismus (z.B. Methodenaufruf) implementiert ist. Der Idealfall hier ist sicher LISP als "programmierbare Programmiersprache" mit einer simplen extrem flexiblen Syntax.


...wobei der einzige Zweck von LISP darin besteht noch mehr LISP Code zu erzeugen ;) *SCNR*

Wegen der Syntax, man kann z.b. auch in C Polymorphes OOP machen, indem man sich structs mit Function Pointern selbst anlegt und manipuliert .....

Ist es deshalb schlecht das C++ keywords wie z.B. class, virtual, .... hat?


Die JVM ist nicht in Java implementiert. Ich kann die JVM nicht innerhalb der JVM laufen lassen und debuggen.


Mann könnte das sicher per Bootstrapping implementieren, aber wozu?
Warum sollte man das wollen?


Ok, angenommen ich will eine Methode zu Stirng, Object, oder sonst einer bel. Klasse hinzufügen. Diese Methode soll aber wegen der Versionskontrolle nicht zu dem Paket gehören, in dem die modifizierte Klasse ist, sondern zu einem anderen. Ich mache einfach ein Protokoll *MeinPaket in der Klasse, füge meine Methode dort hinzu in gut ist. Wenn ich mich mutig fühle kann ich mit *MeinPaket-override, sogar Methoden mit eigenen erstetzen..


Wo ist dabei der praktische Nutzen?
Das sorgt IMHO dazu dass es unübersichtlicher wird und der Library Coder noch sorgen hat dass irgendjemand an seinen Methoden rumspielt.

z.B.
in der Lib

public class BaseClass
{
.... Methoden
}

private class MyPrivateClass : BaseClass
{
void MySecretMethod()
}

Jetzt fügt jemand von aussen der BaseClass eine virtuelle MySecretMethod hinzu die einen ganz anderen Zweck hat. Was dann?

So kannst du zwar bel. Zahlen zu deinen hinzuzählen, du kannst aber deine Zahl z.B nicht zu 1 hinzuzählen. Ist also nur die Hälfte.

Keine Hürde, müsste man sicher um es nutzbar zu machen überarbeiten ;)

using System;
namespace OperatorTest
{
// struct -> werttyp
struct Bruch
{
public Bruch( long z) : this(z,1)
{
}
public Bruch( long z, long n)
{
m_zähler = z;
m_nenner = n;
}

// mit operatoren * ; * ist das einfachste für brüche ;)
static public Bruch operator * ( Bruch left, long right)
{
return new Bruch(left.m_zähler * right,left.m_nenner);
}
static public Bruch operator * ( long left,Bruch right)
{
return new Bruch(left * right.m_zähler, right.m_nenner);
}

// typumwandlungen
static public implicit operator float(Bruch right)
{
return (float)right.m_zähler / (float)right.m_nenner;
}
static public implicit operator Bruch(long right)
{
return new Bruch(right);
}
public override string ToString()
{
return m_zähler +"/"+ m_nenner;
}
private long m_zähler;
private long m_nenner;
}


Nutzbar so:

class MainClass
{
static void Main(string[] args)
{
Bruch a = new Bruch(1 ,5);
Bruch i = 4 * a;
float j = 4 * a;
Bruch k = a * 4;
float l = a * 4;
Console.WriteLine("a= {0}",a);
Console.WriteLine("a= {0}",(float)a);
Console.WriteLine("i = {0}",i);
Console.WriteLine("j = {0}",j);
Console.WriteLine("k = {0}",k);
Console.WriteLine("l = {0}",l);
/* output:
a= 1/5
a= 0,2
i = 4/5
j = 0,8
k = 4/5
l = 0,8
*/
Console.ReadLine();
}
}
}

ScottManDeath
2005-05-26, 14:03:07
*push*


ich hab mir hoffentlich nicht umsonst einen Wolf geschrieben ;)

RoKo
2005-05-26, 22:41:50
Dann antworte ich halt was ;)

In C#2 gibt es Closures.
Aber
public class MyClass
{
public T Add<T>( T a, T b)
{
return a + b;
}
}
funktioniert nicht. Sowas klappt nur in C++. In C# bräuchte man etwas ala
public T Add<T>( T a, T b) where T : INumber
{
return (T) a.Add(b); //Add, weil Operatoren static sind
}
Etwas wie INumber gibt es aber leider nicht, man müsste also diesbezüglich alles selber implementieren und immer explizit in die eigenen neuen structs konvertieren (benutzerdefinierte, implizite Konvertierungen sind auch static). Und dann müsste man immer noch rumcasten, weil Add nur INumber zurückgeben kann.

ScottManDeath
2005-05-26, 22:48:32
Dann antworte ich halt was ;)
funktioniert nicht. Sowas klappt nur in C++. In C# bräuchte man etwas ala
public T Add<T>( T a, T b) where T : INumber
{
return (T) a.Add(b); //Add, weil Operatoren static sind
}
Etwas wie INumber gibt es aber leider nicht, man müsste also diesbezüglich alles selber implementieren und immer explizit in die eigenen neuen structs konvertieren (benutzerdefinierte, implizite Konvertierungen sind auch static). Und dann müsste man immer noch rumcasten, weil Add nur INumber zurückgeben kann.

Ich weis, hab ich aber aus didaktischen Gründen geflissentlich vereinfacht ;) Man könnte mit Reflection sich die op_Plus Methode raussuchen und dann ausführen, wäre dann wohl nicht performant, aber.... ;)

Ist aber kein Problem, ich kann C++ ja auch als .NET MSIL compilieren

RoKo
2005-05-26, 23:41:56
Ich weis, hab ich aber aus didaktischen Gründen geflissentlich vereinfacht ;) Man könnte mit Reflection sich die op_Plus Methode raussuchen und dann ausführen, wäre dann wohl nicht performant, aber.... ;)
Hm, ich denke aber, dass es gerade darum ging, ob das einfach machbar ist. Und das ist alles nicht mehr einfach.
Ist aber kein Problem, ich kann C++ ja auch als .NET MSIL compilieren
Aus C++Templates werden aber keine .net-Generics, Du kannst Deine Add-Methode dann also nur innerhalb der C++Assembly benutzen.

HellHorse
2005-05-27, 09:55:35
Unter C++ sieht das so aus
....
unter C# 2.0 muss man halt eine Klasse drumrumbauen
Und diese eine Methode funktioniert so für bel Zahlen. Also auch wenn a ein float und b ein BigInteger oder a ein int und b ein double ist? Und umgehkehrt auch? Ehrlich?


Mhmm, warum sollte man darauf Zugriff haben wollen (Stack, GC)
GC:
- weil man einen eigenen GC implementieren will (weil keiner der bestehenden für den gegebenen Fall ideal ist, oder weil man ein Paper über GCs schreibt und es nicht bei der Theorie belassen will (da müssen Tabellen und Graphiken mit Zahlen hin ;)))
- weil man den besthenden GC profilen will (wieviele Objekte, welcher Klasse werden wann gekillt, ok für Java gibt es da so ein Projekt, dass den verbose GC output parst, aber stell dir vor, wie viel besser es wäre, wenn man direkt mit dem GC reden, oder ihn anpassen könnte)

Stack:
- Stringrepresentation des gesamten Stack, inkl allen lokalen, instanz, klassen und sonstigen Variablen zu erstellen (wenn auf dem Produktionsserver eine unerwartete Exception auftrat um diese dann als ein Mail an den Entwickler zu schreiben, man könnte den Stack sogar serialisieren (was je natürlich recht gross werden kann) damit dann der Entwickler auf seiner Entwicklungsmachine den Stack wieder herstellen kann, oder man könnte ihn irgendwohin speichern (im RAM), dann kann ein Entwickler vorbeikommen (idealerweise selbstgehostet), drückt eine Knopf, und hat einen Debugger mit dem vollen Stack)
- um einfach einen eigenen Debugger zu implementieren (z.B. webbasierend)
- um einfach einen Debugger nur zu öffnen, falls eine Methode nur von einer best. anderen Methode aufgerufen wird
- um continuations zu implementieren


Mittels Reflection kann man in .NET und Java auf Klassen und Methoden zugreifen, um z.B. dynamische neue Instanzen erstellen. Wenn man es braucht kann mit den Klassen für CodeDocumentObject auch dynamisch neue Typen erstellen, compilieren und Instanzen erstellen.
Und einfach und simpel per-Objekt Aspekte implementieren?


Wegen der Syntax, man kann z.b. auch in C Polymorphes OOP machen, indem man sich structs mit Function Pointern selbst anlegt und manipuliert .....
Ja, so Geschichten wie ObjVLISP. Dürfte ganz lustig sein. Sicher die Hölle bis es debugged ist, aber ganz lustig.
Aber sicher, man kann mit einer Programmiersprache immmer eine bessere Programmiersprache implementieren ;)

Ist es deshalb schlecht das C++ keywords wie z.B. class, virtual, .... hat?
Ich finde es schlecht, dass C++ so verdammt viele keywords hat.


Warum sollte man das wollen?
- Protabilität
- vereinfachtes JVM (weiter)entwickeln und debuggen


Wo ist dabei der praktische Nutzen?
Hast du dir noch nie gewünscht, wenn Object/String/Collection doch nur diese eine Methode implementieren würde.

"Hilfsmethoden"
z.B. #first und #last in List/Array (und #second, #third, #fourth, #fifth, #sixth, #eventh, #eight und #ninth gleich mit)
#asSuperCoolFormattedString, das auch mit null läuft
oder eine Iterationsmethode über Collections, die immer die zwei nächsten Objekte zurückgibt
oder eine Iterationsmethode über Collections, die immer nur jedes zweite Objekt zurückgibt
oder eine Methode, die irgend einen spezielle Median über eine Collection zurückgibt
oder eine Iterationsmethode über Files, die die Zeile und die Zeilennummer zurückgibt
oder eine Iterationsmethode die zusätzlich einen Fortschrittsbalken updatet

Klar könnte man das zum Teil in eine "Utilityklasse" tun, aber das nicht nicht objektorientiert, da das Verhalten zu den Daten gehört.
Darum ist auch so etwas wie java.lang.Math scheisse. Das ist Verhalten, das nun mal auf die Instanzseite (!!!) einer Numberklasse gehört.
Aus dem gleichen Grund gehört der + operator sicher nicht in eine statische Methode auf der Klassenseite. Ausser natürlich man will + für Klassen implementieren.

"Framework-Methoden":
- du baust ein Framework und willst, dass alle Objekte (oder nur Collections, oder ...) eine bestimmte Nachricht verstehen.
- z.B. du hast ein Methodell und musst deswegen Methoden (z.B #description) bei Object
hinzufügen


Das sorgt IMHO dazu dass es unübersichtlicher wird und der Library Coder noch sorgen hat dass irgendjemand an seinen Methoden rumspielt.
Nein, der hat sich darum nicht zu kümmern. Wie soll er auch?

z.B.
in der Lib
Du kannst einfach so in .Net String, Object oder Date Methoden hinzufügen?
Wie ich sage, classextenstions gehören nicht zu dem Paket, in dem die Klasse definiert ist, sondern einem anderen, vom Nutzer frei wählbaren -> du hast das Paket nicht, du hast die Methode nicht


Keine Hürde, müsste man sicher um es nutzbar zu machen überarbeiten ;)
Warum zum Henker endet das in einer statischen (!) methode auf der Klassenseite (!!) des Argumentes (!!!). Wie viel falscher geht es denn noch?
Jemand anderen würde man deswegen zu lebenslänglich COBOL verurteilen.

Man könnte mit Reflection sich die op_Plus Methode raussuchen und dann ausführen,

Es schlussendlich als virtuelle Methode auf der Instanzseite implementieren, was die einizig saubere Lösung wäre.

Etwas wie INumber gibt es aber leider nicht, man müsste also diesbezüglich alles selber implementieren ... Und dann müsste man immer noch rumcasten, weil Add nur INumber zurückgeben kann.
Genau das ist das Problem.

*push*
sorry, vorher nicht gesehen :(

RoKo
2005-05-27, 13:29:45
Eins von den Zitaten stammt nicht von ScottManDeath ;)

HellHorse
2005-05-27, 14:03:16
*'tschuldigung*
Besser? :)

ScottManDeath
2005-05-27, 15:14:41
Und diese eine Methode funktioniert so für bel Zahlen. Also auch wenn a ein float und b ein BigInteger oder a ein int und b ein double ist? Und umgehkehrt auch? Ehrlich?


Unter C++, ja, unter C#2.0 nein :) Gut Du hast mich halb erwischt ;)


GC:
- weil man einen eigenen GC implementieren will (weil keiner der bestehenden für den gegebenen Fall ideal ist, oder weil man ein Paper über GCs schreibt und es nicht bei der Theorie belassen will (da müssen Tabellen und Graphiken mit Zahlen hin ;)))
- weil man den besthenden GC profilen will (wieviele Objekte, welcher Klasse werden wann gekillt, ok für Java gibt es da so ein Projekt, dass den verbose GC output parst, aber stell dir vor, wie viel besser es wäre, wenn man direkt mit dem GC reden, oder ihn anpassen könnte)


Dafür gibts den CLRProfiler (http://www.c-sharpcorner.com/Code/2004/Aug/CLRProfiler.asp), damit kann man sich anzeigen lassen welche Objekte es gibt, wieviel Speicher sie belegen... etc.

Mhmm IMHO ist der default .NET / Java GC in 99% der Anwendungsfällen ok, ist es für das andere 1% gerechtfertigt des GC anpassbar zu machen? Sowas ist ja auch mit Aufwand (Entwicklung, Testen) verbunden.

Das mit den Diagrammen & co, jups, das versteh ich ;)


Stack:
- Stringrepresentation des gesamten Stack, inkl allen lokalen, instanz, klassen und sonstigen Variablen zu erstellen (wenn auf dem Produktionsserver eine unerwartete Exception auftrat um diese dann als ein Mail an den Entwickler zu schreiben, man könnte den Stack sogar serialisieren (was je natürlich recht gross werden kann) damit dann der Entwickler auf seiner Entwicklungsmachine den Stack wieder herstellen kann, oder man könnte ihn irgendwohin speichern (im RAM), dann kann ein Entwickler vorbeikommen (idealerweise selbstgehostet), drückt eine Knopf, und hat einen Debugger mit dem vollen Stack)
- um einfach einen eigenen Debugger zu implementieren (z.B. webbasierend)
- um einfach einen Debugger nur zu öffnen, falls eine Methode nur von einer best. anderen Methode aufgerufen wird
- um continuations zu implementieren


Hmmm, hört sich sexy an, kann man das mit Smalltalk?


Ich finde es schlecht, dass C++ so verdammt viele keywords hat.


Deutsch und English haben deutlich mehr... *SCNR*

Man muss in jeder Sprache die keywords lernen, ich persönlich hab keine Probleme die C++/C# keywords zu kennen, wie hat Smalltalk das Problem gelöst? Ob ich nun die Klassen des Sprachframeworks lernen muss, oder keywords, wo ist da der Unterschied


"Hilfsmethoden"
z.B. #first und #last in List/Array (und #second, #third, #fourth, #fifth, #sixth, #eventh, #eight und #ninth gleich mit)
#asSuperCoolFormattedString, das auch mit null läuft
oder eine Iterationsmethode über Collections, die immer die zwei nächsten Objekte zurückgibt
oder eine Iterationsmethode über Collections, die immer nur jedes zweite Objekt zurückgibt
oder eine Methode, die irgend einen spezielle Median über eine Collection zurückgibt
oder eine Iterationsmethode über Files, die die Zeile und die Zeilennummer zurückgibt
oder eine Iterationsmethode die zusätzlich einen Fortschrittsbalken updatet


Mhmm die C++ STL hat das IMHO elegant gelöst, es wurden die Container von den Algorithmen getrennt, Die Container geben Iteratoren zurück, die Algorithmen nutzen diese und bauen dann komplexere Verhaltensweisen.

Es gibt z.b. eine "sort" funktion die mit allen (!) Containern zusammenarbeitet die die benötigten Iteratoren zur verfügung stellt. Wenn das nicht so wäre hätte man z.B. ein ListQuickSort, ListBubbleSort, VectorQuickSort, VectorBubbleSort... So hat man nur ein QuickSort und ein BubbleSort, wenn Du dann einen MyÜberContainer hat mit den Iteratoren, kann man die Sort Algorithmen einfach so verwenden.

Analog dazu "find" oder auch "search" oder andere Algorithmen.

Das sieht dann so aus.


void PrintInt(int i)
{
printf("%i\n",i);
}

vector<int> the_list;
fill_list(the_list); // irgendwie füllen
sort((the_list.begin(), the_list.end()); // sortieren
for_each(the_list.begin(), the_list.end(),PrintInt); // mit der for_each Funktion,(kein Keyword!) iterieren und ausgeben
for_each(the_list.begin(), the_list.end(),cout << _1); // mit boost hat man auch lambda ausdrücke mit anonymen funktionen

vector<int>::iterator iter = the_list.begin(); // Iterator auf begin
advance(iter,7); // 7 felder nach vorne
PrintInt(*iter);



Klar könnte man das zum Teil in eine "Utilityklasse" tun, aber das nicht nicht objektorientiert, da das Verhalten zu den Daten gehört.
Darum ist auch so etwas wie java.lang.Math scheisse. Das ist Verhalten, das nun mal auf die Instanzseite (!!!) einer Numberklasse gehört.
Aus dem gleichen Grund gehört der + operator sicher nicht in eine statische Methode auf der Klassenseite. Ausser natürlich man will + für Klassen implementieren.


Stimme ich so nicht ganz mit überein. Zahlen sind IMHO einfache einelementige Container die die Daten halten. Sinus, Kosinus, ..... braucht nicht jeder und sollten deshalb auch nicht das Interface von Int und Float "versauen", deswegen entweder sin/ cos als freie Funktionen (in C++) oder als Static Member (C#, Java) einer Klasse die dafür zuständig ist. Was machst Du z.b. mit der Sinc funktion oder anden nichtalltäglichen? Sollen die immer mit als Instanzmethode dabei sein?


Warum zum Henker endet das in einer statischen (!) methode auf der Klassenseite (!!) des Argumentes (!!!). Wie viel falscher geht es denn noch?
Jemand anderen würde man deswegen zu lebenslänglich COBOL verurteilen.


Die Operatoren sind lediglich syntaktisches Entgegenkommen für Methodenaufruf,
MyClass a, b;
a + b wird vom Compiler umgewandelt zu MyClass:: Op_Plus(a,b).

Operatoren und Polymorphismus sind Dinge die man nicht in der selben Klasse vermischen sollte. Arithmethische Operatoren sollten nur für Objekte die Zahlen ähneln ( wie z.B. Vektoren) verwendet werden. Do it like the ints do it

Wo ist der Unterschied zwischen Typkonvertierung von A zu B ob es nun als Instanzenmethode oder als Klassenmethode definiert ist. Bei Gebrauch ist es sowieso egal. Bei der Klassenmethode hat man das Objekt als Parameter übergeben, in der Instanzmethode hab ich Zugriff auf die this Member. Syntaktisch leicht unterschiedlich, semantisch Identisch

Ich persönlich finde die C# Typkonversion als Klassenmethoden übersichtlicher als die C++ Konvertierungskonstruktor/Konvertieroperator Implementation. Es ist alles an einer Stelle und orthogonal.



Es schlussendlich als virtuelle Methode auf der Instanzseite implementieren, was die einizig saubere Lösung wäre.


Das sicherlich, dann kann ich aber nicht + und - schreiben

So zum Abschluss die Ketzerfrage: Wieviele große Softwareprodukte werden in Smalltalk (neu) entwickelt? Wieviele in C++/C#/Java? Ist das nicht ein Indiz das C++/C#/Java doch für die Masse der Programmierer handhabbar sind?

ScottManDeath
2005-05-27, 15:16:43
Aus C++Templates werden aber keine .net-Generics, Du kannst Deine Add-Methode dann also nur innerhalb der C++Assembly benutzen.

Ok, ich könnte aber bei Bedarf das ganze als private Member nutzen und müsste das dann nach aussen hin wrappen

Coda
2005-05-27, 17:40:26
std::sort funktioniert nicht mit std::list.

Da gibt's extra ein std::list::sort, weil std::sort random access iteratoren braucht

ScottManDeath
2005-05-27, 18:05:00
std::sort funktioniert nicht mit std::list.

Da gibt's extra ein std::list::sort, weil std::sort random access iteratoren braucht

Stymmt

RoKo
2005-05-27, 18:29:43
Ok, ich könnte aber bei Bedarf das ganze als private Member nutzen und müsste das dann nach aussen hin wrappen
Dann hast Du aber nach aussen hin Deine Generizität verloren.
Templates sind statisch, in Smalltalk ist das ganze Zeug dynamisch nutzbar - das ist der Unterschied.
So zum Abschluss die Ketzerfrage: Wieviele große Softwareprodukte werden in Smalltalk (neu) entwickelt? Wieviele in C++/C#/Java? Ist das nicht ein Indiz das C++/C#/Java doch für die Masse der Programmierer handhabbar sind?
Glaube nicht. Ich habe zwar so meine Probleme mit Smalltalk, aber ich bin eben schon anderes gewöhnt. Die Situation ist wahrscheinlich üblich.

*'tschuldigung*
Besser? :)
Könntest Du es noch rot einrahmen? :)

Trap
2005-05-27, 20:27:54
Man muss in jeder Sprache die keywords lernen, ich persönlich hab keine Probleme die C++/C# keywords zu kennen, wie hat Smalltalk das Problem gelöst?
Common Lisp hat keine keywords, nur keyword-parameter und die sind was ganz anderes. Man hat nur Funktionen und Makros.
Keine Lösung durch Sprachunterstützung die nur in einem Spezialfall funktioniert, sondern ein allgemein verwendbarer Sprachmechanismus den man auch für seine eigenen Konstruktionen verwenden kann.

GC ersetzbar halte ich für extrem aufwändig zu implementieren, für eine effiziente Implementierung muss man extrem viel anpassbar gestalten (Tags, read-/write-barrier, Speicheranforderung vom OS). Der Gewinn dagegen ist recht klein.
GC durch das Programm manipulierbar halte ich dagegen für unverzichtbar. Beispielsweise so: http://www.lispworks.com/documentation/lww42/LWUG-W/html/lwuser-w-60.htm

Das mit dem Stack halte ich für dumm. Stack ist ein Implementierungskonzept, kein Sprachkonzept. Sobald man expliziten Zugriff auf den Stack in die Sprache aufnimmt muss man auch festschreiben wie der Stack benutzt wird, sonst ist das Feature unbenutzbar.

Methoden Klassen zuordnen zu müssen halte ich für einen der grundlegendsten Fehler aller modernen OOP Denkweise. Das ist eine völlig künstliche Zwangsbedingung ohne jede Grundlage in der Problemanalyse.

Falls jemand ein gutes Buch zu Lisp lesen möchte: http://www.gigamonkeys.com/book/
Wer nur in ein Kapitel reingucken möchte, dem empfehl ich: http://www.gigamonkeys.com/book/practical-parsing-binary-files.html

HellHorse
2005-05-27, 23:26:52
Hmmm, hört sich sexy an, kann man das mit Smalltalk?
- Stringrepresentation des gesamten Stack, inkl allen lokalen, instanz, klassen und sonstigen Variablen zu erstellen (wenn auf dem Produktionsserver eine unerwartete Exception auftrat um diese dann als ein Mail an den Entwickler zu schreiben
Machen wir (lassen Klassenvariablen weg, könnte man hinzufügen). Code kann ich aus nachvollziehbaren Gründen leider nicht zeigen, ist aber sehr wenig.

drückt eine Knopf, und hat einen Debugger mit dem vollen Stack
Macht seaside, haben wir auf den Produktionsmachinen deaktiviert.

- um continuations zu implementieren
hat Avi für seaside gemacht, sind vielleicht 20 LOC

- um einfach einen Debugger nur zu öffnen, falls eine Methode nur von einer best. anderen Methode aufgerufen wird

haltIf: aSelector
| cntxt |
cntxt := thisContext.
[ cntxt sender isNil ] whileFalse: [
(cntxt selector = aSelector) ifTrue: [
Halt signal ] ]
Schiebt man am besten als classextension (*hint*) in Object, damit es überall zur Verfügung steht.
Benutzt wird das Ganze dann so.

verbuggteMethode
self haltIf: #verdaechtigeMethode.
"code hier"


- um einfach einen eigenen Debugger zu implementieren (z.B. webbasierend)
Sollte recht einfach sein. Seaside rendert im Fall einer Exception schon den gesamten Stack inkl. Variablen (vielleicht 25 LOC). Code holen ist kein Problem (siehe Sig). pc und solche Gesichten abfragen ist kein Problem. ContextPart ist eine normale Klasse mit Methoden, Instanzvariablen, .... . Zum Code bearbeiten und highlighten des aktuellen Ausruckes machst du am besten zwei verschieden Widgets. Erstes ist kein Problem, es gibt schon ein CodeBrowser-Widget, dass sich wie ein vereinfachter Codebrowser von Smalltalk verhält (Klassen anzeigen, Methoden hinzufügen und ändern). Das highlighten des aktuellen Ausdruckes drüfte wohl das Schwerste sein. Aber man kann sich natürlich den Code des bestehenden Debuggers anschauen, der natürlich in Smalltalk implementiert ist.
Geschätzer Aufwand: ein Wochende :D


Deutsch und English haben deutlich mehr... *SCNR*
Und man hat fast so lange zum lernen ... *SCNR*


Man muss in jeder Sprache die keywords lernen, ich persönlich hab keine Probleme die C++/C# keywords zu kennen, wie hat Smalltalk das Problem gelöst?
Was keywords? Gibt es eigentlich nicht. Ok, super vielleicht und ^ für return. Daneben gibt es halt einfach variablen, die immer da sind (nil, ture, false, self, thisContext). Aber es hindert dich niemand daran sowas zu machen:
self
^ self
Der Rest ist eigentlich mit message sends implementiert, wobei die IDE einen Teil versteckt.


Ob ich nun die Klassen des Sprachframeworks lernen muss, oder keywords, wo ist da der Unterschied
Der Unterschied ist, dass du es nicht lernen musst. Smalltalk's kommen mit einer IDE, dort hast du dann ein Textfeld in das du den Methodencode schreiben kannst. Du musst also den Methodenaufruf für die Generierung nicht lernen. Du willst eine Methode auf der Klassenseite implementieren? Wechsle in der IDE einfach von der Instanz auf die Klassenansicht.
Beispiel Klassenerstellung. Du clickst auf die Kategorie, in der du die Klasse erstellen willst, im GUI erscheint etwas ähliches wie:
Object subclass: #NameOfSubclass
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'MyPackage'
Eventuell fällt dir auf, dass das ein Methodenaufruf ist. Muss es aber nicht. Was du jetzt machen musst um eine Klasse mit Instanzvariable zu erstellen, dürfte wohl klar sein.


Mhmm die C++ STL hat das IMHO elegant gelöst, es wurden die Container von den Algorithmen getrennt, Die Container geben Iteratoren zurück, die Algorithmen nutzen diese und bauen dann komplexere Verhaltensweisen.

Es gibt z.b. eine "sort" funktion die mit allen (!) Containern zusammenarbeitet die die benötigten Iteratoren zur verfügung stellt. Wenn das nicht so wäre hätte man z.B. ein ListQuickSort, ListBubbleSort, VectorQuickSort, VectorBubbleSort... So hat man nur ein QuickSort und ein BubbleSort, wenn Du dann einen MyÜberContainer hat mit den Iteratoren, kann man die Sort Algorithmen einfach so verwenden.
-> wo ist genau der Vorteil, dass ich BubbleSort habe?
Ich will doch nicht extra einen Algorithmus implementieren, der mir das zweite Element gibt.

Zudem finde ich Iteration in Smalltalk wesentlich eleganter.
aCollection do: [ :each | Transcript show: each ]
Ich will ein cooles Item in einer Collection suchen:
aCollection detect: [ :each | each isCool]
Alle Items, die cool sind:
aCollection select: [ :each | each isCool ]
Alle Items, die uncool sind:
aCollection reject: [ :each | each isCool ]
Eine Collection mit dem Coolwert aller Items:
aCollection collect: [ :each | each isCool ]
Gibt es ein cooles Objekt in der Collection?
aCollection anyStatisfy: [ :each | each isCool ]
das Beispiel
ich implementiere in Collection das als classextension

doPairs: aBlock
| odd last |
odd := true.
last := nil.
self do: [ :each |
odd
ifTrue: [ last := each ]
ifFalse: [ aBlock value: last value: each ].
odd := odd not ]
und das geht dann für alle Collections so:
aCollection doPairs: [ :first :second | Transcript show: (first raisedTo: second)]
fortgeschritten:
aCollection inject: 0 into: [ :sum :each | sum + each ]
(bildet summe über elemente)

Sortieren:
da gibt es viele Möglichkeiten
- das einfachste ist wohl asSortedCollection
- dann kannst du natürlich auch SequencableCollectionSorter verweden, der funktioniert dann aber nicht auf Sets


Stimme ich so nicht ganz mit überein. Zahlen sind IMHO einfache einelementige Container die die Daten halten.
Ich sehe sie als Objekte, die Zustand und Verhalten haben.

Sinus, Kosinus, ..... braucht nicht jeder und sollten deshalb auch nicht das Interface von Int und Float "versauen",
Die Frage ist doch: zu wechlem Objekt gehört das Verhalten? Die Antwort ist kar, zu der Zahl. Das ist wirlich alles, was es dazu zu sagen gibt.
Zudem:
Object selectors size.
gibt bei mir im Moment 405 und das macht es nicht schwerer mit Objekten zu arbeiten.


Was machst Du z.b. mit der Sinc funktion oder anden nichtalltäglichen? Sollen die immer mit als Instanzmethode dabei sein?
Sicher, tun ja niemandem weh.


Operatoren und Polymorphismus sind Dinge die man nicht in der selben Klasse vermischen sollte.
Warum denn das?


Arithmethische Operatoren sollten nur für Objekte die Zahlen ähneln ( wie z.B. Vektoren) verwendet werden. Do it like the ints do it
Ja und? Wo ist das Problem mit Operatoren? Verhalten sich Zahlen in Smalltalk etwa nicht wie Zahlen?


Wo ist der Unterschied zwischen Typkonvertierung von A zu B ob es nun als Instanzenmethode oder als Klassenmethode definiert ist.
Es ganz klar nicht Veranwortung der Klassenseite, Verhalten der Instanstzseite zu definieren (und es ist Verhalten der Instanzen). Sonst können gleich sturcts und Prozeduren, die auf structs arbeiten, nehmen. Das ist einfach nicht objektorientiert.

Bei Gebrauch ist es sowieso egal. Bei der Klassenmethode hat man das Objekt als Parameter übergeben, in der Instanzmethode hab ich Zugriff auf die this Member. Syntaktisch leicht unterschiedlich, semantisch Identisch
Ja genau. Warum nicht einfach gleich _alle_ Methoden auf der Klassenseite implentieren. Wir könnnen ja die Instanzen als Parameter übergeben. :rolleyes:

-> structs und Prozeduren reichen, niemand braucht Objekte?

Sorry, aber da hast du mich gerade schwer enttäuscht.

Das sicherlich, dann kann ich aber nicht + und - schreiben
Und genau das ist das Problem.


So zum Abschluss die Ketzerfrage: Wieviele große Softwareprodukte werden in Smalltalk (neu) entwickelt? Wieviele in C++/C#/Java? Ist das nicht ein Indiz das C++/C#/Java doch für die Masse der Programmierer handhabbar sind?
Nein. Eine Mehrheit kann auch nur eine Ansammlung von Idioten sein. ;)

HellHorse
2005-05-28, 08:26:51
Sobald man expliziten Zugriff auf den Stack in die Sprache aufnimmt muss man auch festschreiben wie der Stack benutzt wird, sonst ist das Feature unbenutzbar.
thisContext: Variable, die auf den aktuellen Kontext zeigt, Instanz einer Subklasse von Context (MethodContext oder BlockContext)
Class Context represents an execution context. The simulation methods return the
new context in which to continue simulation. This is normally the same context, except
after sends and returns.

Subclasses must implement the following messages:
accessing
home
homeReceiver
selector
sourceCode
private-accessing
findTemp:do:elseDo:

Instance Variables:
sender <Context|nil> context that invoked this context
receiver <Object>
stackp <SmallInteger> amount of stack that is occupied
stack <Array|nil> arguments, temporaries, and working stack. The stack and
its contents are not guaranteed to be valid after a context
has returned. In particular the stack of a context that has
been returned-from may be nil. N.B. To allow the VM to
map contexts to native stack frames care should be taken
when accessing the stack instance variable. To ensure
you see up-to-date values in the stack either access the
stack via "stack at: index [put: foo]" or use localAt:[put:].
Do *not* hold onto the stack array via some other variable
as you may see stale values. Essentially the VM ensures
the stack's contents are up-to-date with respect to any
underlying stack frame only when the stack Array is accessed
as an instance variable of a Context or via localAt:[put:].

ScottManDeath
2005-05-28, 14:10:53
-> wo ist genau der Vorteil, dass ich BubbleSort habe?
Ich will doch nicht extra einen Algorithmus implementieren, der mir das zweite Element gibt.

Zudem finde ich Iteration in Smalltalk wesentlich eleganter.
aCollection do: [ :each | Transcript show: each ]
Ich will ein cooles Item in einer Collection suchen:
aCollection detect: [ :each | each isCool]
Alle Items, die cool sind:
aCollection select: [ :each | each isCool ]
Alle Items, die uncool sind:
aCollection reject: [ :each | each isCool ]
Eine Collection mit dem Coolwert aller Items:
aCollection collect: [ :each | each isCool ]
Gibt es ein cooles Objekt in der Collection?
aCollection anyStatisfy: [ :each | each isCool ]
fortgeschritten:
aCollection inject: 0 into: [ :sum :each | sum + each ]
(bildet summe über elemente)

Sortieren:
da gibt es viele Möglichkeiten
- das einfachste ist wohl asSortedCollection
- dann kannst du natürlich auch SequencableCollectionSorter verweden, der funktioniert dann aber nicht auf Sets


BubbleSort war nur ein Beispiel, viele Algorithmen sind unabhängig vom Container und es wäre IMHO unnützer Aufwand sie für jeden Container neu per copy & paste zu implementieren.


Die Beispiele die Du gezeigt hast sind in C++ mit der STL (und eventuell boost (http://www.boost.org/) ) auch keine keywords ;), sondern Libraryklassen und Funktionen.

Hier eine Auswahl:

Summe der Elemente eines Containers

vector<int> v1;
int total;
total = accumulate ( v1.begin ( ) , v1.end ( ) , 0 );


Durschnitt eines Containers bilden

Diese Klasse sollte normalerweise in einer Lib sein
// The function object to determine the average
class Average
{
private:
long num; // The number of elements
long sum; // The sum of the elements
public:
// Constructor initializes the value to multiply by
Average ( ) : num ( 0 ) , sum ( 0 )
{
}
// The function call to process the next elment
void operator ( ) ( int elem ) \
{
num++; // Increment the element count
sum += elem; // Add the value to the partial sum
}
// return Average
operator double ( )
{
return static_cast <double> (sum) /
static_cast <double> (num);
}
};

vector<double> v1;
.... v1 füllen
double average = for_each ( v1.begin ( ) , v1.end ( ) , Average ( ) );


Alle Coolen elemente holen


bool is_cool(const Element & e)
{
return e.IsCool;
}

vector<Element> the_elements; // ist gefülle
vector<Element> cool_elements;

copy_if(elements.begin(), elements.end(), back_inserter(cool_elements),is_cool);



Object selectors size.
gibt bei mir im Moment 405 und das macht es nicht schwerer mit Objekten zu arbeiten.


Je mehr Klassen, desto besser (in der Regel) ist die Aufteilung und die Modularisierung.


Sicher, tun ja niemandem weh.

Mhmm dann kann man ja auch alle Methoden ( für Grafikausgabe, Statistik...) auch gleich direkt der Masterbasisklasse (Object) zuordnen, dort tun sie ja auch niemanden weh....




Es ganz klar nicht Veranwortung der Klassenseite, Verhalten der Instanstzseite zu definieren (und es ist Verhalten der Instanzen). Sonst können gleich sturcts und Prozeduren, die auf structs arbeiten, nehmen. Das ist einfach nicht objektorientiert.

Ja genau. Warum nicht einfach gleich _alle_ Methoden auf der Klassenseite implentieren. Wir könnnen ja die Instanzen als Parameter übergeben. :rolleyes:

-> structs und Prozeduren reichen, niemand braucht Objekte?

Sorry, aber da hast du mich gerade schwer enttäuscht.

Und genau das ist das Problem.


In C++ sind Typkonvertierungen Instanzenmethoden (Konvertierungskonstruktor für AnotherType nach MyType und der Konvertieroperator von MyType nach AnotherType)

In C# ist das nicht möglich (mit dem Konvertierungskonstruktor) deshalb braucht man eine statische Klassenmethode in MyType um von AnotherType (dessen Source man u.Umständen nicht ändern kann/darf) nach MyType zu konvertieren. Wo sonst soll dann die Umwandlung hin?

Bsp: Lineare Algebra:
Vektorklasse, Methode zur linearen Interpolation


Vector a;
Vector b;
Vector c;

c = Lerp(a,b,0.6);

vs

c = a.Lerp(b,0.6);


Ich finde ersteres eingänglicher als zweiteres, irgendwie auch ästethischer, Bei zweiteres Form sieht man nicht sofort welcher Vektor zu welchem interpoliert wird.


Nein. Eine Mehrheit kann auch nur eine Ansammlung von Idioten sein. ;)

Jau, da gibts genügend Beispiele dafür (Bundestag/Bundesrat). Es gibt aber auch kranke Minderheiten (NPD in Landtagen) ;)

HellHorse
2005-05-29, 10:36:49
viele Algorithmen sind unabhängig vom Container und es wäre IMHO unnützer Aufwand sie für jeden Container neu per copy & paste zu implementieren.
Darum kann man es ja in Collection als classextension implementieren und es steht überall zur Verfügung.
Je mehr Klassen, desto besser (in der Regel) ist die Aufteilung und die Modularisierung.
Ich stimme zu.
Das Problem ist halt eben, falls man ein System in sich selbst implementiert, muss Object halt ein bisschem mächtiger werden.
Beispiel:
Da das Inspizieren und Browsen von Objekten für alle Objekte funktionieren soll (Smalltalk kommt schon mit einem GUI) und Subklassen es z.T anpassen müssen, muss Object #inspect und #explore (und noch ein paar andere Methoden) implementieren. Subklassen können das dann überschreiben (wird eigentlich nur von Collections gemacht).
Wie willst du es sonst machen?

Mehrere Abstrakte Superklassen von Object zu haben macht irgendwie auch nicht so viel Sinn.

Mhmm dann kann man ja auch alle Methoden ( für Grafikausgabe, Statistik...) auch gleich direkt der Masterbasisklasse (Object) zuordnen, dort tun sie ja auch niemanden weh....
Ok, scheiss Begründung. Neuer Versuch:
sinc sollte implementiert sein, wo andere Mathematische Funktionen wie sin, log und Konsorten implementiert sind. Zudem wollen wir sinc nur einmal implementieren und es sollte für alle Zahlen (Float, Double, Integer, Fraction ... ) funktionieren.
Diese beiden Anforderungen lassen nur einen Schluss zu: Number.
sinc
^self isZero
ifTrue: [ 1 ]
ifFalse: [ self sin / self ]
sin und / kümmern sich um Konvertierung


Wo sonst soll dann die Umwandlung hin?
Bei Smalltalk sind sie auf der Instanzseite des zu konvertierenden Objektes. Beispiel sin in Number
sin
"Answer the angle in radians."

^self asLimitedPrecisionReal sin
in Float is es überschrieben:
sin
"return the sine of the receiver (an angle in radians)
The receiver can be any valid Float
The result will be between -1.0 and 1.0"

<primitive: 600>
^self primitiveFailed

ScottManDeath
2005-05-29, 20:38:46
Wenn ich nicht gerade soviel mit meiner Diplomarbeit zu tun hätte, würde ich mit Smalltalk ein bischen rumspielen um zu sehen wie das ganze ist, hab halt nur noch bis Anfang Juli Zeit um fertig zu werden :(

Coda
2005-05-29, 21:48:39
Hui eine Sprachendiskussion ohne Flamewar *ausdruckt und einrahmt*

ScottManDeath
2005-05-29, 22:00:30
Hui eine Sprachendiskussion ohne Flamewar *ausdruckt und einrahmt*

Wir sind ja schon große Jungs, stimmts, Hellhorse? =)

HellHorse
2005-05-29, 22:39:46
Wenn ich nicht gerade soviel mit meiner Diplomarbeit zu tun hätte ... hab halt nur noch bis Anfang Juli Zeit um fertig zu werden :(
Sklaventreiber! :(
Einfach Doktorstudium anhängen ;)

ScottManDeath
2005-05-29, 23:02:09
Sklaventreiber! :(
Einfach Doktorstudium anhängen ;)


Ganz so ist es nicht, ich hab es ja selbst so gewollt. ;)

Ich muss um den 10. Juli abgeben, am 18. verteidigen da die Profs danach in den Urlaub gehen.

Grund des Ganzen: Ich gehen im August für ein Jahr in den USA (http://www.utah.edu/) studieren, das Semester beginnt dort schon Mitte August, deswegen der knappe Zeitplan.

Das Promotionstudium kommt danach, wenn alles so kommt wie ich es gerne möchte :cool:

Jihaaa, 1F4 Posts X-D

Coda
2005-05-30, 00:14:35
Wir sind ja schon große Jungs, stimmts, Hellhorse? =)Das muss nichts heißen :D

HellHorse
2005-09-18, 15:55:51
Ok, ich bin ein selbstverliebstes, besserwisserisches Arschloch, aber :wayne:

Ich glaube mich trifft der Schlag, das wird doch tatsächlich in C# 3 sein:

- keine Closures
- keine classextensions
Ist alles scheisse, was Micro$~1 nicht hat, bis Micros$~1 es hat. Alles klar :rolleyes:

Ich habe die Spec bloss kurz überflogen aber man scheint sich sogar ein klein bisschen in Richtung dynamische Programmiersparche zu bewegen.

Der Link:
http://msdn.microsoft.com/vcsharp/future/

P.S.:
Ist das jetzt eigentlich der am meisten OT Thread im ganzen Forum? :biggrin:

Senior Sanchez
2005-09-18, 16:09:47
P.S.:
Ist das jetzt eigentlich der am meisten OT Thread im ganzen Forum? :biggrin:

ich würde ihn ja noch mehr @OT treiben ;) aber könnteste mal deine Programmierlaufbahn in diesem komischen Fred der hier irgendwo rumgurkt posten? *g* Würde mich mal ehrlich interessieren, was das Höllenpferdchen bisher so gemacht hat :)

EDIT: Ab wann ist eine Programmiersprache eigentlich dynamisch? Zum Teil wird Java als eine bezeichnet, aber C# und Java sind ja eigentlich sehr ähnlich und in diesem Atemzug bezeichnest du C# vllt bald als dynamische Sprache. Also wäre jetzt die Frage, wie das ganze _genau_ definiert ist.

HellHorse
2005-09-18, 18:11:20
ich würde ihn ja noch mehr @OT treiben ;) aber könnteste mal deine Programmierlaufbahn in diesem komischen Fred der hier irgendwo rumgurkt posten? *g* Würde mich mal ehrlich interessieren, was das Höllenpferdchen bisher so gemacht hat :)
Lad' mich auf ein Bier ein, und ich erzähls dir ;)

EDIT: Ab wann ist eine Programmiersprache eigentlich dynamisch?
Wenn sie ein dynamisches Typsystem hat, so wie die meisten Skriptsprachen (Python, Ruby, ...). Das heisst Variablen haben keinen Typ, sondern nur Werte. Schlussendlich heisst das der Compiler macht keine Checks mehr, ob die Methode für eine Variable angemessen ist, es wird nur noch zu Laufzeit geschaut ob die Methode für den Wert angemessen ist (muss sowieso gemacht werden, da z.B in Java die Klasse gegen die man kompiliert und die zur Laufzeit da ist verschieden sein können). Tönt langsam ist aber in so gut wie allen Fällen schnell genug.

und in diesem Atemzug bezeichnest du C# vllt bald als dynamische Sprache.
Oh nein, man macht einen Schritt in die Richtung.

Senior Sanchez
2005-09-18, 18:40:42
Lad' mich auf ein Bier ein, und ich erzähls dir ;)

Würde ich machen, wo wohnste denn? *g*


Wenn sie ein dynamisches Typsystem hat, so wie die meisten Skriptsprachen (Python, Ruby, ...). Das heisst Variablen haben keinen Typ, sondern nur Werte. Schlussendlich heisst das der Compiler macht keine Checks mehr, ob die Methode für eine Variable angemessen ist, es wird nur noch zu Laufzeit geschaut ob die Methode für den Wert angemessen ist (muss sowieso gemacht werden, da z.B in Java die Klasse gegen die man kompiliert und die zur Laufzeit da ist verschieden sein können). Tönt langsam ist aber in so gut wie allen Fällen schnell genug.

Achso, verstehe. Demzufolge ist Java im Grunde keine dynamische Sprache, da die Variablen ja Typen haben und nicht nur Werte, sehe ich das richtig?
Was ist der Vorteil einer dynamischen Programmiersprache? schöne Fehler erst zur Laufzeit? *g*


Oh nein, man macht einen Schritt in die Richtung.

Naja, das meinte ich ja *g* deswegen dieses vllt bald. ;)

Xmas
2005-09-18, 19:49:21
Die Frage ist doch: zu wechlem Objekt gehört das Verhalten? Die Antwort ist kar, zu der Zahl. Das ist wirlich alles, was es dazu zu sagen gibt.
Das sehe ich ein wenig anders.

Es ganz klar nicht Veranwortung der Klassenseite, Verhalten der Instanstzseite zu definieren (und es ist Verhalten der Instanzen). Sonst können gleich sturcts und Prozeduren, die auf structs arbeiten, nehmen. Das ist einfach nicht objektorientiert.
OO ist aber auch nicht das einzig Seligmachende. Es bringt nichts, ein Paradigma um jeden Preis durchzudrücken, wenn es nicht zur Problemstellung passt.

Zu deinen Codebeispielen kann ich allerdings nur sagen, dass ich die Syntax nicht so recht verstehe ;)

RoKo
2005-09-18, 20:43:40
Ich glaube mich trifft der Schlag, das wird doch tatsächlich in C# 3 sein:
Closures gibt's schon im 2er.

HellHorse
2005-09-18, 22:07:58
It's alive! :eek:


OO ist aber auch nicht das einzig Seligmachende.
Hat auch niemand behauptet. Es wurde bloss behauptet die Sprache sei objektorientiert.

Das sehe ich ein wenig anders.
Ok, welches Objekt sollte deiner Meinung nach in einem objektorientieren System den Sinus eines Objektes berechnen?
Ich beschränkte die Frage klar auf objektorientierte Sprachen, da es im Thread bisher nur um "komplett objektorientierte" Sprachen ging. Dass es in funktionalen anders gelöst werden sollte ist klar.

Es bringt nichts, ein Paradigma um jeden Preis durchzudrücken, wenn es nicht zur Problemstellung passt.
Sicher. Aber Verhalten von Instanzen auf der Instanzseite festzulegen passt nun mal zur Problemstellung. Sonst brauchst du keine Objekte und eine andere Programmiersprache.

Zur Verdeutlichung:
In einer objektorierentierten Sprache sollte eine Methode #concat die einen String mit einem anderen konkateniert eine Instanzmehtode von String sein. Soweit stimmst du mir doch zu? Warum sollte nun einen Methode #+, die das gleiche macht plötzlich auf der Klassenseite sein?

Dass man in C strcat verwendet weil Strings in C einfach keine gekapselten Obejkte sind und das deswegen oft nicht hinhaut ist klar und zeigt bloss die Schächen von C.

Zu deinen Codebeispielen kann ich allerdings nur sagen, dass ich die Syntax nicht so recht verstehe ;)
Welche? Ich helfe gerne.

Closures gibt's schon im 2er.
Annonyme Klasse gibt's. Das ist aber so hässlich, dass ich weigere mich das als Closure zu bezeichnen. Und wenn sie toll wären, würde man ja nicht noch lambdas einführen.

RoKo
2005-09-19, 01:13:23
Annonyme Klasse gibt's. Das ist aber so hässlich, dass ich weigere mich das als Closure zu bezeichnen. Und wenn sie toll wären, würde man ja nicht noch lambdas einführen.
Du meinst anonyme Methoden, richtig? Die neuen Lambdas sind nur eine Kurzschreibweise dafür.

ScottManDeath
2005-09-19, 07:20:05
@Hellhorse
Hehe, ich hab mir gerade das Channel 9 Interview mit Anders Heilsberg angesehn, als dass mit den Classextension kam, hab ich unsere Diskussion gedacht und just ist der Thread hier wieder reanimiert worden =)

In C++ wird auch über eine automatisch Typinferenz nachgedacht, so in der Art:


vector<int> a;
auto it = a.begin();
....
gegenüber

vector<int> a;
vector<int>::iterator it = a.begin();



Ja, in C#2.0 gibts anonyme delegates. Im November hol ich mir VS 2k5 über die MSAA meiner Uni und kann dann mit rumspielen. :)