나는 Stephen Wolfram의 열렬한 팬이지만 그는 분명히 자신의 경적을 너무 부끄럽지 않은 사람입니다. 많은 참고 문헌에서 그는 Mathematica를 다른 상징적 프로그래밍 패러다임으로 칭찬합니다. 저는 Mathematica 사용자가 아닙니다.
내 질문은 :이 상징적 프로그래밍은 무엇입니까? 기능적 언어 (예 : Haskell)와 어떻게 비교됩니까?
답변:
Mathematica의 기호 프로그래밍은 검색 및 바꾸기 규칙을 지정하여 프로그래밍하는 검색 및 바꾸기 시스템으로 생각할 수 있습니다.
예를 들어 다음 규칙을 지정할 수 있습니다.
area := Pi*radius^2;
다음에을 (를) 사용할 때 area
으로 대체됩니다 Pi*radius^2
. 이제 새 규칙을 정의한다고 가정합니다.
radius:=5
당신이 사용할 때마다 지금 radius
, 그것은으로 다시거야 5
. 당신이 평가하는 경우 area
그것은으로 다시거야 Pi*radius^2
에 대한 규칙을 다시 작성하는 트리거 radius
그리고 당신은 얻을 것이다 Pi*5^2
중간 결과. 이 새 양식은 ^
작업 에 대한 기본 제공 다시 쓰기 규칙을 트리거 하므로식이 Pi*25
. 이 시점에서 적용 가능한 규칙이 없기 때문에 다시 쓰기가 중지됩니다.
대체 규칙을 함수로 사용하여 함수형 프로그래밍을 에뮬레이트 할 수 있습니다. 예를 들어, 추가하는 함수를 정의하려면 다음을 수행 할 수 있습니다.
add[a_,b_]:=a+b
지금 add[x,y]
으로 다시 작성됩니다 x+y
. 숫자 a, b에만 적용하도록 추가하려면 대신 할 수 있습니다.
add[a_?NumericQ, b_?NumericQ] := a + b
이제 규칙 add[2,3]
을 2+3
사용하여 다시 작성된 다음에 5
대한 기본 제공 규칙을 사용 +
하는 반면 add[test1,test2]
변경되지 않은 상태로 유지됩니다.
다음은 대화 형 대체 규칙의 예입니다.
a := ChoiceDialog["Pick one", {1, 2, 3, 4}]
a+1
여기서는으로 a
바뀌고 ChoiceDialog
팝업 된 대화 상자에서 사용자가 선택한 숫자로 대체되어 수량을 모두 숫자로 만들고 대체 규칙을 트리거합니다 +
. 여기서는 ChoiceDialog
"ChoiceDialog [일부 항목]를 사용자가 클릭 한 버튼의 값으로 교체"라는 줄을 따라 기본 제공되는 교체 규칙입니다.
True
또는 을 생성하기 위해 규칙 재 작성을 거쳐야하는 조건을 사용하여 규칙을 정의 할 수 있습니다 False
. 예를 들어 새로운 방정식 풀이 방법을 발명했지만 방법의 최종 결과가 양수일 때만 작동한다고 가정 해 보겠습니다. 다음 규칙을 수행 할 수 있습니다.
solve[x + 5 == b_] := (result = b - 5; result /; result > 0)
여기서는 solve[x+5==20]
15로 대체되지만 solve[x + 5 == -20]
적용되는 규칙이 없기 때문에 변경되지 않습니다. 이 규칙이 적용되지 않도록하는 조건은 /;result>0
입니다. Evaluator는 기본적으로 규칙 적용의 잠재적 출력을 살펴보고 계속 진행할지 여부를 결정합니다.
Mathematica의 평가자는 해당 기호에 적용되는 규칙 중 하나로 모든 패턴을 탐욕스럽게 다시 작성합니다. 때로는 더 세밀하게 제어하고 싶을 때가 있습니다. 그런 경우 자신의 규칙을 정의하고 다음과 같이 수동으로 적용 할 수 있습니다.
myrules={area->Pi radius^2,radius->5}
area//.myrules
myrules
결과 변경이 중지 될 때까지에 정의 된 규칙이 적용됩니다 . 이것은 기본 평가자와 매우 유사하지만 이제 여러 규칙 세트를 가지고 선택적으로 적용 할 수 있습니다. 고급 예제 는 일련의 규칙 애플리케이션을 검색하는 Prolog와 유사한 평가자를 만드는 방법을 보여줍니다.
당신이 (의 메이크업에 사용 티카의 기본 평가를 사용해야하는 경우에 현재 매스 매 티카 버전 중 하나 단점은 온다 Integrate
, Solve
등) 및 평가의 변경 기본 순서로합니다. 그것은 가능하지만 복잡합니다 . 그리고 저는 기호 프로그래밍의 일부 향후 구현이 평가 시퀀스를 제어하는 더 우아한 방법을 가질 것이라고 생각합니다.
Solve
은 단지 또 다른 재 작성 규칙 이라고 생각할 수 있습니다 . Mathematica가 풀 수없는 방정식을 제공하면 Solve[hard_equations]
그대로 남아 있으며이 경우에 적용되는 Solve[hard_equations]
사용자 지정 Solve
규칙을 정의 할 수 있습니다 . 이 경우에는 /를 사용한다고 생각합니다. "Mathematica의 방법으로 풀 수있는 모든 방정식"에 대한 패턴을 정의하는 조건부, 따라서 하드 방정식의 경우 기본 제공 규칙이 적용되지 않고 Solve
원래 형식으로 유지됩니다.
"기호 프로그래밍"이라는 말을 들었을 때 LISP, Prolog 및 (예) Mathematica가 즉시 떠 오릅니다. 나는 상징적 프로그래밍 환경을 프로그램 텍스트를 표현하는 데 사용되는 표현식이 기본 데이터 구조이기도 한 것으로 특징 지을 것입니다. 결과적으로 데이터를 코드로 쉽게 변환하거나 그 반대로 변환 할 수 있기 때문에 추상화를 기반으로 추상화를 구축하는 것이 매우 쉬워집니다.
Mathematica는이 기능을 많이 활용합니다. LISP 및 Prolog (IMHO)보다 훨씬 더 많습니다.
기호 프로그래밍의 예로 다음 이벤트 시퀀스를 고려하십시오. 다음과 같은 CSV 파일이 있습니다.
r,1,2
g,3,4
나는 그 파일을 다음에서 읽었습니다.
Import["somefile.csv"]
--> {{r,1,2},{g,3,4}}
결과 데이터 또는 코드입니까? 둘 다입니다. 파일을 읽은 결과 데이터이지만 해당 데이터를 구성하는 표현식이기도합니다. 그러나 코드가 진행됨에 따라이 표현식은 평가 결과가 단순히 그 자체이기 때문에 비활성입니다.
이제 결과에 변환을 적용합니다.
% /. {c_, x_, y_} :> {c, Disk[{x, y}]}
--> {{r,Disk[{1,2}]},{g,Disk[{3,4}]}}
세부 사항을 고려하지 않고 발생한 모든 것은 Disk[{...}]
각 입력 줄의 마지막 두 숫자를 둘러싼 것입니다. 결과는 여전히 데이터 / 코드이지만 여전히 비활성입니다. 또 다른 변화 :
% /. {"r" -> Red, "g" -> Green}
--> {{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}
예, 여전히 비활성입니다. 그러나 놀랍게도이 마지막 결과는 Mathematica의 그래픽 용 기본 제공 도메인 별 언어의 유효한 지시문 목록입니다. 마지막 변화와 일이 시작됩니다.
% /. x_ :> Graphics[x]
--> Graphics[{{Red,Disk[{1,2}]},{Green,Disk[{3,4}]}}]
사실, 당신은 그 마지막 결과를 보지 못할 것입니다. 통사론 적 설탕의 서사적 디스플레이에서 Mathematica는 빨간색과 녹색 원의 그림을 보여줍니다.
그러나 재미는 여기서 끝나지 않습니다. 그 모든 통 사적 설탕 아래에는 여전히 상징적 표현이 있습니다. 다른 변환 규칙을 적용 할 수 있습니다.
% /. Red -> Black
프레스토 악장! 빨간색 원이 검은 색이되었습니다.
상징적 프로그래밍을 특징 짓는 것은 이러한 종류의 "기호 추진"입니다. Mathematica 프로그래밍의 대부분은 이러한 특성을 가지고 있습니다.
심볼릭 프로그래밍과 함수형 프로그래밍의 차이점을 자세히 다루지는 않겠지 만 몇 가지 언급을하겠습니다.
"표현식 변환 만 사용하여 모든 것을 모델링하려고하면 어떻게 될까요?"라는 질문에 대한 대답으로 기호 프로그래밍을 볼 수 있습니다. 반대로 함수형 프로그래밍은 "함수 만 사용하여 모든 것을 모델링하려고하면 어떻게 될까요?"에 대한 대답으로 볼 수 있습니다. 심볼릭 프로그래밍과 마찬가지로 함수형 프로그래밍을 사용하면 추상화 계층을 쉽게 빠르게 구축 할 수 있습니다. 여기서 제가 제시 한 예제는 기능적 반응 애니메이션 접근 방식을 사용하여 Haskell에서 쉽게 재현 할 수 있습니다. 함수형 프로그래밍은 함수 구성, 상위 수준 함수, 결합 자, 함수로 할 수있는 모든 멋진 일에 관한 것입니다.
Mathematica는 기호 프로그래밍에 최적화되어 있습니다. 기능적 스타일로 코드를 작성하는 것은 가능하지만 Mathematica의 기능적 특징은 실제로 변환에 대한 얇은 베니어 일뿐입니다 (그리고 그에 대한 누출 된 추상화, 아래 각주 참조).
Haskell은 함수형 프로그래밍에 최적화되어 있습니다. 기호 스타일로 코드를 작성하는 것은 가능하지만 프로그램과 데이터 의 구문 표현이 상당히 다르므로 경험이 차선책이 된다는 점을 의심 할 것 입니다.
결론적으로, 나는 함수형 프로그래밍 (하스켈로 표현한)과 상징적 프로그래밍 (Mathematica로 표현한) 사이에 차이가 있다고 주장합니다. 한 사람이 두 가지를 모두 공부한다면, 하나만 공부하는 것보다 훨씬 더 많은 것을 배울 것이라고 생각합니다.
그래, 새는. 예를 들면 다음과 같습니다.
f[x_] := g[Function[a, x]];
g[fn_] := Module[{h}, h[a_] := fn[a]; h[0]];
f[999]
WRI에 정식으로보고하고 승인했습니다. 응답 : Function[var, body]
( Function[body]
괜찮습니다) 의 사용을 피하십시오 .
Function[var, body]
? 문서에서 권장되므로 이상합니다 ...
Function[var, body]
. 왜 이것이 고칠 수 없는지에 대한 설명은 제공되지 않았지만, Function
1.0 이후로 등장한 이후 게임 후반부에 동작을 변경하는 것은 재앙이 될 것이라고 추측합니다 . 문제는 여기 에 (약간) 자세히 설명되어 있습니다 .
Function
원칙적으로도 자신을 포함하여 내부 범위 지정 구문의 바인딩을 존중하지 않는 Rule
and 의 현재 침입 의미로도 치료할 수 있는지조차 확신 할 수 RuleDelayed
없습니다 . 이 현상은 날이 이상이 부동산에 관한 보인다 과 특히보다는, . 그러나 어느 쪽이든, 나는 이것을 변경하는 것이 지금 매우 위험하다는 데 동의합니다. 사용해서는 안되기 때문에 안타깝습니다. 이러한 버그는 대규모 프로젝트에서 잡기가 거의 불가능합니다. Rule
RuleDelayed
Function
Function[var,body]
다른 사람들이 이미 언급했듯이 Mathematica는 많은 용어를 다시 작성합니다. 아마도 Haskell이 최고의 비교 는 아니지만 Pure 는 기능적인 용어 재 작성 언어입니다 (Haskell 배경을 가진 사람들에게 친숙 할 것입니다). 용어 재 작성에 대한 Wiki 페이지를 읽으면 몇 가지 사항을 알 수 있습니다.
기호는 기능과 대조되어서는 안되며 수치 프로그래밍과 대조되어야합니다. 예를 들어 MatLab 대 Mathematica를 고려하십시오. 행렬의 특성 다항식을 원한다고 가정합니다. Mathematica에서 그렇게하려면 단위 행렬 (I)과 행렬 (A) 자체를 Mathematica로 가져올 수 있습니다.
Det[A-lambda*I]
그리고 나는 특성 다항식을 얻을 것입니다 (아마 특성 다항식 함수가 있다는 사실은 신경 쓰지 마십시오), 반면에 MatLab에 있었다면 기본 MatLab으로 할 수 없었습니다 (아마 특성 다항식이 있다는 것은 신경 쓰지 마십시오) 함수)는 유한 정밀도 수를 계산하는 데 능숙하며 거기에 임의의 람다 (우리의 기호)가있는 것은 아닙니다. 추가 기능 Symbolab을 구입 한 다음 람다를 자체 코드 줄로 정의한 다음이를 작성해야합니다 (여기서 A 행렬을 유한 정밀도 십진수 대신 유리수의 행렬로 변환합니다). , 그리고 이와 같은 작은 경우에는 성능 차이가 눈에 띄지 않을 수 있지만 상대 속도 측면에서 Mathematica보다 훨씬 느릴 것입니다.
이것이 차이입니다. 기호 언어는 완벽한 정확도로 계산을 수행하는 데 관심이 있으며 (종종 수치가 아닌 유리수를 사용함) 반면에 수치 프로그래밍 언어는 수행해야 할 대부분의 계산에 매우 능숙하며 경향이 있습니다. 그들이 의미하는 수치 연산에서 더 빠르기 위해 (MatLab은 C ++ 등을 제외한 더 높은 수준의 언어와 관련하여 이와 관련하여 거의 타의 추종을 불허합니다) 기호 연산에 열악합니다.