Progettare il letterale della gamma perfetta

9

Ho pensato a come avrei potuto progettare la gamma letterale "perfetta" se dovessi progettare un linguaggio. Per te che non conosci, conosci un intervallo letterale in un'istruzione che rappresenta un intervallo di valori, come 1-4. Sono più comunemente usati in / foreach loop

Sembra che ci siano un paio di problemi da tenere in considerazione

  • Supporto per inclusivo e gamme esclusive, virando su +1 o -1 ai punti finali sembra un po 'fugace e errorprone.

  • Supporto per lo stepping, quindi puoi fare una serie di numeri pari o dispari per esempio

  • Leggibilità, dovrebbe essere prontamente apparente ciò che la gamma letterale descrive

  • Unambiguity, dovrebbe essere perfettamente non ambizioso quale sia la gamma letterale descrive

  • L'impostazione predefinita dovrebbe essere da inclusiva ad esclusiva poiché è ciò che viene utilizzato nella maggior parte dei casi per il loop su array ecc.

Comunque, un esempio di range letterale che ho visto è Ruby che ha la forma di 1..3 per un range esclusivo (alla fine) e 1 ... 3 per l'inclusivo (alla fine). Puoi anche fare 1..10.step (5). Dopo un'attenta considerazione ho trovato comunque un paio di cose che non mi piacevano di quell'approccio (dalla mia conoscenza limitata del rubino)

  1. Puoi descrivere solo inclusivo ed esclusivo per la fine. Mentre descrivendo la maggior parte degli scenari che fa sembra un po 'incoerente.

  2. Variabile solo di un ulteriore. sembra una ricetta per farlo difficile vedere se un intervallo è incluso o esclusivo. Non lo so su di te ma i punti tendono a diventare qualcosa di sfocato:)

  3. Aggiunta del metodo come notazione per le gamme sembrano mescolare la nozione di a letterale con quello di una classe che sembra un po 'incoerente (anche se gli intervalli vengono compilati in una classe)

Comunque, dopo aver riflettuto su diverse alternative. Mi sono inventato questo

  • [5..1] 5,4,3,2,1
  • [1..5 [ 1,2,3,4
  • ] 1..5] 2,3,4,5
  • [ 0..5..20] 0,5,10,15,20

e così via. Mi piace perché [normalmente denomina un set e questo si inserisce in questo, anche se questo in contrasto con un set sarebbe stato ordinato.

Una cosa di cui mi sento un po 'lacerato è rendere obbligatori o meno gli indicatori esclusivi / inclusivi, ovvero se scrivi solo 1,5. il default sarebbe 1,2,3,4 poiché è il caso più comune con array, ecc. È più facile e più leggibile, ma meno specifico e se dovessi scrivere [1..5 [impari presto come funzionano.

Quindi cosa ne pensi, ho coperto la maggior parte delle basi, ho trascurato qualcosa? vuoi rendere [] obbligatorio? Progetteresti letterali di gamma in modo diverso nel tuo linguaggio di programmazione?

Candidati

  • stile parentesi: [0..10 [, con passaggio: [0..5..20 [
  • notazione intervallo: [0..10) con passaggio: [0..5..20)
  • esclamativo per esclusivo. 0 ..! 10, con passaggio: 0..5 ..! 20
    • con passo diverso. 0 ..! 20, 5
    • tuttavia, renderebbe predefinito * 0..10 ' inclusive-inclusive
  • wordy: [0 a! 20 di 5]

Devo dire che il mio preferito fino ad ora è 0 ..! 10 e 0..5 ..! 20 , desidero solo il predefinito 0..10 to inclusive-exclusive sarebbe più logico

    
posta Homde 04.04.2011 - 12:11
fonte

11 risposte

1

E il vincitore è

Ci scusiamo per aver scelto la mia soluzione, apprezzo molto tutti i commenti e i commenti e ti prego di criticare questa soluzione se trovi qualcosa di sbagliato con essa

Quindi ho deciso di andare con:

0..5           = 0,1,2,3,5
0..5..10       = 0,5,10
..3            = 0,1,3
!0..!5         = 1,2,3,4
3..            = 3 to infinity

segmented ranges
-
0..5,..5..20   = 0,1,2,3,4,5,10,15,20
0..3,10..5..20 = 0,1,2,3,10,15,20

Come puoi vedere inclusivo è il default su entrambi i sensi, è ciò che rende intuitivamente più sensato specialmente quando si usa lo stepping. Puoi usare ! per fare una fine esclusiva.

Lo svantaggio è che normalmente si desidera utilizzare l'esclusiva quando si lavora contro un array, ma di nuovo, la maggior parte delle volte si dovrebbe probabilmente usare qualcosa come per-ciascuno in questi casi. Se davvero hai davvero bisogno di lavorare contro l'indice, il parser potrebbe riconoscere quando hai dimenticato il marker di esclusione alla fine ed emettere un avviso

Sono andato usando ... su entrambi i lati della variabile step invece di usare la virgola o qualsiasi altra cosa poiché è quello che sembrava più pulito e spero sia il più leggibile.

Ho anche inserito alcune sintassi con le virgole per poter creare intervalli in cui parti diverse hanno passaggi diversi

    
risposta data 07.04.2011 - 12:02
fonte
14

Perché inventare ciò che esiste già in Matematica?

Notazione intervallata

Dovrebbe coprire il tuo punto "Unambiguity" così com'è già.

Il tuo unico problema sarebbe la definizione del passo. Forse qualcos'altro in matematica può essere d'aiuto?

    
risposta data 04.04.2011 - 12:41
fonte
8

Hai visto le gamme Haskell? La loro idea di passaggi è simile alla tua (nel mezzo) ma indicata con una differenza sintattica (da @ luqui's answer ):

[1,2..10] = [1,2,3,4,5,6,7,8,9,10]
[1,3..10] = [1,3,5,7,9]
[4,3..0]  = [4,3,2,1,0]
[0,5..]   = [0,5,10,15,20,25,30,35...  -- infinite
[1,1..]   = [1,1,1,1,1,1,1,1,1,1,1...  -- infinite

Trovo questa notazione molto intuitiva: inizi a enumerare e saltare il corpo per contrassegnare dove dovrebbe finire.

Non copre il caso di "esclusivo", ma francamente, preferisco essere chiaro riguardo al comportamento una volta (specificare quale limite è inclusivo e quale è esclusivo), e si aspetta che l'utente esegua le regolazioni a meno che la sintassi non sia < em> estremamente clear (e non confonde gli editor agnostici della lingua).

    
risposta data 04.04.2011 - 21:49
fonte
5

Dovresti leggere la comprensione degli elenchi nelle lingue che li offrono.

Python, ad esempio, copre i tuoi casi molto bene con la funzione range() e la comprensione delle liste per i casi troppo complessi da esprimere con range() .

    
risposta data 04.04.2011 - 12:57
fonte
2

Credo che la tua notazione sia lontana dall'essere ambigua. Intuitivamente, [0..5..20] non mi sembra un intervallo con larghezza del passo = 5. In alcuni casi d'angolo fallisce anche: per quanto riguarda l'espressione del set (0,2) - [0..2..2] o cosa dovrei mettere nel mezzo ?

Penso che la notazione a slice di Python sia un approccio solido: [start:end:step] (il passaggio è facoltativo).

Se hai davvero bisogno di supporto per intervalli esclusivi e inclusivi, utilizzerei la notazione degli intervalli standard (cioè utilizzando ( e [ ) a meno che ciò non introduca ambiguità sintattiche nella tua lingua.

    
risposta data 04.04.2011 - 15:56
fonte
1

Penso che quando imposti un terzo valore di incremento, è meglio aggiungerlo alla fine piuttosto che al centro, poiché si tratta di un valore facoltativo e sembra più intuitivo per i programmatori esperti che aggiungere un terzo argomento opzionale nel mezzo.

così invece di [1..5..20] potresti fare qualcosa come [1..20] [5] o [1..20.5]

    
risposta data 04.04.2011 - 12:27
fonte
1
  • [1..5 [1,2,3,4
  • ] 1..5] 2,3,4,5
  • ] 1..5 [2,3,4

Perché non usare solo [1..4], [2..5], [2..4]? L'esclusione degli intervalli non offre molti vantaggi. Non è necessario scrivere MIN + 1 o MAX-1, sì, ma non lo vietano comunque. Troppa variazione, imho. Il mio linguaggio di scelta, scala, ha (da 1 a 3) e (1 fino a 3) [= (1 a 2)] ma mi ha appena confuso all'inizio. Ora uso sempre 'xey' e so, quindi, che l'opzione che non uso è quella esclusa, ma ovviamente non traggo vantaggio da un'opzione che non uso.

  • [5..1] 5,4,3,2,1

è ovviamente (da 1 a MAX) (x = > y = (MAX + 1) - x) ma questo è molto più semplice e non facile da usare.

  • [0..5..20] 0,5,10,15,20

è ovviamente (da 0 a 4) (x = > y = x * 5) non è tanto una caldaia. Discutibile.

    
risposta data 04.04.2011 - 15:36
fonte
1

Che dire di qualcosa di simile:

  • [5..1] 5,4,3,2,1
  • [1..5] [i, e] 1,2,3,4
  • [5..1] [i, e] 5,4,3,2
  • [1..5] [e, i] 2,3,4,5
  • [1..5] [e, e] 2,3,4
  • [0..20] di 5 0,5,10,15,20

Il i e e nella seconda coppia di parentesi quadre indica se l'inizio o la fine dell'intervallo è inclusivo o esclusivo (oppure potresti usare incl e excl se vuoi essere più chiaro). il by 5 indica l'intervallo di passo. Il primo e l'ultimo esempio sono comprensivi del primo e dell'ultimo valore, quindi ho omesso [i,i] , che a mio avviso sarebbe un comportamento predefinito assunto correttamente.

I valori predefiniti potrebbero essere [i,i] per lo specificatore inclusivo / esclusivo e by 1 per lo specificatore del passo.

Normalmente avrei suggerito la notazione standard che comprendeva ( e [ come menzionato da @Dan McGrath, ma sono d'accordo sul fatto che nel codice questo potrebbe sembrare confuso.

    
risposta data 04.04.2011 - 15:36
fonte
0

Non userei il modulo [1..5 ['per uno degli stessi motivi per evitare di mescolare parens e parentesi graffe: confonderà la maggior parte delle parentesi graffe degli editor esistenti. Forse usa un pennarello all'interno delle parentesi graffe, come '[1 .. | 5]'.

L'altra cosa da considerare è il comportamento dei metodi per ottenere i limiti. Ad esempio, 'begin' / 'end' vs. 'first' / 'last' vs. 'min' / 'max'. Hanno bisogno di essere sani per i limiti sia inclusivi che esclusivi, così come quelli con una dimensione di passo.

    
risposta data 04.04.2011 - 16:19
fonte
0

Ruby ha notazione e un intervallo oggetto che funziona. Essenzialmente assomiglia a questo:

1..5  # range 1,2,3,4,5

Con Ruby, la dimensione del passo non è una funzione dell'intervallo, ma piuttosto una funzione di iterazione nell'intervallo. Potremmo usare lo stesso intervallo sopra e iterarlo diversamente se vogliamo:

(1..5).step(3) { |x| puts x }
(1..5).step(2) { |x| puts x }

Quindi ecco alcune cose che potresti voler prendere in considerazione:

  • L'aggiunta del supporto linguistico per endpoint inclusivi / esclusivi può essere problematica. Se tutti gli intervalli sono inclusi (scelta di Ruby), gli sviluppatori modificheranno di conseguenza gli endpoint dell'intervallo. Come rappresenti l'endpoint o l'esclusività in un modo che sia visivamente non ambiguo e non ambiguo con una semplice grammatica del parser?
  • Stai utilizzando l'intervallo per più di una semplice iterazione? Esempi comuni includono confronti tra range, splicing, value in range selection. Se sì, come rappresenti queste possibilità? (Vedi il link alla classe Range per le idee su ciascuno di questi esempi.)

A proposito, gli intervalli sono piuttosto buoni se si consente loro di essere inclusi in un'istruzione switch come fa Ruby:

switch(myval)
    when 0..33 then puts "Low"
    when 34..66 then puts "Medium"
    when 67..100 then puts "High"
end

Non sto dicendo che l'oggetto della gamma di Ruby sia il fine e tutto, ma è un'implementazione funzionante del concetto di cui stai parlando. Gioca con esso per vedere cosa ti piace, non ti piace e farebbe diversamente.

    
risposta data 04.04.2011 - 16:59
fonte
0

Una soluzione che ritengo senz'altro stia utilizzando l'overloading dell'operatore per consentire ad es.

1+[0..3]*5

Non sarebbe necessariamente immediatamente trasparente per tutti, ma una volta che si fermano e pensano che spero la maggior parte dei programmatori lo capiscano, e le persone che usano regolarmente la lingua lo apprenderanno semplicemente come un idioma.

Per chiarire, il risultato sarebbe [1, 6, 11, 16] , sollevando la moltiplicazione e quindi l'aggiunta sull'intervallo. Non mi ero reso conto che potrebbe essere ambiguo per gli utenti Python; Penso agli intervalli come sottoinsiemi di ordini totali piuttosto che a elenchi. e ripetere un set non ha senso.

    
risposta data 04.04.2011 - 17:34
fonte

Leggi altre domande sui tag