선언적 프로그래밍의 꿈 [닫기]


26

선언적 프로그래밍의 꿈이 실현되지 않은 이유는 무엇입니까? 방해가되는 구체적인 장애물은 무엇입니까? 간단한 예를 들어 말할 수없는 이유

sort(A) is defined by sort(A) in perm(A) && asc(sort(A))

정렬 알고리즘을 자동으로 가져옵니다. perm순열과 asc오름차순을 의미합니다.


4
그건 그렇고 당신의 특정 예는 이미 사용할 수 있습니다 : gkoberger.github.io/stacksort
Den

3
프롤로그에 대해 들어 보셨습니까? "응답 세트 프로그래밍"을 찾으십시오. 기본 로직에 많은 시스템이 구축되어 있습니다.
schlingel

16
이 질문에 쉽게 대답 할 수 있습니다. 그러한 시스템을 구현하려고 시도하십시오 . 무엇을 성공적으로하지 못했습니까? 당신이 멈춘 것이라도 다른 사람들을 멈췄을 가능성이 높다.
Eric Lippert

4
나는이 질문이 얻는 것보다 더 많은 신용을 얻을 가치가 있다고 생각하고 싶습니다. 언뜻 보면, 간단 하다고 생각할 것입니다 ! 그 뒤에 모든 논리를 프로그래밍해야하며 컴퓨터는 그렇게 똑똑하지 않습니다. ...하지만 다시 돌아와서이 질문에 대해 다시 한 번 살펴보면 다시 한 번 생각할 것 입니다. 간단합니다. 모든 논리를 프로그래밍해야합니다. 컴퓨터가 반드시 가장 날카로운 도구는 아닙니다. 창고에서, 사실-그러나 단순히 표면에 놓여있는 것보다 그 설명에 훨씬 더 깊이가 있습니다.
Panzercrisis

3
정렬 알고리즘에 대한 설명은 선언적입니다. 그러나 효율적이지 않습니다. n!시퀀스의 순열 이 있으며 최악의 경우 알고리즘은 정렬 된 시퀀스를 찾기 위해 모두 시도해야합니다. 계승 시간은 시퀀스를 처리하는 알고리즘만큼이나 나쁘다.
Benjamin Hodgson

답변:


8

아주 좋은 답변이 있습니다. 나는 토론에 기여하려고 노력할 것이다.

Prolog의 선언적, 논리 프로그래밍 주제 에 대해 Richard O'Keefe의 "The Craft of Prolog"라는 저서가 있습니다. 매우 비효율적 인 프로그램을 작성할 수있는 프로그래밍 언어를 사용하여 효율적인 프로그램을 작성하는 것입니다. 이 책에서 저자는 여러 알고리즘의 효율적인 구현 ( "프로그래밍 방법"장에서)을 논의하면서 다음과 같은 접근법을 취합니다.

  • 영어로 문제를 정의하다
  • 가능한 한 선언적인 작업 솔루션을 작성하십시오. 일반적으로, 그것은 당신이 당신의 질문에 가지고있는 것을 거의 정확하게 의미합니다.
  • 거기에서 구현을 개선하여 더 빠르게 구현하십시오.

이 작업을 수행하는 동안 내가 할 수있는 가장 깨달은 (나를 위해) 관찰 :

예, 구현의 최종 버전은 저자가 시작한 "선언적"사양보다 훨씬 효율적입니다. 여전히 매우 선언적이고 간결하며 이해하기 쉽습니다. 그 사이에 일어난 일은 최종 솔루션이 초기 솔루션이 잊어 버린 문제의 속성을 캡처한다는 것입니다.

다시 말해, 솔루션을 구현하는 동안 가능한 한 문제에 대한 많은 지식을 사용했습니다. 비교:

모든 요소가 오름차순으로되도록 목록의 순열을 찾습니다.

에:

정렬 된 목록 두 개를 병합하면 정렬 된 목록이됩니다. 이미 정렬 된 하위 목록이있을 수 있으므로 길이가 1 인 하위 목록 대신 시작 지점으로 사용하십시오.

