Skip to content

Commit 549ccca

Browse files
committed
Update README with API difference
1 parent 457227e commit 549ccca

File tree

3 files changed

+110
-18
lines changed

3 files changed

+110
-18
lines changed

README.md

+106-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# ESLINQ - LINQ for ES2018+
1+
# ESLINQ - LINQ for ES2018
22

33
## Abstract
44

5-
This library provides a set of functional programming APIs with deferred execution, copied from [LINQ](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/) from the .NET world. These predefined functional programming APIs allows you to manipulate an [Iterable<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) (available since ES2015) or an [AsyncIterable<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator) (available since ES2018) in an easy and maintainable shape.
5+
This library provides a set of functional programming APIs with deferred execution, migrated from [LINQ](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/) from the .NET world. These predefined functional programming APIs allows you to manipulate an [Iterable<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) (available since ES2015) or an [AsyncIterable<T>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator) (available since ES2018) efficiently in an easy and maintainable shape.
66

7-
This library attempts to provide exact the same API defined in [Enumerable](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable) of .NET with TypeScript types. On top of that, its attempts to provide consistent API experience between synchronous and asynchronous operations by leveraging TypeScript code generation.
7+
This library attempts to provide exact the same API defined in [Enumerable](https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable) of .NET with TypeScript types. On top of that, it attempts to provide consistent API experience between synchronous and asynchronous operations by leveraging TypeScript code generation.
88

9-
There are still some missing or slightly different APIs from this port comparing to the original .NET implementation. That is either because some nature difference between JavaScript and .NET (such as lack of `default(T)`), or to avoid complicated method overloading. If you find missing methods or overloading signatures which do not land into any of those reasons, they will be supported in a future version of this library some day.
9+
There are still a few missing or slightly different APIs from this port comparing to the original .NET implementation. Please refer to [Difference from .NET implementation](#difference-from-net-implementation) section for details. That is either because some nature difference between JavaScript and .NET (such as lack of `default(T)`), or to avoid complicated method overloading. If you find missing methods or overloading signatures which do not land into any of those reasons, they will be supported in a future version of this library some day.
1010

1111
## Usage
1212

@@ -15,7 +15,7 @@ Since this library is a ES2018 port of LINQ from .NET, please refer to [System.L
1515
### Start using LINQ
1616

1717
```javascript
18-
import { from } from "es-linq"; // Note: hasn't published to NPM yet!
18+
import { from } from "es-linq";
1919

2020
console.log(
2121
from([-1, 0, 1, 2])
@@ -142,7 +142,7 @@ For example, a template implementation method, its generated asynchronous method
142142
```typescript
143143
// Template implementation template class
144144
class EnumerableImplementationTemplate<T> {
145-
private async *where(predicate: (element: T) => AsyncOrSync<boolean>): AsyncIterable<T> {
145+
public async *where(predicate: (element: T) => AsyncOrSync<boolean>): WrapWithAsyncEnumerable<T> {
146146
for await (const element of this.iterable) {
147147
if (await predicate(element)) {
148148
yield element;
@@ -154,12 +154,12 @@ class EnumerableImplementationTemplate<T> {
154154
// Generated asynchronous class
155155
class AsyncEnumerable<T> {
156156
// A wrapper method will be generated
157-
public const(predicate: (element: T) => AsyncOrSync<boolean>): AsyncEnumerable<T> {
158-
return new AsyncEnumerable(this.constImpl(predicate));
157+
public where(predicate: (element: T) => AsyncOrSync<boolean>): AsyncEnumerable<T> {
158+
return new AsyncEnumerable(this.whereImpl(predicate));
159159
}
160160

161161
// The template method will have a prefix "Impl" in its name
162-
private async *constImpl(predicate: (element: T) => AsyncOrSync<boolean>): AsyncIterable<T> {
162+
private async *whereImpl(predicate: (element: T) => AsyncOrSync<boolean>): AsyncIterable<T> {
163163
// Method body will be kept as is
164164
for await (const element of this.iterable) {
165165
if (await predicate(element)) {
@@ -173,13 +173,13 @@ class AsyncEnumerable<T> {
173173
class Enumerable<T> {
174174
// A wrapper method will be generated
175175
// Asynchronous types will be removed from its signature or turned into its synchronous alternative
176-
public const(predicate: (element: T) => boolean): Enumerable<T> {
177-
return new Enumerable(this.constImpl(predicate));
176+
public where(predicate: (element: T) => boolean): Enumerable<T> {
177+
return new Enumerable(this.whereImpl(predicate));
178178
}
179179

180180
// The template method will have a prefix "Impl" in its name
181181
// Asynchronous types will be removed from its signature or turned into its synchronous alternative
182-
private *constImpl(predicate: (element: T) => boolean): Iterable<T> {
182+
private *whereImpl(predicate: (element: T) => boolean): Iterable<T> {
183183
// Method body will *almost* be kept as is, except await keywords will be removed.
184184
for (const element of this.iterable) {
185185
if (predicate(element)) {
@@ -190,5 +190,99 @@ class Enumerable<T> {
190190
}
191191
```
192192

193+
## Difference from .NET implementation
194+
195+
Missing methods due to lack of feature in JavaScript runtime:
196+
```csharp
197+
Cast<TResult>(IEnumerable) // No runtime cast in JavaScript
198+
199+
LongCount<TSource>(IEnumerable<TSource>) // No long in TypeScript
200+
LongCount<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) // No long in TypeScript
201+
```
202+
203+
Missing methods to be added later:
204+
```csharp
205+
ToLookup<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>) // Will add later
206+
ToLookup<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>) // Will add later
207+
```
208+
209+
Missing overloads due to lack of feature in JavaScript runtime:
210+
```csharp
211+
Aggregate<TSource>(IEnumerable<TSource>, Func<TSource,TSource,TSource>) // No `default(T)` in TypeScript
212+
213+
Distinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>) // JavaScript Set does not support comparers
214+
215+
Except<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>) // JavaScript Set does not support comparers
216+
217+
GroupBy<TSource,TKey,TElement,TResult>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>, Func<TKey,IEnumerable<TElement>,TResult>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
218+
GroupBy<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
219+
GroupBy<TSource,TKey,TResult>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TKey,IEnumerable<TSource>,TResult>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
220+
GroupBy<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
221+
222+
GroupJoin<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,IEnumerable<TInner>,TResult>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
223+
224+
Intersect<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>) // JavaScript Set does not support comparers
225+
226+
Join<TOuter,TInner,TKey,TResult>(IEnumerable<TOuter>, IEnumerable<TInner>, Func<TOuter,TKey>, Func<TInner,TKey>, Func<TOuter,TInner,TResult>, IEqualityComparer<TKey>) // JavaScript Set does not support comparers
227+
228+
Max<TSource>(IEnumerable<TSource>) // No IComparable in JavaScript
229+
230+
Min<TSource>(IEnumerable<TSource>) // No IComparable in JavaScript
231+
232+
OfType<TResult>(IEnumerable) // No generic type check method in JavaScript
233+
234+
ToDictionary<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
235+
ToDictionary<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
236+
237+
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>) // JavaScript Set does not support comparers
238+
239+
ToList<TSource>(IEnumerable<TSource>) // Duplicate with ToArray in context of JavaScript
240+
241+
ToLookup<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
242+
ToLookup<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>, IEqualityComparer<TKey>) // JavaScript Map does not support comparers
243+
244+
Union<TSource>(IEnumerable<TSource>, IEnumerable<TSource>, IEqualityComparer<TSource>) // JavaScript Set does not support comparers
245+
```
246+
247+
Missing overloads whose overload signature is too complicated to implement in JavaScript with other overloads:
248+
```csharp
249+
Aggregate<TSource,TAccumulate,TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate,TSource,TAccumulate>, Func<TAccumulate,TResult>)
250+
251+
Average<TSource>(IEnumerable<TSource>, Func<TSource,TNumber>)
252+
253+
GroupBy<TSource,TKey,TResult>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TKey,IEnumerable<TSource>,TResult>)
254+
255+
Max<TSource>(IEnumerable<TSource>, Func<TSource,TNumber>)
256+
257+
Min<TSource>(IEnumerable<TSource>, Func<TSource,TNumber>)
258+
259+
Sum<TSource>(IEnumerable<TSource>, Func<TSource,TNumber>)
260+
261+
```
262+
263+
264+
Methods and overloads who returns `undefined` instead of `default(T)`
265+
```csharp
266+
DefaultIfEmpty<TSource>(IEnumerable<TSource>) // Use undefinedIfEmpty instead
267+
268+
ElementAtOrDefault<TSource>(IEnumerable<TSource>, Int32) // Use ElementAtOrUndefined instead
269+
270+
FirstOrDefault<TSource>(IEnumerable<TSource>) // Use FirstOrUndefined instead
271+
FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) // Use FirstOrUndefined instead
272+
273+
LastOrDefault<TSource>(IEnumerable<TSource>) // Use LastOrUndefined instead
274+
LastOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) // Use LastOrUndefined instead
275+
276+
SingleOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) // Use SingleOrUndefined instead
277+
```
278+
279+
Renamed methods:
280+
```csharp
281+
ToDictionary<TSource,TKey,TElement>(IEnumerable<TSource>, Func<TSource,TKey>, Func<TSource,TElement>) // Use toMap instead
282+
ToDictionary<TSource,TKey>(IEnumerable<TSource>, Func<TSource,TKey>) // Use toMap instead
283+
284+
ToHashSet<TSource>(IEnumerable<TSource>) // Use toSet instead
285+
```
286+
193287
## Prior art
194288
* https://github.com/balazsbotond/eslinq

TODO

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
P0
2-
- Document unsupported methods and overrides
3-
41
P1
52
- Support method extension
6-
- Support Lookup
73
- Generate code with JSDoc
84
- Performance warning for OrderBy with AsyncEnumerable and synchronous comparer
9-
- Optimization for SortedEnumerable
5+
- Support Lookup
6+
7+
P2
108
- More validation and exceptions
119
- Support full Aggregate, GroupBy signature set
1210
- Support comparer for set operations

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "eslinq",
2+
"name": "es-linq",
33
"version": "1.0.0",
44
"description": "LINQ for ES2018+",
55
"author": "Martin Chloride <i@martincl2.me>",

0 commit comments

Comments
 (0)