在C++中,我可以执行以下操作:
template<typename T, typename V>
struct{
void operator()(T _1, V _2){
_2.foo( _1 );
}
};
Run Code Online (Sandbox Code Playgroud)
这让我随意决定使用任何有一些名为"foo"的方法的对象,它采用某种类型"T",而不事先指定"foo"函数的参数类型和所述函数的返回类型.
当我看到Scala时,看到像Function1这样的特征,并且正在使用像.这样的函数定义
def foo[T<:{def foo():Unit}]( arg:T ) = //something
def bar( x:{def foo():Unit} ) = //something
def baz[T,V<:Function1[T,_]]( x:T, y:V ) = y( x )
Run Code Online (Sandbox Code Playgroud)
我看着自己,想想为什么我不能做同样的事情?为什么"baz"会返回Any?它不能在编译时推断出实际的返回类型吗?如果我甚至不使用它,为什么我必须声明返回类型"foo"?
我希望能够做到
def biff[T,V:{def foo( x:T ):Unit}] = //something
Run Code Online (Sandbox Code Playgroud)
要么
def boff[T<:{def foo( x:Double ):_}]( y:T ) = y.foo _
Run Code Online (Sandbox Code Playgroud)
你能做到这一点,我只是错过了一些东西吗?如果没有,为什么不呢?
Aar*_*rup 11
更新:
实际上,你可以做得更好,类型推断器将帮助你:
def boff[T,R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _
Run Code Online (Sandbox Code Playgroud)
因为baz,相同的技术将改进类型推断:
def baz[T,R,V]( x:T, y:V )(implicit e: V <:< (T => R)) = e(y).apply( x )
scala> baz(1, (i: Int) => i+1)
res0: Int = 2
Run Code Online (Sandbox Code Playgroud)
你可以通过currying做得更好:
def baz[T,R](x: T)(f: T => R) = f(x)
Run Code Online (Sandbox Code Playgroud)
第一解决方案
类型推断器不会T为您提供类型,但您可以这样做:
class Boff[T] {
def apply[R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _
}
object boff {
def apply[T] = new Boff[T]
}
Run Code Online (Sandbox Code Playgroud)
Scala和C++之间的根本区别在于Scala中的每个类都被编译一次,然后可以原样用于依赖它的任何东西,而C++中的模板化类必须为每个新依赖项编译.
因此,事实上,C++模板生成N个编译类,而Scala只生成一个.
它不能在编译时推断出实际的返回类型吗?
因为必须在编译类时决定,这可能与编译它的时间不同.
| 归档时间: |
|
| 查看次数: |
1747 次 |
| 最近记录: |