2009-11-02 3 views
11

Perché Perl non supporta l'operatore normale [] per indicizzare una stringa?Perché Perl non supporta l'operatore normale [] per indicizzare una stringa?

Quasi tutti i principali linguaggi di programmazione supportano questo operatore, in particolare gli altri due "P": Python e PHP. Inoltre, penso che dovrebbe essere facile implementare questa piccola sintassi. Inoltre, come filosofia del linguaggio di programmazione Perl - il più pigro possibile, quindi perché ci prendiamo la briga di usare una funzione per indicizzare una stringa?

Perl 6 supporterà questa sintassi?

+2

Non è una funzionalità. È solo sintassi. – postfuturist

+4

Non c'è niente di 'normale' su '[]'. Non solo, ma '[]' può o non può essere implementato come una funzione nonostante la sua sintassi (per esempio, in Ruby '[]' è in realtà un metodo). – rfunduk

+3

Nota a margine: non è necessario che Perl, Python e PHP condividano funzionalità o sintassi di sorta. Queste tre lingue hanno una sintassi molto diversa, una semantica molto diversa e obiettivi di design molto diversi.Se ti aspetti che siano uguali, allora ti verrà una grande delusione. (Ad esempio, in Haskell, l'operatore per estrarre l'ennesimo carattere da una stringa, o l'ennesimo elemento da qualsiasi elenco, è '$$. Nessuno si lamenta che Haskell non usi' [] 'per quello scopo. .) –

risposta

45

Mi piacciono tutte le risposte finora, ma la vera risposta è "perché Larry vuole che sia così". Veramente. Larry ha inventato un insieme di idiomi e strumenti che ha funzionato per lui, e lo ha condiviso con noi sotto forma di Perl. Se non pensi come pensa Larry, allora ci sono molti altri strumenti da usare. Non abbiamo bisogno del mondo intero usando Perl ... solo le persone che "ottengono" il modo in cui fa Larry.

+0

Sì, ma quale era la logica di Larry? Forse hai qualche intuizione? –

18

Vuoi indicizzare per byte, caratteri o grafemi?

Questo è il motivo per cui in Perl 6 length is "banned", invece di utilizzare una delle seguenti opzioni:

  • bytes
    Esattamente un byte alla volta
  • chars
    A seconda del testo sorgente questo può essere un singolo byte o più byte.
  • graphs
    Questo è simile ai caratteri, ma combina più caratteri di "combinazione" tra loro.

Se si vuole veramente che si può fare qualcosa di simile, utilizzando split.

(split '', $str)[$index]; 

Probabilmente è meglio usare solo substr.

substr $str, $index, 1; 
+0

Avrei scritto '(split //, $ str) [$ index]' in quanto evita di creare una lista anonima non necessaria, ma entrambi sembrano un po 'strani, no? 'substr ($ str, $ index, 1)' (o '$ str.substr ($ index, 1)', in Perl 6) è probabilmente il migliore, in termini di leggibilità. – ephemient

+1

Per quelli confusi da "split undef", split può prendere un'espressione regolare in // - notation (ad es. 'Split/foo /') o qualsiasi espressione che dovrebbe essere interpretata come un'espressione regolare (ad esempio 'split" fo ". "o" '). L'undef è promosso a una stringa vuota e compilato come espressione regolare, producendo lo stesso risultato di 'split //', tranne con un avviso di "Uso di valore non inizializzato". (L'altra differenza è che Perl deve cercare di compilare l'espressione regolare per ogni volta che viene eseguita la divisione invece di una sola volta.) – ysth

+0

Ho usato 'split '', ...' qui invece di 'split //, ... 'a causa di problemi con l'evidenziatore del codice. –

7

In Perl, le stringhe sono scalari e pertanto non sono sottoscrivibili per impostazione predefinita. È possibile utilizzare funzioni come substr() o index() per accedere a caratteri specifici in una stringa.

A meno che Perl 6 non interrompa questo concetto modificando le stringhe in un array di caratteri, non penso che ci saranno cambiamenti in questo.

+0

Bene, in Perl 6, gli scalari sono oggetti, quindi potrebbe esserci un metodo che fa la stessa cosa. –

+0

Sono aperto per le modifiche fintanto che non interrompono tutte le cose esistenti;) – Shirkrin

+0

Probabilmente si potrebbe fare un po 'di magia usando 'autobox' e sovrascrivendo l'operatore' [] '. – Ether

12

Perl ha un modo per indicizzare una stringa con index o substr. Supporta l'operazione. Che lo faccia con un'altra sintassi non dovrebbe avere importanza. C'è un motivo per cui abbiamo più di un linguaggio di programmazione. :)

Non direi che [] è un operatore "normale". Sono sicuro che le persone possono elencare molte lingue che non lo fanno.

+0

Sarebbe utile aggiungere una riga che descrive "un'altra sintassi" –

+0

C'è qualcosa di ironicamente ironico in qualcuno che si lamenta della risposta di Brian ai dettagli :) Modificherò la risposta di brian per includere la sintassi suggerita nel commento qui sotto. – DVK

+0

... BTW, la ragione per cui è ironico è brian sembra essere il più prolifico editore degli altri Perl Qs e As, aggiungendo dettagli chiarificatori abbastanza spesso. – DVK

23

Utilizzare [] per indicizzare in una stringa è un effetto collaterale del modo in cui molti linguaggi di programmazione trattano le stringhe: come matrici di caratteri (o caratteri ampi, nel caso di Unicode). In Perl, le stringhe sono entità di prima classe. Perl offre molti modi per lavorare con stringhe intere come un unico valore. Se stai cercando di indicizzare una stringa probabilmente stai facendo qualcosa di sbagliato. (ad esempio scrivendo C in Perl piuttosto che usando gli idiomi Perl). Per i casi in cui è davvero necessario indicizzare in una stringa, utilizzare substr.

+5

Che una stringa sia un'entità di prima classe (al contrario di una semplice matrice di caratteri) non significa che non possa essere trattata sintatticamente come una matrice. Vedi Java, C# e Delphi, per esempio. –

9

Se si desidera veramente trattare gli scalari come oggetti, è possibile utilizzare autobox.

Io non uso autobox, ma questo dovrebbe funzionare:

my $indexed = ('foo'->list)[1]; 

autobox ha ganci per definire gli oggetti da utilizzare per il confezionamento di vari tipi di dati.

Quindi, se davvero, vuole veramente, si dovrebbe essere in grado di utilizzare autobox per creare la propria classe stringa che permetterà codice come questo:

my $indexed = 'foo'->[3]; 

Quindi, credo che la risposta alla tua domanda , "Perché Perl non ha la sintassi [] per l'indicizzazione delle stringhe?" è "Nessuno lo ha voluto abbastanza per implementarlo."

Per quanto riguarda Perl 6, non ho seguito abbastanza da dare una risposta oltre, "Se non è presente e lo vuoi veramente, sarai in grado di aggiungerlo da solo."

+2

Non è presente in Perl 6, ma penso che dovresti semplicemente essere in grado di definire un 'multi metodo postcircumflex: <[ ]> (Str, Int)' (anche se non posso controllare poiché Rakudo non lo supporta ancora). – ephemient

7

Qual è il nome della stringa? È scalare, quindi il sigillo sarà ovviamente $. Il resto segue gli standard standard di denominazione delle variabili; diciamo $abc.

my $abc = 'A string'; 

Come sigilli significano contesto s dell'espressione, e non sono una parte del nome, abbiamo una collisione.

my $def = $abc[2]; 

non è il 3 ° lettera dello scalare $abc, ma il terzo elemento di un array - condividono lo stesso simbolo (ma con un diverso sigillo): @abc.

Così quell'espressione, che è stata probabilmente progettata in anticipo per la risoluzione di un simbolo simile a uno script, ha già un significato assegnato.

Ovviamente, come la risposta di Brad sottolinea, può esserci un significato solo se facciamo assunzioni implicite su cosa rende una parte della stringa un "elemento" nella "lista". Più codifiche devi utilizzare, peggio queste ipotesi predefinite funzionano.

Si può trovare una sintassi si preferisce di più utilizzando autobox:

$string->ch(2); 

(che avrebbe dovuto scrivere ch te stesso.) Ma che è necessariamente più prolissa che semplicemente mettere la staffa di sopra stringhe.