작은 것을 제외하고 : 당신이 제공 한 것과 같은 정의는 매우 일반적이기 때문에 매력적입니다. 그러나 순열이 조합 문제라는 사실을 의도적으로 무시한다는 느낌을 피할 수는 없습니다. 이것은 우리가 이미 알고있는 것입니다 ! 이것은 비판이 아니라 관찰 일뿐입니다.

실제 질문에 관해서 : 앞으로 나아가는 방법? 글쎄, 한 가지 방법은 우리가 컴퓨터에 선언하는 문제에 대해 많은 지식을 제공하는 것입니다.

내가 실제로 문제를 해결하기 위해 알고있는 최선의 방법은 Alexander Stepanov가 공동으로 저술 한 책인 "Programs of Programming""Mathematics에서 Generic Programming"에 나와 있습니다. 슬프게도이 책의 모든 내용을 요약 (또는 완전히 이해)하는 일은 아닙니다. 그러나 입력의 모든 관련 속성을 미리 알고 있다는 조건 하에서 효율적인 (또는 최적의) 라이브러리 알고리즘 및 데이터 구조를 정의하는 방법이 있습니다. 최종 결과는 다음과 같습니다.

  • 잘 정의 된 각 변환은 이미 적용된 제약 조건 (알려진 속성)을 개선 한 것입니다.
  • 우리는 컴퓨터가 기존의 제약 조건에 따라 최적의 변환을 결정하도록합니다.

왜 아직 일어나지 않았는 지에 관해서는, 컴퓨터 과학은 정말 어린 분야이며, 우리는 여전히 대부분의 참신함을 진정으로 이해하고 있습니다.

추신

"구현을 구체화"함으로써 내가 의미하는 바를 맛 보려면 : Prolog에서 목록의 마지막 요소를 얻는 쉬운 문제를 예로 들어 보자. 정식 선언적 해결책은 다음과 같습니다.

last(List, Last) :-
    append(_, [Last], List).

여기에서 선언적 의미는 다음과 같습니다 append/3.

List1AndList2연결 List1List2

두 번째 인수 이후에 append/3우리는 단 하나 개의 요소 목록을 가지고 있고, 첫 번째 인수는 무시 (밑줄), 우리 (목록의 전면 폐기 원래 목록의 분할 수있다 List1의 맥락에서를 append/3)과 요구가 뒷면 ( List2의 컨텍스트에서 append/3)은 실제로 하나의 요소 만있는 목록입니다. 따라서 마지막 요소입니다.

SWI-Prolog에 의해 제공되는 실제 구현은 , 그러나, 말한다 :

last([X|Xs], Last) :-
    last_(Xs, X, Last).

last_([], Last, Last).
last_([X|Xs], _, Last) :-
    last_(Xs, X, Last).

이것은 여전히 ​​훌륭하게 선언적입니다. 위에서 아래로 읽습니다.

목록의 마지막 요소는 하나 이상의 요소 목록에만 적합합니다. 꼬리 쌍과 목록 머리의 마지막 요소는 머리, 꼬리가 비었을 때 또는 비어 있지 않은 꼬리의 마지막입니다.

이 구현이 제공되는 이유 는 Prolog 의 실행 모델 과 관련된 실제 문제를 해결하기위한 것 입니다. 이상적으로는 사용되는 구현에 차이를 두지 않아야합니다. 마찬가지로 다음과 같이 말할 수 있습니다.

last(List, Last) :-
    reverse(List, [Last|_]).

리스트의 마지막 요소는 반전 된리스트의 첫 번째 요소입니다.

유익하고 선언적인 프롤로그에 대한 결론을 얻지 않으려면 스택 오버플 로의 프롤로그 태그 에서 몇 가지 질문과 답변을 살펴보십시오 .


2
반복적 인 디자인 프로세스를 통해 선언적인 디자인이 간단한 추상화에서보다 구체적인 구현으로 어떻게 발전 할 수 있는지 보여줍니다.
itsbruce

1
@Boris 이것은 좋은 답변입니다. 그 책은 나의 책장에 앉아있다. 아마 내가 열었을 때입니다.
davidk01

