2.24. Generic Functions

Felix functions and procedures can be generic too. Here is a simple example.
Start felix section to tut/tutorial/tut-1.24-0.flx[1 /1 ]
     1: #line 2840 "./lpsrc/flx_tutorial.pak"
     2: header "#include <iostream>";
     3: type int = "int";
     4: proc print[T]:T="std::cout << $1 << std::endl;";
     5: fun fst[T,U](x:T,y:U): T ={ return x; }
     6: fun snd[T,U](x:T,y:U): U ={ return y; }
     7: 
     8: val x = (1,2);
     9: print[int] (fst[int,int] x);
    10: print[int] (snd[int,int] x);
    11: 
    12: proc pp[T] (x:T) { print[T](x); }
    13: 
    14: pp[int] (snd[int,int] x);
End felix section to tut/tutorial/tut-1.24-0.flx[1]
Start data section to tut/tutorial/tut-1.24-0.expect[1 /1 ]
     1: 1
     2: 2
     3: 2
End data section to tut/tutorial/tut-1.24-0.expect[1]
When declaring a generic function or procedure, if one of the parameters has the type of a type variable which is not used elsewhere, you can leave out the type variable, and one will be synthesised for you. Synthesised type variables are added to the type variable list at the end. For example:
Start felix section to tut/tutorial/tut-1.24-1.flx[1 /1 ]
     1: #line 2869 "./lpsrc/flx_tutorial.pak"
     2: header "#include <iostream>";
     3: type int = "int";
     4: proc print[T]:T="std::cout << $1 << std::endl;";
     5: fun fst(x,y) = { return x; }
     6: fun snd(x,y) = { return y; }
     7: 
     8: val x = (1,2);
     9: print[int] (fst[int,int] x);
    10: print[int] (snd[int,int] x);
    11: 
    12: proc pp[T] (x:T) { print[T](x); }
    13: 
    14: pp[int] (snd[int,int] x);
End felix section to tut/tutorial/tut-1.24-1.flx[1]
Start data section to tut/tutorial/tut-1.24-1.expect[1 /1 ]
     1: 1
     2: 2
     3: 2
End data section to tut/tutorial/tut-1.24-1.expect[1]
Note in this example, the return type cannot be stated since it depends on a synthesised type variable.

When there is only one argument which has a type which is a type variable, then if the type variable is omitted, the parentheses can also be omitted. This is particularly useful with curried declarations.

Note carefully that in the call to pair below, both the type subscripts must be given explicity, because they cannot be deduced from the argument.

Start felix section to tut/tutorial/tut-1.24-2.flx[1 /1 ]
     1: #line 2903 "./lpsrc/flx_tutorial.pak"
     2: #import <flx.flxh>
     3: fun pair1 x y = { return x,y; }
     4: fun pair2[t,u] (x:t) (y:u) = { return x,y; }
     5: fun diag x = { return x,x; }
     6: fun fst (x,y) = { return x; }
     7: fun snd (x,y) = { return y; }
     8: 
     9: {
    10:   val x34 = pair1[int,int] 3 4;
    11:   val a = fst x34;
    12:   val b = snd x34;
    13:   print a; print ","; print b; endl;
    14: };
    15: 
    16: {
    17:   val x34 = pair2[int,int] 3 4;
    18:   val a = fst x34;
    19:   val b = snd x34;
    20:   print a; print ","; print b; endl;
    21: };
    22: 
    23: val x22 = diag 2;
    24: val x = fst x22;
    25: val y = snd x22;
    26: print x; print ","; print y; endl;
End felix section to tut/tutorial/tut-1.24-2.flx[1]
Start data section to tut/tutorial/tut-1.24-2.expect[1 /1 ]
     1: 3,4
     2: 3,4
     3: 2,2
End data section to tut/tutorial/tut-1.24-2.expect[1]