어떤 유용한 대체 제어 구조를 알고 있습니까? [닫은]


12

비슷한 질문 이 너무 닫혔습니다.

때로는 프로그래밍 할 때 특정 제어 구조가 우리에게 매우 유용하지만 프로그래밍 언어로 직접 사용할 수는 없습니다.

어떤 대체 제어 구조가 계산을 구성하는 유용한 방법이라고 생각하십니까?

여기서의 목표는 청크 및 추론을 향상시키기 위해 코드 구조화에 대한 새로운 사고 방식을 얻는 것입니다.

현재 사용할 수없는 원하는 구문 / 의미론을 작성하거나 기존 프로그래밍 언어에 대해 덜 알려진 제어 구조를 인용 할 수 있습니다.

답변은 새로운 프로그래밍 언어에 대한 아이디어를 제공하거나 실제 언어를 향상시켜야합니다.

이것을 브레인 스토밍으로 생각하면 미친 생각이라고 생각하는 것을 게시하지만 일부 시나리오에서는 가능할 수 있습니다.

명령형 프로그래밍에 관한 것입니다.


1
이 질문이 왜 "제국 프로그래밍"에 관한 것이어야합니까?
missingfaktor

@missingfaktor : 제어 구조는 명령형 프로그래밍에 관한 것입니다. 물론, 일부 접근 방식은 기능적 접근 방식이나 다른 방법으로 해결할 수 있지만 다른 패러다임은 제어 구조를 개발 중심에 두지 않습니다. 그러나 어쨌든 창의력을 발휘할 수 있습니다.
Maniero

3
글쎄, 나는 Pattern Matching을 Guards와 공유하려고했는데, 이것들은 Case 문과 If-Thens보다 일반적이기 때문에, 이것이 FP 영역이 아닌 경우, 그것은 우리의 나머지 사람들에게 더 많은 Pattern Matching이라고 생각합니다!
CodexArcanum

@CodexArcanum : 음, 패턴 매칭은 명령형 구문과 매우 유사한 구문입니다. 실제로 패턴 매칭 자체는 명령형 제어 구조의 대안입니다. 부끄러워하지 마십시오 ;-)
Maniero

모든 답변을 살펴보면 실제 제안서 중 어느 것도 존재하지 않는다는 것을 기쁘게 생각합니다. 죄송합니다 :)
serg

답변:


14

좋아, 이것은 재미있는 질문이다.

또한 첫 번째 테스트 else에서 조건이 true가 아닌 동안 while 및 for 루프에 대한 일반 정보 를 원합니다 .

while (condition) {
    // process
}
else {
    // condition was never true
}

이렇게하면 조건을 어색하게 다시 계산하거나 변수에 저장하지 않아도됩니다.


파이썬은 이것을 가지고 있습니다.
베리 브라운

야! 마지막으로 내가 동의하는 기발한 파이썬 선택! ;-)
Macneil

5
루프 for 루프 동안 else의 절은 루프가 정상 종료되면 실행됩니다. 즉, 루프가 break 또는 return 문이나 예외를 통해 종료되지 않습니다. for 루프에서 else clasuse는 루프 된 요소 시퀀스가 ​​소진 된 후에 실행되고 루프 동안 루프 조건이 처음으로 False로 평가 된 후에 실행됩니다.
pillmuncher

4
거기에 요청 추가하는 while ... else구조를 맥닐은 PHP로 설명하는 방법. "여기 결과가 있고 결과가 없었습니다"는 웹앱에서 상당히 일반적인 관용구이기 때문에 좋은 생각이라고 생각합니다.
Dean Harding

1
@SnOrfus : while 조건이 충족되지 않는 경우에만 실행되는 코드 블록 (루프 블록과 분리)을 원합니다. Do-While은 while 조건에 관계없이 루프의 코드 블록 (일부 블록이 아닌)을 한 번 실행합니다.
군단

10

왜 몇 가지 답변을 하나로 뭉개지 않겠습니까?

while (expr) {

    // Executed every iteration, unless first{} is present.
    // May be explicitly called rest{} if you like first{} to come first.

    // Blocks may return results, and consequently be used in expressions.
    return expr;

} first {

    // Executed only on the first iteration.

} pre {

    // Executed before every iteration.

} post {

    // Executed after every iteration.

} catch (oops) {

    // All blocks are implicitly try{}ed if followed by a catch{}.

} finally {

    // Executes after the block completes, regardless of exceptions.

} else {

    // Executed if the loop body or rest{} never executes.

} never {

    // Executes only when a client is present.

} drop (bad, worse), // Explicitly ignore certain exceptions.
  until (expr);      // Here, have a post-body condition, too.

