2013-07-17 14 views
8

Według źródeł underscore.js (https://github.com/jashkenas/underscore/blob/master/underscore.js):Dlaczego metoda łańcuchowa() metody Underscore.js nie jest leniwy?

// Start chaining a wrapped Underscore object. 
chain: function() { 
    this._chain = true; 
    return this; 
}, 

// Extracts the result from a wrapped and chained object. 
value: function() { 
    return this._wrapped; 
} 

łańcuch() i wartość() funkcje są tylko proste otoki dla obiektu podkreślenia.

Więc jeśli używam następujące budowy:

_.chain(someCollection) 
.map(function1) 
.map(function2) 
.map(function3) 
.value() 

Podkreślenie stworzy dwie kolekcje pośrednich i wykona trzy wyliczeń.

Dlaczego metody chain() i value() nie są zaimplementowane jako leniwe wartościowane, tak jak LINQ implementuje swoje metody? Na przykład ten łańcuch może być traktowany jako:

_.chain(someCollection) 
.map(function(x){ 
    return function3(function2(function1(x))); 
}) 
.value(); 

Czy są jakieś problemy związane z JS dla tego rodzaju realizacji?

Odpowiedz

12

Zasadniczo, aby uczynić leniwym .chain() tak, jak opisujesz, wymagałoby to prawie dwóch wersji każdej metody. Potrzebowalibyśmy metod natychmiastowej odpowiedzi, które wykonałyby to, co mówi dokumentacja (zwraca tablicę) i potrzebowalibyśmy leniwych metod, które wykonują leniwą ocenę (zwraca funkcję, która oczekuje, że zostanie uruchomiona później dla każdego elementu).

Jednym ze sposobów implementacji tego byłoby napisanie całego podkreślenia jako leniwego i odsłonięcie tego jako podkreślonego łańcucha. Następnie odsłaniaj zwykły podkreślnik jako opakowanie leniwego podkreślenia, które wywołuje leniwe podkreślenie, natychmiastowo ocenia, a następnie zwraca wyniki. Występują dwa główne problemy: (1) to dużo więcej pracy i (2) jest to całkowicie przeciwna architektura, która wymaga, aby cały podkreślnik był napisany tak leniwym, aby wspierać leniwą ocenę metody łańcucha.

Jest to z pewnością możliwe do zrealizowania, tak jak zostało to zaprezentowane przez JSLinq i LINQ firmy .NET, ale wiąże się to z ogromnymi kosztami, jeśli chodzi o czas projektowania i konserwacji, a także większą złożoność i prawdopodobieństwo błędów. Podkreślenie zapewnia leniwe oceny 80 różnych metod użytkowych w 1200 liniach kodu. JSLinq zapewnia leniwą ocenę 21 różnych metod użytkowych w 7000 linii kodu. Dużo więcej kodu, mniejsza ilość funkcji.

Jest kompromis. Każdy programista musi podejmować własne decyzje (o ile pracują dla siebie).

7

wierzę szukasz czegoś jak Lazy.js:

Lazy.js jest biblioteką narzędzie do JavaScriptu, podobny do podkreślenia i Lo-Dash, ale z jedną istotną różnicą: leniwa ewaluacja (znany także jako odroczona realizacja). Może to w wielu przypadkach przekładać się na lepszą wydajność, szczególnie gdy mamy do czynienia z dużymi tablicami i/lub "łączymy" razem wiele metod. Dla prostych przypadków (map, filter, itp.) Na małych tablicach, wydajność Lazy powinna być podobna do wydajności Underscore lub Lo-Dash.

Edit: to wyglądać tak, jakby Lo-Dash may be adding the ability to do lazy evaluation również.

Powiązane problemy