2013-05-16 8 views
5

Come leggere una linea come intervallo in D?Come leggere una stringa carattere per carattere come intervallo in D?

So che ci sono intervalli in D, ma mi sono semplicemente chiesto come semplicemente scorrere su ogni carattere di una stringa usando questo concetto?

per mostrare quello che sto dopo, il codice simile a Go è:

for _, someChar := range someString { 
    // Do something 
} 
+1

http://ddili.org/ders/d.en/ranges.html – sigod

+0

@sigod, sì, avrebbe dovuto controllare il libro di Ali! È sicuramente la risorsa giusta per leggere su D stuff in questo momento. –

risposta

12

Dipende dal fatto se si desidera eseguire iterazioni su unità di codice o punti di codice. Il linguaggio stesso itera su array di elementi di matrice e le stringhe sono array di unità di codice, quindi se è sufficiente utilizzare foreach con inferenza di tipo, quindi con

foreach(c; "La Verité") 
    writeln(c); 

gli ultimi due caratteri stampati sarebbe senza senso, perché é è un punto di codice composto da due unità di codice UTF-8 e si stampano unità di codice individuali (poiché char è un'unità di codice UTF-8). Considerando che, se si fa

foreach(dchar c; "La Verité") 
    writeln(c); 

quindi il runtime decodificare le unità di codice di punti di codice, e é verrà stampato come ultimo carattere. Ma niente di tutto ciò funziona realmente su stringhe come intervalli. foreach opera su array in modo nativo senza dover utilizzare l'API dell'intervallo di input. Tuttavia, per tutti i tipi di stringa, l'API gamma assomiglia

@property bool empty(); 
@property dchar front(); 
void popFront(); 

Esso opera su stringhe come gamme di dchar - non loro tipo di unità di codice. Ciò evita problemi con funzioni come std.algorithm.filter che operano su singole unità di codice, poiché ciò non avrebbe senso. Operare sui punti di codice non è corretto al 100%, dal momento che Unicode diventa molto complicato per quanto riguarda la combinazione di punti di codice e grafemi e quant'altro, ma operare su punti di codice è molto più vicino all'essere corretto (e credo che ci sia lavoro per aggiungere gamma supporto per i grafemi nella libreria standard per i casi in cui è necessario e sono disposti a pagare il successo in termini di prestazioni). Quindi, avendo l'API gamma per le stringhe operano su di loro come gamme di dchar è molto più corretto, e se hai fatto qualcosa di simile

foreach(c; filter!"true"("La Verité")) 
    writeln(c); 

si sarebbe iterazione sopra dchar e é sarebbe stampare correttamente.Il lato negativo di tutto questo è ovviamente il fatto che foreach su stringhe opera a livello di unità di codice per impostazione predefinita mentre l'API di intervallo per stringhe opera su di esse come punti di codice, quindi è necessario fare attenzione quando si mischiano operazioni di array e range-based operazioni su stringhe. Questo è anche il motivo per cui string e wstring non sono considerati intervalli di accesso casuale, ma solo intervalli bidirezionali. Non è possibile eseguire l'accesso casuale in O (1) sui punti di codice quando sono costituiti da un numero variabile di unità di codice (mentre dstringè un intervallo di accesso casuale, poiché con UTF-32 ogni unità di codice è un punto di codice).

+0

Cosa accade se importiamo std.array che fornisce le funzioni di intervallo necessarie a livello UFCS, continuando a scorrere su una stringa sarà sempre lo stesso? – dav1d

+0

@ dav1d 'foreach' su array utilizzerà sempre l'API dell'array. Per gli array, le funzioni basate sulla gamma devono essere utilizzate in modo esplicito. In realtà, per quanto fastidiosa sia l'incoerenza con foreach, il fatto che il suo comportamento dipenda dal fatto che std.array sia stato importato o meno sarebbe molto incline al bug, dal momento che semplicemente aggiungere o rimuovere quell'importazione potrebbe cambiare drasticamente il comportamento del codice a seconda di cosa stava facendo. –

+0

Sì, speravo davvero che non avrebbe cambiato il codice. D'altro canto, UFCS consente di iterare su oggetti che non implementano l'opApply (potrebbe essere sbagliato qui) o l'interfaccia dell'intervallo. Grazie per il chiarimento. – dav1d

1
foreach(ch; str) 
    do_something(ch); 

Una stringa è un InputRange. Un InputRange implementa tre elementi:

  • vuoto; è vuoto?
  • anteriore; dammi il prossimo oggetto.
  • popFront; far avanzare la gamma, altrimenti la parte anteriore restituirà lo stesso.

foreach "capisce" come lavorare con gli intervalli, quindi "funziona".

Ma io non parlo Go, quindi non sono del tutto sicuro che stiamo parlando la stessa lingua.

+0

Sì, certo, Ugh, non so come potrei dimenticarlo, l'ho già usato alcune volte, quindi dovrei saperlo ... Devo incolpare la mancanza di sonno la scorsa notte :) –

+0

Ho sentito, Al momento non sono completamente lucido. – 0b1100110

+2

Attenzione per l'inferenza del tipo qui però. Quel codice sta iterando su unità di codice, non su punti di codice, quindi è improbabile che funzioni su Unicode correttamente. –

Problemi correlati