我现在开始进行函数式编程,并且在没有变量的情况下工作变得非常疯狂。
我读过的每一个教程都说,重新定义变量并不酷,但我不知道如何在不保存变量状态的情况下解决实际问题。
例如:我正在研究API,我希望通过请求保留值。假设我有一个添加Sub OCRReader()
Dim doc1 As MODI.Document
Dim inputFile As String
Dim strRecText As String
Dim imageCounter As Integer
inputFile = Application.GetOpenFilename
strRecText = ""
Set doc1 = New MODI.Document
doc1.Create (inputFile)
doc1.OCR ' this will ocr all pages of a multi-page tiff file
For imageCounter = 0 To (doc1.Images.Count - 1) ' work your way through each page of results
strRecText = strRecText & doc1.Images(imageCounter).Layout.Text ' this puts the ocr results into a string
Next
fnum = FreeFile()
Open "C:\Test\testmodi.txt" For Output As fnum
Print #fnum, strRecText
Close #fnum
doc1.Close
End Sub
的终点,我有一个person
列表,我想persons
或更改redefine
的值列表添加新persons
。我怎么能这样做?
可以使用person
,var-set
或alter-var-root
吗?
(对于api我正在使用conj!
而每个compojure-api
都是person
)
答案 0 :(得分:6)
Clojure将值与身份区分开来。您可以使用atoms来管理compojure应用程序中的状态。
(def persons (atom [])) ;; init persons as empty vector
(swap! persons #(conj % {:name "John Doe"})) ;; append new value
您可以在文档中找到更多内容:
https://clojure.org/reference/atoms
答案 1 :(得分:1)
您可能需要在大型应用程序中的某个位置使用可变状态,但在所有情况下都不需要。
我不熟悉compojure,但这是一个使用不变性的小例子,可能会给你一个更好的想法:
(loop [requests []
people []
(let [request (receive-request)]
; Use requests/people
; Then loop again with updated lists
(recur (conj requests request)
(conj people (make-person request))))])
我在这里使用假设的receive-request
和make-person
函数。
loop
会创建一对绑定,并在每个recur
更新它们。这是“重新定义变量”的简便方法。这与纯递归相似,你不会在任何时候改变最终结果,只需改变传递给下一次迭代的值。
当然,这非常简单,而且不切实际,因为您一次只收到一个请求。如果您同时收到来自多个线程的请求,这对于一个原子来说是合理的情况:
(defn listen [result-atom]
(Thread.
(fn []
(while true ; Infinite listener for simplicity
(let [request (receive-request)]
(swap! result-atom #(conj % (make-person request))))))))
(defn listen-all []
(let [result-atom (atom [])]
(listen result-atom)
(listen result-atom)))
; result-atom now holds an updating list of people that you can do stuff with
swap!
通过conj
oining将原子变为它所拥有的列表。原子中的列表没有变异,它只是被自身的修改版本所取代。 任何持有对旧人员名单的引用的人都不会受到swap!
的调用的影响。
更好的方法是使用像core / async这样的库,但这样就远离了这个问题。
关键是,您可能需要在某处使用可变变量,但对它们的需求比您习惯的要少得多。在大多数情况下,几乎所有事情都可以像第一个例子中那样使用不变性来完成。