Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to code generic return types in Scala similar to C++ templates?

In C++ I can do the following:

template<typename T, typename V>
struct{
    void operator()(T _1, V _2){
        _2.foo( _1 );
    }
};

which lets me arbitrarily decide to use any object which has some method called "foo" that takes some type "T" without specifying in advance either the argument type of the "foo" function nor the return type of said function.

When I look at Scala, see traits like Function1, and am playing around with function definitions like

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 )

I look at myself and think why can't I do the same thing? Why does "baz" return an Any? Can't it deduce the actual return type at compile time? Why do I have to declare the return type of "foo" if I might not even use it?

I'd like to be able to do

def biff[T,V:{def foo( x:T ):Unit}] = //something

or

def boff[T<:{def foo( x:Double ):_}]( y:T ) = y.foo _

Can you do this and am I just missing something? Or if not, why not?

like image 835
wheaties Avatar asked Nov 17 '10 03:11

wheaties


People also ask

Are generics and templates the same?

Comparing Templates and GenericsGenerics are generic until the types are substituted for them at runtime. Templates are specialized at compile time so they are not still parameterized types at runtime.

What is a generic class class template?

Templates are the foundation of generic programming, which involves writing code in a way that is independent of any particular type. A template is a blueprint or formula for creating a generic class or a function.

Do generics exist in C?

Generics are syntax components of a programming language that can be reused for different types of objects. Typically, generics take the form classes or functions, which take type(s) as a parameter.

Does c language have templates?

C has no templates like C++, though you can achieve something similar with "clever" (or WTFey, depending on how you look at it) use of #define macros. However, take a look at how for example GLib does it for singly linked lists or doubly linked lists.


3 Answers

Update:

Actually, you can do much better, and the type inferencer will help you:

def boff[T,R](y: T)(implicit e: T <:< {def foo(x: Double): R}) = e(y).foo _

For baz, the same technique will improve type inference:

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

You can do better by currying:

def baz[T,R](x: T)(f: T => R) = f(x)

First solution:

The type inferencer won't supply the T type for you, but you can do:

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]
}
like image 102
Aaron Novstrup Avatar answered Sep 21 '22 12:09

Aaron Novstrup


The fundamental distinction between Scala and C++ is that each class in Scala is compiled once, and then becomes available as-is for use with anything that depends on it, whereas a templated class in C++ must be compiled for every new dependency.

So, in fact, a C++ template generates N compiled classes, while Scala generates just one.

Can't it deduce the actual return type at compile time?

Because it must be decided at the time the class is compiled, which may be different than the time its use is compiled.

like image 22
Daniel C. Sobral Avatar answered Sep 22 '22 12:09

Daniel C. Sobral


For foo:

def foo[R,T<:{def foo():R}]( arg:T ) = ...

In case of baz, you say that V must be a function from T to some type. This type can't appear in result type: how could you write it? So the compiler can only infer that the result type is Any. If you give it a name, however, you get

scala> def baz[T,R,V<:Function1[T,R]]( x:T, y:V ) = y( x )
baz: [T,R,V <: (T) => R](x: T,y: V)R
like image 34
Alexey Romanov Avatar answered Sep 21 '22 12:09

Alexey Romanov