명령형 언어로 확장 가능한 일반화 된 흐름 제어 구문은 다소 유용하고 재미있을 것입니다. 그것이 나타날 때까지, 나는 단지 Lisp 또는 무언가를 사용할 것이라고 생각합니다.


5
유용하지 않고 혼란 스럽습니다. 재미없고 천천히.
Josh K

2
@ 조쉬 K : 네, 그렇습니다. 내가 동의하지 않는다고 생각 했어요? 이 답변은 웃지 않도록 혀를 물고 있습니다.
Jon Purdy

그것이 아이러니 한 의도라면 확실히 성공했습니다!
Josh K

11
+1 나를 웃게 만들었다. 반복간에 코드를 실행하려면 "사이에"절이 필요합니다.
Barry Brown

1
+1이지만 필요합니다 seventh { ... }.
j_random_hacker

7

기능으로서 구조를 제어합니다.

내가 원하는 for, if, else, while, 등의 기능이 아닌 특별한 구조가 될 수 있습니다.

나는 return, try/except그리고 goto연속의 파생물이기를 원합니다 .

물론 이것은 특정 제어 구조와는 관련이 없으며 제어 구조를 일반적으로 보는 제어 구조의 메타와 관련이 있습니다.


2
연속은 언어에 대한 헤비급 개념이므로 여러 언어에서 제외시키는 데에는 충분한 이유가 있습니다.
David Thornley

동의하지 않습니다. 데 for, if, else, 및 while나 그 함수 파라미터가 느리게 원래 구조와 동일하게 동작하기 위해 실행되어야한다는 추론하게 기능한다. 게으른 실행 능력이 있으면 좋을 것입니다.
윌리 박사의 견습생

1
@David : 그들이 있다고해서 반드시 사용해야한다는 것은 아닙니다. 정규 프로그래머는 자신이 사용하는 것을 사용하거나 return예외 등 을 사용할 수 있습니다 . 그러나 이제 전문 프로그래머는 필요에 따라 도구 상자에 강력한 추가 도구를 가지고 있습니다. 게다가 IMHO 언어는 "멍청하게"해서는 안됩니다. 언어는 전문 지식과 CS 지식의 성장을 지원할 수 있어야합니다.
dietbuddha

1
@dietbuddha : (계속) 나는 연속이 나쁘다고 말하지 않고, 헤비급이라고 말하며, 사용 가능하게 만드는 것은 예외와 같은 언어에 영향을 미칩니다. 또한 계속해서 C ++의 예외와 같이 사람들이 언어를 사용하는 방식에 변화를 줄 수 있습니다. 연속을 지원하는 언어는 좋은 방법과 나쁜 방법 모두에서 그렇지 않은 언어와 다릅니다.
David Thornley

1
@ Steve314-longjmp는 유사성이 있지만 연속이 아닙니다. 계속하면 전체 상태 (모든 로컬, 글로벌 및 스택)가 저장됩니다. longjmp는 스택 포인터를 저장 하므로 setjmp가 사용 된 범위를 벗어나면 프레임이 더 이상 존재하지 않으므로 segfault가 표시됩니다. 나는 그것이 절약하는 변수에도 약간의 한계가 있다고 생각합니다.
dietbuddha

6

링크 된 기사는 확실히 Donald Knuth의 N + 1 / 2 루프에 대해 잘 알고 있습니다. C / C ++ / Java로 표현 :

for (;;) {
  get next element;
  if (at the end) break;
  process the element;
}

파일에서 행이나 문자를 읽고 EOF에 도달했는지 테스트 한 다음 처리하는 데 유용합니다. 나는 패턴 for(;;)..if(..)break;이 나에게 관용적 인 것처럼 보이는 것을 보는 데 너무 익숙합니다 . (저는 Literate Programming 책에서 재 인쇄 된 Knuth 기사를 읽기 전에이 기사 는 "wtf?"였습니다.)

Knuth는 키워드를 제안했습니다 loop/while/repeat.

loop:
  S;
while C:
  T;
repeat

어디 ST0 개 이상의 일련의 명령문 장소 홀더, 그리고 C부울 조건이다. S명령문 이 없으면 while 루프가되고 T명령문 이 없으면 do 루프가됩니다.

