완벽한 범위 리터럴 설계


10

언어를 디자인하려면 "완벽한"범위 리터럴을 디자인하는 방법에 대해 생각했습니다. 1-4와 같이 값의 범위를 나타내는 명령문에서 범위 리터럴을 모르는 경우 for / foreach 루프에서 가장 일반적으로 사용됩니다.

고려해야 할 몇 가지 문제가있는 것 같습니다.

  • 포괄적이고 배타적 인 범위에 대한 지원, 엔드 포인트에 +1 또는 -1을 적용하는 것은 약간 애매하고 오류가 발생하기 쉽습니다.

  • 스테핑 지원, 예를 들어 짝수 또는 홀수의 범위를 만들 수 있습니다

  • 가독성, 범위 리터럴이 설명하는 내용을 쉽게 알 수 있어야합니다.

  • 확실성, 범위 리터럴이 설명하는 것은 완벽하게 명확해야합니다.

  • 대부분의 경우 배열을 반복하는 등의 이유로 사용되므로 기본값은 아마도 포함에서 배타적이어야합니다.

어쨌든, 내가 본 범위 리터럴의 한 가지 예는 루비입니다. 루비는 독점적 인 (끝) 범위는 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

기타 등등. 일반적으로 세트를 제거하고 세트와 대조적으로 주문하더라도이 종류에 적합하기 때문에 나는 그것을 좋아한다.

내가 조금 찢어 버린 한 가지 독점적 인 / 포괄적 인 지표를 필수 여부로 만드는 것입니다. 즉, 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을 포함하는 포괄적 인
  • wordy : [0에서! 20까지 5]

나는 지금까지 내가 가장 좋아하는 aestically가 0 ..! 100..5 ..! 20 이라고 말해야 합니다. 포괄적 인 배타적 인 기본 0..10 이 더 논리적 이기를 바랍니다.


2
1,5,10,15,20갭 4, 5, 5, 5 ?!
피터 테일러

죄송합니다 :) 수정
Homde

답변:


14

수학에 이미 존재하는 것을 왜 발명합니까?

간격 표기법

그것은 이미 존재하는 '모호하지 않은'점을 포함해야합니다.

유일한 문제는 스테핑을 정의하는 것입니다. 수학의 다른 것이 도움이 될 수 있습니까?


