0

How are arguments from wrapper functions passed on to functions after the keyword 'return'?

function greeting(name){
    console.log("Hello, " + name)
}


function wrapper(f){
    return function(args){
        
        if(typeof(f)==='function'){
            console.log("before executing wrapped")
            f(args)
            console.log("after executing wrapped")
        }
        else{
            return f
        }        
    }
}

let a = wrapper(greeting)

a("Maria")

So, this works fine, and prints the intended

before executing wrapped
Hello, Maria
after executing wrapped 

because arguments from f are passed on to the line return function(args){ . However, had I not the returnkeyword there, the arguments from fwouldn't have been passed on to the anonymous function. How/why does this happen?

Example of a non-working-version of similar code (only changes to the wrapper function):

function greeting(name){
   console.log("Hello, " + name)
}

function wrapper(f){
   
   if(typeof(f)==='function'){
       
       function a (args){
              
           console.log("before executing wrapped")
           f(args)
           console.log("after executing wrapped")
       }

       return a(args)
   }
   else{
       return f
   }  
}

let a = wrapper(greeting)

a('Maria')

Of course, this returns ReferenceError: args is not defined.

I'm curious to know what's up with the return keyword that makes the first piece of code work.

Vitor Hugo
  • 25
  • 1
  • 7
  • @Pointy first of all, thanks for your feedback. but, if ```f``` is nor a function then how can the ```if(tyopeof(f)==='function')```be being evaluated to ```true``` ? – Vitor Hugo Jul 19 '22 at 15:07
  • "I'm curious to know what's up with the return keyword that makes the first piece of code work." — You seem happy enough with the idea of passing a function as an argument to a another function. What's confusing about returning one from a function? – Quentin Jul 19 '22 at 15:10
  • However, had I not the returnkeyword there, the arguments from fwouldn't have been passed on to the anonymous function" — Yes they would. – Quentin Jul 19 '22 at 15:10
  • @Quentin thanks, for commenting. I don't see how they would. how could I fetch the arguments from f inside the wrapper function without the ```return``` keyword (other than using a callback function)? – Vitor Hugo Jul 19 '22 at 15:14
  • `f` **is** the argument. It's a variable. You can use it in the function you define inside `wrapper`. – Quentin Jul 19 '22 at 15:17
  • @VitorHugo I'm not sure what you mean by "fetch the arguments from `f` inside the wrapper function` – Dave Newton Jul 19 '22 at 15:17
  • @DaveNewton thanks, Dave. I mean how can you make the arguments from ```f```be passed to the variable ```args``` – Vitor Hugo Jul 19 '22 at 15:29
  • @VitorHugo In your second example you're passing the results of *calling* `a`, with an undefined `args` parameter, as you noted--in the original version `args` *is* the parameter to the anonymous function so they're defined. – Dave Newton Jul 19 '22 at 15:29
  • @VitorHugo You can't; the only thing you have in `wrapper` is the function `f`, you know nothing at that point about how `f` is being called. In your second example you need to return `a`, not the result of *calling* `a`. The only difference then is that instead of returning an anonymous function you're returning a named function--that doesn't actually change anything functionally. – Dave Newton Jul 19 '22 at 15:30
  • @DaveNewton that is true. It's like BigLiao pointed out in his answer. I still don't get how ```args``` can be identified with the argument of the ```a('Maria')``` – Vitor Hugo Jul 19 '22 at 15:36

1 Answers1

0

How can args be identified with 'Maria'?

The anonymous function in function wrapper, let's name it func1; So the code equals to:

function wrapper(f){
  function func1(args) {
    // do someting
  }

  return func1
}

let a = wrapper(greeting), actually a is func1;

Calling a("Maria") is just like calling func1("Maria"), because a is func1. So "Maria" is passed to func1 as the variable args.

Makes the second code work

Just return a function(not a function call) in your second code.

function greeting(name){
   console.log("Hello, " + name)
}

function wrapper(f){
   
   if(typeof(f)==='function'){
       
       function a (args){
              
           console.log("before executing wrapped")
           f(args)
           console.log("after executing wrapped")
       }

       return a // <--- change at here
   }
   else{
       return f
   }  
}

let a = wrapper(greeting)

a('Maria')

Actually, those writing are equivalent:

function wrapper(f){
    return function(args){
        
        if(typeof(f)==='function'){
            console.log("before executing wrapped")
            f(args)
            console.log("after executing wrapped")
        }
        else{
            return f
        }        
    }
}

function wrapper(f){
   function a(args){
        
        if(typeof(f)==='function'){
            console.log("before executing wrapped")
            f(args)
            console.log("after executing wrapped")
        }
        else{
            return f
        }        
    }
    return a
}

function wrapper(f){
   
   if(typeof(f)==='function'){
       
       function a (args){
              
           console.log("before executing wrapped")
           f(args)
           console.log("after executing wrapped")
       }

       return a
   }
   else{
       return f
   }  
}

function wrapper(f){
   
   if(typeof(f)==='function'){
       
       return function (args){
              
           console.log("before executing wrapped")
           f(args)
           console.log("after executing wrapped")
       }
   }
   else{
       return f
   }  
}
BigLiao
  • 507
  • 3
  • 9
  • Thanks for your answer. the thing I don't understand is: how can ```args```be identified with 'Maria'. Can you explain that in your answer, please? – Vitor Hugo Jul 19 '22 at 15:26
  • @VitorHugo Because that's what you call the wrapped function with. `wrapper` *returns a function* (iff a function is passed in). That function, whether it's anonymous or not, has a parameter named `args`. `args` will be whatever you call the function wrapper with. It's no different than calling a non-wrapped function. – Dave Newton Jul 19 '22 at 15:36
  • how can ```args``` be identified with the argument of the a('Maria') – Vitor Hugo Jul 19 '22 at 15:37
  • @VitorHugo I don't understand. That's what you're passing to the function returned by `wrapper`. What else could it be other than what you pass in? – Dave Newton Jul 19 '22 at 15:38
  • @VitorHugo Consider this function: `const multBy = x => n => x * n`. It's a function returning a function. If you create `const by5 = multBy(5)` then `by5` is a function you call with a number. `by5(10)` passes `10` to the function returning by `multBy`. That function's parameter is `n`, and it'll be whatever you pass in. You're doing the same thing in this code, except the function returned by `multBy` would call the function passed into it. – Dave Newton Jul 19 '22 at 15:43
  • @VitorHugo So a minimal wrapper would be `const wrap = f => args => { console.log(\`wrapper: ${args}\`); f(args); }`. Create a reference to the returned function by passing in a function: `const wrap1 = wrap(x => console.log(x))`. Now when you call `wrap1` with a parameter it'll be logged twice, but the wrapper will add something to the call: `wrap1('hi')` – Dave Newton Jul 19 '22 at 15:46
  • @DaveNewton thanks for taking the time to try to explain that to me. I would understand the logic if I could define ```wrapper``` like this (mock-code)```function wrapper(f(args))``` . In this case, there would be some bridge between the argument passed to wrapper when we call it and the identifier ```args``` . But, as it is, why is args being associated with 'Maria' is what I don't get – Vitor Hugo Jul 19 '22 at 15:46
  • @VitorHugo But `f(args)` *calls `f`*. You need to pass the function itself, a function *reference*, not the results of calling the function. – Dave Newton Jul 19 '22 at 15:47
  • @VitorHugo https://stackoverflow.com/a/8537635/438992 and/or https://stackoverflow.com/a/7969111/438992 may help explain further. – Dave Newton Jul 19 '22 at 15:51
  • @DaveNewton thanks once again. But ```function a (args)```is not calling ```f``` (second piece of code, which you already explained, doesn't work because I'm returning a function call, instead of the function itself - which is understandable and fine. Thing that I'm struggling to wrap my mind around is: how is args being identified with the argument we're sending, if I there's no code line making that that connection – Vitor Hugo Jul 19 '22 at 15:56
  • @DaveNewton thanks. I'm gonna check those out – Vitor Hugo Jul 19 '22 at 15:57
  • @BigLiao thanks, just got it. Don't know why you were downvoted. Your first answer was not perfectly formatted but it definitely took me in the right direction, and I wouldn't downvote it in any way. this edited one is really good. I would just emphasize that * a("Maria") is just like calling func1("Maria") * because we're returning ```funct1```. I know this is obvious, but it would make your answer perfect for beginners. Thanks. Thanks to @DaveNewton as well for his effort in trying to make me understand this wrapper concept – Vitor Hugo Jul 19 '22 at 16:08