การออกแบบช่วงตัวอักษรที่สมบูรณ์แบบ


10

ฉันคิดว่าฉันจะออกแบบตัวอักษรที่ "สมบูรณ์แบบ" ได้อย่างไรถ้าฉันจะออกแบบภาษา สำหรับคุณที่ไม่ทราบว่าเป็นช่วงตัวอักษรในคำสั่งที่แสดงถึงช่วงของค่าเช่น 1-4 พวกมันถูกใช้บ่อยที่สุดใน for / foreach loops

ดูเหมือนจะมีปัญหาสองข้อที่ควรคำนึงถึง

  • การสนับสนุนสำหรับช่วงที่รวมและไม่เหมือนใครการตรึงบน +1 หรือ -1 ถึงจุดสิ้นสุดดูเหมือนว่าจะผิดพลาดและไม่มีข้อผิดพลาด

  • สนับสนุนการก้าวดังนั้นคุณสามารถสร้างช่วงของเลขคู่หรือคี่ได้

  • ความสามารถในการอ่านควรชัดเจนว่าช่วงตัวอักษรหมายถึงอะไร

  • ความไม่น่าสงสัยมันควรจะไร้เหตุผลอย่างสมบูรณ์แบบในสิ่งที่ช่วงตัวอักษรอธิบาย

  • ค่าเริ่มต้นควรเป็นแบบรวมถึงแบบเอกสิทธิ์เนื่องจากเป็นสิ่งที่ใช้ในกรณีส่วนใหญ่สำหรับการวนซ้ำอาร์เรย์เป็นต้น

อย่างไรก็ตามตัวอย่างหนึ่งของช่วงตัวอักษรที่ฉันได้เห็นคือ Ruby ซึ่งอยู่ในรูปแบบของ 1..3 สำหรับช่วงพิเศษ (ที่สิ้นสุด) และ 1 ... 3 สำหรับการรวม (บนสุด) คุณยังสามารถทำ 1..10.step (5) หลังจากพิจารณาอย่างถี่ถ้วนแล้วฉันพบบางสิ่งที่ฉันไม่ชอบเกี่ยวกับวิธีการนั้น (จากความรู้ที่ จำกัด เกี่ยวกับทับทิม)

  1. คุณสามารถอธิบายได้อย่างครอบคลุมและพิเศษเฉพาะตอนท้าย ในขณะที่อธิบายสถานการณ์ส่วนใหญ่ดูเหมือนจะไม่สอดคล้องกันเล็กน้อย

  2. แตกต่างกันเพียงเพิ่มเติม ดูเหมือนว่าเป็นสูตรสำหรับทำให้ยากที่จะดูว่าช่วงนั้นครอบคลุมหรือเป็นเอกสิทธิ์ ฉันไม่รู้เกี่ยวกับคุณ แต่จุดที่มักจะกลายเป็นสิ่งที่เบลอ :)

  3. การเพิ่มวิธีการเช่นสัญกรณ์สำหรับช่วงดูเหมือนจะผสมผสานความคิดของตัวอักษรเข้ากับชั้นเรียนซึ่งดูเหมือนว่าจะไม่สอดคล้องกันเล็กน้อย

อย่างไรก็ตามหลังจากไตร่ตรองทางเลือกที่แตกต่างกัน ฉันมากับสิ่งนี้

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