1
@ davidk01 더 나은 책 중 하나입니다. Prolog와 프로그래밍에 익숙하다고 가정하지만 프로그래밍에 대한 접근 방식은 실용적이고 철저합니다.
XXX

2
@Boris 나는 예제가 복잡하지 않다는 것을 알고 있지만 반복적 디자인 프로세스의 생산성-선언적 언어의 진정한 강점-매우 실용적 가치는 매우 중요합니다. 선언적 언어는 반복적 인 개선에 대한 명확하고 일관된 재귀 적 접근 방식을 제공합니다 . 명령형 언어는 그렇지 않습니다.
itsbruce

1
"선명하고 선언적인 프롤로그가 무엇 이냐에 대한 결정적이지 않은 토론을하십시오"에 대해 + 1… 우리가 동의하지 않는 경향이 있습니다!
Daniel Lyons

50

논리 언어는 이미이 작업을 수행합니다. 당신이하고있는 것과 마찬가지로 정렬을 정의 할 수 있습니다.

주요 문제는 성능입니다. 컴퓨터는 많은 것들을 계산하는 데 능숙하지만 본질적으로 바보입니다. 컴퓨터가 만들 수있는 모든 "영리한"결정은 프로그래머에 의해 프로그래밍되었습니다. 그리고이 결정은 일반적으로 최종 결과의 모양이 아니라이 최종 결과를 단계별로 달성하는 방법에 의해 설명됩니다.

골렘 의 이야기를 상상해보십시오 . 당신이 그에게 추상적 인 명령을 주려고한다면, 기껏해야 그는 비효율적으로 그것을 할 것이고 최악의 경우 자신이나 다른 사람을 해칠 것입니다. 그러나 원하는 것을 최대한 자세하게 설명하면 작업이 효과적이고 효율적으로 완료 될 것입니다.

사용할 추상화 수준을 결정하는 것은 프로그래머의 임무입니다. 응용 프로그램의 경우 높은 수준으로 진행하여 추상적 인 방식으로 설명하고 성능을 저하 시키거나 낮게 설정하고 10 배 더 많은 시간을 소비하지만 1000 배 더 성능이 뛰어난 알고리즘을 사용 하시겠습니까?


6
Golem גולם이라는 단어는 실제로 "원재료", 즉 기계 / 실체가 존재할 수있는 가장 기본적인 상태를 의미한다는 것을 아는 것이 도움이 될 수 있습니다.
dotancohen

2
선언적 언어는 본질적으로 낮은 수준의 추상화에 장애가되지 않습니다. Haskell과 Standard ML은 서로 다른 방식으로 한 장소에서 유형 / 함수에 대한 간단한 선언적 진술을 작성하고, 별도의 장소에서 다양한 구체적이고 구체적인 기능 구현을 제공하며 유형을 구현에 다른 방법으로 일치시키는 방법을 제공합니다. 한편 OO / 제국 언어의 모범 사례는 이제 고 / 간단한 시작과 구현 세부 사항 추가에 관한 것입니다. 차이점은 FP에서 높은 추상화가 더 쉽고, 낮은 수준이 필수적으로 쉽다는 것입니다.
itsbruce

2
언급 된 언어 중 하나라도 하드 코딩 특정 일치 항목이 아닌 유형의 속성을 기반으로 특정 구현 선택을 자동으로 해결할 수 있으며 OP가 원하는 것을 거의 전달할 수 있습니다. Haskell에서 타입 클래스는이를위한 핵심 도구입니다. 표준 ML에서 펑터.
itsbruce

22
@BAR Golem! = Golum Golem은 유대인 민속에서 온다
Euphoric

10
이 답변에서 나의 테이크 아웃은 내 노트북에 אמת를 쓰는 것입니다.
Dan J

45

