Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

transducers and swift porting javascript code to swift code

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 ) ) );
like image 623
George Host Avatar asked Jan 25 '26 04:01

George Host


1 Answers

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]
like image 172
Martin R Avatar answered Jan 26 '26 18:01

Martin R