儘管如此,if
在方案中與algol家族中的if
有很大不同。 algol衍生物中的If
是分支或條件跳轉指令; if
直接改變代碼的流程。在scheme/lisps中,每個if
都會返回一個值。由於解釋器或編譯器的內部結構的限制,它不是一個完整的函數,但是對於大多數目的,您可以將它視爲另一個函數。
(if (something)
Do something //true, #t
Do one thing AND another thing)) //false, #t
錯了,究竟是怎麼回事。
(if condition
(return value of this first exp) //true value
(return value or this second exp)) //false value
在方案中,當你想一個函數有一個副作用,那就是你必須非常明確發生變異的狀態,它的標記是變異狀態用「!」的功能是個好主意在函數名稱的末尾。
程序如set!
vector-set!
等返回未指定的值。如果您需要特定順序的副作用和特定值或多個副作用,則必須用begin
包裝整個事物。另外,如果你只是(set! x 0)
你只能改變本地範圍內的x的值,這可能不是你想要做的。不管你使用什麼綁定符號來傳遞函數,它仍然帶有舊值(set-car
,v ector-set!
和set-cell-contents!
確實修改了跨越詞法邊界調用的數據結構的基礎狀態)顯式遞歸或在閉包中隱藏值通常是合適的。
begin
的語法是(begin exp1 ... expN)
。 Begin
依次評估每個表達式,並返回最後一個表達式的值。唯一有用的是,如果所有表達式在最後創建副作用(mutate state或執行I/O)之前。同時請記住define
和cond
的每個子句包含和隱含begin
。
在Java中,打印字符串的過程會產生副作用。如果不是簡單地返回一個字符串,這是(if (> x 5) ..
的第一個分支正在做的事情。
所以爲了簡化事情,我們將保留字符串打印作爲副作用,並將x的下一個或新值作爲語句的返回值。
(cond ((> x 5) (display "Greater than five") (newline) x)
(else (display "Less than or equal to 5") (newline) 0))
或幾乎等同
(if (> x 5)
(begin (display "Greater than five") (newline) x)
(begin (display "Less than or equal to 5") (newline) 0))
查看'begin'和'cond'的文檔。 – uselpa
'(= x 0)'不會將'x'設置爲'0'。這將是'(set!x 0)',但你試圖在Scheme中避免這種情況。嘗試找到一個體面的計劃教程,這種語言可能與你習慣的非常不同。 – uselpa
不要嘗試按照其他語言編寫代碼的方式進行逐行轉換 - 您需要將自己從分配和排序中解放出來。免費在線書籍:[SICP](https://www.mitpress.mit.edu/sicp/),[HtDP](http://htdp.org/)。 DrRacket的文檔中還有一個教程。 – molbdnilo