Merancang kisaran literal yang sempurna

9

Saya telah memikirkan bagaimana saya akan mendesain kisaran literal "sempurna" jika saya ingin mendesain bahasa. Bagi Anda yang tidak tahu, ketahui rentang literal dalam pernyataan yang mewakili kisaran nilai, seperti 1-4. Mereka paling sering digunakan untuk foreach loop

Tampaknya ada beberapa masalah yang harus dipertimbangkan

  • Dukungan untuk rentang inklusif dan eksklusif, menempel pada +1 atau -1 ke titik akhir tampaknya agak jelek dan tidak sesuai kesalahan.

  • Dukungan untuk melangkah, sehingga Anda dapat membuat kisaran angka genap atau ganjil misalnya

  • Keterbacaan, harus jelas apa yang digambarkan oleh rentang literal

  • Tidak ambigu, harusnya sama sekali tidak beragama seperti yang digambarkan oleh rentang literal

  • Defaultnya mungkin dari inklusif ke eksklusif karena itulah yang digunakan dalam kebanyakan kasus untuk pengulangan array dll.

Ngomong-ngomong, salah satu contoh kisaran literal yang pernah saya lihat adalah Ruby yang dalam bentuk 1..3 untuk rentang eksklusif (di ujung) dan 1 ... 3 untuk inklusif (di ujung). Anda juga dapat melakukan 1..10.step (5). Namun setelah pertimbangan yang cermat saya menemukan beberapa hal yang saya tidak suka tentang pendekatan itu (dari pengetahuan saya yang terbatas tentang ruby)

  1. Anda hanya dapat menggambarkan inklusif dan eksklusif untuk bagian akhir. Sementara menggambarkan sebagian besar skenario itu tampaknya sedikit tidak konsisten.

  2. Memvariasikan dengan hanya tambahan. sepertinya resep untuk membuatnya sulit untuk melihat apakah rentang inklusif atau eksklusif. Saya tidak tahu tentang Anda tetapi titik cenderung menjadi sesuatu yang kabur :)

  3. Menambahkan metode seperti notasi untuk rentang tampaknya mencampurkan gagasan literal dengan kelas yang tampaknya sedikit tidak konsisten (bahkan jika rentang dikompilasi ke kelas)

Bagaimanapun, setelah mempertimbangkan berbagai alternatif. Saya datang dengan ini

  • [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

Dan seterusnya. Saya suka karena [biasanya melambangkan satu set dan ini agak cocok dengan itu, meskipun ini berbeda dengan satu set akan dipesan.

Satu hal yang saya agak singgung adalah membuat indikator eksklusif / inklusif wajib atau tidak, yaitu jika Anda menulis hanya 1..5 standarnya adalah 1,2,3,4 karena ini adalah kasus yang paling umum dengan array dll Lebih mudah dan lebih mudah dibaca, tetapi kurang spesifik dan jika Anda harus menulis [1..5 [Anda belajar lebih awal tentang cara kerjanya.

Jadi apa yang Anda pikirkan, apakah saya menutupi sebagian besar pangkalan, mengabaikan sesuatu? Anda akan membuat [] wajib? Apakah Anda merancang berbagai literal berbeda dalam bahasa pemrograman Anda?

Calon

  • gaya braket: [0..10 [ , dengan langkah: [0..5..20 [
  • notasi interval: [0..10) dengan langkah: [0..5..20)
  • seru untuk eksklusif. 0 ..! 10, dengan langkah: 0..5 ..! 20
    • dengan langkah berbeda. 0 ..! 20, 5
    • namun, itu akan membuat default * 0..10 ' inklusif-inklusif
  • wordy: [0 to! 20 by 5]

Saya harus mengatakan bahwa favorit saya sejauh ini adalah 0 ..! 10 dan 0..5 ..! 20 , saya hanya berharap standar 0..10 untuk inklusif-eksklusif akan lebih logis

Homde
sumber
2
1,5,10,15,20Gap 4, 5, 5, 5 ?!
Peter Taylor
oops :) dikoreksi
Homde

Jawaban:

14

Mengapa menemukan apa yang sudah ada dalam Matematika?

Notasi Interval

Itu harus mencakup poin 'Kerancuan' ​​Anda karena sudah ada.

Satu-satunya masalah Anda akan menentukan langkah. Mungkin sesuatu yang lain dalam matematika dapat membantu dengan itu?

Dan McGrath
sumber
3
Hai, Saya sudah benar-benar tentang notasi interval. Namun apa yang membuat saya tidak ingin menggunakannya adalah fakta bahwa itu tidak simetris dengan keduanya [dan) dan menggunakan paranthesis serta tidak memiliki langkah (seperti yang Anda sebutkan). Menggunakan paranthesis tampaknya berpotensi membingungkan pencocokan penjepit dan saya lebih suka menyimpannya untuk ekspresi. Menggunakan] dan [adalah standar iso dan sepertinya berjalan lebih baik dengan mengintegrasikan stepping, tapi itu hanya pendapat saya saja.
Homde
7
@ MKO: Gagasan Anda menggunakan tanda kurung yang tidak cocok (seperti [1..5[) akan membingungkan editor setidaknya sebanyak notasi interval standar.
David Thornley
2
Hmm, ide lain, bagaimana dengan menggunakan! untuk, yaitu: 1 ..! 5 atau 0..5 ..! 20 (dengan loncatan)
Homde
1
@ MKO: Menggunakan !untuk mengecualikan elemen pertama atau terakhir bisa jadi bagus.
FrustratedWithFormsDesigner
8

Pernahkah Anda melihat rentang Haskell? Gagasan mereka untuk langkah-langkah ini mirip dengan Anda (di tengah) tetapi ditandai dengan perbedaan sintaksis (dari jawaban @ luqui ):

[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

Saya menemukan notasi ini sangat intuitif: Anda mulai menghitung dan melewati tubuh untuk menandai di mana seharusnya berakhir.

Itu tidak mencakup kasus untuk "eksklusif", tapi terus terang, saya lebih suka jelas tentang perilaku sekali (tentukan batas mana yang inklusif dan mana yang eksklusif), dan mengharapkan pengguna untuk melakukan penyesuaian kecuali sintaksinya sangat jelas (dan tidak membingungkan editor agnostik bahasa).

Matthieu M.
sumber
5

Anda harus membaca tentang pemahaman daftar dalam bahasa yang menawarkannya.

Python, misalnya, mencakup kasing Anda dengan range()fungsi dan pemahaman daftar untuk kasing yang terlalu rumit untuk diungkapkan range().

S.Lott
sumber
2

Saya percaya notasi Anda jauh dari tidak ambigu. Secara intuitif, [0..5..20]tidak terlihat bagi saya seperti rentang dengan langkah lebar = 5. Bahkan gagal dalam beberapa kasus sudut: bagaimana dengan mengekspresikan set (0,2) - [0..2..2]atau apa yang harus saya letakkan di tengah?

Saya pikir notasi irisan Python adalah pendekatan yang solid: [start:end:step](langkah menjadi opsional).

Jika Anda benar-benar membutuhkan dukungan untuk rentang eksklusif dan inklusif, saya akan menggunakan notasi rentang standar (yaitu menggunakan (dan [) kecuali ini memperkenalkan ambiguitas sintaksis dalam bahasa Anda.

Alexander Gessler
sumber
1
mengenai "standar" notasi, sekolah Eropa mengajar [], [[, ]]dan ][, tidak ada tanda kurung ... dan kami standar yang lebih baik, tentu saja;)
Matthieu M.
@Matthieu: Sebenarnya, di Belanda (yang merupakan di Eropa), kami juga mengajarkan bahwa notasi standar.
Frits
1

Saya pikir ketika Anda menetapkan nilai kenaikan ketiga Anda lebih baik menambahkan ini akhir, daripada tengah, karena ini adalah nilai opsional, dan tampaknya lebih intuitif untuk programmer berpengalaman daripada menambahkan argumen ke-3 opsional di tengah .

jadi alih-alih [1..5..20] Anda bisa melakukan sesuatu seperti [1..20] [5] atau [1..20,5]

Canuteson
sumber
Itu poin yang valid dan mungkin masalah selera, bagi saya tampaknya lebih mudah untuk berpikir "1 langkah 5 hingga 20" daripada, "dari 1 ke 2, dengan langkah 5" menggunakan [1..20] [5] tampaknya sedikit berantakan tetapi mungkin pendekatan koma akan dapat dilakukan. Saya akan menghargai lebih banyak umpan balik tentang hal itu
Homde
1
  • [1..5 [1,2,3,4
  • ] 1..5] 2,3,4,5
  • ] 1..5 [2,3,4

Mengapa tidak menggunakan [1..4], [2..5], [2..4]? Tidak termasuk Ranges tidak menawarkan banyak manfaat. Anda tidak perlu menulis MIN + 1 atau MAX-1, ya, tetapi mereka tidak melarangnya. Terlalu banyak variasi, imho. Bahasa pilihan saya, scala, memiliki (1 hingga 3) dan (1 hingga 3) [= (1 hingga 2)] tetapi itu hanya membingungkan saya di awal. Sekarang saya selalu menggunakan 'x to y' dan karena itu tahu, bahwa opsi yang tidak saya gunakan adalah yang tidak termasuk, tetapi tentu saja saya tidak mendapat manfaat dari Opsi yang tidak saya gunakan.

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

tentu saja (1 hingga MAX) (x => y = (MAX + 1) - x) tapi itu jauh lebih sederhana dan tidak ramah pengguna.

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

tentu saja (0 hingga 4) (x => y = x * 5) tidak terlalu banyak. Disangkal.

Pengguna tidak diketahui
sumber
Manfaat utama dari mengecualikan rentang, afaik, adalah bahwa jumlah elemen adalah perbedaan titik akhir.
Justin L.
@JustinL .: 5-1 adalah 4 dalam aljabar saya tetapi mengandung 3 elemen, tidak termasuk batas: 2, 3, 4.
pengguna tidak diketahui
1

Bagaimana dengan sesuatu yang seperti ini:

  • [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] oleh 5 0,5,10,15,20

Tanda kurung siku idan edalam pasangan kedua menunjukkan apakah awal atau akhir rentang termasuk atau eksklusif (atau Anda dapat menggunakan incl, dan excljika Anda ingin lebih jelas). yang by 5menunjukkan interval loncatan. Contoh pertama dan terakhir termasuk nilai pertama dan terakhir, jadi saya menghilangkan [i,i], yang saya pikir akan menjadi perilaku default OK diasumsikan.

Nilai default bisa [i,i]untuk specifier inklusif / eksklusif dan by 1untuk specifier langkah.

Biasanya saya sudah menyarankan notasi standar yang melibatkan (dan [seperti yang disebutkan oleh @Dan McGrath, tapi saya setuju bahwa dalam kode ini bisa terlihat membingungkan.

FrustratedWithFormsDesigner
sumber
Adakah yang bisa menjelaskan downvote?
FrustratedWithFormsDesigner
Saya tidak melihat sesuatu yang salah . Saya memilih untuk melawan downvote.
Berin Loritsch
1

Dan pemenangnya adalah

Maaf untuk memilih solusi saya sendiri, saya sangat menghargai semua komentar dan umpan balik dan mohon kritik solusi ini jika Anda menemukan sesuatu yang salah dengan itu

Jadi saya memutuskan untuk pergi dengan:

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

Seperti yang Anda lihat inklusif adalah default pada kedua indera, itulah yang secara intuitif paling masuk akal terutama ketika menggunakan stepping. Kamu bisa menggunakan ! untuk mengakhiri eksklusif.

The downside adalah bahwa biasanya Anda ingin menggunakan eksklusif ketika bekerja melawan array, tetapi sekali lagi, sebagian besar waktu Anda mungkin harus menggunakan sesuatu seperti untuk masing-masing dalam kasus tersebut. Jika Anda benar-benar perlu bekerja melawan indeks parser dapat mengenali kapan Anda mungkin lupa penanda pengecualian di akhir dan mengeluarkan peringatan

Saya pergi dengan menggunakan .. di kedua sisi variabel step alih-alih menggunakan koma atau apa pun karena itulah yang tampak paling bersih dan saya harap adalah yang paling mudah dibaca.

Saya juga melemparkan beberapa sintaks dengan koma untuk dapat membuat rentang di mana bagian yang berbeda memiliki langkah yang berbeda

Homde
sumber
Sepertinya tidak apa-apa kecuali saat menentukan langkahnya. Saya pikir itu akan menjadi lebih bersih sebagai [0..10 oleh 5]. Rentang tersegmentasi dapat [0..5, ..20 x 5], dll. Anda juga dapat menentukan [numitem dari langkah demi langkah], yang (tidak seperti bentuk lainnya) dapat memungkinkan ukuran langkah nol.
supercat
0

Saya tidak akan menggunakan formulir '[1..5 [' untuk salah satu alasan yang sama Anda akan menghindari pencampuran paren dan kawat gigi - itu akan membingungkan pencocokan penjepit editor yang paling ada. Mungkin gunakan spidol di dalam kurung kurawal, seperti '[1 .. | 5]'.

Hal lain yang perlu dipertimbangkan adalah perilaku metode untuk mendapatkan batasan. Misalnya, 'mulai' / 'akhir' vs 'pertama' / 'terakhir' vs 'min' / 'maks'. Mereka harus waras untuk batas inklusif dan eksklusif, serta batas langkah.

ASHelly
sumber
0

Ruby memiliki notasi dan objek Range yang berfungsi. Pada dasarnya seperti ini:

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

Dengan Ruby, ukuran langkah bukanlah fungsi rentang, melainkan fungsi pengulangan melalui rentang. Kita dapat menggunakan rentang yang sama di atas dan beralih melalui itu secara berbeda jika kita ingin:

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

Jadi, inilah beberapa hal yang mungkin ingin Anda pertimbangkan:

  • Menambahkan dukungan bahasa untuk titik akhir inklusif / eksklusif dapat menjadi masalah. Jika semua rentang inklusif (pilihan Ruby), maka pengembang akan menyesuaikan titik akhir rentang sesuai. Bagaimana Anda merepresentasikan titik akhir inklusif atau eksklusivitas dengan cara yang secara visual tidak ambigu dan tidak ambigu dengan tata bahasa parser sederhana?
  • Apakah Anda menggunakan rentang untuk lebih dari sekadar iterasi? Contoh umum termasuk perbandingan rentang, splicing, nilai perbandingan rentang. Jika demikian, bagaimana Anda mewakili kemungkinan-kemungkinan itu? (Lihat tautan ke kelas Rentang untuk ide ke masing-masing contoh ini.)

BTW, rentang agak bagus jika Anda mengizinkannya untuk dimasukkan dalam pernyataan beralih seperti yang dilakukan Ruby:

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

Saya tidak mengatakan bahwa objek jangkauan Ruby adalah yang terakhir dan menjadi segalanya, tetapi ini adalah implementasi konsep yang sedang Anda bicarakan. Mainkan dengannya untuk melihat apa yang Anda sukai, tidak suka, dan akan lakukan secara berbeda.

Berin Loritsch
sumber
Baca pertanyaan dengan seksama, OP sudah mengetahui kisaran Ruby:Anyways, one example of range literal I've seen is Ruby which is in the form of 1..3 for an exclusive (on the end) range and 1...3 for inclusive (on the end). You can also do 1..10.step(5).
FrustratedWithFormsDesigner
0

Salah satu solusi yang pasti akan saya pertimbangkan adalah menggunakan operator yang berlebihan untuk memungkinkan misalnya

1+[0..3]*5

Ini tidak harus langsung transparan bagi semua orang, tetapi begitu mereka berhenti dan berpikir saya berharap sebagian besar programmer akan memahaminya, dan orang-orang yang menggunakan bahasa secara teratur hanya akan mempelajarinya sebagai ungkapan.

Untuk memperjelas, hasilnya adalah [1, 6, 11, 16], mengangkat perkalian dan kemudian penambahan di atas jangkauan. Saya tidak menyadari bahwa itu mungkin ambigu bagi pengguna Python; Saya menganggap rentang sebagai himpunan bagian dari total pesanan dan bukan sebagai daftar. dan mengulang set tidak masuk akal.

Peter Taylor
sumber
2
Sangat ambigu. list expression * 5bisa juga berarti "ulangi nilai list expression5 kali", seperti halnya dengan Python.
nikie
Ini terlihat sangat aneh dan saya tidak yakin akan seperti apa ini ... 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3? 1,3,6,9,12? 5,10,15? sesuatu yang lain, mungkin? Either way, saya menemukan notasi ini sepenuhnya berlawanan dengan intuisi. Sepertinya itu mungkin semacam operasi pointer C aneh ...
FrustratedWithFormsDesigner