scala 类型匹配

发布于 2024-11-07 18:23:30 字数 421 浏览 1 评论 0原文

我想编写一个通用方法来获取 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)
}

谢谢!

I want to write a generic method to get the element at position x of a String or Int.
Now my question is, how can I force Scala to convert T to Int or to call a Int specific method.

Here is the code:

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)
}

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

删除会话 2024-11-14 18:23:30
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) 
}
def key[T](elm:T,pos:Int) = elm match { 
    case x:Int => x.toString.charAt(pos) 
    case s:String => s.charAt(pos) 
}

A solution using views:

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) 
}
乖乖哒 2024-11-14 18:23:30

我想说,你的问题是,你有两种你喜欢操作的类型,一个 Int 和一个 String,并且你想对该输入执行一个键方法,但你没有指定你想要什么返回。

我对 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,该怎么办?对于 String 类型的输入,Char 似乎更自然,并且一个字节足以返回 0-9 之间的数字,但如果我们为 T 返回 T,我们就有更简单的类型依赖关系。

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

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

我定义了一个 atti-class,对于类型 T 需要一个函数,该函数接受一个 Int,并返回一个 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) }
                                                                                                 ^

I would say, your problem is, that you have two types on which you like to operate, an Int and a String, and you want to perform a key-method on that input, but you don't specify, what you like to return.

My first idea for the Int would be to return an Int. toString().charAt (n) seems like a form of cheating, but maybe cheating is alright, so let's start cheating:

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

That was nice and easy, wasn't it? But what, if you like to return an Int for an input of Int, and an String, for an Input of String? Char seems more natural for an input of type String, and a byte would be sufficient to return a digit from 0-9, but we have a simpler type dependency, if we return a T for a T.

I'm not convinced of my solution, but I'm not convinced about the cheating, and the first solutions are only a more complicated way of cheating, aren't they?

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

I defined an atti-class, which, for a type T needs a function, which takes an Int, and returns an T, and if you call at on this class, it will invoke that function.

Now we define a function iGet, to get from an Int the digit at position n, and we use two parameter lists, ...

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

... to pass the Int, on which to operate, eagerly, to define a partially defined function:

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

Analog function for a string, and declaration of 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)

I guess you see that the String is evaluated left to right, while the Int is evaluated right to left, as in your introduction to the problem.

What I don't like myself is, that sAt with the payload 'foobar' isn't a String anymore, and 2345 is somehow hidden in the iAt-object.

And the function to use for a String needs to be specified for every String - which gives you more flexibility than you asked for, and more work for every instance.

I tried to build a trait and mix it into Int or String, but wasn't successful:

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) }
                                                                                                 ^
蓝梦月影 2024-11-14 18:23:30
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)
}
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)
}
旧话新听 2024-11-14 18:23:30

如何强制 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)
}

how can I force Scala to convert T to
Int

You can't. Well, you could with some implicit checking, but that's way harder than what you have to do. Instead of using elm, use 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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文