Euphoric의 탁월한 요점 외에도 , 우리는 이미 잘 작동하는 많은 장소에서 선언적 언어를 사용하고 있다고 말하고 싶습니다. 즉, 컴퓨터가 실제로 효율적인 코드를 생성 할 수있는 것을 변경하거나 요청하지 않는 상태를 설명합니다 자체적으로 :

  • HTML은 웹 페이지의 내용이 무엇인지 선언합니다.

  • CSS는 웹 페이지에서 다양한 유형의 요소가 어떻게 보일지를 선언합니다.

  • 모든 관계형 데이터베이스에는 데이터베이스의 구조를 선언하는 데이터 정의 언어가 있습니다.

  • SQL은보고자하는 것을 말하고 데이터베이스의 쿼리 플래너는 실제로이를 수행하는 방법을 파악하므로 명령보다 선언에 훨씬 더 가깝습니다.

  • 대부분의 구성 파일 (.vimrc, .profile, .bashrc, .gitconfig)이 크게 선언적인 도메인 별 언어를 사용하고 있다고 주장 할 수 있습니다.


3
GNU Make, XSLT, Angular.js를 선언적으로 사용하는 것으로 널리 사용합니다 (각형은 정의를 약간 밀어 넣지 만).
Mark K Cowan

해당 목록에 정규식을 추가하겠습니다.
Schwern

7
사람들은 선언적인 언어가 일반적 이라는 것을 잊어 버리는 경향이 있습니다 . 그들은 단지 완전한 언어를 다루지 않습니다. 해당 목록에 정규식을 추가하십시오.
slebetman

약간의 비판적이지만 여전히 : 모든 데이터베이스에 DDL이있는 것은 아니며 스키마없는 NoSQL 데이터베이스의 수를 생각하십시오. 모든 관계형 데이터베이스에는 모든 데이터베이스가있을 수 있지만 모든 데이터베이스가있는 것은 아닙니다.
Reinstate Monica-dirkk

1
@dirkk는 그렇게 생각하지 않았습니다. 내 대답을 수정했습니다.
Ixrec

17

추상화가 새다

원하는 것을 선언하는 선언적 시스템을 구현할 수 있으며 컴파일러 또는 해석기는 실행 순서를 알아냅니다. 이론적 인 이점은 '방법'에 대해 생각할 필요가 없으며이 구현을 자세히 설명 할 필요가 없다는 것입니다. 그러나 범용 컴퓨팅의 경우 실제로 어떻게 구현할지를 생각하면서 '어떻게'에 대해 생각하고 모든 종류의 트릭을 작성해야합니다. 그렇지 않으면 컴파일러가 구현을 선택할 수 있기 때문에 매우, 매우, 매우 느리다 (예 : n이 충분한 n! 연산).

특정 예에서, 당신은 얻을 것이다 정렬 알고리즘을 - 당신이 좋은 또는 다소 가능한 하나를 얻을 것을 의미하지 않습니다. 문자 그대로 (컴파일러가 예상 할 수있는) 문자 그대로 구현 한 경우 http://en.wikipedia.org/wiki/Bogosort가 발생하면 더 큰 데이터 세트에는 사용할 수 없습니다. 기술적으로는 정확하지만 수천 개의 숫자를 정렬하려면 영원이 필요합니다. .

일부 제한된 도메인의 경우 SQL과 같은 우수한 구현을 파악하는 데 거의 항상 효과적인 시스템을 작성할 수 있습니다. 특히 잘 작동하지 않는 범용 컴퓨팅의 경우, Prolog로 시스템을 작성할 수 있지만 선언이 명령형 실행 순서로 정확히 어떻게 변환되고 예상 선언의 많은 부분을 잃는지를 시각화해야합니다. 프로그래밍 이점.


당신이 말하는 것은 본질적으로 사실이지만, 인터페이스 / 계약이 당신에게 실행 시간에 대한 보장을 제공하지 않으면 나쁜 성능은 누출의 징후가 아닙니다.
valenterry

3
피터스 (Peters)는 나쁜 퍼포먼스가 누출 추상화의 징후라고 말하지 않고있다. @valenterry. 그는 반대를 말하는 어떤 경우 좋은 성능을 달성하는 것을 구현 세부 사항되어 강제 누출.
itsbruce

