Function currying

Function currying

Post by Mike Austi » Sat, 08 Jan 2005 13:13:58


An idea came to mind after reading some NewtonScript, Haskell and
SuperCollider code -- using nested frame slots as arguments to create
curried functions.

In NewtonScript you can create 'frames', which are key value pairs to
hold objects:

f := { a: { x: 10, y: 20 } }

You can also use a syntax to create frames implicitly:

f.a.x := 10
f.a.y := 20

Functions can be assigned to variables just like values:

f.x.y := func( x, y ) begin x * y end

Frames can be simulated to use lexical scoping by settings it's parent
or proto slot to the outer frame. Now, if we simply substituted the
.x.y with values, instead of having a function take actual arguments -
then gave it a new syntax:

f x y = { x * y }

This would create a tree structure like the following (x * y is also a
tree, but I don't expand it here for sake of brevity):

f
\
x
\
y
\
{ x * y }

You would call it with the syntax:

f 2 3

which would return the value 6. If you wanted to return the function,
or partial application of the function, you could write this:

f.x.y >> { x * y } -- actual function
f 2 >> { y = { x * y } } -- partial application

Since defining a function is really defining a tree structure, could
matching be easily added?

f n (n == 0) = 1
f n = { n * f (n-1) }

f
\
n
/ \
/ \
/ \
{n * f (n-1)} (n == 0)
\
1

Regards,
Mike
 
 
 

Function currying

Post by cr8819 » Sun, 09 Jan 2005 12:00:00

"Mike Austin" < XXXX@XXXXX.COM > wrote in message
news:a0oDd.1232$ XXXX@XXXXX.COM ...
this part is seemingly interesting, but I have trouble following the rest...

I am stupid sometimes I guess, eg, given that even though I have looked at
them, I still don't really understand, eg, how self and smalltalk work. the
pieces seem sane, but the actual code is unintelligable and bewildering, or
at least to me. maybe I am just too much of a c head for it or whatever.

however, at least I was able to understand enough of self to rip some things
off, of course recently I discover newtonscript which seems dubiously close
on a few facets:
f := { a: { x: 10, y: 20 } }
becomes:
var f = [ a:= [ x:= 10, y:= 20 ] ];
(var can be ommited if f allready exists, or could be 'local' if a lexical
var is desired).

of course, there are differences, mine can't implicitly create vars, but has
arbitrary delegation and cyclic graphs.

var ox=[x:=3];
var oy=[y:=4];
var oxy=[_x:=ox, _y:=oy];

now, I can delegate ox back to oxy:
ox._xy=oxy;
and state that the interpreter is to handle this cleanly.

yes, this is understood (though I don't get the relevance).

by here I have lost it.


the mystery is how the values get propagated to the function or bound to
slots, I don't get this.

maybe it works, I just don't understand it...


I have currying, but it works very much different, and is rather explicit.
the main reason for the currying is not so much the currying, but more how I
deal with application and the presence of closures...

foo(3)(4) is something totally different than foo(3, 4). the former requires
both that syntax and a definition of a function that serves to return
another function, and the latter is a single function accepting 2
arguments...

it is about as natural as being like 'foo(3).x' with a function that returns
an object...




 
 
 

Function currying

Post by Mike Austi » Sun, 09 Jan 2005 19:08:41

r88192 wrote:

I know you've borrowed features from lisp or scheme, and from C. Do you
understand Smalltalk but just can't 'read' the code easily? I like many
of the features of Smalltalk, but I believe it has a few too many
symbols. In Inertia, I have been introducing symbols - but more for
added features such as predicates and such.



f.x.y := func( x, y ) begin x * y end

Throw away the arguments, because x and y are in the graph hierarchy.
When you invoke a function, simply substitute x and y for values:

f.x.y := func() begin x * y end

f 2 3

This wouldn't 'replace' the graph that was previously created, only
substitute the values for those slots. So x would be 2, and y would be
3, and the function would be called. The function references x and y,
which are defined in the graph, and return 6.

I don't really like that syntax, so I removed the dots, and {} is a block.

f x y = { x * y }

Would actually be the same as:

f = { x = { x * y } }


I'm not sure it works either. :) When I have time I'll try to implement
it. I just wondered if there is something similar out there.


I found a site that has a generic curry builder for JavaScript. For
example, you can write functions like this:

function add (a,b,c){
if (arguments.length < this.add.length) {
return curry(this.add,arguments,this);
}
return a+b+c;
}

alert(add()(1,2,4)); // 7
alert(add(1)(2)(5)); // 8
alert(add(1)()(2)()(6)); // 9
alert(add(1,2,7,8)); // 10

http://www.svendtofte.com/code/curried_javascript/


Yes. But what is really fun is partial application. :)


Regards,
Mike
 
 
 

Function currying

Post by cr8819 » Mon, 10 Jan 2005 00:00:10

"Mike Austin" < XXXX@XXXXX.COM > wrote in message
news:JiODd.5530$ XXXX@XXXXX.COM ...
well, it is more like I have often got totally lost...

I could look at them more maybe, I don't know.

I still don't get it though it seems...

ok, you create a function and put it in the object. f.x.y would thus refer
to the function, yes.


now, I don't get how the argument values are associated with the x/y
bindings (ow how it would be possibly without being ambigous and/or breaking
the graph). I fail to get it.

maybe I am just stupid.

can't answer really.

ok.

ok.



 
 
 

Function currying

Post by Mike Austi » Mon, 10 Jan 2005 06:18:39


>>f.x.y := func( x, y ) begin x * y end
>
> ok, you create a function and put it in the object. f.x.y would thus
> refer to the function, yes.

Yes, the graph f.x.y would refer to the function.

>>Throw away the arguments, because x and y are in the graph hierarchy.
>>When you invoke a function, simply substitute x and y for values:
>>f.x.y := func() begin x * y end
>>f 2 3
>
> now, I don't get how the argument values are associated with the x/y
> bindings (ow how it would be possibly without being ambigous and/or
> breaking the graph). I fail to get it.

I think it would work something like function frames. When you call a
function, you set up an environment for it to execute in. You wouldn't
overwrite the graph structure.

When you type f 2 3, it would internally be something like this:

f.x.value = 2
f.x.y.value = 3
apply f.x.y

The { x * y } has lexical scope, so would find x and y in the upper
frames. I'm just experimenting. It's all about creating a graph:

f n (n == 0) = 1
f n = { n * (f (n-1)) }

f
\
n
/ \
/ \
(n==0) {n * f (n-1)}
/
1

Substitute n for a number, say 5. If it is equal to 0, return 1. If
not, backtrack to find a another node.

Mike
 
 
 

Function currying

Post by cr8819 » Mon, 10 Jan 2005 08:23:54


ok.

ok.


ok, now I get it I guess...
it is an odd way of doing it though imo.