2011-11-11 14 views
5
function asArray(quasiArray, start) { 
    var result = []; 
    for (var i = (start || 0); i < quasiArray.length; i++) 
    result.push(quasiArray[i]); 
    return result; 
} 

function partial(func) { 
    var fixedArgs = asArray(arguments, 1); 
    return function(){ 
    return func.apply(null, fixedArgs.concat(asArray(arguments))); 
    }; 
} 

function compose(func1, func2) { 
    return function() { 
    return func1(func2.apply(null, arguments)); 
    }; 
} 

var isUndefined = partial(op["==="], undefined); 
var isDefined = compose(op["!"], isUndefined); 
show(isDefined(Math.PI)); 
show(isDefined(Math.PIE)); 

Dlaczego nie można po prostu funkcja komponować powrotu:Czytam Eloquent Javascript i jestem trochę zdezorientowany przez ten przykład częściowej funkcji. Proszę pomóc wyjaśnić

func1(func2); 

i dać właściwego wyjścia. Myślałem funkcję częściową, która jest przechowywana w zmiennej isUndefined już wraca func.apply

var op = { 
"+": function(a, b){return a + b;}, 
"==": function(a, b){return a == b;}, 
"===": function(a, b){return a === b;}, 
"!": function(a){return !a;} 
/* and so on */ 
}; 
+0

gdzie jest zadeklarowane op? Czy możesz to dodać? –

+0

Ups, tak, przepraszam – Shaan

Odpowiedz

2

Zarówno partial i composehigher-order functions.

isUndefined zwróci funkcję, która po wywołaniu wywoła pierwotnie przekazaną funkcję z oryginalnymi argumentami oraz nowymi argumentami przekazanymi podczas wywołania.

Aby odpowiedzieć na to pytanie, chcesz być wywołanie apply funkcję wrócił z partial która z kolei nazywają apply funkcję pierwotnie przekazany do partial.

Chcesz, aby zwrócił funkcję, która po wywołaniu zwróci wynik wywołania pierwszej funkcji, która przekazała drugą funkcję jako argument (druga funkcja przekazała argumenty przekazane do inwokacji compose). Jeśli compose zwrócił func1(func2), wówczas przypisać wynik wywołania do zmiennej isDefined.

EDIT:

Teraz, gdy mamy op, spróbujmy się rozkładać to:

var isUndefined = partial(op["==="], undefined); 

jest to równoważne

var isUndefined = partial(function(a, b){return a === b;}, undefined); 

isUndefined jest przypisana funkcja, która, gdy wywoływana, wywoła funkcję przekazaną jako pierwszy argument do partial, przekazując n undefined jak pierwszy argument do wywołania tej funkcji, a następnie przekazywane do argumentów funkcji isUndefined tj

partial(function(a, b){return a === b;}, undefined /* this will become 'a' when isUndefined is invoked */)(argumentForisUndefined /* this will become 'b' when isUndefined is invoked */); 

isDefined komponuje isUndefined inną funkcję, która neguje wynik isUndefined.

var isDefined = compose(op["!"], isUndefined); 

jest równoważna

var isDefined = compose(function(a){return !a;}, isUndefined); 

co jest równoznaczne z (nazwa zmieniona zmiennych dla przejrzystości)

var isDefined = compose(

    function(a){return !a;}, 

    partial( /* partial function becomes 'a' passed to first function */ 
     function(b, c) { 
      return b === c; 
     }, 
     undefined /* undefined becomes 'b' passed to partial */ 
    ) 

)(argumentForisDefined /* argumentForisDefined becomes 'c' passed to partial */); 

Jeśli spojrzymy na to, co mamy do tej pory i podstawiając dla czytelności, sprowadza do funkcji, która pobiera argument i porównuje go z niezdefiniowanym, neguje wynik i zwraca wartość boolowską

var isDefined = function (b) { return !undefined === b; } 
+0

OK Myślę, że rozumiem własne zamieszanie. Byłem zdezorientowany, dlaczego function.apply pojawił się dwa razy. Ale jeśli funkcja Compose byłaby tylko func1 (func2), argumenty (w tym przypadku Math.PI lub Math.PIE) nigdy nie zostałyby przekazane do funkcji częściowej. Czy mam rację? – Shaan

+0

Zgadza się - kompozycja nie zwróciłaby składu funkcji dwóch funkcji, które zostały pierwotnie przekazane, ale zwróciłaby wynik natychmiastowego wywoływania ich, więc nie byłoby żadnego przejścia od dodatkowych wartości do "częściowego"; to już zostałoby wywołane. –

0

Więc pozwala po prostu wnikliwie go (null [stałe, argumenty]). Zakładając, że mamy tę funkcję komponowania:

function compose(func1, func2) { 
    return func1(func2.apply(null, arguments)); 
} 

Co się stanie, gdy użyjesz go w ten sposób?

a = compose(function(){console.log(1)}, function(){console.log(2)}); 

Druga funkcja będzie zadzwonić natychmiast wyprowadzania 2 i prosto potem pierwsza funkcja zostanie wywołana wyprowadzania 1. a będzie undefined, ponieważ pierwsza funkcja niczego nie zwróci.

Co chcesz połączyć, to zwrócić nową funkcję, która łączy w sobie dwie inne funkcje i którą możesz dowolnie wywoływać.

Wykonując powyższe czynności na oryginalnej kompozycji, zwróci nową funkcję, która po wywołaniu jej z numerem a() wyświetli 2, a następnie 1.