The next high risk feature I want to tackle is functional programming and closures. I want this style of programming to be highly integrated into the language and the core library (like collections). I suspect how we design functional programming features will force us to rethink other aspects of the language (like parameterized types - I already have some new ideas). I think there are three major components to the functional design:
Method References: how to specify a strongly typed functional signature which may be called on demand. Method references are needed to define the parameters for methods like Int.times() or List.each()
Method Binding: how to bind existing instance and static methods to method references to use where method references are needed potentially with this or other arguments predefined)
Closures: the ability to define an "anonymous method" to use where a method reference is expected. Closures provide access to the lexical space including local variables.
All three aspects need to be nailed down regarding terminology, syntax, and implementation.
Method Reference
A method reference is a method signature to "type a function pointer". I want to avoid having to define Java-like interfaces for the common case of a single method call - rather I want the signature defined inlined just like any other variable such as Int or Str[]. We need a term to use in discussions, and possibly a class name (or maybe just use Method itself). Possible terms to use:
MethodRef
Func/Function
Method
Delegate
Hook
Handler
Callback
Op/Operation
I dislike the C function pointer syntax (C# delegates use similar syntax) because the name is sandwiched between the return and param types, which goes against normal "Type name" declarations. I've been kind of thinking of using Ruby-like {|x| ...} as the closure syntax, which leads me to propose a syntax such as:
// Sys::Int.times
Void times(|Int i| func)
{
for (Int i=0; i<this; ++i) func(i)
}
// Sys::List.collect
List collect(|Obj item, Int index -> Obj| func)
{
List result = List.make(size);
for (Int i=0; i<size; ++i)
result.add( func(get(i), i) )
return result;
}
Method Binding (Currying)
I want it to be really easy to specify a method as a first class object ("curried" methods). My current thinking is to use the C style address-of "&" operator with a normal method call. Instead of executing the method, it would turn it into a method reference (MethodRef, Method, Function, whatever). You could prebind zero or more parameters to the method. If the method was an instance method you could bind it to a target or use a static like signature so that target was unbound:
Method m = &"hello".upper; m() -> "HELLO"
Method m = &Str.upper; m("hello") -> "HELLO"
Method m = &Sys.type; m("sys::Int") -> sys::Int
Method m = &Sys.type("foo::Bar"); m() -> foo::Bar
In the first example we bind m to Str.upper with an explicit target - the string "hello". So we call m without any arguments. However in the second example we bind the same Str.upper method without specifying a target. So the target must be explicitly passed as the first argument. In the last two examples we bind a static method - without any arguments, and with an argument. Given a static method with n parameters, we can bind 0 to n arguments. Given an instance method we can bind 0 to n+1 arguments (with the first argument being the implicit this).
To use our examples above:
x.times(&echo("hello"))
// print "hello" three times on the console
["a", "b"].collect(&Str.upper) -> ["A", "B"]
// we ignore collect's 2nd arg - see below
Closures
Of course what we really want to enable is an elegant syntax for closures so that we can build functional style libraries for working with collections and resources like files/streams. I haven't really seen anything I like better than the Ruby-style syntax: {|arg1, arg2, ...| ...}.
The arguments may be explicitly typed such as {|Str s| ...} or may be implied such as {|s| ...}. In the case of the an implied type, the type is defined by the method ref it is bound to (not sure about this - we will need to see how it works). A closure with n arguments may be bound to a callback that provides n or more parameters (the extra parameters are ignored). For example I can bind a closure to List.each with 0, 1, or 2 arguments. But I cannot bind a closure with 3 or more arguments to List.each (since I only have 2 parameters). I think the same rules apply to method binding.
Like Ruby, a closure may be used inline as an expression or if a method's last parameter is a closure, it may be specified outside the method call:
brian Sun 15 Jan 2006
The next high risk feature I want to tackle is functional programming and closures. I want this style of programming to be highly integrated into the language and the core library (like collections). I suspect how we design functional programming features will force us to rethink other aspects of the language (like parameterized types - I already have some new ideas). I think there are three major components to the functional design:
All three aspects need to be nailed down regarding terminology, syntax, and implementation.
Method Reference
A method reference is a method signature to "type a function pointer". I want to avoid having to define Java-like interfaces for the common case of a single method call - rather I want the signature defined inlined just like any other variable such as Int or Str[]. We need a term to use in discussions, and possibly a class name (or maybe just use Method itself). Possible terms to use:
I dislike the C function pointer syntax (C# delegates use similar syntax) because the name is sandwiched between the return and param types, which goes against normal "Type name" declarations. I've been kind of thinking of using Ruby-like {|x| ...} as the closure syntax, which leads me to propose a syntax such as:
Some examples in Fan code:
Method Binding (Currying)
I want it to be really easy to specify a method as a first class object ("curried" methods). My current thinking is to use the C style address-of "&" operator with a normal method call. Instead of executing the method, it would turn it into a method reference (MethodRef, Method, Function, whatever). You could prebind zero or more parameters to the method. If the method was an instance method you could bind it to a target or use a static like signature so that target was unbound:
In the first example we bind m to Str.upper with an explicit target - the string "hello". So we call m without any arguments. However in the second example we bind the same Str.upper method without specifying a target. So the target must be explicitly passed as the first argument. In the last two examples we bind a static method - without any arguments, and with an argument. Given a static method with n parameters, we can bind 0 to n arguments. Given an instance method we can bind 0 to n+1 arguments (with the first argument being the implicit this).
To use our examples above:
Closures
Of course what we really want to enable is an elegant syntax for closures so that we can build functional style libraries for working with collections and resources like files/streams. I haven't really seen anything I like better than the Ruby-style syntax: {|arg1, arg2, ...| ...}.
The arguments may be explicitly typed such as {|Str s| ...} or may be implied such as {|s| ...}. In the case of the an implied type, the type is defined by the method ref it is bound to (not sure about this - we will need to see how it works). A closure with n arguments may be bound to a callback that provides n or more parameters (the extra parameters are ignored). For example I can bind a closure to List.each with 0, 1, or 2 arguments. But I cannot bind a closure with 3 or more arguments to List.each (since I only have 2 parameters). I think the same rules apply to method binding.
Like Ruby, a closure may be used inline as an expression or if a method's last parameter is a closure, it may be specified outside the method call:
Let's repeat the examples above using a closure:
Anyways, these are just my initial thoughts. We have a really long way to go before we can turn this into a coherent design.