2

I am new to functional programming and I am having a big trouble to understand what is actually going on in the following function.

const someFnc = arg => arg("You can print that string :)");
someFnc(msg => console.log(msg))

From what I can understand is that I actually pass a function to the function someFnc. But how can the function arg be self invoked as arg(...) (in my example with an argument of a string)? I am really confused in that concept.

2
  • 1
    arg isn’t self-invoked. The invocation is in the function body of someFnc (arg("You can print that string :)")). Commented Aug 8, 2017 at 18:11
  • 1
    I'm not sure what you mean by "self invoked". The someFnc invokes the function arg that it declared as a parameter when it executes. Commented Aug 8, 2017 at 18:15

2 Answers 2

3

If you break it apart you can see what's going on:

function someFunction(fn) {
    fn('hello')
}

function logFunction(msg) {
    console.log(msg)
}

someFunction(logFunction)

Essentially, someFunction takes an argument (fn) which should be a function.

It then passes a string ("hello") as the argument for that function (fn('hello')).

someFunction then executes the function it received, so it's executing logFunction('hello').

logFunction takes a string argument and console logs it (console.log('hello'))

Arrow functions ((arg) =>) are a shorthand for writing function(arg) { }.

Sign up to request clarification or add additional context in comments.

Comments

0
const someFnc = arg => arg("You can print that string :)");

Is just the anonymous way to make:

function someFnc (arg) {
  arg("You can print that string :)");
}

The other anonymous function you define:

msg => console.log(msg)

This makes a anoynous function that takes msg and uses it to a call to console.log. Since it just calls console.log with the first argument it is a wrapper that does nothing. You can indeed just replace it with console.log:

someFnc(console.log)

Now using substitution rules we can replace a function call with the body of the function with the argument replaced for the bound variable, thus:

arg("You can print that string :)");        // replace arg with console.log
// ===
console.log("You can print that string :)");

Now when you write barewords in JavaScript, like parseInt, it is a variable. It evaluates to a function. Thus parseInt("10"); // ==> 10. In the body of your function arg is a variable that gets the value of the attribute log on the object console. It is a function just like parseInt. Variable are values and functions are also values.

When you pass a value to as function it is bound to the variable in it's definition. It can even shadow existing functions:

((parseInt, value) => parseInt(value))(Number, "10"); 
// => 10

So the rule is replace the bound variables with the arguments, thus it is really:

Numer("10"); //=> 10

Variables are just names for values. A function is a value you can put () after to apply, optionally with arguments within.

4 Comments

”just the anonymous way” — Since ES 2015 the function in the above snippet would have the inferred function name someFnc.
@Xufox Yes, that is true. It makes debugging much easier that the parser decorates the function object from the closest binding, but the expression that is assigned makes an anonymous function. IMO ((fun=>fun.name)(()=>1)) could have returned fun too, but it doesn't.
Isn't msg => console.log(msg) a lambda function not a wrapper?
It is both. lambda is usually a name for anonymous functions and both msg => console.log(msg) is a lambda that can replace console.log in your code without changing the functionality. The second it doesn't change anything it's a wrapper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.