【问题标题】:scala type matchingscala类型匹配
【发布时间】:2011-08-25 16:04:21
【问题描述】:

我想编写一个通用方法来获取位于 String 或 Int 的 x 位置的元素。 现在我的问题是,如何强制 Scala 将 T 转换为 Int 或调用 Int 特定方法。

代码如下:

def key[T](elm:T,pos:Int) = elm match{
  case x:Int => {
    def digit(number:Int, pos:Int):Int = {
      if(pos == 0) number % 10
        else digit(number/10, pos-1)
    }
    digit(elm.toInt,(elm.toInt).length-pos-1)
  } 
  case x:String => (elm.toString).charAt(pos)
}

谢谢!

【问题讨论】:

    标签: generics scala pattern-matching


    【解决方案1】:
    def key[T](elm:T,pos:Int) = elm match { 
        case x:Int => x.toString.charAt(pos) 
        case s:String => s.charAt(pos) 
    }
    

    使用视图的解决方案:

    implicit def i2s(i:Int):String = i.toString
    def key2[T <% String](elm:T,pos:Int) = elm match { 
      case x:Int => x.charAt(pos) 
      case s:String => s.charAt(pos) 
    }
    

    【讨论】:

    • 很酷,这正在工作:) 但我的问题仍然存在。我怎样才能强迫 scala 认为 elm 是类型,例如 Int 以便我可以例如调用方法 elm.length ?
    • 第二种解决方案也适用于 x.length,而不是 x.charAt,以防您想递归地找到答案。
    • x is elm 但被视为 Int.
    【解决方案2】:

    我会说,你的问题是,你有两种你想操作的类型,一个 Int 和一个 String,你想在那个输入上执行一个 key-method,但你没有指定,什么你喜欢回来。

    我对 Int 的第一个想法是返回一个 Int。 toString().charAt(n) 看起来像是作弊的一种形式,但也许作弊是可以的,所以让我们开始作弊吧:

    def cheat (a: Any, n: Int) = a.toString ().charAt (n) 
    cheat (2345, 2) 
    // res414: Char = 4
    cheat ("foobar", 2) 
    // res415: Char = o
    

    这很好很容易,不是吗?但是,如果你想为 Int 的输入返回一个 Int,为 String 的输入返回一个字符串呢?对于 String 类型的输入,Char 似乎更自然,一个字节足以返回一个 0-9 的数字,但如果我们为 T 返回一个 T,我们有一个更简单的类型依赖性。

    我不相信我的解决方案,但我不相信作弊,第一个解决方案只是一种更复杂的作弊方式,不是吗?

    class Atti [T] (val fun: (Int => T)) {
      def at (n: Int): T = fun (n) 
    }
    

    我定义了一个atti-class,对于一个类型T,它需要一个函数,它接受一个I​​nt,并返回一个T,如果你在这个类上调用at,它会调用那个函数。

    现在我们定义一个函数 iGet,从 Int 中获取位置 n 的数字,我们使用两个参数列表,...

    def iGet (i: Int) (n: Int) : Int = {
      if (n == 0) i % 10
        else iGet (i / 10)(n - 1) }
    

    ...传递 Int,急切地对其进行操作,以定义部分定义的函数:

    val iAt = new Atti[Int] (iGet (2345) _)
     (0 to 3).map (iAt.at (_))
    // res412: scala.collection.immutable.IndexedSeq[Int] = Vector(5, 4, 3, 2)
    

    字符串的模拟函数和sAt的声明:

    def sGet (s: String) (n: Int) : String = "" + s.charAt (n)
    
    val sAt = new Atti[String] (sGet ("foobar") _) 
     (0 to 3).map (sAt.at (_))
    // res413: scala.collection.immutable.IndexedSeq[String] = Vector(f, o, o, b)
    

    我猜你看到 String 是从左到右计算的,而 Int 是从右到左计算的,就像你对问题的介绍一样。

    我不喜欢自己的是,带有有效负载“foobar”的 sAt 不再是字符串,并且 2345 以某种方式隐藏在 iAt 对象中。

    并且需要为每个字符串指定用于字符串的函数 - 这为您提供了比您要求的更大的灵活性,并且为每个实例提供了更多的工作。

    我尝试构建一个特征并将其混合到 Int 或 String 中,但没有成功:

    trait Key [T] { def at (n: Int): T }
    val s : String with Key[String] = "Foobar" { def at (n: Int) : String = "" + s.charAt (n) }  
    <console>:7: error: type mismatch;
     found   : Unit
     required: Int
           val s : String with Key[String] = "Foobar" { def at (n: Int) : String = "" + s.charAt (n) }
                                                                                                     ^
    

    【讨论】:

      【解决方案3】:
      def key[T](elm:T,pos:Int) = elm match {
        case x:Int => {
          def digit(number:Int, pos:Int):Int = {
            if(pos == 0) number % 10
              else digit(number/10, pos-1)
            }
          digit(x,x.length-pos-1)
        } 
        case x:String => x.charAt(pos)
      }
      

      【讨论】:

      • 同样的问题:值长度不是 Int digit(x,x.length-pos-1) 的成员
      • 呃。 length 不是 Int 的方法,但你可以取对数(以 10 为底)。
      • Int 没有长度方法。
      【解决方案4】:

      如何强制 Scala 将 T 转换为 诠释

      你不能。好吧,您可以进行一些隐式检查,但这比您必须做的要难得多。不要使用elm,而是使用x

      def key[T](elm:T,pos:Int) = elm match{
        case x:Int => {
          def digit(number:Int, pos:Int):Int = {
            if(pos == 0) number % 10
              else digit(number/10, pos-1)
          }
          digit(x,x.toString.length-pos-1)
        } 
        case x:String => x.charAt(pos)
      }
      

      【讨论】:

        猜你喜欢
        • 2013-12-21
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 2020-08-09
        • 2019-04-15
        • 2017-02-25
        相关资源
        最近更新 更多