2
성능에 어떤 영향을 미치는지 이해하기 위해 구현을 이해해야하기 때문에 추상화가 유출된다고 말하는 것은 오해의 소지가 있다고 생각합니다. 추상화의 목적은 성능에 대해 생각할 필요가 없도록하는 것이 아닙니다.
Doval

1
@jamesqf 선언적 프로그래밍에서는 무언가가 정렬되어 있다고 말하면됩니다. 정렬 순서가 일부 변수 / 속성에 바인딩되도록 선언 할 수 있습니다. 그리고 그렇게 될 것입니다. 새 데이터가 추가되거나 정렬 순서가 변경 될 때마다 명시 적으로 정렬을 호출 할 필요가 없습니다.
hyde

1
@jamesqf 실제로 시도하지 않으면 요점을 실제로 알 수 없습니다 (선언적 아이디어로 연주하기 위해 Qt의 QML을 권장합니다). 명령형 프로그래밍 만 아는 사람이 OOP 또는 기능적 프로그래밍을 실제로 시도하지 않고 이해하려고 노력한다고 상상해보십시오.
hyde

11

계산적 결정 가능성은 선언적 프로그래밍이 쉬운 것처럼 보이지 않는 가장 중요한 이유입니다.

상대적으로 설명하기 쉬운 많은 문제는 결정 불가능하거나 NP- 완전한 복잡성이 해결 된 것으로 입증되었습니다. 이것은 종종 부정적인 클래스와 분류, 계산 및 재귀를 고려할 때 발생합니다.

잘 알려진 일부 도메인에서이를 확인하고 싶습니다.

사용할 CSS 클래스를 결정하려면 모든 CSS 규칙에 대한 지식과 고려가 필요합니다. 새 규칙을 추가하면 다른 모든 결정이 무효화 될 수 있습니다. NP- 완전 문제로 인해 부정적인 CSS 클래스는 의도적으로 언어에 추가되지 않지만 부정적인 클래스가 없으면 CSS 디자인 결정이 복잡해집니다.

(SQL) 쿼리 옵티 마이저 내에서 조인 순서, 사용할 인덱스 및 어떤 메모리를 어떤 임시 결과에 할당 할지를 결정하는 데는 약간의 문제가 있습니다. 이것은 알려진 NP 완료 문제이며 데이터베이스 디자인 및 쿼리 구성을 복잡하게합니다. 데이터베이스 또는 쿼리를 디자인 할 때 디자이너는 쿼리 최적화 프로그램이 수행 할 수있는 작업 및 작업 순서를 알아야합니다. 숙련 된 엔지니어는 주요 데이터베이스 공급 업체에서 사용하는 휴리스틱에 대한 지식이 필요합니다.

구성 파일은 선언적이지만 특정 구성은 선언하기 어렵습니다. 예를 들어 기능을 올바르게 구성하려면 버전 관리, 배포 (및 배포 기록), 가능한 수동 재정의 및 다른 설정과의 충돌 가능성을 고려해야합니다. 구성의 유효성을 올바르게 검사하면 NP-complete 문제가 될 수 있습니다.

결과적으로 이러한 복잡성으로 인해 초보자가 놀라워지고 선언적 프로그래밍의 '미'를 깨뜨리고 일부 엔지니어가 다른 솔루션을 검색하게됩니다. 경험이없는 엔지니어를 SQL에서 NoSQL로 마이그레이션하는 것은 관계형 데이터베이스의 기본 복잡성에 의해 시작되었을 수 있습니다.


2
"NP- 완전 문제로 인해 부정적인 CSS 클래스는 의도적으로 언어에 추가되지 않습니다."
John Dvorak

약간의 연습이지만 부정적인 CSS 선택기를 사용하면 가능한 모든 조합을 시도하여 일치하는지 확인하기 위해 3SAT 문제 (마지막 절이 DOM 임)로 다시 작성할 수 있습니다.
Dibbeke

1
작은 추가. CSS 3과 4에서는 네거티브 셀렉터가 허용되지만 의사 클래스는 중첩되지 않을 수 있습니다.
Dibbeke

