2012-04-07 13 views
3

私はこのようなものがあります:なぜ私はクロージャにdefrecordをバインドできませんか?

user> (defrecord vertex [id val]) => user.vertex 
user> (def v vertex)    => #'user/v 
user> (= v vertex)    => true 
user> (type v)     => java.lang.Class 
user> (type vertex)    => java.lang.Class 
user> (vertex. 1 2)    => #user.vertex{:id 1, :val 2} 
user> (v. 1 2)     => "Unable to resolve classname v" 
user> (new v 1 2)     => "Unable to resolve classname v" 

だから、基本的に、私は別の名前に頂点をバインドすることはできませんが。関数にdefrecord型を渡そうとすることと同じこと、let、または他の何か。 なぜこのような場合ですか?一時的にdefrecordの名前を変更するにはどうすればよいですか?

私は、Javaの相互運用性と関係があるいくつかのトリックだと思います。

答えて

2

これは私の知る限りではありません。

defrecordの仕組みについて考えるなら、実際にはバイトコードは(java)クラスを生成します。あなたは1つの名前空間にdefrecordを行うと、他の中でそれを使用したいときは、この動作を確認することができます...

(ns my-first-namespace) 
(defrecord Foo [x y]) 

(ns my-second-namespace 
    (:use my-first-namespace) 
    (:import my_first_namespace Foo)) ; still have to import the java class 
            ; underlying the defrecord even tho 
            ; the defining namespace is use'd (note 
            ; hyphen/underscore changes). 

を不幸に別のクラス名を別名にする(実際にはJVMで)Javaで方法はありませんクラス名。あなたが得ることができる最も近い新しい名前にサブクラス化することですが、それはかなり総体です。

+0

これは意味がありますが、私はクローゼッとどのようにして再定義/名前を変更することができるのかというと、クラス名をローカル変数にバインドできないことに驚きました。特に '(= v vertex)' trueを返します – Sonicsmooth

4

defrecordは、実際にはClojureの特殊ケースの1つとして扱われていると思いますが、特にinterop(ただし私は肯定的ではありません)に関してはJavaクラスを生成します。

あなたの目的が、頂点を作成できる関数を簡単に渡すことができるようにするには、interopを自分で行うのではなく、コンストラクタを呼び出すローカル関数を使用することです。 Clojureの1.3

、のDeftypeと自動的に二つの追加のメソッドを生成defrecord:

  • ->{type}コンストラクタと等価である
  • map->{type}は、上記の場合

引数として引数の地図を取り、(->vertex 1 2)(map->vertex {:id 1 :val 2})の作業を行い、後で作業することができます。

実際にクラスを渡す際にクラスを使用する必要がある場合は、わかりませんが、マクロでできることがあります。

+0

素晴らしいです!分かち合ってくれてありがとうございます.3日間は「名前付き引数」を使って新しいレコードを作成する方法を見つけようとしています。 –

関連する問題