4

i'm writing some scala code to emulate a python decorator. i'm considering implementing this by having the decorator extend a Function trait. the issue is that i want this decorator to extend a Function that accepts any number of arguments, and the only Function traits i can find only allow a specific number of arguments, e.g. Function1, Function2, etc.

does such a trait exist? alternatively, is there a better way to implement such a decorator?

Edit: I recast this question to be more clear at scala: memoize a function no matter how many arguments the function takes?.

Community
  • 1
  • 1
Heinrich Schmetterling
  • 6,614
  • 11
  • 40
  • 56

3 Answers3

2
scala> val bar: (Int*) => Int = {args => args.sum}
bar: (Int*) => Int = <function1>

scala> bar(1,2,3)
res4: Int = 6

Unfortunatelly, you can't use type inference here:

scala> val bar = {args: Int* => args.sum}
<console>:1: error: ';' expected but identifier found.
       val bar = {args: Int* => args.sum}
IttayD
  • 28,271
  • 28
  • 124
  • 178
0

There is not a function supertrait. You will have to wrap the method you want to decorate into an own class with an implicit. That class gonna have to handle the different method types. Then you have to create some class what generates your decorated method.

Or if you can you just create new methods like that:

def myF(x:Int,y:Int)={x*y}

def myF2(x:Int,y:Int)={myDecorator(myF(x,y))}
def myDecorator[X](f:=>X)={println("entering");val ret=f();println("exiting");ret}

or try:

def myF_old(x:Int,y:Int)=x*y 
def paramDecorator(x:Any*):List[Any]={/*do some match operations or something*/} 
def outputDecorator(x:Any*):Any={/*do some match operations or so*/} 
def myF(x:Int,y:Int):Int={
params=paramDecorator(x,y);
val res=myF_old(params(1),params(2));
outputDecorator(res);
}
Alex
  • 8,518
  • 4
  • 28
  • 40
  • can you give a few more details on the first method? – Heinrich Schmetterling Apr 29 '11 at 23:18
  • the second method doesn't allow the decorator to look at the arguments to the function that's decorated, right? – Heinrich Schmetterling Apr 29 '11 at 23:18
  • myF is the function you want to decorate. with myf2 you can modify the parameters and with myDecorator you can modify the results. – Alex Apr 30 '11 at 09:45
  • you can modify myDecorator to accept a function (int,int):Int and the two parameters so you could write def myF2(x:Int,y:Int)={myDecorator(myF,x,y)} – Alex Apr 30 '11 at 09:47
  • is there a way to programatically generate myF2 and myDecorator from a single function? my desired syntax is basically something like this. instead of the normal function definition that is undecorated: def myF(x:Int, y:Int)=x*y instead it would look like: def myF(x:Int, y:Int)=decorate({x*y}) or def myF = decorate (x:Int,y:Int) => x*y ... it's too much to ask of all users who ever write a function that we want to decorate to redefine something like myF2. – Heinrich Schmetterling May 03 '11 at 20:44
  • what makes it harder is that i need the decorator function to work no matter how many arguments there are. – Heinrich Schmetterling May 03 '11 at 20:47
  • so you do not need to operate on the parameters. just on the result? – Alex May 03 '11 at 20:58
  • no, both operation the parameters and manipulate the result. ideally this could be done if decorate had access to the parameters of the function object passed to it, potentially as a tuple. – Heinrich Schmetterling May 03 '11 at 21:01
  • you can use that approach. def myF_old(x:Int,y:Int)=x*y def paramDecorator(x:Any*):List[Any]{/*do some match operations or something*/} def outputDecorator(x:Any*):Any{/*do some match operations or so*/} def myF(x:Int,y:Int):Int={params=paramDecorator(x,y);val res=myF_old(params(1),params(2));outputDecorator(res);} – Alex May 03 '11 at 21:24
  • i'm going with the approach described here: http://stackoverflow.com/questions/5875767/scala-memoize-a-function-no-matter-how-many-arguments-the-function-takes/5877235#5877235 – Heinrich Schmetterling May 10 '11 at 00:29
0

I'm not sure what you try to accomplish, but if you have problems with the arity of functions, you can work on a Function1 which uses a Tuple as input parameter. As it is easy to convert between tupled and untuples versions for any function, this should be not too inconvenient. I could give you a code example if you would describe more detailed what you need.

Landei
  • 54,104
  • 13
  • 100
  • 195
  • when you declare the Function1 whose input is a Tuple, how do you specify that Tuple can itself be variable length? i cannot find anything like a TupleN or similar. – Heinrich Schmetterling May 02 '11 at 21:17