2

우리는 디지털 로직의 검증에 잘 사용되는 프로그래밍 언어의 선언에 차이 가 있습니다.

일반적으로 디지털 로직은 레지스터 간 신호의 로직 레벨이 정의 되는 레지스터 전송 레벨 (RTL)에서 설명 됩니다. 보다 추상적이고 선언적인 방식으로 정의 된 속성을 추가하고 있는지 확인합니다.

보다 선언적인 언어 / 언어 하위 집합 중 하나 를 속성 사양 언어의 PSL 이라고 합니다. 예를 들어, 여러 클록 사이클에 걸쳐 시프트 및 추가의 모든 논리 연산을 지정해야하는 승수 의 RTL 모델을 테스트 할 때 ; 의 방식으로 속성을 작성할 수 있습니다 assert that when enable is high, this output will equal the multiplication of these two inputs after no more than 8 clock cycles. 그런 다음 PSL 설명을 시뮬레이션에서 RTL과 함께 확인하거나 PSL을 RTL 설명을 위해 공식적으로 보유 할 수 있습니다.

보다 선언적인 PSL 모델은 RTL 설명과 동일한 동작을 설명하지만 RTL에 대해 자동으로 확인하여 동의하는지 여부를 충분히 다른 방식으로 설명합니다.


1

대부분 문제는 데이터를 모델링하는 방법입니다. 선언적 프로그래밍은 여기서 도움이되지 않습니다. 명령형 언어에는 이미 많은 작업을 수행하는 수많은 라이브러리가 있으므로 호출 할 내용 만 알면됩니다. 특별한 방법 으로이 선언적 프로그래밍을 고려할 수 있습니다 (아마도 이것의 가장 좋은 예 는 Java 8의 Stream API 입니다 ). 이를 통해 추상화가 이미 해결되었으며 선언적 프로그래밍이 필요하지 않습니다.

또한, 논리 프로그래밍 언어는 이미 원하는대로 정확하게 수행합니다. 문제는 성능이라고 말할 수 있지만, 오늘날의 하드웨어와이 분야의 연구를 통해 프로덕션 환경에 적합하도록 상황을 개선 할 수 있습니다. 실제로 Prolog 는 AI에 사용되지만 학계에서만 믿습니다.

범용 프로그래밍 언어에 적용됩니다. 도메인 특정 언어의 경우 선언적 언어가 더 좋습니다. SQL이 가장 좋은 예일 것입니다.


3
데이터 모델링? 명령이 최악 인 것을 골랐습니다. Haskell 및 ML과 같은 선언적 기능 언어는 데이터 모델링에 탁월합니다. 예를 들어 대수 데이터 형식과 재귀 데이터 형식은 일반적으로 한 줄 또는 두 줄로 포괄적으로 정의 할 수 있습니다. 물론 작성해야 할 함수가 있지만 해당 코드는 형식 정의에서 필연적으로 따르며 이에 의해 제한됩니다. 기괴한 비교를합니다.
itsbruce

1
@itsbruce 가장 실제 데이터는 ADT에 쉽게 매핑되지 않습니다. 대부분의 데이터베이스 작동 방식을 생각하십시오. Prolog-Erlang으로서 당신은 맞습니다, 그들은 다른 언어입니다. 하나는 기능적이지만 다른 하나는 논리적이지만 전체 비교를 삭제하면 가장 좋습니다.
m3th0dman

1
@ m3th0dman 데이터베이스는 단지 수많은 튜플 / 레코드입니다. Haskell은 레코드가 부족하지만 튜플이 있고 ML에는 두 가지 모두가 있기 때문에 약간 무섭습니다. 그리고 Haskell의 경우 새로운 의사 레코드 데이터 유형을 선언하는 데 필요한 상용구의 양은 평균 정적 유형 OOP 언어로 가짜 구조를 만드는 데 걸리는 것보다 훨씬 적습니다. 대부분의 데이터가 ADT에 쉽게 매핑되지 않는 방법에 대해 자세히 설명 할 수 있습니까?
Doval

1
@ m3th0dman Ah, 이것이 바로 데이터베이스 스키마가 작업에 적합한 명령형 언어로 정의 된 이유입니다. 아뇨, 그건 선언적인 DDL입니다. 실제로 전체 데이터 모델링 프로세스는 응용 프로그램 을 구현하는 언어가 아니라 데이터 흐름 및 구조와 함께 작동 하는 응용 프로그램 과 관련 이 있습니다. 때로는 언어의 OO 기능 및 해당 ORM이 지원하는 기능과 일치하도록 왜곡되어 있지만 일반적으로 기능이 아니라 나쁜 것입니다. 선언적 언어는 개념적 / 논리적 데이터 모델을 표현하는 데 더 적합합니다.
itsbruce

1
@itsbruce 나는 절차 적 패러다임이 데이터를 정의 할 때 선언적 패러다임보다 낫다고 말하지 않았다. 나는 선언적 패러다임이 절차 적 것 (범용 언어)보다 나쁘지 않다고 말하고 있었다. 데이터 조작과 관련하여 SQL의 선언 부분은 실제 응용 프로그램으로는 충분하지 않습니다. 그렇지 않으면 아무도 절차 적 확장을 발명하고 사용하지 않았을 것입니다. 이 기사에 관해서는, 나는 그것이 Brooks와 모순되는 추상과는 일치하지 않는다. 그는 실제 프로젝트에서 아이디어를 구축했지만 그 사람들은 이론을 입증하기 위해 뛰어난 것을 만들지 않았습니다.
m3th0dman 2016 년

0

다음과 같이 보일 것입니다 .. {(whatever => 파일 읽기 및 URL 호출) | url을 호출하고 파일을 읽습니다.} 그러나 이는 수행 할 조치이며 결과적으로 시스템 상태가 변경되지만 소스에서는 분명하지 않습니다.

선언문은 유한 상태 기계 및 해당 전이를 설명 할 수 있습니다. FSM은 유일한 조치가 상태를 다음 상태로 변경하는 경우에도 조치가없는 선언의 반대와 같습니다.

이 방법을 사용하면 하나의 전환이 아니라 여러 전환에 적용되는 술어로 전환 및 조치를 지정할 수 있다는 장점이 있습니다.

나는 이것이 조금 이상하게 들린다는 것을 알고 있지만 2008 년에는이 방법을 사용하는 프로그램 생성기를 작성했으며 생성 된 C ++은 소스의 2 ~ 15 배입니다. 이제 20,000 줄의 입력에서 75,000 줄 이상의 C ++을 가지고 있습니다. 일관성과 완전성이라는 두 가지가 있습니다.

일관성 : 동시에 사실 일 수있는 두 술어는 x = 8 및 x = 9 또는 다른 다음 상태와 같이 일관성없는 조치를 내포 할 수 없습니다.

완전성 : 모든 상태 전이에 대한 논리가 지정됩니다. 이는 2 개 이상의 N 상태 인 N 개의 하위 상태를 가진 시스템을 확인하기 어려울 수 있지만 모든 것을 확인할 수있는 흥미로운 조합 방법이 있습니다. 1962 년에 이런 종류의 조건부 코드 생성 및 조합 디버그를 사용하여 7070 시스템에 대한 시스템 1 단계를 작성했습니다. 8,000 개 라인 중 첫 번째 릴리스 이후의 버그 수는 영원했습니다!

12,000 라인 인 2 단계는 처음 2 개월 동안 60 개가 넘는 오류가있었습니다. 이것에 대해 훨씬 더 말할 것이 있지만 효과가 있습니다. 자동차 제조업체가이 방법을 사용하여 펌웨어를 확인하면 현재 볼 수있는 오류가 표시되지 않습니다.


1
이것은 실제로 원래 질문에 대답하지 않습니다. 일관성과 완전성은 대부분의 프로그래밍이 선언적이 아니라 여전히 절차 적이라는 사실에 어떻게 영향을 미칩니 까?
Jay Elston