3
안녕하세요, 실제로 간격 표기법에 대해 이야기했습니다. 그러나 그것을 사용하고 싶지 않은 것은 그것이 [와)와 대칭 적이 지 않았고 사용 된 마비뿐만 아니라 (당신이 언급했듯이) 단계가 없다는 사실이었습니다. 마비를 사용하면 중괄호 일치를 혼동시킬 가능성이있는 것 같으며 표현식에 저장하고 싶습니다. ]와 [를 사용하는 것은 iso 표준이며 스테핑 통합으로 더 잘되는 것처럼 보였지만 그것은 내 의견입니다.
Homde

7
@MKO : (와 같은 [1..5[) 대괄호를 사용하려는 생각은 최소한 표준 간격 표기법만큼 편집기를 혼란스럽게 만듭니다.
David Thornley

2
흠, 또 다른 아이디어, 사용하는 것은 어떻습니까! 예 : 1 ..! 5 또는 0..5 ..! 20 (스테핑 포함)
Homde

1
@ MKO : !첫 번째 요소 또는 마지막 요소를 제외시키는 것이 좋습니다.
FrustratedWithFormsDesigner

8

Haskell 범위를 보셨습니까? 단계에 대한 그들의 아이디어는 (중간에) 비슷하지만 구문상의 차이로 @ 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

나는이 표기법이 매우 직관적이라는 것을 알았습니다 : 당신은 열거를 시작하고 본문을 건너 뛸 곳을 표시합니다.

그것은 "배타적"의 경우를 다루지 않지만 솔직히 말해서 행동에 대해 한 번 명확하게하고 (어떤 범위가 포함되고 독점적인지를 지정하십시오) 구문이 매우 명확 하지 않으면 사용자가 조정을 기대합니다 (그리고 언어에 구애받지 않는 편집자를 혼동하지 않습니다).


5

제공하는 언어로 된 목록 이해에 대해 읽어야합니다.

예를 들어, 파이썬은 range()함수를 사용하여 사례를 꽤 잘 다루고 너무 복잡하게 표현할 수없는 경우에 대한 목록 이해도를 제공 range()합니다.


2

나는 당신의 표기법이 명확하지 않다고 생각합니다. 직관적으로, [0..5..20]단계 너비 = 5의 범위처럼 보이지 않습니다. 일부 경우에는 실패합니다. 세트 (0,2)를 표현하는 [0..2..2]것은 어떻습니까? 또는 중간에 무엇을 넣어야합니까?

파이썬의 슬라이스 표기법은 확실한 접근법이라고 생각합니다 [start:end:step](단계는 선택 사항입니다).

배타적이고 포괄적 인 범위에 대한 지원이 실제로 필요한 경우 언어에 구문상의 모호성이 도입되지 않는 한 표준 범위 표기법 (예 : ([)을 사용 합니다.


1
"표준"표기에 관한 유럽 학교는 가르 칠하지 [], [[, ]]그리고 ][어떤 괄호 ... 그리고 우리의 표준은 물론, 더 나은)
마티유 M.

@Matthieu : 사실, 여기 (네덜란드 입니다 유럽), 우리는 또한 표준 표기법 것을 배웠다.
Frits

1

세 번째 증분 값을 설정할 때이 값은 중간이 아닌 끝 부분에 추가하는 것이 좋습니다. 이는 선택적 값이므로 중간에 선택적 세 번째 인수를 추가하는 것보다 노련한 프로그래머에게 더 직관적 인 것처럼 보입니다. .

[1..5..20] 대신 [1..20] [5] 또는 [1..20,5]와 같은 작업을 수행 할 수 있습니다.


그것은 타당하고 아마도 맛의 문제 일뿐입니다. [1..20]을 사용하여 "1에서 2까지, 5에서 5 단계로"보다는 "1 단계 5에서 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

ie대괄호의 두 번째 쌍은이 태초 또는 범위를 종료하는 것이 포함 또는 독점 여부를 나타내는 (또는 사용할 수 있습니다 incl, 그리고 excl당신이 더 명확 할 경우). 는 by 5스테핑 간격을 나타냅니다. 첫 번째와 마지막 예제는 첫 번째와 마지막 값을 포함하므로을 생략했습니다 [i,i]. 이것은 OK 기본 동작이라고 생각합니다.

[i,i]포함 / 배타 지정자 및 by 1단계 지정자에 대한 기본값이 될 수 있습니다 .

일반적으로 나는 포함하는 표준 표기법을 제시 한 것 ([@Dan 맥그래스에서 언급 한 바와 같이,하지만 난 코드에서이 혼란을 볼 수 있었다 동의합니다.


누구나 공감대를 설명 할 수 있습니까?
FrustratedWithFormsDesigner

나는 특허 적으로 잘못된 것을 보지 못했다 . 나는 downvote를 반대하기 위해 upvoted.
Berin Loritsch

1

그리고 승자는

내 솔루션을 선택해 주셔서 죄송합니다. 모든 의견과 의견을 보내 주셔서 감사합니다. 문제가 발견되면이 솔루션을 비판하십시오.

그래서 나는 함께 가기로 결정했습니다.

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

보시다시피 포괄적 인 것이 두 가지 의미에서 기본값이므로, 특히 스테핑을 사용할 때 직관적으로 가장 의미가 있습니다. 당신이 사용할 수있는 ! 끝을 독점하기 위해.

단점은 일반적으로 배열에 대해 작업 할 때 독점적으로 사용하고 싶지만 대부분의 경우 아마도 각각의 경우 for-each와 같은 것을 사용해야한다는 것입니다. 인덱스에 대해 실제로 작업 해야하는 경우 파서는 끝에서 제외 마커를 잊어 버렸을 때 인식하고 경고를 발행 할 수 있습니다

쉼표 또는 다른 것을 사용하는 대신 단계 변수의 양쪽에 ..를 사용하여 가장 깨끗하게 보였으므로 가장 읽기 좋기를 바랍니다.

또한 다른 부분이 다른 단계를 갖는 범위를 만들 수 있도록 쉼표로 구문을 던졌습니다.


단계를 지정할 때를 제외하고는 괜찮습니다. 나는 그것이 [0..10 by 5]처럼 더 깨끗할 것이라고 생각합니다. 세그먼트 범위는 [0..5, ..20 x 5] 등일 수 있습니다. (다른 형식과 달리) [1 단계에서 숫자]를 지정할 수도 있습니다 (다른 형식과 달리).
supercat 2019

0

필자는 괄호와 중괄호를 섞지 않는 것과 같은 이유로 '[1..5 ['형식을 사용하지 않을 것입니다. 대부분의 기존 편집기의 괄호 일치를 혼동합니다. 아마도 '[1 .. | 5]'와 같이 중괄호 안에 마커를 사용하십시오.

고려해야 할 다른 것은 한계를 얻는 방법의 동작입니다. 예를 들어, '시작'/ '종료'vs. '첫 번째'/ '마지막'vs. '최소'/ '최대'. 포함 및 배타적 한계와 단계 크기의 한계에 대해 제정신이어야합니다.


0

루비에는 표기법과 작동 하는 Range 객체가 있습니다. 기본적으로 다음과 같습니다.

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

Ruby의 경우 단계 크기는 범위의 기능이 아니라 범위를 반복하는 기능입니다. 위와 동일한 범위를 사용할 수 있고 원하는 경우 다르게 반복 할 수 있습니다.

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

다음은 고려해야 할 사항입니다.

  • 포괄적 / 독점 엔드 포인트에 대한 언어 지원을 추가하는 것은 문제가 될 수 있습니다. 모든 범위가 포괄적 인 경우 (Ruby의 선택) 개발자는 그에 따라 범위의 끝점을 조정합니다. 간단한 파서 문법으로 시각적으로 명확하고 모호하지 않은 방식으로 끝점 포함 또는 독점 성을 어떻게 표현합니까?
  • 반복 이상의 범위를 사용하고 있습니까? 일반적인 예에는 범위 비교, 스 플라이 싱, 범위 비교 값이 포함됩니다. 그렇다면 그러한 가능성을 어떻게 표현하십니까? (이러한 각 예제에 대한 아이디어는 Range 클래스 링크를 참조하십시오.)

BTW, 범위가 Ruby처럼 switch 문에 포함되도록 허용하면 범위가 다소 좋습니다.

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

루비의 범위 객체가 전부가 아니라고 말하는 것은 아닙니다.하지만 그것은 당신이 이야기하고있는 개념의 실제 구현입니다. 당신이 좋아하고 싫어하는 것과 다르게 행동하는 것을보기 위해 그것을 가지고 놀아 라.


OP는 이미 루비 범위를 알고 있습니다.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]곱셈을 들어 올린 다음 범위에 더하는 것입니다. 파이썬 사용자에게는 그것이 모호 할 수도 있다는 것을 깨닫지 못했습니다. 범위는 목록이 아닌 총 주문의 하위 집합으로 생각합니다. 세트를 반복하는 것은 의미가 없습니다.


2
매우 모호합니다. 파이썬에서와 같이 "5 번 list expression * 5반복하는 값"을 의미 할 수도 있습니다 list expression.
nikie April

이것은 매우 이상하게 보이며 이것이 무엇인지 잘 모르겠습니다 ... 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.