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

DuduAlul
  • 6,313
  • 7
  • 39
  • 63
  • 2
    you can access `a` in your function. Its bound up in a *closure* – hvgotcodes Jun 14 '11 at 22:34
  • 3
    That definition of functional programming is suspect; where did you get that from? There's nothing wrong with intermediate results in FP. – Jacob Jun 14 '11 at 22:34
  • 1
    Definition: http://www.ibm.com/developerworks/library/wa-javascript/index.html#functional – DuduAlul Jun 14 '11 at 22:36
  • _"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. – Matt Ball Jun 14 '11 at 22:40
  • 1
    I am trying to understand how do FP people overcome those "problems".. – DuduAlul Jun 14 '11 at 22:42
  • 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. – Neil Jun 14 '11 at 22:44
  • Since when is javascript a "pure functional" language? – Zirak Jun 14 '11 at 23:10
  • @Jacob is right, functional paradigm forbids mutation (changing the state), but **not** storing the intermediate results in variables. Think `let` in Haskell. – Mirzhan Irkegulov Apr 08 '13 at 06:55

3 Answers3

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.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • @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. – Raynos Jun 14 '11 at 22:50
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]
RHSeeger
  • 16,034
  • 7
  • 51
  • 41
  • 2
    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. – RHSeeger Jun 20 '11 at 14:55
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.

NSaran
  • 561
  • 3
  • 19