익명 함수의 귀속 (2)
n개 이상의 원소가 없는 목록은 아래의 익명 함수를 사용하여 계산할 수 있습니다.좀 그렇긴 한데 귀환까지는 아직 거리가 멀어요.
((lambda(mk-length)
(lambda(lat)
((mk-length
(mk-length -------> n mk-length
......
(mk-length infinity))...) lat)))
(lambda(length)
(lambda(lat)
(cond
((null? lat) 0)
(else
(+ 1 (length (cdr lat))))))))
만약 n이 0이라면 우리는 mk-length-0을 얻게 될 것이다
((lambda(mk-length)
(mk-length infinity))
(lambda(length)
(lambda(lat)
(cond
((null? lat) 0)
(else
(+ 1 (length (cdr lat))))))))
전편에서 알 수 있듯이 인피니티의 의미는 절대 호출하지 말라는 것이기 때문에 사실 인피니티가 어떤 함수인지는 우리에게 아무런 영향을 주지 않는다.그러니까 우리가 마음대로 바꿀 수 있다는 거야.
우리 는 mk-length 로 인피니티 를 바꾸었다
(lambda(mk-length)(mk-length mk-length)------>infinity를 mk-length(lambda(length)(lambda(cond--------->length-length 함수로 대체하고, 최종적으로 mk-length 형삼((null?lat)0)(else(+1(cdr lat))))))))))))
length-length를 대입한 다음 다음 다음 코드를 확장합니다.
((lambda(length) (lambda(lat) (cond ----------> length-length ((null? lat) 0) (else (+ 1 (length (cdr lat))))))) (lambda(length) (lambda(lat) (cond ----------> length-length ((null? lat) 0) (else (+ 1 (length (cdr lat))))))))
우리는 이어서length-length를length-length에 대입하고,계속(lambda(lat)(cond((null?lat)0)(else(+1(((lambda(length)(lambda)(cond -------------------------->length-length로 length 인삼을 교체했다.(null?lat)0)(else (+ 1 (length (cdr lat))))))) (cdr lat))))))
최종 전개 후 함수의 논리를 살펴봅시다.목록이 비어 있으면 0을 되돌려줍니다. 그렇지 않으면 1 + (length-length (cdr lat) 를 되돌려줍니다.
우리는length-length가 고급 함수라는 것을 알고 있다. 그 매개 변수는 하나의 함수이고, 되돌아오는 것은 목록을 매개 변수로 하는 또 다른 함수이다.그래서 (length-length(cdr lat)) 틀림없이 잘못 보고할 것이다.그래서 이 함수와length-0은 등가이다.이것 또한 우리가 mk-length로 인피니티를 대체하는 것이 함수의 의미에 아무런 영향을 미치지 않는다는 것을 검증했다.
이렇게 교체하는 것은 무슨 의의가 있습니까?우리는 인피니티의 의미를 고려하고 있다.우리는 이 함수가 목록의 길이를 계산하는 데 아무런 작용이 없다는 것을 알고 있다. 이 함수에 도달하기 전에 목록의 길이를 계산해야만 목록의 길이를 정확하게 얻을 수 있다.위에서 length-length를length-length에 대입한 결과를 다시 한 번 살펴보자. 얻은 것은 0개의 원소 목록 길이만 계산할 수 있는 함수이다.만약 우리 함수가 인피니티 위치에 도착했을 때 새로운length-0 함수를 생성할 수 있다면 무한히 호출할 수 있지 않겠습니까?우리는 임의의 길이 목록을 계산하는 함수를 얻지 않았습니까?
우리 mk-length-0 전개 전 상태로 돌아가자.
(lambda(mk-length)(mk-length mk-length)-------->인피니티를 mk-length(lambda(mk-length)로 바꾸었다----->우리는 형삼 이름을 바꾸었다.이것은 함수에 아무런 영향을 미치지 않습니다 (lambda (lat) (cond --------> length-length 함수, 최종적으로 mk-length형 참조 ((null?lat) 0) (else (+ 1 (mk-length (cdr lat)))))))))))))))))))))))))))
위에 녹색이 표시된 곳을 주의해라.우리가 지금 해야 할 일은 함수가 그곳에 도착하면 0원소 목록의 길이만 계산할 수 있는 새로운 함수를 얻는 것이다.이렇게 하면 함수는 우리가 목록의 길이를 계산할 때까지 무한히 먼저 갈 수 있다.위 함수 중의 mk-length는 최종적으로length-length로 대체되고, (length-length length-length)는 우리 위의 전개 과정에 따라 0원소의 목록만 계산할 수 있는 함수이다.그래서 우리는 녹색이 표시된 곳을 (mk-length mk-length)로 바꾸면 임의의 목록 길이를 계산하는 함수를 얻을 수 있다.코드는 다음과 같습니다.
((lambda(mk-length) (mk-length mk-length)) (lambda(mk-length) (lambda(lat) (cond ((null? lat) 0) (else (+ 1 ((mk-length mk-length)(cdr lat))))))))
이렇게 해서 우리는 임의의 목록 길이를 계산해 낼 수 있는 함수를 얻었다.근데 이 함수는 귀속함수 같지 않아요.우리 변환해서 (mk-length mk-length) 꺼내자.함수식 프로그래밍 경험에 따르면 일단 일부 코드를 추상화하면 반드시 새로운 함수를 도입해야 한다.우리가 얻은 새로운 함수는 다음과 같다.
(lambda(mk-length)(mk-length mk-length)(lambda(mk-length)((lambda(length)-------------->새로 추상적으로 나온 함수(lambda(lat)(cond((null?lat)0)0)(else(+1(length(cdr lat)))))))))))(mk-length mk-length mk-length)))))))))))
위에 색을 표시한 코드를 보면 진정한 귀속 함수 같지 않습니까?위의 코드를 실행하면 창고가 넘칠 때까지 되돌릴 수 없습니다.원인은 추출된 (mk-length mk-length)에서 나온다.schemer는 표현식을 계산할 때, 먼저 서브 표현식을 구한 다음에 전체 표현식을 계산한다.그래서 함수는 (mk-length mk-length)의 값을 구하려고 시도하지만, 매개 변수를 직접 바꾸어 구하면 무한한 귀속을 일으킬 수 있음을 발견할 수 있다.여기에 작은 기교가 하나 있는데, 바로 '게으른 계산' 의 한 용법이다.우리가 관찰한 (mk-length mk-length)은 하나의 매개 변수만 있는 함수(위에서 우리가 전개한 최종 형태)를 되돌려준다.그래서 (mk-length mk-length)와 아래의 표현식은 등가이다.
(lambda(x) ((mk-length mk-length) x))
여기에lisp에서 코드가 데이터라는 사상을 구현했으니 잘 체득하세요.이 표현식은 진정으로 매개 변수를 전달할 때만 진정으로 계산할 수 있다.그래서 무한귀속 문제가 생기지 않는다.다음 코드는 이 표현식(mk-length mk-length)으로 대체합니다.
(lambda(mk-length)(mk-length mk-length)(lambda(mk-length)(lambda(length)(lambda(lat)(cond((null?lat)0)0)0))------------->진짜 귀속 함수 같은 부분(else(+1(length(cdr lat)))))))))))(lambda(x)------------------>교체됨(mk-length mk-length)((mk-length mk-length) x))
지금은요, 우리는 진정으로 돌아가는 부분과 같은 부분을 다시 추출해 봅시다.
(lambda(len)((lambda(mk-length)(mk-length) (mk-length))(lambda(mk-length)(f(lambda(x)((mk-length mk-length) x)))))))))(lambda(lat)(cond-------------------------------------------------------------------------------------------------------------->매개 변수(null? lat)(lense) (lense) 0)(lelse)(lels(+ 1 (length(cdr lat))))))))
지금 우리는 주로 위에 노란색이 표시된 부분을 살펴보자.우리는 이 부분과 진정으로 목록의 길이를 구하는 논리가 이미 완전히 분리되었다는 것을 발견했다.녹색 표지 부분은 목록의 길이를 구하는 위귀환이다.왜 위귀환인가요?length는 익명 함수의 매개 변수일 뿐이기 때문에, 우리가 진정한 함수 이름을 얻을 수 없을 때 도입한 매개 변수입니다.우리는 노란색 표시 부분을 따로 꺼내서 Y로 명명했다.
(define Y(lambda(len)((lambda(f)--------->몇 글자를 적게 두드리기 위해 mk-length를 f(f)로 바꾸기(lambda(f))(len(lambda(x)(f)x)))))))))))))))
위의 이 함수가 있으면 우리는 익명 함수도 귀속시킬 수 있다.위의 이 표현식에는 매우 재미있는 이름이 있다. Y.이것은 결코 내가 마음대로 취한 것이 아니다. 그것은 바로 명성이 자자한 Y 계산이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Windows 10에서 vim의 CommonLisp 환경 만들기다음 사이트에서 Steel Bank Common Lisp을 다운로드합니다. SBCL은 vim에서만 사용되므로 vim 디렉토리 $VIM 아래에 저장합니다. 또한 Steel Bank Common Lisp라는 파일 이름이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.