JavaScript callbacks and functional programming
Asked Answered
A

3

14

"Functional programming describes only the operations to be performed on the inputs to the programs, without use of temporary variables to store intermediate results."

The question is how to apply functional programming and yet use async modules that utilize callbacks. In some case you had like the callback to access a variable that a function that invokes the async reference poses, yet the signature of the callback is already defined.

example:

function printSum(file,a){
     //var fs =....
     var c = a+b;
     fs.readFile(file,function cb(err,result){
          print(a+result);///but wait, I can't access a......
     });
}

Of-course I can access a, but it will be against the pure functional programming paradigm

Apathy answered 14/6, 2011 at 22:31 Comment(8)
you can access a in your function. Its bound up in a closureWimberly
That definition of functional programming is suspect; where did you get that from? There's nothing wrong with intermediate results in FP.Semiotic
Definition: ibm.com/developerworks/library/wa-javascript/…Apathy
"Of-course I can access a, but it will be against the pure functional programming paradigm" - what is the point? Closures are nice. Use them.Colonist
I am trying to understand how do FP people overcome those "problems"..Apathy
Aren't closures part of FP? For instance, you can write a function that takes a parameter and returns a function that takes a parameter and returns the sum of the two. So the inner function needs to know what the value of the parameter was at the time of the outer function call.Cher
Since when is javascript a "pure functional" language?Arsenide
@Semiotic is right, functional paradigm forbids mutation (changing the state), but not storing the intermediate results in variables. Think let in Haskell.Equalitarian
B
10
fs.readFile(file, (function cb(err,result){
    print(this.a+result);
}).bind({a: a});

Just inject context with variables and scope into the function if you must.

Because you complain about the API

fs.readFile(file, (function cb(a, err,result){
    print(a+result);
}).bind(null, a);

It's called currying. This is a lot more FP.

Brooks answered 14/6, 2011 at 22:44 Comment(1)
@MrOhad it's the only other way to inject state into the callback. Either go up the scope chain or inject data into the context. There is another option actually. I added the currying example which is probably better.Brooks
T
1

I think the problem is that you're misunderstanding what they mean by the use of an intermediate value (or they're misrepresenting it, I haven't read the link). Consider that a variable in a functional language is the definition of something, and that definition cannot change. It's perfectly acceptable to use names for values/formulas in functional programming, as long as they don't change.

function calculate(a,b,c) {
    // here we define an name to (a+b) so that we can use it later
    // there's nothing wrong with this "functionally", since we don't 
    // change it's definition later
    d = a + b;
    return c * d;
}

On the other hand, the following would not be ok, functionally

function sum(listofvalues) {
    sum = 0;
    foreach value in listofvalues
        // this is bad, since we're re-defining "sum"
        sum += value;
    return sum
}

For something closer to what you had in your code... consider you have a function call map that takes a list of things and a function to apply to a thing and returns a new list of things. It's perfectly acceptable to say:

function add_value(amount) {
    amount_to_incr = amount * 2;
    return function(amount, value) {
        // here we're using that "amount" value provided to us
        // the function returned will always return the same value for the same
        // input... its "referentially transparent"
        // and it uses the "intermediate" value of amount_to_incr... however, since 
        // that value doesn't change, it's fine
        return amount_to_incr + value;
    }
}
map [1,2,3] add_value(2) ;// -> [3,4,5]
Trisyllable answered 15/6, 2011 at 4:3 Comment(1)
Given the multiple negative downvotes, I'd appreciate comments about what it is that warranted them. It would be nice to know where I was wrong, and what I can correct.Trisyllable
C
0
function printSum(file, a) {
     //var fs =....
     var c = a + b;
     fs.readFile(file, function cb(err, result, aa = a) {
          print(aa + result);
     });
}

With the default parameters nowadays, a can be passed into the callback.

Cleotildeclepe answered 26/4, 2019 at 0:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.