懲りずにまたやってみるw
ていうかあさいさんの書いたやつちょっといじるだけみたいなw
まったく改良にはなっていない、というか個人的になんとなくいじってみたくなっただけです、すいません(´Д`)
"こういう書き方もできるよ"的なサンプルとして、誰かの役にたてば・・・
import java.io.{File => jFile} //パターンマッチの為だけに、FileとDirの objectとunapply定義したみたりとか object Dir{ def unapply( f:jFile ) = if( f.isFile ) Some( f ) else None } object File{ def unapply( f:jFile ) = if( f.isDirectory ) Some( f ) else None } abstract class Node(file : jFile, indent: String ) { val branch : String val childBranch : String // メソッドの途中にprintlnとかあるの嫌なのでとりあえずtoStringにして純粋に // これだと、毎回計算するので、toStringと別のもので、lazy valとかにしてメモ化するのもありか? override def toString = { indent + branch + file.getName + "\n" + { if (file.isDirectory) ls.foldLeft("")( _ + _.toString ) else "" } } // zipWithIndexで新しく生成しても、配列の最後かどうかの判断しか使ってないなら、これでもいい気が・・・ // この場合の問題は、Arrayのlastのオーダーが、 O(1) と O(n) のどっちなのか?(たぶん定数時間な気がするけど) // あとで調べる or だれか教えて。 Arrayのlastのオーダー // ていうか、l.last は、collectの外側で変数に束縛したほうが効率いいのか? // まぁ効率だけ考えたら、もっと良いやり方ありそうだけど private def ls : Array[Node] = { try { val l = file.listFiles l.collect { case File(f) => { if( l.last eq f ) new LastDir(f, indent + childBranch) else new NormalDir(f, indent + childBranch) } case Dir(f) => { if( l.last eq f ) new LastFile(f, indent + childBranch) else new NormalFile(f, indent + childBranch) } } } catch { case e: NullPointerException => println("Permission Denied. [%s]".format(file)) Array() } } } class RootDir(file : jFile) extends Node(file, "") { // 親コンストラクタに直接渡しちゃだめなの? val branch = "" val childBranch = "" } // なんだか、DRYじゃないので、ためしにtraitでつくってみるものの、 // 微妙・・・てか行数増えてるw 改悪www // classが5種類あるけど、classは減らして、代わりに、childBranchとかbranchもコンストラクタの引数で渡すっていうのもありかなぁ? trait F{ val childBranch = "" } trait Last{ val branch = "`-- " } trait Normal{ val branch = "|-- " } class NormalDir(file : jFile, indent : String) extends Node(file, indent) with Normal { val childBranch = "| " } class NormalFile(file : jFile, indent : String) extends Node(file, indent) with F with Normal class LastDir(file : jFile, indent : String) extends Node(file, indent) with Last { val childBranch = " " } class LastFile(file : jFile, indent : String) extends Node(file, indent) with F with Last
これ書いてて思ったのが、matchの中で、
(f, indent + childBranch)
という、(生成するクラスは違うが)すべて同じ引数を渡していること。
これが、scala3.0で導入されるらしい、
Tupleと複数引数の互換性*1があれば、
一度、
val a = (f, indent + childBranch)
みたいに、束縛して、それを
val a = (f, indent + childBranch) if( l.last eq f ) new LastDir(a) else new NormalDir(a)
っていうように渡せて、読みやすくて便利だね(・∀・)
っていうことですかね?
*1:こんな言い方でいいの?