2009-12-08 3 views
6

예제 코드 here (아래 예제)을 이해하려고합니다. 나는 파라미터 구조를 이해하지 못한다. 문서는 here이지만 도움이되지 않습니다. 그것은 무엇을합니까?DrScheme에서 '매개 변수화'는 무엇입니까?

+0

왜 tinyurl.com을 사용하십니까? 전체 URL을 사용하는 데 상당한 공간 제약이 없으며, 짧은 URL로 인해 링크의 의심이 더 커집니다. –

+1

링크에는 꼬리표가 붙어있어 마크 업과 함께 작동하지 않는 꼬리표가 있습니다. 즉, – Claudiu

+0

지미니 크리스마스 (Zimmermy Christmas)를 사용하면 해당 링크는 인용순 하단 인용 스타일로 작동하지 않습니다. – Chuck

답변

13

parameterize은 "동적으로 범위가 지정된"값을 사용합니다. make-parameter으로 매개 변수를받습니다. 매개 변수 자체는 함수로 작동합니다. 입력이 없으면이 매개 변수를 호출하고 해당 값을 가져 와서 한 값으로 호출하면 값이 설정됩니다. 예 :

> (define p (make-parameter "blah")) 
> (p) 
"blah" 
> (p "meh") 
> (p) 
"meh" 

많은 기능 (많은 기본 기능 포함)은 동작을 사용자 정의하는 방법으로 매개 변수를 사용합니다. 예를 들어 printfcurrent-output-port 매개 변수의 값인 포트를 사용하여 항목을 인쇄합니다. 이제, 인쇄 몇 가지 기능을 가지고 있다고 무언가 : 당신은 일반적으로이 함수를 호출하고 뭔가 화면에 출력 참조

> (define (foo x) (printf "the value of x is ~s\n")) 

-하지만 어떤 경우에는 파일이나 어떤 뭔가를 인쇄하는 데 사용할 . 당신은 이것을 할 수있다 :

(define (bar) 
    (let ([old-stdout (current-output-port)]) 
    (current-output-port my-own-port) 
    (foo some-value) 
    (current-output-port old-stdout))) 

이것에 대한 하나의 문제는 지루한 일이다. 그러나 그것은 매크로로 쉽게 해결된다. (사실, PLT에는 여전히 일부 언어에서는 해당 작업을 수행하는 구문이 있습니다. fluid-let) 그러나 여기에는 더 많은 문제가 있습니다. foo을 호출하면 런타임 오류가 발생합니까? 이렇게하면 시스템이 모든 상태로 돌아가는 나쁜 상태가 될 수 있습니다. 아무 것도 출력하지 않으므로 문제가 보이지 않습니다. (fluid-let도 사용하는) 그 해결책은 매개 변수의 저장/복원을 dynamic-wind으로 보호하는 것입니다. 그러면 오류가있는 경우 (계속해서 계속 알면) 값이 복원됩니다.

그렇다면 전역과 fluid-let을 사용하는 대신 매개 변수를 사용하는 것이 중요한 이유는 무엇입니까? 단지 전역 변수로는 풀 수없는 두 가지 문제가 더 있습니다. 하나는 여러 개의 스레드가있을 때 일어나는 일입니다.이 경우 일시적으로 값을 설정하면 다른 스레드가 영향을 받아 표준 출력으로 계속 인쇄됩니다. 매개 변수는 스레드마다 특정 값을 가짐으로써이를 해결합니다. 각각의 스레드는 스레드를 생성 한 스레드의 값을 "상속"하며 한 스레드의 변경 사항은 해당 스레드에서만 볼 수 있습니다.

다른 문제는 더 미묘합니다.당신이 숫자 값을 가진 매개 변수가 있음을 말해, 당신은 다음을 수행 할 : 계획에서

(define (foo) 
    (parameterize ([p ...whatever...]) 
    (foo))) 

는 "꼬리 호출"중요하다 - 그들이 루프 등을 만들기위한 기본 도구입니다. parameterize은 일시적으로 매개 변수 값을 변경하지만 이러한 꼬리 호출을 유지할 수있는 마법을 수행합니다. 예를 들어, 위의 경우에 이 스택 오버플로 오류가 발생하지 않고 무한 루프가 발생합니다. 이전에 parameterize이 더 이상 필요하지 않은 경우 이러한 parameterize 표현식을 각각 감지 할 수 있습니다 대청소.

마지막으로 parameterize은 실제로 PLT의 두 가지 중요한 부분을 사용합니다. 스레드 셀을 사용하여 스레드 당 값을 구현하고 연속 호출을 사용하여 꼬리 호출을 보존 할 수 있습니다. 이러한 각 기능은 그 자체로 유용합니다.

+0

흥미로운 답변 - 감사합니다! – Claudiu

3

parameterize은 특정 매개 변수를 블록 기간 동안 지정된 값으로 설정합니다. 단, 외부 매개 변수의 값에는 영향을주지 않습니다.

+0

흥미로운 – Claudiu

3

매개 변수화는 람다를 사용하지 않고 기존 함수 내에서 값을 동적으로 다시 바인딩 할 수있는 방법입니다. 실제로 매개 변수를 전달하고 람다를 사용하여 바인드해야하는 대신 함수 내에서 값을 다시 바인드하려면 parameterize를 사용하는 것이 훨씬 쉽습니다.

예를 들어, 사용하는 라이브러리가 HTML을 표준 출력으로 내보내지만 편의상 그 값을 문자열로 캡처하여 추가 작업을 수행한다고 가정하십시오. 라이브러리 설계자는 1) 기능에 대한 인수로 출력 포트를 승인하거나 2) 현재 출력 포트 값을 매개 변수화하는 데 필요한 최소한 두 가지 선택 사항이 있습니다. 1은 추악하고 번거 롭습니다. 2는 stdout으로 인쇄하는 것이 가장 좋기 때문에 더 좋지만, 문자열 포트로 인쇄하고자 할 경우에는 해당 함수에 대한 호출을 매개 변수화 할 수 있습니다.

관련 문제