2012-03-21 22 views
1

私はScalaには新しく、定義するのに苦労しています。また、ポーランド語の表記法で記述された計算を評価するためにRubyから自分のコードを翻訳しています。 (+、3,2)またはArrayBuffer( - 、4、ArrayBuffer(+、3 2))を構成する文字列を正しく解析しました。 ))ポーシング表記の評価関数

再帰的評価関数を定義しようとすると実際に問題が発生します。単純にArrayBufferを引数として受け取り、int(評価されたアプリケーションの結果)を返すだけです。 BASEケースに

: - とリターンint型 私は2番目の要素はINSTANCEOF [INT] & &第三の要素であれば、単純にチェックしたいINSTANCEOF [int]はその後、(第一要素サインオペレータに依存する)それらを一緒に評価しています。

しかし、いずれかの要素が別のArrayBufferである場合、その要素を再帰的にeval関数と呼ばれる戻り値に再割り当てしたいだけです。以下のような:。 ストレージは、(2)=のeval(ストレージ(2)(私は変更可能なArrayBufferを使用していますなぜ** ** thatsの)

エラー、私が手です: scala.collection.mutable.ArrayBufferをすることはできません私はもちろん、すべてのコピー&ペーストの答えのためではなく、いくつかのアドバイスや観察を捜しているわけではないがjava.lang.Integer

にキャスト。完全に歓迎 建設的な批判が。

これはテストですコード私は追加のためだけに使用しています*

def eval(Input: ArrayBuffer[Any]):Int = { 

    if(ArrayBuffer(2).isInstaceOf[ArrayBuffer[Any]]) {  
    ArrayBuffer(2) = eval(ArrayBuffer(2)) 
    } 

    if(ArrayBuffer(3).isInstaceOf[ArrayBuffer[Any]]) {  
    ArrayBuffer(3) = eval(ArrayBuffer(3)) 
    } 

    if(ArrayBuffer(2).isInstaceOf[Int] && ArrayBuffer(3).isInstanceOf[Int]) { 
    ArrayBuffer(2).asInstanceOf[Int] + ArrayBuffer(3).asInstanceOf[Int] 
    } 
} 
+0

あなたは、評価のためにあなたが持っているもののコード貼り付けることができます関数?これにより、問題が発生している場所をより簡単に把握し、支援をより適切にすることができます。 – dhg

答えて

5

あなたのコードを持ついくつかの問題:

  • ArrayBuffer(2)は ":2一つの要素でArrayBufferを構築する" という意味します。あなたのコードのどこにでもあなたのパラメータInputを参照しています。これを行うには、ArrayBuffer(2)のインスタンスをInput(2)に置き換える必要があります。
  • ArrayBuffer(およびScalaのすべてのコレクション)は0でインデックス付けされているので、コレクションの2番目のものにアクセスする場合は、input(1)となります。
  • 最後にifを残すと、関数が常にIntを返すとは限りませんので、コンパイラは不平を言います。入力に予期せぬものが含まれていた場合は、最後のiffalseと評価され、にはなりません。

ここにあなたのコードを直接書き換えます:問題を修正:

def eval(input: ArrayBuffer[Any]):Int = { 
    if(input(1).isInstanceOf[ArrayBuffer[Any]]) 
    input(1) = eval(input(1).asInstanceOf[ArrayBuffer[Any]]) 
    if(input(2).isInstanceOf[ArrayBuffer[Any]]) 
    input(2) = eval(input(2).asInstanceOf[ArrayBuffer[Any]]) 

    input(1).asInstanceOf[Int] + input(2).asInstanceOf[Int] 
} 

(ノートもinputのようなその変数名は、小文字する必要があります。)


前記、入力のエントリを評価に置き換える手順は、おそらく評価の過程で入力を破棄するため、最善の方法ではありません。代わりにArrayBufferを取り、オリジナルを変更せずに単純に反復処理する関数を書くべきです。

evalは、特定のケースを確認する機能が必要になります。

def eval(e: Seq[Any]): Int = 
    e match { 
    case Seq("+", a: Int,  b: Int)  => a + b 
    case Seq("+", a: Int,  b: Seq[Any]) => a + eval(b) 
    case Seq("+", a: Seq[Any], b: Int)  => eval(a) + b 
    case Seq("+", a: Seq[Any], b: Seq[Any]) => eval(a) + eval(b) 
    } 

ですから、(+ arg1 arg2)の単純なケースのために、4例があることがわかります。ここではデモンストレーションとしての単純な実装です。いずれの場合も、引数がIntであれば、追加で直接使用します。引数自体がシーケンス(like ArrayBuffer)の場合、追加する前に再帰的に評価します。また、Scalaのcase構文では、パターンマッチをタイプと一致させることができるので、isInstanceOfasInstanceOfの項目はスキップできます。

Anyの代わりにEitherを使用し、"+"をハードコーディングするのではなく、スタイルを改善する必要がありますが、これは正しい軌道に乗るはずです。

そして、ここでは、あなたがそれを使用する方法は次のとおりです。

eval(Seq("+", 3, 2)) 
res0: Int = 5 

scala> eval(Seq("+", 4, Seq("+", 3, 2))) 
res1: Int = 9 

、あなたが本当にScalaの機能を利用したい場合、あなたはEval抽出使用することができます

object Eval { 
    def unapply(e: Any): Option[Int] = { 
    e match { 
     case i: Int => Some(i) 
     case Seq("+", Eval(a), Eval(b)) => Some(a + b) 
    } 
    } 
} 

これは次のように使用します:

scala> val Eval(result) = 2 
result: Int = 2 

scala> val Eval(result) = ArrayBuffer("+", 2, 3) 
result: Int = 5 

scala> val Eval(result) = ArrayBuffer("+", 2, ArrayBuffer("+", 2, 3)) 
result: Int = 7 

それともeval機能でそれをラップすることができます:ここで

def eval(e: Any): Int = { 
    val Eval(result) = e 
    result 
} 
0

は左スタックベースの評価に右の私の感想です:

def eval(expr: String): Either[Throwable, Int] = { 
    import java.lang.NumberFormatException 
    import scala.util.control.Exception._ 

    def int(s: String) = catching(classOf[NumberFormatException]).opt(s.toInt) 
    val symbols = expr.replaceAll("""[^\d\+\-\*/ ]""", "").split(" ").toSeq 
    allCatch.either { 
    val results = symbols.foldRight(List.empty[Int]) { 
     (symbol, operands) => int(symbol) match { 
     case Some(op) => op :: operands 
     case None => val x :: y :: ops = operands 
     val result = symbol match { 
      case "+" => x + y 
      case "-" => x - y 
      case "*" => x * y 
      case "/" => x/y 
     } 
     result :: ops 
     } 
    } 
    results.head 
    } 
}