Quote:

> Has anyone ever explored the idea of using JS (pure) as a language for

> functional programming? It seems ideally suited to me but I'm not an

> expert in FP.

I'm not an expert in either functional programming or

JavaScript. But here's my take: functions are first-class

objects in JS--they can be passed to, returned from, or

created by a function, and can be bound to variables.

JS supports recursion and has garbage collection. What

more do you need? After writing the code below, I'd say

nothing. However, I wouldn't use the word "ideal", as

the syntax gets a little awkward compared to say, Haskell.

I welcome comments on either the JavaScript or functional

programming aspects of the following.

/**

* Functional programming in JavaScript

*/

/**

* This was developed on Windows Scripting Host. To use

* on other environments change WScript.echo() to whatever

* displays a string on the console.

*/

function trace(str) {WScript.echo(str + " -> " + eval(str))}

trace("2 + 2")

/**

* Given a number n, returns a string of the form

* '"a1", "a2", ..., "an"'.

*

* Useful in constructing functions because the runtime won't

* allow changing a function's length property (number of

* arguments expected) after the function has been created.

*/

function make_formal_arg_list(n) {

if (0 == n) {

return ""

}

return make_formal_arg_list(n - 1) + "\"a" + n + "\","

Quote:

}

trace("make_formal_arg_list(0)")

trace("make_formal_arg_list(3)")

/**

* Given a number n, returns a string of the form

* ", arguments[0], arguments[1], ..., arguments[n-1]".

*

* What is really needed is a way to call a function with

* a program generated argument array (like apply but

* without the "thisArg" parameter.)

*/

function make_actual_arg_list(n) {

if (0 == n) {

return ""

}

var n_1 = n - 1

return make_actual_arg_list(n_1) + ", arguments[" + (n_1) + "]"

Quote:

}

trace("make_actual_arg_list(0)")

trace("make_actual_arg_list(3)")

/**

* Given a function f of n arguments, and an argument a1,

* returns a new function g of n-1 arguments such that

* f(a1, a2, ..., an) == g(a2, ..., an).

*/

function bind1st(f, a) {

var num_args = f.length - 1

var g = eval("new Function(" + make_formal_arg_list(num_args)

+ "\"return arguments.callee.f(arguments.callee.a"

+ make_actual_arg_list(num_args) + ")\")")

g.f = f

g.a = a

return g

Quote:

}

function add(x, y) {return x + y}

var succ = bind1st(add, 1)

trace("succ(succ(40))")

/**

* Given a function f of n arguments, returns a new function g

* of 1 argument such that f(a1, a2, ..., an) == g(a1)(a2)...(an).

*/

function curry(f) {

if (f.length < 2) {

return f

}

else

{

var g = new Function("a1",

"return curry(bind1st(arguments.callee.f, arguments[0]))")

g.f = f

return g

}

Quote:

}

function triplet(a, b, c) {return [a, b, c]}

trace("triplet('X', 'Y', 'Z')")

trace("curry(triplet)('A')('B')('C')")

/**

* Given a 2 argument function, returns a new function g,

* such that f(x,y) == g(y, x).

*/

function flip(f) {

var g = eval("new Function(" + make_formal_arg_list(2)

+ "\"return arguments.callee.f(arguments[1], arguments[0])\")")

g.f = f

return g

Quote:

}

function minus(x, y) {return x - y}

var pred = curry(flip(minus))(1)

trace("pred(pred(44))")

/**

* Given 1-argument functions f and g, returns a new function h,

* such that f(g(x)) == h(x).

*/

function compose(f, g) {

var h = new Function("x",

"return arguments.callee.f(arguments.callee.g(arguments[0]))")

h.f = f

h.g = g

return h

Quote:

}

var two_to_the = curry(Math.pow)(2)

trace("two_to_the(8)")

trace("compose(two_to_the, pred)(8)")

trace("compose(pred, two_to_the)(8)")

Sent via Deja.com

http://www.*-*-*.com/