I am trying practice writing transducers in swift, but I cannot successfully translate this functional javascript code to swift.
http://phuu.net/2014/08/31/csp-and-transducers.html
function mapping(transform) {
return function (reduce) {
return function (result, input) {
return reduce(result, transform(input));
};
};
}
func mapping<T,U> ( transform:(T)-> T ) -> ( (U,T)-> ( (U,T)->U ) ) {
return { ( transducer:(U,T) ) -> ( (U,T)->U ) in
return { (initial:U,element:T) -> U in
var transformedElement = transform(element);
var mInitial = transducer(initial,transformedElement); // this line is the problem
return mInitial;
}
}
func addOne (a:Int) -> (Int) {
return a+1;
}
func concat (c:Array<Int>,element:Int) -> (Array<Int>) {
var collection = c;
collection.append(element);
return collection;
}
var example3 = [1,2,3].reduce([], concat( mapping ( addOne ) ) );
According to http://phuu.net/2014/08/31/csp-and-transducers.html and http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming, a reducing function has the signature
whatever, input -> whatever
In Swift, this is a function (or closure) of the type
(U, T) -> U
(using the usual short names T, U for generic types). A transducer is a function that takes one reducing function as an argument and returns another reducing function
(whatever, input -> whatever) -> (whatever, input -> whatever)
The corresponding Swift type is
((U,T) -> U) -> (U,T) -> U
mapping()
takes a transformation as an argument an returns a transducer,
so it must be defined as
func mapping<T,U> (transform:(T) -> T) -> ((U,T)->U) -> (U,T) -> U
(Also the parameter in the first inner function of mapping
is better called
"reducer" instead of "transducer", because it is the argument of the return value.)
In your example,
concat : ([Int], Int) -> [Int]
is a reducing function and mapping(addOne)
is a transducer, therefore
mapping(addOne)(concat) : ([Int], Int) -> [Int]
is another reducing function, so that
var example3 = [1,2,3].reduce([], mapping(addOne)(concat))
gives the result [2,3,4]
.
Complete sample code:
func mapping<T,U> (transform:(T) -> T) -> ((U,T)->U) -> (U,T) -> U {
return { (reducer:((U,T) -> U)) -> (U,T) -> U in
return { (initial:U, element:T) -> U in
return reducer(initial,transform(element))
}
}
}
func addOne (a:Int) -> (Int) {
return a+1;
}
// Slightly simplified and generalized:
func concat<T> (c:[T], element:T) -> [T] {
return c + [element];
}
var example3 = [1,2,3].reduce([], mapping (addOne)(concat))
println(example3) // [2, 3, 4]