태그 보관물: declarative-programming

declarative-programming

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

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

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

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



답변

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

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|_]).

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

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


답변

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

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

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

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


답변

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

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

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

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

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

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


답변

추상화가 새다

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

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

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


답변

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

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

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

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

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

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

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


답변

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

일반적으로 디지털 로직은 레지스터 간 신호의 로직 레벨이 정의 되는 레지스터 전송 레벨 (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에 대해 자동으로 확인하여 동의하는지 여부를 충분히 다른 방식으로 설명합니다.


답변

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

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

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