2011-07-14 12 views
6

私は実際にTie::Fileが好きで、tieにファイルの行への配列を許可します。あなたは何らかの形で配列を変更することができます。そしてそれを完了するとuntieとなり、ファイルの内容がそれに応じて変更されます。ScalaでTie :: Fileをどのように再実装できますか?

私はScalaでは、このような行動を再実装したいのですが、これは私がこれまで持っているものです。

class TiedBuffer(val file:File) extends ArrayBuffer[String] { 

    tieFile 

    def untie = { 
     val writer = new PrintStream(new FileOutputStream(file)) 
     this.foreach(e => writer.println(e)) 
     writer.close 
     this 
    } 

    private def tieFile = this ++= scala.io.Source.fromFile(file).getLines() 
} 

しかし、ArrayBufferに定義された「事業者が」自分とは異なるさまざまなクラスを返し、例えば、

println((new TiedBuffer(somefile) +: "line0").getClass) 

は、immutable.Vectorを与える。私はクラスをあらかじめ定義されたメソッドの非常に小さなセットに制限することができましたが、私がそれらのすべてを提供できるなら(foreach/map/...)良いと思った。

私はどのように継承する必要がありますか、私は流体のようなインターフェイスを持っているので、私はファイルの内容を変更することができますこの問題にアプローチする必要がありますか?

BOUNTY:賞金を獲得するには、このタスクを達成するためにCanBuildFromを使用する実例を表示できますか?

+0

Tie :: Fileは実際にはここに表示するより複雑です。解凍時に結びつけたときにファイルを読み込むだけではありません。配列を操作する際にファイルを読み書きします(パフォーマンスを向上させるためにいくつかの最適化を行います)。しかし、このような基本的な実装でさえ、依然として有効です。 – cjm

+0

@cjm、もちろん分かります。 Tie :: Fileは私がここに示したものよりはるかに複雑です。しかし、私は、これを読んでいる人々が何が起きているのか、なぜこのモジュールが有用であるのかをはっきりと理解したかったのです。 – Senthess

答えて

4

コロンで終わるの方法はあなたの例では、パラメータとしてTiedBufferString+:を呼び出しているのでright associativeです。あなたが行うことができますArrayBufferから+:テストする場合:

println((new TiedBuffer(somefile).+:("line0")).getClass) 

または

println(("line0" +: new TiedBuffer(somefile)).getClass) 

EDIT

を私が代わりにTiedBufferオブジェクトを返すためにジョンのanswerを参照してください、あなたの質問のポイントを逃しましたArrayBufferです。ここ

EDIT2

CanBuildFrom有する例です。ビルダーが新しいTiedBufferインスタンスを作成するたびにファイルが縛られないように、tieを手動で呼び出す必要があります。改善の余地はまだまだあります。例えば、++は動作しませんが、それはあなたが始めるはずです。

マルクスJayxcelaで述べたように

http://www.scala-lang.org/docu/files/collections-api/collections-impl.html

、理由:

import collection.generic.CanBuildFrom 
import collection.mutable._ 
import java.io.{PrintStream, FileOutputStream, File} 

class TiedBuffer(val file: File) extends ArrayBuffer[String] 
           with BufferLike[String, TiedBuffer] 
           with IndexedSeqOptimized[String, TiedBuffer] { 

    def tie = { 
    clear 
    this ++= scala.io.Source.fromFile(file).getLines() 
    } 

    def untie = { 
    val writer = new PrintStream(new FileOutputStream(file)) 
    this.foreach(e => writer.println(e)) 
    writer.close 
    this 
    } 

    override def newBuilder: Builder[String, TiedBuffer] = 
    new ArrayBuffer mapResult { 
     x: Seq[String] => (new TiedBuffer(file) ++= x) 
    } 
} 

object TiedBuffer { 
    implicit def canBuildFrom: CanBuildFrom[TiedBuffer, String, TiedBuffer] = 
    new CanBuildFrom[TiedBuffer, String, TiedBuffer] { 
     def apply(): Builder[String, TiedBuffer] = 
     throw new RuntimeException("Cannot create a new TiedBuffer from scratch") 

     def apply(from: TiedBuffer): Builder[String, TiedBuffer] = from.newBuilder 
    } 
} 
4

の拡張既存のコレクションは、これは完全にここで説明されるような

object TiedBuffer { 
    implict def canBuildFrom[T] = new CanBuildFrom[TiedBuffer[T],T,TiedBuffer[T]] { ... } 
} 

コンパニオンオブジェクトにビルダーを定義する必要がありあなたはベクトルを取得しているのですが、正しい連想演算子を使用していれば、暗黙のビルダーが選択され、 ArrayBufferを取得する

関連する問題