AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

For xx In xxx Schleife rückwärts?

Ein Thema von milos · begonnen am 24. Jan 2014 · letzter Beitrag vom 27. Jan 2014
Antwort Antwort
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

AW: For xx In xxx Schleife rückwärts?

  Alt 27. Jan 2014, 13:49
Für arrays ist es so implementiert, dass ein for-in einem for-to entspricht.
Reiner Zufall. Heute so, morgen anders (Rückwärtszählen geht vielleicht schneller, Speicher ist nicht mehr linear aufgebaut, wer weiß das schon).
Sich darauf zu verlassen, wie etwas implementiert ist, ist -mit Verlaub- ganz großer Käse.

Eigentlich darf man in einer For-In Schleife auch keine Änderungen an der der laufenden Enumeration zugrundeliegenden Datenstruktur vornehmen (auf Gut Deutsch: Die Liste verändern). Aber da ist Delphi wohl nicht so safe.
Zu glauben, dass sich das Verhalten einer for-in Schleife für ein Array ändert ist eher der große Käse. Die Compiler Optimierung des rückwärts zählens auf 0 bei einer for-to Schleife wird auch nur vorgenommen, wenn der Index in der Schleife nicht benötigt wird und dementsprechend die Logik des Programms nicht verändert wird. Das trifft auf eine for-in Schleife wohl auch nur dann zu, wenn man im Schleifenrumpf nix mit der Laufvariable macht. Wobei dann die Reihenfolge auch Rille wäre.

Was die Veränderung der durchlaufenden Struktur angeht ist die Implementierung in der Delphi RTL wirklich nicht sehr dolle. In Spring4d hingegen wird dir ein Enumerator mit einer Exception ins Gesicht springen, wenn du zwischendurch die zugrundelegende Datenmenge veränderst (analog zum Verhalten in .Net).

Ich stimme den meisten hier zu, dass es gefährlich sein kann, anhand eines abstrakten Interfaces (IEnumerable<T>) auf ein Implementierungsdetail zu schließen. Deshalb würde ich in einem solchen Fall eher vorschlagen, ein weniger abstraktes zu benutzen. In Spring4d/.Net würde sich dort z.B. IList<T> anbieten. Dieses bietet direkten Indexzugriff und man kann sich sicher sein, dass implementierende Klassen den Enumerator auch in einer solchen Weise implementieren, dass die Liste von vorn nach hinten durchlaufen werden.

Im übrigen macht das .Net Framework selber bei den diversen IEnumerable<T> extension methods implizite Annahmen über die Ausführung. Schaut euch einfach mal First, Last oder ElementAt an (welche intern eine Optimierung für den Fall haben, dass es sich um IList<T> handelt).

Dass eine enumeration ein nicht erwartetes Ergebnis hat, habe ich erst kürzlich selbst erlebt, einfach mal eine PriorityQueue enumerieren und sich wundern, dass die Elemente eine andere Reihenfolge haben, als wenn man Dequeue aufruft, bis sie leer ist
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (27. Jan 2014 um 13:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.562 Beiträge
 
Delphi 12 Athens
 
#2

AW: For xx In xxx Schleife rückwärts?

  Alt 27. Jan 2014, 13:59
Dass eine enumeration ein nicht erwartetes Ergebnis hat, habe ich erst kürzlich selbst erlebt, einfach mal eine PriorityQueue enumerieren und sich wundern, dass die Elemente eine andere Reihenfolge haben, als wenn man Dequeue aufruft, bis sie leer ist
Das dürfte im Delphi vermutlich auch auf TStack und TQueue zutreffen (solange man sie nicht als FIFO benutzt).
Also falls die überhaupt einen Enumerator haben.

Und wenn, müsste der Enumerator, bei sowas, nicht sogar der Liste geleert werden? (jedes Element müsse trausgenommen werden, sobaldes verarbeitet wird )
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (27. Jan 2014 um 14:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: For xx In xxx Schleife rückwärts?

  Alt 27. Jan 2014, 14:26
Dass eine enumeration ein nicht erwartetes Ergebnis hat, habe ich erst kürzlich selbst erlebt, einfach mal eine PriorityQueue enumerieren und sich wundern, dass die Elemente eine andere Reihenfolge haben, als wenn man Dequeue aufruft, bis sie leer ist
Das dürfte im Delphi vermutlich auch auf TStack und TQueue zutreffen (solange man sie nicht als FIFO benutzt).
Also falls die überhaupt einen Enumerator haben.

Und wenn, müsste der Enumerator, bei sowas, nicht sogar der Liste geleert werden? (jedes Element müsse trausgenommen werden, sobaldes verarbeitet wird )
Nö, sowohl TStack<T> als auch TQueue<T> werden ganz simpel mit einem Array implementiert und sind somit deterministisch enumerierbar (beides von TEnumerable<T> abgeleitet). Da sich hier im Gegensatz zu einer mit Binärheap implementierten Prioritätsqueue die Elemente bei Einfügen und Entfernen nicht im Array verschieben, gibts kein Problem - außer dass der Stack Enumerator die Elemente umgekehrt ausgibt, im Gegensatz zu einem Pop bis Stack leer.

Und nein, ein Enumerator darf niemals die Datenmenge verändern!
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.562 Beiträge
 
Delphi 12 Athens
 
#4

AW: For xx In xxx Schleife rückwärts?

  Alt 27. Jan 2014, 14:30
Und nein, ein Enumerator darf niemals die Datenmenge verändern!
War auch nur eine Überlegung.


"gehe alle Elemente durch", so ala "poppe" Alles aus der Liste raus, bis sie leer ist.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.689 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: For xx In xxx Schleife rückwärts?

  Alt 27. Jan 2014, 21:08
Zu glauben, dass sich das Verhalten einer for-in Schleife für ein Array ändert ist eher der große Käse.
Ebenso, wie "Integer" immer brav mitgewachsen ist (obwohl es da sogar ursprünglich so garantiert wurde), gelle?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz