1

Is there a way to achieve the code bellow with Javascript (ES6)?

If yes, how can I do it? I try this example, but it didn't work.

const funcA = (callback, arg1) => {
  console.log("Print arg1: " + arg1); /* Print arg1: argument1 */
  let x = 0;
  x = callback(x, );
  return x;
}

const funcB = (x, prefix) => {
  console.log("Print prefix: " + prefix); /* Print prefix: PREFIX_ */
  x = x + 1;
  return x;
}

/* Exec function funcA */
let x = funcA(funcB( ,"PREFIX_"), "argument1");
console.log("Value of x: " + x); /* Value of x: 1 */
Pedro Gabriel Lima
  • 1,122
  • 1
  • 9
  • 24

3 Answers3

2

This is an approach with a defined placeholder as symbol to identify the parameter which is not yet set.

It features a this object which is bind to the calling function for further check and evaluation.

If the combined array of arguments object and this.arg has no more placeholder items, the function is called with parameters and return the function call.

If not, the new arguments array is bind to the function and returnd.

[?] denotes the placeholder symbol

 funcB    x    prefix       this.args        args       action
-------  ---  ---------  -------------  --------------  ------------------------------
1. call  [?]  "PREFIX_"                 [?], "PREFIX_"  return calling fn w/ bound args
2. call   0      [?]     [?], "PREFIX_"  0,  "PREFIX_"  return fn call with args
3. call   0   "PREFIX_"                                 return 1

(Of course it could be a bit shorter and delegated to another function, but it's a proof of concept.)

function funcA(callback, arg1) {
    console.log('funcA', callback, arg1)
    return callback(0, placeholder);
}

function funcB(x, prefix) {
    var args = this && this.args || [],
        temp = Array.from(arguments);

    console.log('funcB', isPlaceholder(x) ? '[?]' : x, isPlaceholder(prefix) ? '[?]' : prefix);

    // placeholder part
    if (temp.some(isPlaceholder)) {
        temp.forEach((a, i) => isPlaceholder(a) && i in args || (args[i] = a));
        return args.some(isPlaceholder)
            ? funcB.bind({ args })
            : funcB(...args);
    }

    // origin function body
    return x + 1;
}

const
    placeholder = Symbol('placeholder'),
    isPlaceholder = v => v === placeholder;

console.log("Value of x: " + funcA(funcB(placeholder, "PREFIX_"), "argument1"));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • nice! +1. Could you explain some details of your example? 1. In funcB, where it come the variable "arguments"? It's a default parameter for functions? 2. In the output, it was printed "funcB 0 [?]" and "funcB 0 PREFIX_", that means funcB was called twice. So the first time it called for binding funcB in funcA, the second time was for returned funcB(...args)? 3. The first call for funcB was made in "funcA(funcB(placeholder, "PREFIX_"), "arguments")", the second call was made in "return callback(0, placeholder)"? – Pedro Gabriel Lima Jan 19 '18 at 12:38
  • 1
    every function in Javascript supplies [`arguments` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments), which is an array like object with all paramters of the actual function. it is right, the calling series, as you stated, but the function is called three times. it always checks if there is no placeholder in the `arguments` list. if so, it returns the origin function body evaluation. – Nina Scholz Jan 19 '18 at 12:49
1

Partial application is not yet possible in js. You need another arrow function that acts as a callback:

funcA(x => funcB(x ,"PREFIX_"), "argument1");

To call that you don't need that extra comma:

x = callback(x)

Somewhen this proposal might allow to write this:

 funcA( funcB(?, "PREFIX_"), "argument1")
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
-1

One approach would be to define a default parameter that is a function for the first parameter passed to funcA and use var to define x when funcA is called

const funcA = (callback, arg1) => {
  console.log("Print arg1: " + arg1);
  let x = 0;
  x = callback(x, arg1);
  return x;
}

const funcB = (x, prefix) => {
  console.log("Print prefix: " + prefix);
  x = x + 1;
  return x;
}

/* Exec function funcA */
var x = funcA(x = () => funcB(x = 0 ,"PREFIX_"), "argument1");
console.log("Value of x: " + x);
guest271314
  • 1
  • 15
  • 104
  • 177
  • If you see in my example, I didn't pass the arg1 as argument to callback. Would it make difference? – Pedro Gabriel Lima Jan 18 '18 at 19:09
  • @PedroGabrielLima Why did you not pass the `arg1` argument? How does that change the expected result? What are you trying to achieve? – guest271314 Jan 18 '18 at 19:10
  • It this example it's not so clear, but the fact that I isolate the arguments in funcB turn the code modular. In your example, arg1 is part of funcA, but I want funcA be immutable. That way, if a want pass a funcC instead of funcB to funcA, it won't depend on the variable arg1. I hope be clearly about that hehe. – Pedro Gabriel Lima Jan 18 '18 at 19:22
  • Do you mean that where `arg1` is not specifically passed `prefix` will still be defined at `funcB`? That is, a default value will be set, and the default value can be the adjacent defined argument? – guest271314 Jan 18 '18 at 19:25
  • From this "Do you mean that where arg1 is not specifically passed prefix will still be defined at funcB?", yes! – Pedro Gabriel Lima Jan 18 '18 at 19:29
  • See my code again! I edited and add the output from the console.log. The "PREFIX_" is printed inside funcB and arg1 is printed inside funcA! – Pedro Gabriel Lima Jan 18 '18 at 19:34
  • 1
    @PedroGabrielLima You can set `prefix` as a default parameter at `funcN`; e.g., `const fn = ({x = 0, prefix = "PREFIX_"} = {x:0, prefix:"PREFIX_"}) => { console.log(x, prefix) }; fn(); fn({x:2});` see also [Can we set persistent default parameters which remain set until explicitly changed?](https://stackoverflow.com/questions/43466657/can-we-set-persistent-default-parameters-which-remain-set-until-explicitly-chang) – guest271314 Jan 18 '18 at 19:36