Skip to content
This repository has been archived by the owner on Mar 9, 2021. It is now read-only.

Enumerable.Flatten should have a strong type instead of object. #3

Open
jrockwood opened this issue Jul 3, 2014 · 2 comments
Open

Comments

@jrockwood
Copy link

This is the current code:

[InlineCode("{$System.Linq.Enumerable}.from({source}).flatten()")]
public static LinqJSEnumerable<object> Flatten(this IEnumerable<object> source);

It would be chainable and more usefult to add <T> instead of defaulting to object.

[InlineCode("{$System.Linq.Enumerable}.from({source}).flatten()")]
public static LinqJSEnumerable<T> Flatten<T>(this IEnumerable<T> source);
@erik-kallen
Copy link
Contributor

I don't think the suggestion can work (correct me if I'm wrong). The conceptual signature to me appears to be

public static IEnumerable<T> Flatten<T>(IEnumerable<TypeOption<T, IEnumerable<TypeOption<T, IEnumerable<T, TypeOption ...>>>>>)

(of course this signature wouldn't really work)

Perhaps this signature would be better:

public static LinqJSEnumerable<T> Flatten<T>(this IEnumerable<object> source)

@jrockwood
Copy link
Author

I'm sorry. I made a type-o in my suggestion. You're correct in that Flatten takes in an array of an undetermined depth of arrays. The incoming parameter should be IEnumerable<object> like you have it, but the return parameter should be LinqJsEnumerable<T> in order to support chaining. Here's an example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

[Imported, IgnoreNamespace, Serializable]
internal class Lyric
{
    public int Line;
    public string Words;

    public Lyric(int line, string words)
    {
        this.Line = line;
        this.Words = words;
    }
}

internal static class Extensions
{
    [ScriptSkip]
    internal static T As<T>(this object obj)
    {
        return default(T);
    }
}

public class LinqStuff
{
    public void UndersoreExample()
    {
        // This is an example from the Underscore web site and what the raw
        // JavaScript code would look like.
        //
        // var lyrics = [
        //   {line: 1, words: "I'm a lumberjack and I'm okay"},
        //   {line: 2, words: "I sleep all night and I work all day"},
        //   {line: 3, words: "He's a lumberjack and he's okay"},
        //   {line: 4, words: "He sleeps all night and he works all day"}
        // ];
        //
        // _.chain(lyrics)
        //   .map(function(line) { return line.words.split(' '); })
        //   .flatten()
        //   .reduce(function(counts, word) {
        //     counts[word] = (counts[word] || 0) + 1;
        //     return counts;
        //   }, {})
        //   .value();
        //
        //   => {lumberjack: 2, all: 4, night: 2 ... }

        var lyrics = new List<Lyric>(
            new Lyric(line: 1, words: "I'm a lumberjack and I'm okay"),
            new Lyric(line: 2, words: "I sleep all night and I work all day"),
            new Lyric(line: 3, words: "He's a lumberjack and he's okay"),
            new Lyric(line: 4, words: "He sleeps all night and he works all day"));

        JsDictionary<string, int> wordCountsLinq = lyrics
            .Map(lyric => lyric.Words.Split(" "))
            // If Flatten took a generic argument, it would be written like this
            // Flatten<string>()
            .Flatten().As<LinqJSEnumerable<string>>()
            .Aggregate(new JsDictionary<string, int>(), (counts, word) =>
            {
                counts[word] = Script.Coalesce(counts[word], 0) + 1;
                return counts;
            });
    }
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants