Skip to content
Saleh Yusefnejad edited this page Sep 1, 2015 · 24 revisions

Welcome to the LINQ4ES2015 (LINQ for ES 2015) wiki.

This wiki demonstrates what does each method do with a brief description and some handy samples.

To start, you should be familiar with following items:

Iterables: An object is iterable if it defines its iteration behavior, such as what values are looped over in a for..of construct. Some built-in types, such as Array or Map, have a default iteration behavior.

Generators: They allow you to define an iterative algorithm by writing a single function. For example, our Where method, has an iterative algorithm, that returns items which are matched by a passed predicate.

Note: You can use our LINQ methods on any ECMA 2015 based generator function. This is a powerful aspect of our library, because it's based on standards.

You can use AsEnumerable method to convert arrays, objects and strings to generators.

Consider this example:

let numericCharacters = 'Number12IsTwelve'.asEnumerable().where(c => !isNaN(c)); 

Deferred Execution

In this sample, our numericCharacters will not be executed, because of Generator's nature. Generators should be iterated to get executed. Our toArray method, iterates a Generator, and then it returns an Array, so this method will execute the Generator Function. This is called Deferred Execution

Note that deferred execution will not occur when the last calling method is not a generator function. For example, where is a Generator Function, but any is not, because its result is a boolean. So this code will be executed immediately:

let isThereAnyEvenNumber = [1,2,3].asEnumerable().any(num => num % 2 == 0);
// isThereAnyEvenNumber will be true.

##Closure side effect

Consider this example:

let someNumber = 2;
let someNumbersGenerator = [1,2,3,4,5,6].asEnumerable().where(num => num % someNumber == 0);
someNumber = 3;
let someNumberArray = someNumberGenerator.toArray();

Instead of [2,4,6], the result will be [3,6] ! Because the where method will be executed when the generator gets iterated (by toArray for example). And when the Where method is being executed, the someNumber is 3, it's not 2. someNumber is captured into where predicate by something called closure.

Don't iterate a generator multiple times:

You should avoid iterating a generator multiple times, because it will be executed from scratch every time. Calling someNumberGenerator.toArray(); two times causes generator to be executed two times. It would be better to declare a variable and assign your array result to that variable. Iterating the result array, will not execute the generator again, and you can use that array how many times you want, without any extra costs.

Smart execution

Consider following example:

let result = [0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9].asEnumerable()
  .where(num => num % 2 == 0)
  .take(3)
  .orderByDescending(num => num)
  .select(num => '[' + num + ']')
  .distinct()
  .toArray();

In this sample, where's predicate will be executed only 4 times, because of take(3) method wants only 3 items. So where method will works until take method satisfaction.

Each generator function can stops other generators from producing more items by breaking their execution.

This results into better performance.

Using object definition in lambda expressions:

Consider following example:

let test = [{ name: 'A', lName: 'AA' }, { name: 'B', lName: 'BB' }].asEnumerable()
    .select(person => ({ name: person.name, lName: person.lName, fullName: person.name + ' ' + person.lName }))
    .toArray();

Note that in select method, we put the object definition of lambda expression inside parentheses:

...  .select(person => ( { name: person.name, ... } ) )  ...

You may experience some troubles when you're not using () for object definitions inside of lambda expression, because {} will be considered as function body definition.

Clone this wiki locally