이 구문 자체는 0 개 이상의 while C절 을 허용하여 일반화 할 수 있으므로 무한 루프를 표현하고 두 가지 검사가 필요한 좀 더 희귀 한 조건을 표현하는 데 적합합니다.

같은 기사에서 Knuth는 로컬 버전의 던지기 / 잡기 예외 (goto 사용의 대안)가 될 시그널링 메커니즘을 제안했습니다.

나를 위해? 나는 자바 내가 표현할 수 그래서, 꼬리 호출 최적화를 지원하고자하는 어떤 필요에 따라 일반 제어 구조를.


업데이트 : 많은 C / C ++ / Java 프로그래머가 다음 조건에서 임베디드 할당을 사용 하여이 문제를 해결한다는 것을 언급하지 않았습니다 while.

while ((c = getc(f)) != -1) {
   T;
}

시 크 누스의 구조에서 용어를 사용이 허용됩니다 SC하나의 표현으로 결합 할 수 있습니다. 어떤 사람들은 위의 내장 과제를보고 싶어하지 않는 반면, 어떤 사람들 breakfor (;;)위의 내용을보고 싶어하지 않습니다. 그러나 여러 명령문 이있는 경우와 같이 결합 할 수없는 경우 S와 코드를 반복하지 않는 것이 유일한 대안입니다. 다른 대안은 단순히 코드 를 복제하는 것 입니다.CSfor (;;)S

S;
while (C) {
  T;
  S;
}

크 누스의 loop/while/repeat대안이 훨씬 나아 보인다.


반복되는 repeat-until루프 는 파스칼 루프 와 비슷합니다 .
메이슨 휠러

@Mason : 차이점은 문장뿐만 아니라 조건을 삽입 할 수있는 두 곳이 있다는 것입니다.
Macneil

오, 무슨 일인지 알 겠어 네, 흥미 롭습니다 ...
Mason Wheeler

ANSI Basic에는 do while ... loop until전제 조건과 사후 조건이 모두 선택 사항이며 하나의 루프에서 두 가지를 모두 사용하는 것을 기억합니다. 귀하의 중간 조건에는 Ada가 exit when ...;있습니다. 주요 장점 if ... break;은 한 exit loopname when ...;번에 여러 개의 중첩 된 루프에서 나가도록 작성할 수 있다는 것 입니다. 아마도 그 휴식보다 약간 더 눈에.니다.
Steve314

재밌어요 에이다는 바로 그 기능을 가지고 있습니다.
John R. Strohm

6

BCPL 언어에는 일련의 명령문을 단일 표현식으로 변환하는 데 사용할 수 있는 valueof표현식 이 있습니다.

foo(a, b, valueof {some series of statements; resultis v});

어디에서 some series of statements무엇 전체가 될 수 valueof로 평가 v.

이것은 this()또는 호출하기 위해 인수를 계산해야 할 때 Java에서 유용 할 수 있습니다 super()(이전에 아무것도 발생하지 않아야 함). 물론 별도의 메소드를 작성할 수도 있지만 컨텍스트에 대해 많은 로컬 값을 전달해야하는 경우에는 고통이 될 수 있습니다.

final필요한 변수 에 사용할 수 있다면 valueof익명의 내부 클래스를 사용하여 Java에서 이미 할 수 있습니다.

foo(a, b, new Object(){String valueof(){
    String v ...; some series of statements; return v;}}.valueof());

1
GCC는 이것에 대한 확장 기능을 가지고 ({ statement1; statement2; ...; result-expr; })있습니다. 나는 다른 곳에서도 비슷한 것을 보았지만 어디에 있는지 기억하지 못한다. 아마도 모든 것이 BCPL에서 복사되었을 것입니다.
Steve314

6
unless(condition) {
  // ...
}

다음과 같은 일을합니다.

if(!condition) {
  // ...
}

repeat {
  // ...
} until(condition)

다음과 같은 일을합니다.

do {
  // ...
} while(!condition)

Lisp에 가고 싶을 수도 있습니다.
duros

1
또는 Ruby의 경우와 비슷한 구문이 unless있습니다.
Josh K

2
꽤 Perlish처럼 보입니다. 여러 가지 방법이 있습니다.

2
@ Steve314 잘못된 버팀대 스타일을 사용해야합니다 . ;-)
42 초에 Orbling

1
@Orbling-전혀 아닙니다. 다른 모든 사람들 은 잘못된 버팀대 스타일을 사용합니다.
Steve314

