Hi mark,
The only difference is one uses a typdef, so you can directly use recursion on any function this way:
typedef RecursiveFunction<P,R> = P->R->R
public static function recursion<P,R>(operation:RecursiveFunction<P,R>, parameter:P, condition:R->Bool, result:R){
trace('recursion: $result');
if (condition(operation(parameter, result))){
return recursion(operation, parameter, condition, operation(parameter, result));
}
return result;
}
class Foo{
// any function that has its last argument of the same type, can be changed into a recursive function just by using
// my pattern, if you have more parameters in your function, its easy to adapt my pattern, i show you beaneath later on
public static function youCanEnableRecursionOnThisFunction(someString:String, someXml:Xml):Xml{
//some code
}
public function youCanEnableRecursionOnThisFunctionToo(someString:String, SomeXml:Xml):Xml {
//some code
}
}
//or in main:
var blaat=function(a:Int, b:Array<String>):Array<String>{
//some code
}
// doing the recursion thing:
var funct1=Foo.youCanEnableRecursionOnThisFunction.recursion(
// your parameter,
// conditionFunction: where false ends recursion and returns value,
// the starting value of a parameter that is used to store your result in and is changed by each recursion until it can be returned as the end result of all recursion
);
var instance=new Foo();
var funct2=instance.youCanEnableRecursionOnThisFunctionToo.recursion(/* put in your arguments here: parameter:String, condition:XML->Bool, result:Xml*/)
blaat.recursion(/*put in your arguments here: parameter:Int, condition:Array<String>->Bool, result:Array<String>*/)
The other function uses an abstract. The interesting part of it, is that you can then choose to extend the functionality of ay function itself
by adding functions to the abstract (there you can use properties etc) or by "using" some static method that has its first parameter of type of that abstract
And interesting about abstract is that you can inline a lot as well.
public static function recursion<P,R>(operation:RecursiveFunction<P,R>, parameter:P, condition:R->Bool, result:R){
trace('recursion: $result');
if (condition(operation(parameter, result))){
return recursion(operation, parameter, condition, operation(parameter, result));
}
return result;
}
@:callable //only works if you add @:callable
abstract RecursiveFunction1<P, R>(P -> R -> R){
public inline function new<P, R>(parameter:P -> R ->R){
this = parameter;
}
but the difference is that you need to instantiate it first before using it.
var func3 = new RecursiveFunction(function(p:Int, r:Int):Int{ return p + r; });
func3.recursion(1, function(r:Int):Bool{return r <= 10; }, 1);
Ok so what if you have a several functions that have 3 parameters
for example
var f = function(p1:Json, p2:String, p3: Int, r:Xml):Xml{ /* your code*/ }
We can describe this function like this
(Json->String->Int->Xml)->Xml
Which we can describe by Genrics like this
(P1->P2->P3->R)->R
so to extending it with "using" it goes like this:
public static function recursion<P1, P2, P3,R>(operation:RecursiveFunction<P,R>, p1:P1, p2:P2, p3:P3, condition:R->Bool, result:R){
trace('recursion: $result');
if (condition(operation(p1,p2,p3, result))){
return recursion(operation, parameter, condition, operation(parameter, result));
}
return result;
}
that simple,
or what if your conditions= to test if recursion is complete you need to compare 2 or more of those parameters (which maybe the case for example when recursing through xml):
public static function recursion<P1, P2, P3,R>(operation:RecursiveFunction<P,R>, p1:P1, p2:P2, p3:P3, condition:R->P1->P2->Bool, result:R){
trace('recursion: $result');
if (condition(operation(p1,p2,p3, result),p1, p2)){
return recursion(operation, parameter, condition, operation(parameter, result));
}
return result;
}
Op vrijdag 14 oktober 2016 10:01:44 UTC+2 schreef Mark Knol: