2017-09-29 7 views
0

T =>ブール型のテストに合格する、T型の要素の配列内の要素の数を数える関数を記述しようとしています。スカラ汎用配列要素

私がこれまで持っていることは次のとおりです。

 def countPass[T](elem: Array[T]) = { 
     var count = 0 
     for(x <- elem) 
      x match { 
       case x: T => count += 1 
      } 
     count 
    } 

    //TEST 
    println(countPass[Boolean](Array(true, 52, "test"))) 

私はエラーのカップルを取得しています、最初のものは次のとおりです。

combinators.scala:45: warning: abstract type pattern T is unchecked since 
it is eliminated by erasure 
         case x: T => count += 1 
           ^

次のエラーは、次のとおりです。

combinators.scala:54: error: type mismatch; 
found : Int(52) 
required: Boolean 
    println(countPass[Boolean](Array(true, 52, "test"))) 
             ^
combinators.scala:54: error: type mismatch; 
found : String("test") 
required: Boolean 
    println(countPass[Boolean](Array(true, 52, "test"))) 
              ^

最初のエラーで何が起こっているのか分かりませんが、2番目のエラーではいつでも例外をスローします。私は型Tの要素の量を配列に数えているだけなので、そのようなことは起こりたくありません。

質問:これらの両方のエラーを修正するには、コードをどのようにリファクタリングする必要がありますか?

答えて

6

このトリックはClassTagを使用しています。次のようにあなたの要求を達成するためのより良い方法がある:

import scala.reflect.ClassTag 

object Main extends App { 

    val array: Array[Any] = Array("string1", "string2", "string3", true, false, 13) 

    def countPass[Other: ClassTag](array: Array[Any]): Int = { 
    array.collect { case x: Other => x }.length 
    } 

    println(s"countPass String = ${countPass[String](array)}") 
    println(s"countPass Boolean = ${countPass[Boolean](array)}") 
    println(s"countPass Int = ${countPass[Int](array)}") 
} 

あなたはClassTagTypeTag

+0

これは私が最初に持っていたものとは非常に遠く、達成したいものです。しかし、あなたの解決策は、私が配列パラメータの中で 'Any'を使用していたはずであることを認識させました。しかし、最初のエラーでまだ問題が残っています – Phillip

+0

配列には異なる型が含まれているので、 。したがって、 'Array [Any]'を定義する必要があります。 – fcat

+0

import scala.reflect.ClassTagを必ずインポートしてください。さらに、これを読むことができます:https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20 – fcat

0

についての詳細を学ぶためにthisを読むことができるので、私は私が欲しかった、まさに動作方法を見つけましたが、ありません。

 def countPass[T](elem: Array[T]) = { 
     var count = 0 
     for(x <- elem) 
      x match { 
       case _: Boolean => count += 1 
       case _ => None 
      } 
     count 
    } 

    //TEST 
    println(countPass[Any](Array(true, 5, "test", false, false))) 

私はそこにさまざまな型があるので、配列にAnyを渡す必要がありました。さらに、ケースを少し変更してデフォルトのケースを追加する必要がありました。

これは完全に機能しますが、私はこのようなものをもっと欲しかったです。 T私の場合として、あるいは、私はこのエラーを取得する:

combinators.scala:44: warning: abstract type pattern T is unchecked since 
it is eliminated by erasure 
       case _: T => count += 1 
+0

'_:T'(正しく)にマッチさせるには、' ClassTag [T] 'が必要ですfcatの答えによれば、 –

0

あなたは直接メソッド・カウントを使用することができますこれは私が_を行うことはできませんいくつかの理由であるため

def countPass[T](elem: Array[Any]) = { 
     var count = 0 
     for(x <- elem) 
      x match { 
       case _: T => count += 1 //Here is the error 
       case _ => None 
      } 
     count 
    } 

    //TEST 
    println(countPass[Boolean](Array(true, 5, "test", false, false))) 

上で指定したのと同じエラーが動作しません。

def countPass[T: ClassTag](elem: Array[Any]): Int = elem.count{ 
    case _ : T => true 
    case _ => false 
} 
+0

これは、OPが望むものではありません。これは固定ブールではなくジェネリックタイプTの要素を数える 'countPass'です。ブール値をTに置き換えると、OPのエラーが発生します。 –

+0

あなたは正しいです、私は質問を誤解...私は解決策を修正しました – Mikel