One of the features I want to have in my AjSharp interpreter is functions and subroutines as first-class citizens in the language (in this post, I use function keyword but you can use sub keyword to define a subroutine).
The code is in my Google code project:
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjLanguage
AjLanguage is the core language definition (without parser and lexer). AjSharp is the parser, lexer implemented using neutral AjLanguage. In this way, I could implement AjBasic or other similar languages, using AjLanguage as core.
In AjSharp, you can define functions as usual:
function Square(n) { return n*n; }You can define and assign a function to a variable:
MySquare = function (n) { return n*n; };A functional value can be used as a parameter:
function Apply(func,values) { list = new List(); foreach (value in values) list.Add(func(value)); return list; } numbers = new List(); numbers.Add(1); numbers.Add(2); numbers.Add(3); function Square(n) { return n*n; } squared = Apply(Square, numbers); squared2 = Apply(function (n) { return n*n; }, numbers);Apply function defined about, take a function, a list, and returns a list of f(e), where f is the function received, applied to each element e of the list parameter. You can invoke Apply with the name of the function (the name of a variable that has a functional value) or defining the function “inline”.
I'm still thinking about some scope implementation (free variables, bounded variables) in function expressions. If you define a function, AjLanguage (the core of AjSharp) uses a closure, so when the function is invoked, the original binding environment is used. I use that feature in the following examples. Every function implements:
public interface ICallable { int Arity { get; } IBindingEnvironment Environment { get; } object Invoke(IBindingEnvironment environment, object[] arguments); object Invoke(object[] arguments); }that is, when it is invoked, it can receive an environment. A functional value doesn't use that received environment, replacing it by the original environment at the point of its definition.
You can return a function as returning value of a function:
function MakeIncrement(x) { return function(n) { return n + x; }; // x is bounded to local parameter } Increment2 = MakeIncrement(2); result = Increment2(2); // result == 4 Increment3 = MakeIncrement(3); result2 = Increment3(2); // result2 == 5 result3 = MakeIncrement(4)(3); // result3 == 7 x = 4; result4 = function(n) { return n+x; }(5); // result4 == 9MakeIncrement returns a function that uses and access the variable x, bounded to the calling binding environment.
In the last command, the function is defined and invoked in place.
AjSharp has classes, and you can define functions as usual:
class Person { var Name; var Age; function AddYears(years) { this.Age = this.Age + years; } }But you can add functions at any moment:
class Person { var Name; var Age; function Person() { x = 100; this.GetYears = function () { return this.Age; }; this.GetX = function() { return x; }; } } adam = new Person() { Name = "Adam", Age = 800 }; result = adam.GetYears(); // result == 800 result2 = adam.GetX(); // result2 == 100or add functions/subroutines directly to objects:
adam.AddYears = sub(n) { this.Age = this.Age + n; };Some weeks ago, I read the post:
Functional Programming in Javascript
by James Carr, so I decided to test AjSharp functional values adapting examples presented in that post. For example:
function runningSum(start){ sum = start; // you could use var sum, it's local return function(a){ sum = sum + a; // function access the "outer" sum return sum; }; } sum = runningSum(3); // makes function result = sum(2); // returns 5 result2 = sum(10); // returns 15You can use directly the parameter as accumulator:
function runningSum(start){ return function(a){ start = start + a; // function access the "outer" start return start; }; } sum = runningSum(3); // makes function result = sum(2); // returns 5 result2 = sum(10); // returns 15I added support to apply a function as a method to an object, as in one of Carr's example (this kind of call is supported by javascript Functions):
person = new { Name = "Adam", Age = 800 }; GetAdjustedAge = function (x) { return x + this.Age; }; result = GetAdjustedAge.Call(person, 10); // result == 810Next steps: stabilize variable scope and access to global environment. By now, I had fun implementing …err.. functional values..
![]()
Keep tuned!
Angel “Java” Lopez
http://www.ajlopez.com
[...] Yes! AjSharp has closures http://ajlopez.wordpress.com/2010/02/05/functional-values-in-ajsharp/ [...]
Pingback by Closures: Links, News and Resources (1) « Angel “Java” Lopez on Blog — September 21, 2011 @ 10:36 am