5

다른 말로, 프로그래밍 언어에서 반복자를 더 잘 지원하고 싶습니다. 특히 두 컬렉션 을 쌍 으로 내려 가려는 경우 :

for (String s, Integer i : stringsSet, integersSet) {
    // use the pair (s, i)
}

일부 동적 언어는 이미 이것을 가지고 있거나 라이브러리와 매크로를 통해 쉽게 지원할 수 있지만 이것이 귀하의 질문의 정신에 있다고 생각합니다.

두 세트의 크기가 동일하지 않으면 예외가 발생하거나 else이후 루프가 발생하여 크기에 차이가 있음을 알릴 수 있습니다.

당연히, 당신은 세 개 이상의 목록을 내려 가기 위해 이것을 일반화 할 수 있습니다.


업데이트 : iterables간에 Cartesian 제품을 수행하는 것도 유용합니다.

for (String s, Integer i : stringsSet * integersSet) {
    // use the pair (s, i), each s with each i
}

이것은 중첩 루프에 지나지 않습니다.

for (String s : stringsSet) {
    for (Integer i : integersSet) {
        // use the pair (s, i), each s with each i
    }
}

나는 여기에 제공 한 두 표기법 사이에 단일 문자의 변경만으로 쌍 수에 O (n) 및 O (n ^ 2) 차이가 있음을 걱정합니다.


2
파이썬에는 이것을 수행하는 zip과 zip_longest가 있습니다.
pillmuncher

쿨, 아마도 파이썬을 과소 평가하고 몇 년 후에 다시 살펴 봐야합니다. 그것은 때때로 당신이 직교 for 루프와 동등한 카티 전 곱을 원한다는 것을 상기시킵니다.
Macneil

1
스칼라 에서이 두 경우 : paste.pocoo.org/show/297429
missingfaktor

1
데카르트 제품과 관련하여 : 파이썬에도 있습니다. for a, b, c in itertools.product(iter1, iter2, iter3):느리게 평가 된 카티 전 곱을 제공합니다. 그게 뭐야? 주어진 반복자의 순열과 조합도 원하십니까? itertools.permutations, itertools.combinations.
aaronasterling

1
Haskell 퍼스펙티브 : 첫 번째 경우에는 "zipWith"를 사용하고 두 번째 경우에는 목록 이해 또는 목록 모나드를 사용하십시오. Python / Scala exmaples와 비슷하지만 더 우아합니다. :)
LennyProgrammers

5

소위 "Dijkstra 's Loop"( "Dijkstra 's Guarded Loop"라고도 함)가 있습니다. Guarded Command Language (GCL) 에 정의되어 있습니다. 위의 Wikipedia 기사 섹션 6 Repetition : do 섹션에서 구문과 의미에 대한 정보를 찾을 수 있습니다 .

요즘 저는 실제로이 제어 구조를 직접 지원하는 프로그래밍 언어를 알고 있습니다. 그것은이다 오베론-07 (PDF 70 KB). 그리고 while 문의 형태로 "Dijkstra 's Loop"를 지원합니다. 섹션 9.6을 살펴보십시오. 위의 PDF에서 While 문.

WHILE m > n DO m := m – n 
ELSIF n > m DO n := n – m 
END

추신 : 이것은 내 SO 답변의 사본입니다 .


모델 검사기 Spin에도 동일한 의미와 기본적으로 동일한 구문을 가진이 구성이 있습니다.
j_random_hacker

4

역 추적 기능이 내장 된 아이콘 스타일 표현.

파이썬은 많은 아이콘 생성기 이점을 얻습니다. 일반적으로 IMO보다 더 잘 작동합니다. 그리고 원칙적으로 역 추적은 일종의 예외를 던지는 것이었지만 표현의 단순성은 대략적으로 동등했습니다 ...

x = (a / b) else c;

0으로 나누는 것과 같은 실패 사례를 처리합니다.

부울 리턴 리턴 비교 연산자가없는 아이콘. 비교는 항상 성공하거나 역 추적을 촉발 시켰으며, 필자가 기억하기 위해 필사적으로 노력하고있는 또 다른 의미 론적 문제가 있었다.

나는 항상 if다른 부분이없는 표현식을 가져야한다고 생각했습니다 if (condition, success-value).