첫 단락은 질문 자체가 아니라 arnaud의 답변 프로그래머 의 요점에 대한 답변 인 것 같습니다 . 댓글이 있어야합니다 (내 화면에서 귀하의 답변이 더 이상 그의 아래에 있지 않습니다). 내가 생각하는 답의 나머지 부분은 선언 적은 양의 코드가 해당 필수적의 많은 양의 코드를 생성 할 수있는 방법의 그림이지만이 명확하지 않다. 당신의 대답은 특히 두드러진 점들과 관련하여 약간의 정리가 필요합니다.
itsbruce

-3

모든 것을 선언적으로 표현할 수있는 것은 아닙니다.

종종 실행 흐름 을 명시 적 으로 제어 하려고 합니다.

예를 들어 다음 의사 코드 : if whatever read a file call an URL else call an URL write a file 어떻게 선언적으로 표현 하시겠습니까?

물론, 이국적인 방법이있을 것입니다. 모나드 처럼 . 그러나 이들은 일반적으로 절차 적 부분보다 더 번거롭고 복잡하며 직관적이지 않습니다.

환경 / 시스템과의 "상호 작용"이 선언적 이지 않다는 사실로 요약됩니다 . I / O와 관련된 모든 것은 본질적으로 절차 적입니다. 언제 어떻게해야하며 어떤 순서로해야하는지 정확히 알려야합니다.

선언은 전적으로 계산과 관련된 모든 것에 적합합니다. 거대한 함수처럼 X를 넣고 Y를 얻습니다. 훌륭합니다. 예를 들어 HTML, 입력은 텍스트, 출력은 브라우저에 표시됩니다.


2
나는 이것을 사지 않습니다. 왜 예입니다 되지는 선언적? 그것은 인 if/ else,이 경우에 무엇을 것 같은 선언적 다른 모습? 그것은 확실히 아니다 read/ write/ call(당신이 그들에 싸여있어 의미하는 경우 값들이있는 거 좋은 선언적 목록 있기 때문에, 부품 {...; ...}, 왜 그들이에 싸여있어 의미하지는 [..., ...]목록 그냥 무료 monoids 있습니다, 물론?); 다른 많은 사람들도 그렇게 할 것입니다. 모나드가 왜 관련이 있는지 모르겠습니다. 그들은 단지 API입니다. Haskell은 스트림에서 모나드 (manad)를 사용하여 수동 구성을 지원했지만 논리 언어는 자동으로 목록을 작성할 수 있습니다.
Warbo

2
Monads 만 -1. 1. 그들은 이국적이지 않습니다 (목록과 세트는 Monads이며 모두가 사용합니다). 2. 그들은 (하스켈 특정 순서로 수행 할 것을 강요하고 무관 표기법 보이는 명령형이 아닌)입니다. 선언적 / 기능적 언어는 관계 및 종속성을 지정합니다. 함수 X에 입력 Y가 필요한 경우 X가 Y보다 먼저 생성됩니다. 종속성을 올바르게 가져 오면 적절한 이벤트 시퀀스가 ​​자체적으로 정의됩니다. 많은 상호 작용이 한 세트의 시퀀스가 ​​아닌 이벤트 중심입니다. 선언적 언어는 이벤트에 대한 반응을 어렵게 만들지 않습니다.
itsbruce

게으름은 그중 일부를 복잡하게하지만 게으름은 선언적 언어의 정의의 일부가 아니며 대부분이 그것을 사용하지 않습니다. 그렇게하는 사람들에게는 평가를 보장하는 방법은 모나드와 아무 관련이 없습니다. 선언적 언어가 추상 계산이 아닌 상호 작용에 독점적으로 사용되는 예를 보려면 순서를 지정하지 않지만 올바른 일이 순서대로 발생하는지 확인하려면 꼭두각시 DSL을 살펴보십시오. 필수 언어만이 아니라 보너스가 있습니다.
itsbruce

1
@itsbruce 예제 외에도 반응 형 프로그래밍은 선언적인 것으로 간주되며 환경과의 상호 작용에 관한 것입니다.
Maciej Piechotka
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.