3

나는 라켓 (Racket)과 라켓 (Dr. Racket)과 함께 SICP 서적을 연구 중입니다. 나는 또한에 강의를 시청하고있다 : 제 3 장에서SICP - 계승의 명령 적 대 기능적 구현

https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/video-lectures/5a-assignment-state-and-side-effects/

은, 저자는 명령형 프로그래밍의 개념을 제시한다.

의미를 설명하려고하면 함수 프로그래밍을 사용한 요인 절차의 구현과 명령형 프로그래밍을 사용한 방법을 비교합니다.

우는 소리는 함수형 프로그래밍을 사용하여 반복 절차의 재귀 정의가 : 교수가 필수적 구현을 ​​제시려고하기 전에

(define (factorial-iter n) 
    (define (iter n accu) 
    (if (= n 0) 
     accu 
     (iter (- n 1) (* accu n)))) 
    ; (trace iter) 
    (iter n 1)) 

을, 나 자신을 시도했다.

는 내가 명령을 사용하여이 코드에 도달 "로 설정을!"

(define (factorial-imp-sicp n) 
    (let ((count 1) (i 1)) 
    (define (loop) 
     (cond ((> count n) i) 
      (else (set! i (* count i)) 
        (set! count (add1 count)) 
        (loop)))) 
    (loop))) 

모두 코드, 내 구현과 :

(define (factorial-imp n count product) 
    (set! product 1) 
    (set! count 1) 
    (define (iter count product) 
    (if (> count n) 
     product 
     (iter (add1 count) (* product count)))) 
    (iter count product)) 

그러나 교수의 구현은 내 필수적 구현의 매우 다르다 교수의 코드는 같은 결과에 도달한다. 그러나 나는 그들이 같은 성질인지 잘 모르겠습니다.

따라서 저는 스스로에게 묻기 시작했습니다. 구현이 정말로 필수적 이었습니까? 그냥 "설정!" 보증 해?

교수의 보조 반복 함수가 아무런 인수도 가지지 않는 동안 보조 보조 프로 시저에서 매개 변수를 사용합니다. 이것이 내 질문에 답하는 핵심 사항입니까?

감사합니다. SO 사용자가 많이 도움이되었습니다!

답변

2

당신의 해결책은 필수적으로 보였기 때문에 훌륭하게 미쳤지 만 실제로 그렇지 않습니다. (다음 무엇을 어떤 중요한 어떤 방법으로 라켓 특정 아니지만.)

을 구현 시작 :

(define (factorial-imp n count product) 
    (set! product 1) 
    (set! count 1) 
    (define (iter count product) 
    (if (> count n) 
     product 
     (iter (add1 count) (* product count)))) 
    (iter count product)) 

음, countproduct 인수에 대한 유일한 이유 것은 바인딩을 만드는 것입니다 이러한 변수의 경우 : 인수의 값은 절대로 사용되지 않습니다. 그래서 let으로 명시 적으로 해보겠습니다. 그리고 처음에는 정의되지 않은 객체에 바인딩 할 것입니다. 바인딩이 사용되지 않았 음이 분명합니다. (내부 함수의 인수를 다른 함수로 변경하여 명확하게 구분되어 있습니다.)

(require racket/undefined) 

(define (factorial-imp n) 
    (let ([product undefined] 
     [count undefined]) 
    (set! product 1) 
    (set! count 1) 
    (define (iter c p) 
     (if (> c n) 
      p 
      (iter (add1 c) (* p c)))) 
    (iter count product))) 

OK가 아니라, 이제 형태 (let ([x <y>]) (set! x <z>) ...) 어떤 식 즉시 오랫동안 <y>는 무엇으로 대체 (let ([x <z>]) ...) 부작용 및 종료를 보유 할 수없는 것은 명백하다.이 하찮게 (f <y>)로 대체 될 수 있습니다 : 그래서 지금 우리가 형태 (let ([x <y>]) (f x))의 무언가가,

(define (factorial-imp n) 
    (let ([product 1] 
     [count 1]) 
    (define (iter c p) 
     (if (> c n) 
      p 
      (iter (add1 c) (* p c)))) 
    (iter count product))) 

확인을 : 그것은 여기의 경우, 그래서 다음과 같이 우리는 위의 내용을 다시 작성할 수 있습니다

(define (factorial-imp n) 
    (define (iter c p) 
    (if (> c n) 
     p 
     (iter (add1 c) (* p c)))) 
    (iter 1 1)) 

이제는 구현이 실제로 유용한 방식으로 필수적이지는 않습니다. 그것은 돌연변이를 일으키지 만 돌연변이 전에는 원래 바인딩을 사용하지 않습니다. 이것은 본질적으로 컴파일러 작성자가 '정적 단일 할당'이라고 부르는 것입니다. 각 변수는 한 번 할당되고 할당되기 전에 사용되지 않습니다.


PS : '화려 미친'모욕, 나는 그것이 같은되지 못했습니다 희망으로 의미되지 않았다, 나는이 답변을 즐길!

+0

나는이 주석을 해석하는 방법에 대해 의문을 가지고있었습니다 ... 당신이 질문에 투표하지 않았으므로 나는 그것이 모욕이라고 생각했습니다. 하지만 고마워. 문제 없어. 좋은 대답! =) –

+1

@fallowzito 죄송합니다. 투표 기억이 안좋아서, 지금 있습니다. – tfb

1

set! 사용은 바인딩을 변경하지만 당신이 전달 된 값을 사용하지 않고 1에 전달 된 값에서 변경 당신은 결코 하나가 상수가 전달 된 1 경우 1로 볼 수 나중에 값을 변경할에 의해 부작용을 소개합니다 이 같은 도우미 :

(define (factorial-imp n ignored-1 ignored-2) 
    (define (iter count product) 
    (if (> count n) 
     product 
     (iter (add1 count) (* product count)))) 
    (iter 1 1)) 

도우미 따라서는 재귀 적으로 countproduct있어 업데이트하고는 100 % 작동합니다.

명령형으로 동일한 작업을 수행하려는 경우 교수형 구현과 마찬가지로 루프 외부에서 변수를 만들어 루프의 각 단계에서 업데이트 할 수 있습니다.

귀하의 버전에서 계약이 변경되었습니다. 사용자는 아무것도 사용되지 않는 두 개의 인수를 전달해야합니다. 나는 그들을 ignored-1ignored-2이라고 부름으로써 설명했다.