편집 내가 기억-정말 분명합니다. 두 개의 인수를 사용한 비교는 성공 또는 실패입니다. 반환 할 새 값을 계산하지 않습니다. 그래서 성공하면, 무슨 않는 그것을 반환? 답-논쟁 중 하나. 하지만 작성하는 경우 a > b반환에 대한 논리적 인수 인 - ab? b < a대신 쓰면 어떨까요? 나는 그것이 항상 옳은 논증을 돌려 주었다고 생각한다. 이것은 다른 것만큼이나 의미가 있지만, 여전히 나에게 잘못된 논증처럼 보였다.


4

이것은 일반적인 아이디어와 구문입니다.

if (cond)
   //do something
else (cond)
   //do something
also (cond)
   //do something
else
   //do something
end

또한 조건은 항상 평가됩니다. ELSE는 평소와 같이 작동합니다.

그것은 경우에도 작동합니다. 아마도 break statement를 제거하는 좋은 방법입니다.

case (exp)
   also (const)
      //do something
   else (const)
      //do something
   also (const)
      //do something
   else
      //do something
end

다음과 같이 읽을 수 있습니다 :

switch (exp)
   case (const)
      //do something
   case (const)
      //do something
      break
   case (const)
      //do something
   default
      //do something
end

이것이 유용하거나 읽기 쉬운 지 모르겠지만 예제입니다.


3

연속 통과 스타일 오릅니다. 물론 Tail Call Optimization 도 원합니다 .


1
이것에 대한 열렬한 팬은 아니며, 이것이 실제로 "제어 구조"가 아니라 기능적 언어와 프로그래밍 스타일의 빌딩 블록이라고 믿습니다. Node.js는 오히려 그것에 푹 빠져있는 것 같습니다.
Josh K

1
물론 제어 구조입니다. 'if'또는 'for'와 같은 키워드와 함께 제공되는 것이 아니라 제어 흐름을 구성하는 패턴 (따라서 제어 구조)입니다. 심지어 많은 컴파일러가 뒤에서 사용합니다. FL에도 국한되지 않습니다. 그래도 일급 객체로서의 기능이 필요합니다.
pillmuncher

1
요즘 C와 C ++에서 테일 콜 최적화를 얻었지만 IMO는 요점을 놓치고 있습니다. 요점은 그것이 최적화 라는 것 입니다 . Scheme에서는 진정한 테일 콜이 분명합니다. 특히 C ++에서 테일 콜이 테일 콜이 아니라는 것을 의미 할 수 있습니다. 스택 오버플로는 앱이 손상되었음을 의미합니다. IMO에는 goto return ...;명령문 과 같은 것이 있어야하며 꼬리 호출을 명시 적으로 명시해야하므로 컴파일러가 반복 할 수 없다면 오류입니다.
Steve314

1
@ Macneil-특정 꼬리 호출 최적화는 GCC, Clang 및 Visual C ++에서 수행됩니다. GCC는 재귀에서 반복으로보다 정교한 변환을 수행하므로 꼬리 재귀가 아닌 많은 경우를 처리 할 수 ​​있습니다. 그러나 많은 것이 잘못 될 수 있습니다. 해당 테일 호출에서 로컬 변수에 포인터를 전달하면 변수를 유지해야하므로 스택 프레임을 제거 할 수 없습니다. C ++에서 로컬 변수 소멸자는 일반적으로 "꼬리"호출이 반환 된 후에 발생합니다. 이는 테일 호출이 아님을 의미합니다.
Steve314

1
@ 마이크-내 요점입니다. 재귀 코딩 스타일을 사용하는 경우 테일 호출 "최적화"없이 스택 오버플로가 오류이므로 코드가 손상 될 수 있습니다. C ++에서는 최적화입니다. 컴파일러가 최적화를 수행하므로 괜찮을 필요는 없지만 신뢰할 수는 없습니다. 재귀 스타일로 자유로이 쓰고 싶지만 스택 깊이 문제에 대해 걱정하지 않으려면 꼬리 호출 제거가 최적화되지 않습니다. 정확도 문제입니다. 재귀가 무언가를 코딩하는 가장 좋은 방법이라면 스택 오버플로에 대해 걱정할 필요가 없습니다.
Steve314

3

원활한 스레드 분기, 함수와 같은 구문이 있지만 별도의 스레드에서 실행되며 처음에 전달되지 않은 데이터에 액세스 할 수 없습니다.

branch foo(data, to, be, processed){
    //code
    return [resulting, data]
}

분기가 호출되면 즉시 핸들을 반환합니다.

handle=foo(here, is, some, data)

