2016-07-31 60 views
2

我有一個矢量值的原子:如何返回取消引用的值作爲函數的結果Clojure中

(def v (atom [1 2])) 

我想寫,將返回該提領原子的功能。也就是說,我基本上想寫將返回相同的結果,因爲這一個功能:

=> @v 
[1 2] 

我的這首取是這樣的:

=> (let [f #(@v)] 
    (println (f))) 
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:429) 

但這當然不工作作爲取消引用原子是不是一個函數:

=> (@v) 
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:429) 

我終於結束了與解決方法是這樣的:

=> (let [f #(vec @v)] 
    (println (f))) 
[1 2] 
nil 

...但肯定有一個更好的方法來做到這一點,不必假設原子的值是矢量?

+2

'(defn deref-v [](deref v))' –

+1

這只是'deref'函數。我不知道爲什麼人們把它作爲一個函數來包裝它,但無論如何,你在評論中提到它是一個簡化的問題。我想你簡化得太多了,所以編輯並給我們更多的細節?作爲你的問題目前的立場,'deref' *是*的功能。如果你只是使用'deref',你根本不會污染你的命名空間,你也可以使用'@'reader宏快速'deref'。 – MasterMastic

+1

這不僅僅是'deref'功能!它不會拒絕它的參數,而是'v'。 FWIW,你也可以寫:'#( - > @v)' – ClojureMostly

回答

2

現有的答案都不給兩個最簡單,最簡潔的解決方案,所以他們在這裏。作爲stated通過@Stefan,你想要的東西相當於這個功能:

(fn [] (deref v)) 

然而,deref這種用法是完全利用的情況下,該@讀者宏是爲了簡化:

(fn [] @v) 

或者由於(deref v)是一個函數調用,您可以改用#()讀者宏:

#(deref v) 

這裏的要點是,在這種情況下,您不能使用@#()在一起。但這並不意味着你不能或不應該使用其中一個

1

有時,最好是離開的讀者結構,如#@出來,只是去的函數(或宏和特殊形式):

user> (def v (atom [1 2])) 
#'user/v 
user> (let [f (fn [] (deref v))] (f)) 
[1 2] 

我走了,你的例子是一個非常簡化的版本你真正想做的事情。如果沒有,deref可能只是您正在尋找的功能。

+0

(deref @v)代替@v,太棒了!我知道必須有一個簡單的解決方案。 :)是的,我花了大約一個星期左右的時間才發現我真正的問題是什麼,並拿出了簡單的例子。 – Domchi

+0

'(derev v)'not'(derev @v)'。 '@'只是/ reader /執行的'deref'的語法糖。請參閱http://clojure.org/reference/reader –

+0

上的「宏字符」部分。您是對的,我在評論中輸入了錯字。感謝您的回答,特別是提醒我有時最好省略#和@並自己使用函數,因爲這正是恰當的情況。 – Domchi

1

I want to write a function that will return this dereferenced atom

(def v (atom [1 2])) 
(defn foo [] @v) 
(foo) ;;=> [1 2] 
+0

是的!我想用匿名函數去做,這樣我就不會用僅被調用一次的函數來污染我的名字空間,但是你的回答讓我想到了簡單地使用擴展形式的匿名函數:(let [f(fn [] @v) ](prn(f))) – Domchi

+0

@Domchi(let [f(fn [] @v)](prn(f)))與(prn @v)實際上是一樣的 - 爲什麼函數? –

+0

這是一個真實用例的簡單例子。我的用例是我實際上有一個函數可以對原子做一些事情(在循環中),我通過傳遞不同的原子在不同的地方使用它。 – Domchi

1

首先:此錯誤的原因,是λ表達式糖語法的擴展。你可以這樣設想一下:

#(expression*) => (fn [] (expression*)) 

所以,這樣的想法:

反過來#(@v) => (fn [] (@v))@v擴大到(deref v)(輕鬆地與宏擴展看到的),導致你這種形式:

(fn [] ((deref v)))

其實你是說對了一半,出現錯誤的假定原因:取消引用的結果被作爲函數調用,但實際上它可能是(作爲載體公頃它的功能語義),而只是缺少一個強制參數(正是在錯誤文本中所說的)。 所以應該對這項工作:#(@v 0) =>(fn [] ((deref v) 0))

user> (let [f #(@v 0)] 
     (println (f))) 
1 
nil 

個人而言,我只想去與部分應用程序,而不是lambda表達式來解決這個問題:

user> (let [f (partial deref v)] 
     (println (f))) 
[1 2] 
nil 
+0

我站在更正 - 這實際上很酷,當然它期望向量中的位置作爲參數。感謝解釋和部分的想法;我總是很驚訝地看到別人怎麼看待同樣的問題。 – Domchi