และอื่น ๆ ฉันชอบเพราะ [โดยปกติ denonates ชุดและชนิดนี้เหมาะกับที่แม้ว่าจะตรงกันข้ามกับชุดจะได้รับคำสั่ง

สิ่งหนึ่งที่ฉันขาดไปนิดหน่อยคือการสร้างตัวบ่งชี้เอกสิทธิ์เฉพาะบุคคล / รวมที่บังคับหรือไม่เช่นถ้าคุณเขียนแค่ 1..5 ค่าเริ่มต้นจะเป็น 1,2,3,4 เนื่องจากเป็นกรณีที่พบบ่อยที่สุดกับอาร์เรย์ ฯลฯ ง่ายขึ้นและอ่านได้มากขึ้น แต่เจาะจงน้อยลงและถ้าคุณต้องเขียน [1..5 [คุณเรียนรู้เร็วเกี่ยวกับการทำงานของมัน

คุณคิดว่าอย่างไรฉันครอบคลุมฐานส่วนใหญ่มองข้ามบางสิ่งบางอย่าง? คุณจะทำให้ [] บังคับหรือไม่? คุณจะออกแบบตัวอักษรช่วงที่แตกต่างกันในภาษาการเขียนโปรแกรมของคุณหรือไม่

ผู้สมัคร

  • สไตล์วงเล็บปีกกา: [0..10 [ , ด้วยขั้นตอน: [0..5..20 [
  • สัญกรณ์ช่วงเวลา: [0..10) กับขั้นตอน: [0..5 .. 20)
  • อัศเจรีย์เพื่อความเกินจริง 0 .. ! 10 พร้อมขั้นตอน: 0..5 .. ! 20
    • ด้วยขั้นตอนที่แตกต่างกัน 0 .. ! 20, 5
    • อย่างไรก็ตามนั่นจะทำให้เป็นค่าเริ่มต้น * 0..10 'รวมทุกอย่าง
  • ใช้คำ: [0 ถึง! 20 จาก 5]

ฉันต้องบอกว่ารายการโปรดของฉันอย่างใจจดใจจ่อจนเป็น0 .. ! 10และ0..5 .. ! 20ฉันแค่หวังว่าเริ่มต้น0..10ถึงรวมแบบเอกสิทธิ์เฉพาะบุคคลจะมีเหตุผลมากขึ้น


2
1,5,10,15,20ช่องว่าง 4, 5, 5, 5!
Peter Taylor

oops :) แก้ไขแล้ว
Homde

คำตอบ:


14

ทำไมคิดค้นสิ่งที่มีอยู่แล้วในวิชาคณิตศาสตร์?

เครื่องหมายช่วงเวลา

ที่ควรครอบคลุมจุด 'Unambiguity' ของคุณตามที่มีอยู่แล้ว

ปัญหาเดียวของคุณคือการกำหนดก้าว บางทีมีอย่างอื่นในวิชาคณิตศาสตร์ที่สามารถช่วยเรื่องนี้ได้?


3
สวัสดีฉันจริง ๆ แล้วเกี่ยวกับสัญกรณ์ช่วงเวลา อย่างไรก็ตามสิ่งที่ทำให้ฉันไม่ต้องการใช้มันเป็นความจริงที่ว่ามันไม่สมมาตรทั้ง [และ) และใช้ paranthesis รวมถึงไม่มีขั้นตอน (ตามที่คุณพูดถึง) การใช้ paranthesis มีแนวโน้มที่จะสร้างความสับสนในการจับคู่รั้งและฉันควรบันทึกไว้ในนิพจน์ การใช้] และ [เป็นมาตรฐาน iso และดูเหมือนจะดีขึ้นเมื่อรวมการก้าว แต่นั่นเป็นเพียงความคิดเห็นของฉัน
Homde

7
@MKO: ความคิดของคุณในการใช้วงเล็บเหลี่ยมที่ไม่ตรงกัน (เช่น[1..5[) จะสร้างความสับสนให้กับบรรณาธิการอย่างน้อยเท่ากับสัญกรณ์ช่วงเวลามาตรฐาน
David Thornley

2
อืมมมมมมมมคิดอะไรเกี่ยวกับใช้! สำหรับเช่น: 1 .. ! 5 หรือ 0..5 .. ! 20 (พร้อมก้าว)
Homde

1
@MKO: การใช้!เพื่อแยกองค์ประกอบแรกหรือองค์ประกอบสุดท้ายอาจทำได้ดี
FrustratedWithFormsDesigner

8

คุณเคยเห็น Haskell range หรือไม่? ความคิดของพวกเขาสำหรับขั้นตอนคล้ายกับของคุณ (ตรงกลาง) แต่ระบุด้วยความแตกต่างทางไวยากรณ์ (จากคำตอบ @ 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

ฉันพบสัญกรณ์นี้ใช้งานง่ายมาก: คุณเริ่มแจกแจงและข้ามร่างกายเพื่อทำเครื่องหมายว่าควรจะปิดที่ใด

มันไม่ครอบคลุมถึงกรณีสำหรับ "เอกสิทธิ์" แต่ตรงไปตรงมาฉันค่อนข้างชัดเจนเกี่ยวกับพฤติกรรมครั้งเดียว (ระบุว่าขอบเขตที่รวมและที่เป็นเอกสิทธิ์) และคาดว่าผู้ใช้จะทำการปรับเว้นแต่ไวยากรณ์ที่ชัดเจนมาก (และ ไม่สับสนบรรณาธิการภาษาผู้ไม่เชื่อเรื่องพระเจ้า)


5

คุณควรอ่านเกี่ยวกับรายการความเข้าใจในภาษาที่เสนอให้

ตัวอย่างเช่น Python ครอบคลุมกรณีของคุณค่อนข้างดีด้วยrange()ฟังก์ชันและรายการความเข้าใจสำหรับกรณีที่ซับซ้อนเกินกว่าที่จะแสดงrange()ได้


2

ฉันเชื่อว่าสัญกรณ์ของคุณอยู่ห่างไกลจากความไม่น่าสงสัย ตามสัญชาตญาณ[0..5..20]ไม่มองฉันเหมือนช่วงที่มีความกว้างของขั้นตอน = 5 มันก็ล้มเหลวในบางกรณีมุม: สิ่งที่เกี่ยวกับการแสดงชุด (0,2) - [0..2..2]หรือฉันควรจะใส่ตรงกลาง?

ฉันคิดว่าสัญกรณ์ชิ้นของ Python เป็นแนวทางที่มั่นคง: [start:end:step](ขั้นตอนเป็นทางเลือก)

หากคุณต้องการการสนับสนุนสำหรับช่วงพิเศษและรวมฉันจะใช้สัญกรณ์ช่วงมาตรฐาน (เช่นการใช้(และ[) ยกเว้นกรณีนี้จะทำให้เกิดความคลุมเครือทางไวยากรณ์ในภาษาของคุณ


1
เกี่ยวกับ "มาตรฐาน" สัญกรณ์โรงเรียนยุโรปสอน[], [[, ]]และ][ไม่มีวงเล็บ ... และเรามาตรฐานคือดีกว่าแน่นอน;)
Matthieu เอ็ม

@ Matthieu: จริง ๆ แล้วที่นี่ในเนเธอร์แลนด์ (ซึ่งอยู่ในยุโรป) เรายังได้รับการสอนสัญกรณ์มาตรฐานที่
Frits

1

ฉันคิดว่าเมื่อคุณตั้งค่าที่เพิ่มขึ้นที่สามคุณจะดีกว่าที่จะเพิ่มจุดจบมากกว่าตรงกลางเนื่องจากนี่เป็นค่าที่ไม่จำเป็นและดูเหมือนว่าโปรแกรมเมอร์ที่มีประสบการณ์จะเข้าใจได้ง่ายกว่าการเพิ่มอาร์กิวเมนต์ตัวที่ 3 ที่เป็นตัวเลือกตรงกลาง .

ดังนั้นแทนที่จะเป็น [1..5..20] คุณสามารถทำอะไรเช่น [1..20] [5] หรือ [1..20,5]


นั่นเป็นจุดที่ถูกต้องและอาจเป็นเรื่องของรสนิยมฉันคิดว่ามันจะง่ายกว่าถ้าจะคิดว่า "1 ขั้นตอนที่ 5 ถึง 20" แทนที่จะเป็น "ตั้งแต่ 1 ถึง 2 กับขั้นตอนที่ 5" โดยใช้ [1..20] [5] ดูเหมือนจะยุ่งเหยิงไปหน่อย แต่บางทีคอมม่าจะใช้งานได้ ฉันขอขอบคุณข้อเสนอแนะเพิ่มเติมเกี่ยวกับเรื่องนี้
Homde

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

ทำไมไม่ใช้ [1..4], [2..5], [2..4] การยกเว้นช่วงไม่ให้ประโยชน์มากนัก คุณไม่จำเป็นต้องเขียน MIN + 1 หรือ MAX-1 ใช่ แต่พวกเขาไม่ได้ห้ามไว้ ความแปรปรวนมากเกินไป imho ภาษาที่ฉันเลือก Scala มี (1 ถึง 3) และ (1 ถึง 3) [= (1 ถึง 2)] แต่มันทำให้ฉันสับสนในตอนแรก ตอนนี้ฉันมักจะใช้ 'x to y' และรู้อยู่เสมอว่าตัวเลือกที่ฉันไม่ได้ใช้คือตัวเลือกยกเว้น แต่แน่นอนฉันไม่ได้รับประโยชน์จากตัวเลือกที่ฉันไม่ได้ใช้

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

แน่นอน (1 ถึง MAX) (x => y = (MAX + 1) - x) แต่นั่นก็มากสำเร็จรูปและไม่เป็นมิตรกับผู้ใช้

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

แน่นอน (0 ถึง 4) (x => y = x * 5) ไม่สำเร็จรูปมาก ยังเป็นปัญหาอยู่


ประโยชน์หลักของการแยกช่วงคือ afaik คือจำนวนขององค์ประกอบคือความแตกต่างของจุดสิ้นสุด
Justin L.

@JustinL .: 5-1 คือ 4 ในพีชคณิตของฉัน แต่มี 3 องค์ประกอบไม่รวมถึงขอบเขต: 2, 3, 4
ผู้ใช้ที่ไม่รู้จัก

1

อะไรประมาณนี้

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

iและeในคู่ที่สองวงเล็บบ่งชี้ถ้าจุดเริ่มต้นหรือสิ้นสุดของช่วงนั้นได้รวมหรือ แต่เพียงผู้เดียว (หรือคุณสามารถใช้inclและexclถ้าคุณต้องการที่จะมีความชัดเจนมากขึ้น) by 5บ่งชี้ช่วงก้าว ตัวอย่างแรกและสุดท้ายรวมค่าแรกและค่าสุดท้ายดังนั้นฉันจึงละเว้น[i,i]ซึ่งฉันคิดว่าเป็นพฤติกรรมเริ่มต้นที่ถือว่าใช้ได้

ค่าเริ่มต้นอาจเป็น[i,i]ตัวระบุแบบรวม / เอกสิทธิ์และby 1สำหรับตัวระบุขั้นตอน

โดยปกติฉันจะแนะนำสัญกรณ์มาตรฐานที่เกี่ยวข้อง(และ[ตามที่ @Dan McGrath พูดถึง แต่ฉันยอมรับว่าในรหัสนี้อาจทำให้เกิดความสับสน


ทุกคนสามารถอธิบาย downvote หรือไม่
FrustratedWithFormsDesigner

ฉันไม่เห็นอะไรยะที่ไม่ถูกต้อง ฉันโหวตขึ้นเพื่อต่อต้านการโหวต
Berin Loritsch

1

และผู้ชนะคือ

ขออภัยที่เลือกโซลูชันของตัวเองฉันขอขอบคุณความคิดเห็นและข้อเสนอแนะทั้งหมดและโปรด critize วิธีแก้ปัญหานี้หากคุณพบสิ่งผิดปกติกับมัน

ดังนั้นฉันตัดสินใจไปกับ:

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

ในขณะที่คุณสามารถเห็นการรวมเป็นค่าเริ่มต้นในความรู้สึกทั้งสองมันเป็นสิ่งที่เหมาะสมที่สุดโดยเฉพาะอย่างยิ่งเมื่อใช้การก้าว คุณสามารถใช้ได้ ! ที่จะทำให้สิ้นพิเศษ

ข้อเสียคือปกติแล้วคุณต้องการใช้แบบเอกสิทธิ์เฉพาะบุคคลเมื่อทำงานกับอาเรย์ แต่จากนั้นอีกครั้งส่วนใหญ่คุณควรจะใช้สิ่งที่ต้องการสำหรับแต่ละในกรณีเหล่านั้น หากคุณจำเป็นต้องทำงานกับดัชนีจริงๆตัวแยกวิเคราะห์สามารถจดจำได้เมื่อคุณอาจลืมเครื่องหมายยกเว้นที่ส่วนท้ายและออกคำเตือน

ฉันไปกับการใช้ .. ทั้งสองด้านของตัวแปรขั้นตอนแทนที่จะใช้เครื่องหมายจุลภาคหรืออย่างอื่นเพราะนั่นคือสิ่งที่ดูดีที่สุดและฉันหวังว่าจะอ่านได้มากที่สุด

ฉันยังใช้ไวยากรณ์ร่วมกับเครื่องหมายจุลภาคเพื่อสร้างช่วงที่ส่วนต่าง ๆ มีขั้นตอนต่างกัน


ดูเหมือนว่าใช้ได้ยกเว้นเมื่อระบุขั้นตอน ฉันคิดว่ามันน่าจะสะอาดกว่า [0..10 คูณ 5] ช่วงการแบ่งกลุ่มอาจเป็น [0..5, ..20 คูณ 5] และอื่น ๆ หนึ่งสามารถระบุ [จำนวน numitems ตั้งแต่ต้น) ซึ่ง (ซึ่งแตกต่างจากรูปแบบอื่น ๆ ) สามารถอนุญาตให้ขนาดขั้นตอนเป็นศูนย์
supercat

0

ฉันจะไม่ใช้รูปแบบ '[1..5 [' สำหรับหนึ่งในเหตุผลเดียวกันกับที่คุณหลีกเลี่ยงการผสม parens และวงเล็บ - มันจะสร้างความสับสนในการจับคู่รั้งบรรณาธิการที่มีอยู่ส่วนใหญ่ อาจใช้เครื่องหมายในวงเล็บปีกกาเช่น '[1 .. | 5]'

อีกสิ่งที่ควรพิจารณาคือพฤติกรรมของวิธีการเพื่อให้ได้ข้อ จำกัด ตัวอย่างเช่น 'เริ่มต้น' / 'สิ้นสุด' กับ 'แรก' / 'สุดท้าย' เทียบกับ 'ขั้นต่ำ' / 'สูงสุด' พวกเขาจะต้องมีสติสำหรับข้อ จำกัด ทั้งแบบรวมและแบบเอกสิทธิ์เฉพาะบุคคล


0

Ruby มีสัญกรณ์และวัตถุRangeที่ใช้งานได้ เป็นหลักดูเหมือนว่านี้:

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

ด้วย Ruby ขนาดขั้นตอนไม่ใช่ฟังก์ชันของช่วง แต่เป็นฟังก์ชันของการวนซ้ำตลอดช่วง เราสามารถใช้ช่วงเดียวกันด้านบนและวนซ้ำมันแตกต่างกันหากเราต้องการ:

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

ดังนั้นนี่คือสิ่งที่คุณอาจต้องการพิจารณา:

  • การเพิ่มการสนับสนุนภาษาสำหรับจุดสิ้นสุดแบบรวม / พิเศษอาจเป็นปัญหาได้ หากทุกช่วงนั้นรวมอยู่ด้วย (ตัวเลือกของรูบี้) ผู้พัฒนาจะปรับจุดสิ้นสุดของช่วงตามนั้น คุณเป็นตัวแทนของจุดสิ้นสุดการรวมหรือการผูกขาดในวิธีที่ทั้งสองมองเห็นได้ชัดเจนและไม่คลุมเครือด้วยไวยากรณ์ parser ง่าย?
  • คุณกำลังใช้ช่วงมากกว่าการวนซ้ำหรือเปล่า? ตัวอย่างทั่วไป ได้แก่ การเปรียบเทียบช่วงการต่อเชื่อมค่าในการเปรียบเทียบช่วง ถ้าเป็นเช่นนั้นคุณเป็นตัวแทนของความเป็นไปได้เหล่านั้นอย่างไร? (ดูลิงก์ไปที่คลาสของ Range เพื่อหาแนวคิดสำหรับตัวอย่างเหล่านี้)

BTW ช่วงค่อนข้างดีถ้าคุณอนุญาตให้รวมอยู่ในคำสั่ง switch เช่น Ruby

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

ฉันไม่ได้บอกว่าวัตถุช่วงของ Ruby เป็นจุดจบและเป็นทั้งหมด แต่เป็นการดำเนินการตามแนวคิดที่คุณกำลังพูดถึง เล่นกับมันเพื่อดูสิ่งที่คุณชอบไม่ชอบและจะทำแตกต่างกัน


อ่านคำถามอย่างระมัดระวัง OP ทราบแล้วเกี่ยวกับช่วง 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

ทางออกหนึ่งที่ฉันจะพิจารณาอย่างแน่นอนคือการใช้ตัวดำเนินการโอเวอร์โหลดเพื่ออนุญาตเช่น

1+[0..3]*5

มันไม่จำเป็นต้องโปร่งใสทันทีสำหรับทุกคน แต่เมื่อพวกเขาหยุดและคิดว่าฉันหวังว่าโปรแกรมเมอร์ส่วนใหญ่จะเข้าใจและคนที่ใช้ภาษาเป็นประจำจะเรียนรู้ว่ามันเป็นสำนวน

เพื่อชี้แจงผลที่ได้[1, 6, 11, 16]คือยกการคูณแล้วบวกเพิ่มในช่วง ฉันไม่ได้ตระหนักว่ามันอาจไม่ชัดเจนสำหรับผู้ใช้ Python ฉันคิดว่าช่วงเป็นชุดย่อยของคำสั่งซื้อทั้งหมดแทนที่จะเป็นรายการ และการทำซ้ำชุดก็ไม่สมเหตุสมผล


2
คลุมเครือมาก list expression * 5อาจหมายถึง "ทำซ้ำค่าlist expression5 ครั้ง" เช่นเดียวกับใน Python
nikie

มันดูแปลกมากและฉันไม่แน่ใจว่ามันจะเป็น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? อย่างอื่นบางที ไม่ว่าจะด้วยวิธีใดฉันพบว่าสัญกรณ์นี้ขัดข้องอย่างสมบูรณ์ ดูเหมือนว่ามันอาจจะเป็นบางส่วนของการดำเนินการตัวชี้ C ที่แปลก ...
FrustratedWithFormsDesigner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.