2016-09-05 8 views
2

私はClojureを学んでいます。私は、Pythonに比べて異様な何かができるかどうかを確認するには、私がやった:(def + - )の後、減算の代わりに+演算子を追加する方法はありますか?

驚くほど働いた
> (+ 2 2) 
4 
> (def + -) 
#'sandbox6693/+ 
> (+ 2 2) 
0 

、しかし、私は上記の定義の後に再び追加する+取得する方法を見つけ出すことはできません。そうする方法はありますか?

答えて

1

clojure.coreファンクション+を削除していないと思われます。ちょうどシャドウイング名前空間にあります。

あなたは、名前空間を含め、それを参照することにより、clojure.coreで機能する+をredeffingことにより、それを取り戻すことができます。

user=> (def + -) 
#'user/+ 
user=> (+ 2 2) 
0 
user=> (def + clojure.core/+) 
#'user/+ 
user=> (+ 2 2) 
4 

しかし....なぜ?

2

@Russellは、clojure.core/+をシャドウするだけでuser/+としています。

は、私はClojureので実験のために何をするのか、(、混乱をしないようにもう一度+とコア+をシャドーイングが、結合範囲内で変更を維持する)だけで、いくつかのローカルな束縛を確立することである。

user> (let [+ -] 
     (+ 1 2 3)) 
-4 

user> (+ 1 2 3) 
6 

しかし、あなたがやりたいために特別な方法がある一般的に (、varの値を変更varが変更された範囲内のいくつかのコードを実行した後、自動的にそれが価値だ復元する):

最初の1 bindinghttps://clojuredocs.org/clojure.core/binding)問題を使用することです、+はダイナミック

ではないので、それは、あなたのケースでは本当に二番目の適用はありませんので、それだけで、特別なdynamic VARSの作品であるwith-redefshttps://clojuredocs.org/clojure.core/with-redefs)を使用することですあなたが必要なものに近いですが、1がありますそこに問題:

user> (with-redefs [+ -] 
     (+ 1)) 
-1 ;; as expected 

user> (with-redefs [+ -] 
     (+ 1 2 3)) 
6 ;; unexpected! 

2番目の例では、失敗し、コンパイラのインラインため+機能は、複数の引数があり、それに渡され、いくつかの純粋educatため、

も)add関数呼び出しに置き換えられている場合あなたは、一般的に古い値を保存し、必要なすべてのものを再定義し、ブロック評価の後にそれを復元しますマクロを作ることができますional目的:

user> (defmacro redefine [old new & body] 
     `(let [v# ~old] 
      (def ~old ~new) 
      (let [res# (do [email protected])] 
      (def ~old v#) 
      res#))) 
#'user/redefine 

user> (redefine 
     + - 
     (+ 1 2 3)) 
-4 

user> (+ 1 2 3) 
6 

user> #'+ 
#'user/+ 

user> (redefine 
     + * 
     (+ 1 2 4)) 
8 

user> (redefine 
     + * 
     (+ 1 2 4)) 
8 

user> (+ 1 2 4) 
7 
+0

add関数のコンパイラのインライン化と面白い落とし穴です! – Russell

+0

これはすばらしい答えですが、Clojure、@Atonalを初めて使う人はマクロを避けることを強くお勧めします。必要な場合はほとんどありませんが、コードの理解容易性の点で些細なコストであり、初心者/中間者によって過度に使用されることがあります。 – Russell

+0

@Russellマクロは複雑で、時には初心者にとっては理解しにくいこともありますが、一方ではリップスを1マイル上に浮かべるような非常に強力な計測器なので、私はちょうど言うでしょう"避ける"の代わりに "反応的に使う") – leetwinski

関連する問題