작업이 완료되었는지 확인하는 데 핸들을 사용할 수 있습니다.

handle.finished() //True if the execution is complete

실행이 완료되기 전에 결과가 요청되면 메인 스레드는 단순히 대기합니다.

[result, storage]=handle.result()

이것은 고급 멀티 스레딩 시나리오를 다루지는 않지만 여러 코어를 사용하기 쉽게 접근 할 수있는 방법을 제공합니다.


Cilk를 살펴 보라는 C의 매우 깨끗하고 단순한 확장이다 : en.wikipedia.org/wiki/Cilk . 나는 그것이이 있는지 모르는 handle.finished()테스트를하지만, spawnsync병렬 프로그래밍 작업의 90 %에 필요한 모든이다.
j_random_hacker

3
if (cond)
   //do something
else (cond)
   //do something
else (cond)
   //do something
first
   //do something
then
   //do something
else (cond)
   //do something
else
   //do something
end

3 개의 조건 중 하나라도 true로 평가되면 FIRST 및 THEN 블록이 실행됩니다. 첫 번째 블록은 조건부 블록 전에 실행되고 THEN은 조건부 블록이 실행 된 후에 실행됩니다.

FIRST 및 THEN 문 다음의 ELSE 조건부 또는 최종 쓰기는이 블록과 독립적입니다.

다음과 같이 읽을 수 있습니다.

