簡體   English   中英

“參數化”在DrScheme中做了什么?

[英]What does 'parametrize' do in DrScheme?

我試圖理解這里的示例代碼(下面的例子)。 我不明白參數化構造。 它的文檔在這里 ,但它們沒有幫助。 它有什么作用?

parameterize用於具有“動態范圍”的值。 你得到一個帶make-parameter 參數本身就像一個函數:在沒有輸入的情況下調用它並獲得它的值,用一個值調用它並設置值。 例如:

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

許多函數(包括許多原始函數)使用參數作為定制其行為的方式。 例如, printf將使用作為current-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使用fluid-let )是使用dynamic-wind保護參數的保存/恢復,這樣可以確保如果出現錯誤(如果你知道延續的話,還有更多),那么值仍然是恢復。

所以問題是如何使用參數而不是僅使用全局變量和fluid-let 只有全局變量還有兩個問題無法解決。 一個是當你有多個線程時會發生什么 - 在這種情況下,臨時設置值將影響其他線程,這可能仍然需要打印到標准輸出。 參數通過為每個線程設置特定值來解決此問題。 會發生什么是每個線程從創建它的線程“繼承”該值,並且一個線程中的更改僅在該線程中可見。

另一個問題更微妙。 假設您有一個帶有數值的參數,並且您想要執行以下操作:

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

在Scheme中,“尾調用”很重要 - 它們是創建循環的基本工具等等。 parameterize化做了一些魔術,允許它暫時更改參數值,但仍保留這些尾調用。 例如,在上面的例子中,你得到一個無限循環,而不是得到一個堆棧溢出錯誤 - 會發生什么是這些parameterize表達式中的每一個都能以某種方式檢測何時有一個不再需要進行清理的早期parameterize

最后, parameterize實際上使用PLT的兩個重要部分來完成它的工作:它使用線程單元來實現每線程值,並使用連續標記來保留尾調用。 這些功能中的每一個本身都是有用的。

parameterize將特定parameterize設置為塊的持續時間的指定值,而不影響它們之外的值。

參數化是一種可以動態重新綁定現有函數中的值的方法,而不使用lambda來實現。 在實踐中,有時使用參數化來重新綁定函數中的值而不是傳遞參數並使用lambda綁定它們要容易得多。

例如,假設您使用的庫將HTML發送到stdout,但為了方便起見,您希望將該值捕獲到字符串並對其執行進一步操作。 庫設計者至少有兩種選擇可以讓您輕松:1)接受輸出端口作為函數的參數或2)參數化current-output-port值。 1是丑陋和麻煩。 2更好,因為最可能的行為是打印到stdout,但是如果你想打印到字符串端口,你可以參數化對該函數的調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM