Reputation: 34498
Suppose I want to wrap an arbitrary function to add something like logging (or anything else). The wrapper should be generic and work for any f
which can be called with any kind of parameters.
createWrapper= (f) ->
wrapper= ->
# do the logging or whatever I want before I call the original
result= ???
# do whatever after the original function call
result
Usage would be:
g=createWrapper(f)
now g
should be called in any way f
would be called, like
result = g(1,2,3)
should return the same as
result = f(1,2,3)
And now I can use g
wherever I would use f
but it calls my wrapper function.
My question is: how should I call f
to get the result?
Upvotes: 1
Views: 76
Reputation: 34498
The answer is
f.apply @, arguments
Therefore the wrapper looks like
createWrapper= (f) ->
->
# do the logging or whatever I want before I call the original
result= f.apply @, arguments
# do whatever after the original function call
result
or if you don't want to do anything after the call
createWrapper= (f) ->
->
# do the logging or whatever I want before I call the original
f.apply @, arguments
or if you want to be a bit more explicit, you can use a splat. This has the advantage that the arguments are a list and you can apply list operations on the arguments.
createWrapper= (f) ->
(args...) ->
# do the logging or whatever I want before I call the original
result= f.apply @, args
# do whatever after the original function call
result
Here is some test code:
createWrapper= (f) ->
(args...) ->
# do the logging or whatever I want before I call the original
result= f.apply @, args
# do whatever after the original function call
result
class cl
i: 10
f: (x) ->
x + @i
getf: (x) ->
(x)=>@f(x)
c =new cl
f1 = c.getf()
g1 = createWrapper(f1)
if f1(1)!=g1(1)
throw new Error("failed f1 #{f1 1} != #{g1 1}")
f2 = (x) -> x+20
g2 = createWrapper(f2)
if f2(1)!=g2(1)
throw new Error("failed f2 #{f2 1} != #{g2 1}")
f3 = (args...) -> "#{args}"
g3 = createWrapper(f3)
if f3(1,2,3)!=g3(1,2,3)
throw new Error("failed f3 #{f3 1,2,3} != #{g3 1,2,3}")
f4 = -> arguments[0]
g4 = createWrapper(f4)
if f4(1)!=g4(1)
throw new Error("failed f4 #{f4 1} != #{g4 1}")
f5 = c.f
g5 = createWrapper(f5)
if f5.apply(c,[1])!=g5.apply(c,[1])
throw new Error("failed f5 #{f5.apply c,[1]} 1= #{g5.apply c,[1]}")
alert("""
Everything is OK:
f1 #{f1 1} == #{g1 1}
f2 #{f2 1} == #{g2 1}
f3 #{f3 1,2,3} == #{g3 1,2,3}
f4 #{f4 1} == #{g4 1}
f5 #{f5.apply c,[1]} == #{g5.apply c,[1]}
""")
Upvotes: 2
Reputation: 6726
Just run f()
createWrapper = (f) ->
wrapper= ->
# do the logging or whatever I want before I call the original
result= f()
# do whatever after the original function call
result
Upvotes: 0