我会说,你的问题是,你有两种你想操作的类型,一个 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,它需要一个函数,它接受一个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) }
^