if (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   first()
   //do something
   then()
else (cond)
   //do something
else
   //do something
end


function first()
   //do something
return
function then()
   //do something
return

이 함수들은 단지 읽을 형식입니다. 그들은 범위를 만들지 않을 것입니다. Basic의 gosub / return과 비슷합니다.

토론의 문제로 유용성과 가독성.


2

때로는 첫 번째 반복 중에 다른 작업을 수행 해야하는 루프를 작성하는 경우가 있습니다. 예를 들어 <td> 태그 대신 <th> 태그를 표시합니다.

이 상황을 부울 플래그로 처리합니다. 이 같은:

first = true

while (some_condition)
    if (first)
        do_something
        first = false
    else
        do_something_else

first대부분의 경우 거짓이 될 때마다 모든 반복 의 가치를 확인하는 것은 어리석은 것처럼 보입니다 .

첫 번째 반복에서 다른 루프 본문을 지정하는 반복 옵션이 필요합니다. 별도의 변수가 필요하지 않습니다. 생성 된 코드에는 두 개의 본문 (첫 번째 반복 용과 나머지에 대한 본문)이 있으므로 컴파일 된 코드에는 하나가 필요하지 않습니다.


SO 질문은 비슷한 생각을 가지고 있지만 값에 사용될 "then"연산자가 있습니다. 그렇게하면 중복 코드가 없을 것입니다. 예print(out, first "<th>" then "<td>")
Macneil

1
더 좋은 방법은 반복 +1을 시작하는 것입니다.
Josh K

1
일반적인 경우는 쉼표 구분 기호로 항목을 나열하는 것과 같이 처리 사이에서 반복됩니다. 엄밀히 말하면, if (!first) gimme-a-comma ();그러나 거의 같은 것입니다. 그래도 내가 이의를 제기한다면-적절하게 마무리하면 파이썬 문자열 조인 메소드와 같은 것들이 생길 수 있습니다. 그러나 종종 기본 패턴이 필요하면 기본 루프를 자주 다시 작성할 필요가 없습니다.
Steve314

물론 Josh가 말했듯이 루프에서 첫 번째 항목을 꺼내는 것이 유효합니다. 쉼표로 구분 된 경우 중복 코드를 의미하지만 중복 된 함수 호출 일 수 있습니다. 개인적으로의 비 효율성을 선호 if (!first)하지만 마이크로 최적화 프로그램은 분기 예측 이의 제기를 제기 할 수 있습니다.
Steve314

1
@Barry Brown : 루프의 첫 번째 반복을 풀면 부울 플래그를 확인하는 것보다 빠르거나 빠를 수 있습니다. 괜찮은 분기 예측 변수는 최악의 첫 번째 2 반복에서 잘못 예측할 것입니다. 나는 예측 if (!first)합니다 first.
j_random_hacker

1

[stackoverflow에 대한 내 답변에서 복사]


ignoring -특정 코드 블록에서 발생하는 예외를 무시합니다.

try {
  foo()
} catch {
  case ex: SomeException => /* ignore */
  case ex: SomeOtherException => /* ignore */
}

제어 구문을 무시하면 다음과 같이보다 간결하고 읽기 쉽게 작성할 수 있습니다.

ignoring(classOf[SomeException], classOf[SomeOtherException]) {
  foo()
}

[Scala는 표준 라이브러리의 util.control 패키지에이 (및 기타 많은 예외 처리 제어 구성)를 제공합니다. ]


4
예외는 무시해서는 안됩니다.
Josh K

1
문맥 상 예외는 오류가 아닐 수 있습니다.
Steve314

1
@Josh, @Steve : 예외를 무시하고 싶을 때가 있습니다. 이러한 경우에는 이 스레드 를 참조하십시오 .
missingfaktor

예외는 무언가 잘못되었을 수 있다는 경고입니다. 빈 try..catch블록은 하나입니다. 오류를 인식하고 고의로 무시하도록합니다. 전역 무시에서 코드 덩어리를 던지면 예외가 발생할 때 문제가 발생할 수 있으며 프로그래밍 습관이 열악해질 수 있습니다.
Josh K

@Josh-내가 똑바로 생각하지 않았기 때문에 두 개의 주석을 삭제했습니다. 그러나 이것에 대한 희망은 높습니다. 그 진술이 전 세계적이라면 아마도 동의 할 것입니다. 그러나 그것은 나에게 블록 구조처럼 보입니다. IOW try블록 은 블록 과 같습니다. 단, 나중에 예외 대신 잡는 예외를 나열하고 예외를 무시합니다. 가독성을 높일 수도 있습니다. 예를 들어 공개 파일을 읽기 전에도 누락 된 파일이 오류가 아니라는 것을 독자에게 알려줍니다.
Steve314

1

대신에:

switch(myEnum) {
  case MyEnum.Val1: do1(); ...
  case MyEnum.Val2: do2(); ...
....

파이썬이나 C # 방식으로하십시오 :

action = val2func[myEnum]
action()

스칼라에는 많은 새로운 기능이 있습니다.

마지막으로 Clojure와 같은 언어를 확장하여 추가 기능을 제공 할 수 있습니다.


1
C도 이것을 할 수 있습니다. 그리고 파스칼. 아마도 모든 오래된 70 년대 / 80 년대 / 90 년대 언어 일 것입니다. 함수 배열은 함수 포인터 배열이되지만 큰 문제는 아닙니다. Lisp, ML에서와 같이 익명의 기능을 사용하는 것이 더 쉬운 방법입니다.
Steve314

Steve314-수정-이것은 값을 함수에 매핑하는 사전의 예입니다. 이곳은 70 년대 / 80 년대 / 90 년대의 대부분의 것들보다 약간 깨끗해집니다.
Job

1

두 가지 아이디어가 있습니다.

종종 나는 블록으로 나 자신반복하고 있음을 발견합니다 catch. 이것은 추출 방법을 통해 다소 도움이 될 수 있지만 방법이 매우 짧거나 방법에 적합하지 않은 경우 불필요한 혼란을 유발할 수 있습니다. 따라서 catch블록 을 중첩하는 것이 좋습니다 .

try {
    // Save something
} catch (Exception e) {
    // Something we do for all Exceptions
    catch (ProcessingException e) {
        // Something we do for all Processing exceptions
        catch (DBExcpetion e) {
            // DBExceptions are a subclass of ProcessingException
        }
        catch (BusinessRuleException e) {
            // BusinessRuleExceptions are also a subclass of ProcessingException
        }
    }
    // Something we do after specific sub class Exceptions
 }

웹 프로그래밍에서 나는 종종 종종 이런 식으로 일하는 것을 종종 발견합니다 (이것은 실제 예가 아니기 때문에 가상의 사례를 분석하지 마십시오).

Account a = getSavedAccount();
if (a == null) {
    a = getAccountFromSessionId();
}
if (a == null) {
    a = getAccountFromCookieId();
}
if (a == null) {
    a = createNewAccount();
}

Javascript (잘, ECMAScript 및 아마도 익숙하지 않은 다른 것)에서는 모든 값을 조건으로 평가할 수 있으므로 ||도움이 될 수 있습니다.

var a = getAFromLocation1() || getAFromLocation2() || default;

나는 그것이 어떻게 보이는지 정말 좋아하고 더 많은 언어, 특히 서버 측의 언어가 그것을 지원하기를 바랍니다. (PHP는 조건으로 모든 것을 평가할 수 있지만 값을 유지하는 대신 전체 조건식을 부울로 변환합니다. 파이썬이나 루비에 대해서는 모르겠습니다.) 세 가지 경우보다 소프트웨어 디자인이 잘못되었을 수 있습니다.


파이썬은 당신의 || 평가, 그러나 조건부 표현식 x if c else y구문을 마침내 얻었을 때 발생 하는 주요 이유는 이러한 의미를 사용 ||하고 &&미묘하게 버그가 많은 표현식 때문이었습니다 . IIRC의 일반적인 경우는로 처리되는 응용 프로그램에 유효한 값 (예 : 0) false이므로 잘못된 대체가 대신 사용되었습니다. 그러나 내 대답 WRT와 같은 아이콘 프로그래밍 언어를 참조하십시오 get1() else get2() else default.
Steve314

1

일반화 된 스위치는 위에서 말했다 :

 switch(x){
  predicate1:
     dosomething();
  predicate2:
     dosomethingelse();
 }

하스켈에서 :

  switch' :: a -> [(a -> Bool, b)] -> b
  switch' a [] = undefined
  switch' a (f,b):xs = if f a
                     then b
                      else switch' a xs

0

C #에서는 simple switch () { ... }과 같은 표현식 을 사용하여 확장하고 싶습니다 .

switch (value)
{
  // string-based operators:
  case begins "Maria": // to catch Maria Carey
    break;
  case ends "Washington": // to catch George Washington
    break;
  case like "ph": // to catch Phil, Phillip, Sophie
    break;
  case between "Aaron" and "April": // to catch all names between
    break;

  // use non-static variables in case expression:
  case Dao.GetDefaultBabyName():
    break;

  // continuable cases without breaking
  case "John":
    bonus = 25;
  case "Peter":
    salary = 500;
    break;

  // jumps between cases
  case "Aleron":
    // do something
    break;
  case "Bella":
    // do something
    jump "Aleron";
    break;

}

등등. 번호 또는 다른 유형과 동일 (즉, 지원 IComparable, IConvertible...)

이것은 내 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다.


사건에 대한 추락은 알려진 악이며, 일반적으로 실패하지 않아도 괜찮습니다. 그리고 제정신 프로그래밍에는 점프가 너무 GOTOish입니다. 그러나이 경우 표현과 비 정적을 갖는 것은 멋진 추가 일 것입니다.
CodexArcanum

0

@Macneil이 말한 것처럼 재미있는 질문입니다.

내가 가장 좋아하는 특이한 제어 구조는 (혹은 기침) 발견 된 차등 실행 입니다.

특정 용도로 사용됩니다. 저에게는 압도적 인 사용이 프로그래밍 사용자 인터페이스에 있으며, 이는 중복 데이터를 상응하게 유지 관리하는보다 일반적인 문제의 예입니다. 한편으로는 응용 프로그램 데이터가 있고 다른 한편으로는 UI 컨트롤이 있으며 그와 일치해야합니다. 이것은 "바인딩"처럼 들리지만 실제로는 더 많은 것이 있습니다.

일반적으로 C 또는 C ++에서 매크로로 구현합니다. C #에서는 수동 확장 문으로 수행해야합니다. 그것은 고통이지만 작동합니다.

일단 Lisp 매크로로 구현 한 후에는 매우 깨끗했습니다. 프로그래머 측에서는주의 할 필요가 없습니다. 완전한 파서를 작성하는 데 어려움을 겪고 모든 올바른 것을 생성하면 다른 구조적 언어로 동일한 작업을 수행 할 수 있습니다. 그것은 큰 프로젝트이며, 나는 그것을하지 않았습니다.


0

"전통적인"통제 구조 for는 일하는 사람을 통제하는 것에 관한 것이며, 지배 자본가 엘리트의 부패한 이데올로기에 종속적이다. 그래서 ph0r대신에 다른 제어 구조를 사용합니다. 그것은 for같지만 더 급진적입니다 : 당신은 ph0r양복과 넥타이를 착용 하지 않고 일부 회사 BS를 내뿜을 것입니다. ph0r진짜로 유지합니다.

힘을 싸워라!


0

가장 간단한 for루프

for(100)
{
    //Will run for 100 times
}


for(i)
{
    //Will run for i times while i must be a positive integer
}


for(i as a)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 0 and 
    //scoped within the loop
}


for(i as a=2)
{
    //Will run for i times while i must be a positive integer
    //and a is the incremental loop variable starting from 2 and 
    //scoped within the loop
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.