

以下のプログラムを実行したとします。

[code]

    sealed trait Expr
    case class N(n: Int) extends Expr
    case class Var(x: String, a: Int, n: Int) extends Expr
    case class Add(n: Expr*) extends Expr
    case class Mul(n: Expr*) extends Expr
    
    def add(xs: List[Expr]): Expr = xs match {
      case List() => N(0)
      case List(xs) => xs
      case xs => Add(xs: _*) // Add(List(N(1), N(2), Var(x,2,2)))
    }
    
    println(add(List(N(1),N(2),Var("x",2,2)))) // Add(List(N(1), N(2), Var(x,2,2)))
    
[/code]

このプログラムで期待する出力結果は

[code]

    Add(N(1), N(2), Var(x,2,2))
    
[/code]

なのですが、実際の出力結果は

[code]

    Add(List(N(1), N(2), Var(x,2,2)))
    
[/code]

となってしまいます。上記のプログラムで期待する出力結果にする方法をご教示いただけますでしょうか。

どうぞよろしくお願いします。


CC BY-SA 3.0
2015-07-12T01:06:45.617
12290
2015-08-11T12:56:51.793
8732
question
scala
case classを利用したパターンマッチで、引数の中身をListにしたくない


~~`toString`をオーバーライドして、出力をいじりました。  
こういうことでしょうか？~~

[code]

    sealed trait Expr
    case class N(n: Int) extends Expr
    case class Var(x: String, a: Int, n: Int) extends Expr
    case class Add(n: Expr*) extends Expr {
        override def toString() : String = "Add(" + n.mkString(", ") + ")"
    }
    case class Mul(n: Expr*) extends Expr
    
    object Main {
    
        def add(xs: Seq[Expr]): Expr = xs match {
            case Seq() => N(0)
            case Seq(xs) => xs
            case xs => Add(xs: _*)
        }    
    
        def main(args: Array[String]) {
            println(add(List(N(1),N(2),Var("x",2,2))))
        }
    }
    
[/code]

* * *

追記：質問はどうも「出力の結果を`Add(N(1), N(2), Var(x,2,2))`にしたい」というより、「コンストラクタ`Add(n:
Expr*)`は可変長個の引数をとるが、それがAddクラスの可変長個のフィールドに格納されるようにしたい」ということのようですね。結論から言えば、Javaのクラスのフィールドの個数が動的に変化することはないように、scalaでも原理的に無理でしょう。

scalaでコンストラクタが`Add(n:
Expr*)`という可変長の引数をとるものだとしても、実際には単に`n`という単一のフィールドを持ったクラスになるだけです。`Add(n:
Expr*)`は引数の渡し方の見た目を変えるだけに過ぎません。


CC BY-SA 3.0
2015-07-12T05:17:13.960
12293
2015-07-12T12:13:18.417
2015-07-12T12:13:18.417
10330
10330
12290
answer