Re[6]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.07 12:23
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>IEnumerable<T> OfType<T>(IEnumerable source);

_FR>IEnumerable<T> Cast<T>(IEnumerable source);

ОК

_FR>T Single(IEnumerable<T> source/*, bool predicate*/);

_FR>T SingleOrDefault(IEnumerable<T> source/*, bool predicate*/);

Что они делают? Выдают первый попавшийся элемент?
Чем это оличается от Find()?

_FR>IEnumerable<S> Select<T, S>(IEnumerable<T> source, Function<T, /* int, */, S> selector);

_FR>IEnumerable<S> SelectMany<T, S>(IEnumerable<T> source, Function<T, /* int, */ IEnumerable<S>> selector);

Это аналоги Map()


_FR>IEnumerable<T> Take<T>(IEnumerable<T> source, int count);

_FR>IEnumerable<T> TakeWhile<T>(IEnumerable<T> source, Function<T, /* int, */ bool> predicate);
_FR>IEnumerable<T> Skip<T>(IEnumerable<T> source, int count);
_FR>IEnumerable<T> SkipWhile<T>(IEnumerable<T> source, Function<T, /* int, */ bool> predicate);

В общем, я и говорил о переносе всего линковского. Но надо решить проблему с дублированием имен.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: Klapaucius  
Дата: 12.01.07 13:09
Оценка: +2
Здравствуйте, konsoletyper.

Немного критики.

K>    public Compare['a, 'b](
K>      a : SCG.IEnumerable['a],
K>      b : SCG.IEnumerable['b],
K>      f : 'a * 'b -> int ) : int
K>    {
K>      def first = a.GetEnumerator();
K>      def second = b.GetEnumerator();
K>      def loop()
K>      {
K>        match ((first.MoveNext(), second.MoveNext()))
K>        {
K>          | (false, false) => 0
K>          | (true, false)  => 1
K>          | (false, true)  => -1
K>          | (true, true)   =>
K>            match (f(first.Current, second.Current))
K>            {
K>              | 0 => loop()
K>              | x => x
K>            }
K>        }
K>      }
K>      def r = loop();
K>      first.Dispose();
K>      second.Dispose();
K>      r
K>    }


Тогда уж, наверное, лучше так:

public Compare['a, 'b](
  a : SCG.IEnumerable['a],
  b : SCG.IEnumerable['b],
  f : 'a * 'b -> int ) : int
  {
    using(def first = a.GetEnumerator(),
            def second = b.GetEnumerator())
        {
            def loop()
            {
                match ((first.MoveNext(), second.MoveNext()))
                {
                    | (false, false) => 0
                    | (true, false)  => 1
                    | (false, true)  => -1
                    | (true, true)   =>
                        match (f(first.Current, second.Current))
                            {
                                | 0 => loop()
                                | x => x
                            }
                }
            }
            loop()
    }
  }


K>    public Compare['a](
K>      a : SCG.IEnumerable['a],
K>      b : SCG.IEnumerable['a]) : int where 'a : System.IComparable['a]
K>    {
K>      def compare(a, b)
K>      {
K>        a.CompareTo(b)
K>      }
K>      Compare(a, b, compare)
K>    }


А так не лучше?

Compare(a, b, (a,b) => a.CompareTo(b))


Или даже

Compare(a, b, _.CompareTo(_))


Но это так, мелкие придирки.

K>    public Reduce['a, 'b](
K>      iter : SCG.IEnumerable['a],
K>      f : 'b * 'a -> 'b,
K>      s : 'b) : 'b


Зачем нужна эта функция, если уже есть

FoldLeft[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;
FoldRight[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;
Fold[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;


А?
Кроме того, лично я предпочитаю экстеншн-методы, да и в стандартной библиотеке Nemerle это теперь стандарт де-факто.

K>Да, и вот что ещё. Как инициализировать массив, например, из IEnumerable?


ToArray[T](this source : IEnumerable[T]) : array[T];


Или имеется в виду уже существующий массив из N элементов, который берет из IEnumerable N элементов?
Что-то такое
From[T](this arr : array[T], iter : IEnumerable[T])
{
    mutable i = 0;
    using(def it = iter.GetEnumerator())
        while(it.MoveNext() && (i < arr.Length))
        {
            arr[i] = it.Current;
            i++;
        }
}


То, чего тут нет, но что может пригодиться:

public static Iter[T](this source : IEnumerable[T], f : T -> void) : void
{
  foreach(elem in source)
    f(elem)
}


И еще
public static Zip['a,'b](ia : IEnumerable['a], ib : IEnumerable['b]): IEnumerable['a * 'b]
{
  using(def first = ia.GetEnumerator(), def second = ib.GetEnumerator())
    while(first.MoveNext() && second.MoveNext())
      yield (first.Current, second.Current)
}


Делает из [1, 2, 3, 4, 5, ...] и [понедельник, вторник, среда, ...]
[(1, понедельник), (2, вторник), ...]
... << RSDN@Home 1.2.0 alpha rev. 655>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[3]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: Klapaucius  
Дата: 12.01.07 13:09
Оценка:
K>Лично я сильно удивился, что нельзя сделать вот так:
K>
K>def lazy5() : IEnumerable[int] 
K>{ 
K>  while(true) yield 5; 
K>}
K>

K>или так:
K>
K>def lazy5 = () => while(true) yield 5;
K>

K>при том, что вот так можно
K>
K>public lazyFive() : IEnumerable[int] 
K>{ 
K>  while(true) yield 5; 
K>}
K>


Впрочем, в данном случае, видимо, можно самому сделаться кузнецом своего (не)счастья и выковать анонимный итератор

def it = iter(n) {inf yield n};

где iter — макрос, генерирующий класс-реализатор IEnumerable['t] или, Function[..., IEnumerable['t]], а inf body это макрос для бесконечного цикла while(true) body
Правда, подозреваю, что реализовывать лексическое замыкание вручную на макросах не очень весело. Без замыкания, конечно, это все просто, но зачем такая штука без замыкания?
Правда, такие экстравагантные вещи я в стандартную библиотеку рекомендовать опасаюсь.

Кстати мне все-таки интересно, почему локальную функцию и лямбду, имеющую в своем теле yield создать нельзя.
... << RSDN@Home 1.2.0 alpha rev. 655>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[4]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: _FRED_ Черногория
Дата: 12.01.07 13:22
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>А чем не нравятся имена, используемые в linq: Map->Select, Filter->Where. Разве нечитабельно?


VD>По двум причинам.


VD>Во-первых, они несколько нелогичны если не рассматривать доступ к коллекциям как SQL-подобные запросы. Например, меня просто клинит с Select, а вот Convert или Map я понимаю прекрасно.


Зато аналоги — SelectMany и используемая мной SelectRecursively (имя, конечно, дурацкое, но лучшего не придумал. Занимается она тем, что преобразует произвольное дерево к IEnumerable) имеют отношение к Select.

Или имя "Map" так же часто используется в некоторых библиотеках для похожих функций?

VD>Во-вторых, когда выйдет Linq сразу будут возникать конфликты имен. Что совсем плохо.


Возможно…
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[7]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: _FRED_ Черногория
Дата: 12.01.07 13:22
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>T Single(IEnumerable<T> source/*, bool predicate*/);

_FR>>T SingleOrDefault(IEnumerable<T> source/*, bool predicate*/);

VD>Что они делают? Выдают первый попавшийся элемент?

VD>Чем это оличается от Find()?

Single: если в наборе (IEnumerable) только одно значение, удовлетворяющее предикату, то это значение и возвращается. Если ни одного или более одного, то исключение.
SingleOrDefault: возвращает значение по-умолчанию для пустого набора. Если же значений больше одного — то исключение.

Но, вообще-то, он для списка лучше реализуется, чем для IEnumerable.

_FR>>IEnumerable<S> Select<T, S>(IEnumerable<T> source, Function<T, /* int, */, S> selector);

_FR>>IEnumerable<S> SelectMany<T, S>(IEnumerable<T> source, Function<T, /* int, */ IEnumerable<S>> selector);

VD>Это аналоги Map()


Твой
Автор: VladD2
Дата: 10.01.07
MapLazy позволяет получить SelectMany?



VD>В общем, я и говорил о переносе всего линковского. Но надо решить проблему с дублированием имен.


Угу.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[7]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 12.01.07 15:29
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Немного критики.


[skip]

K>Тогда уж, наверное, лучше так:


K>
K>public Compare['a, 'b](
K>  a : SCG.IEnumerable['a],
K>  b : SCG.IEnumerable['b],
K>  f : 'a * 'b -> int ) : int
K>  {
K>    using(def first = a.GetEnumerator(),
K>            def second = b.GetEnumerator())
K>        {
K>            def loop()
K>            {
K>                match ((first.MoveNext(), second.MoveNext()))
K>                {
K>                    | (false, false) => 0
K>                    | (true, false)  => 1
K>                    | (false, true)  => -1
K>                    | (true, true)   =>
K>                        match (f(first.Current, second.Current))
K>                            {
K>                                | 0 => loop()
K>                                | x => x
K>                            }
K>                }
K>            }
K>            loop()
K>    }
K>  }
K>


Да, да, точно.

K>
K>Compare(a, b, _.CompareTo(_))
K>


K>Но это так, мелкие придирки.


И это правильно.

K>Зачем нужна эта функция, если уже есть


K>
K>FoldLeft[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;
K>FoldRight[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;
K>Fold[A, B](this source : IEnumerable[B], ini : A, f : B * A -> A) : A;
K>


Сорри, проглядел.

K>Кроме того, лично я предпочитаю экстеншн-методы, да и в стандартной библиотеке Nemerle это теперь стандарт де-факто.


Это вопрос вкуса. Ну если это так принято, то следует переделать так, как принято. Мы с Владом это уже обсуждали.

K>То, чего тут нет, но что может пригодиться:


K>
K>public static Iter[T](this source : IEnumerable[T], f : T -> void) : void
K>{
K>  foreach(elem in source)
K>    f(elem)
K>}
K>


Iter ~ foreach? Если есть второй, зачем тогда первый?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: Klapaucius  
Дата: 12.01.07 19:00
Оценка: 82 (2) +2
Здравствуйте, konsoletyper, Вы писали:

K>>Кроме того, лично я предпочитаю экстеншн-методы, да и в стандартной библиотеке Nemerle это теперь стандарт де-факто.

K>Это вопрос вкуса. Ну если это так принято, то следует переделать так, как принято. Мы с Владом это уже обсуждали.

K>>
K>>public static Iter[T](this source : IEnumerable[T], f : T -> void) : void
K>>{
K>>  foreach(elem in source)
K>>    f(elem)
K>>}
K>>


K>Iter ~ foreach? Если есть второй, зачем тогда первый?


Сейчас объясню. Это для единообразия, чтобы организовать конвейер, например. Точно также это замечание касается и экстеншн-методов.
Вот код иллюстрирующий мои соображения (тем более, что конвейеры не так давно обсуждались в философии применительно как раз к такой задаче)
using(def sw = File.CreateText("result.txt"))
Directory("c:\logs").Files("*.log").Lines().SMatch("Klapaucius").Iter(sw.WriteLine);

Понятно, что если я уж напридумывал несуществующих ленивых экстеншн-методов вполне логично было бы закончить еще одним несуществующим .WriteTo("result.txt"), но идея, которую я пытаюсь донести, кажется, ясна — если хотите сделать что-то с элементами полученными от конвейера — более единообразно выглядит Iter в конце, а не foreach вначале.
using(def sw = File.CreateText("result.txt"))
foreach(elem in Directory("c:\logs").Files("*.log").Lines().SMatch("Klapaucius"))
  sw.WriteLine(elem);

нэ'с па?

Кстати, метод
Lines(this files : IEnumerable[FileInfo]) : IEnumerable[string]

довольно странноватый, а более естественнен
Lines(this file : FileInfo) : IEnumerable[string]

и, соответственно
Directory("c:\logs").Files("*.log").LMap(_.Lines()).Flatten().SMatch("Klapaucius").WriteTo("result.txt"));

так что есть еще востребованная функция
Flatten[T](this source : IEnumerable[IEnumerable[T]]) : IEnumerable[T]
{
  foreach(seq in source)
    foreach(elem in seq)
      yield elem
}
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[7]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.07 21:05
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>
K>public static Iter[T](this source : IEnumerable[T], f : T -> void) : void
K>{
K>  foreach(elem in source)
K>    f(elem)
K>}
K>


Тогда уж по анлогии с list[T] надо еще добавить IterI и Iter2. Первый предоставит индекс, второй позволяит перебирать два списка одновременно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.07 21:05
Оценка: +1
Здравствуйте, Klapaucius, Вы писали:

K>Вот код иллюстрирующий мои соображения (тем более, что конвейеры не так давно обсуждались в философии применительно как раз к такой задаче)

K>
K>using(def sw = File.CreateText("result.txt"))
K>Directory("c:\logs").Files("*.log").Lines().SMatch("Klapaucius").Iter(sw.WriteLine);
K>



Мне кажется что даже более важно не это, а то что foreach не является первоклассным значением, а стало быть его нельзя передать в качестве параметра. А вот Iter можно. Это позволяет иногда получать более выразительный код. Например, что-то вроде:
Go(x);
Go(y.Iter);
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.07 21:11
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Зато аналоги — SelectMany и используемая мной SelectRecursively (имя, конечно, дурацкое, но лучшего не придумал. Занимается она тем, что преобразует произвольное дерево к IEnumerable) имеют отношение к Select.


Дерево? Как это?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Nemerle] map, filter, etc. возвращающие IEnumerable['t]
От: GlebZ Россия  
Дата: 14.01.07 18:59
Оценка:
Интересно. В Nemerle генерики полностью наследуются от стандартных генериков. И я не могу сделать так?
class TwoList[T]
{
A:list[T];
b:list[T];
TwoList(a, b){this.A=a;this.B=b;}
Revert(){TwoList[T](B,A)}
}

То есть сделать свою немутирующую коллекцию на генериках сделать нельзя? Или я чего-то не понимаю.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[2]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: PhantomIvan  
Дата: 14.01.07 23:52
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Интересно. В Nemerle генерики полностью наследуются от стандартных генериков. И я не могу сделать так?

GZ>
GZ>class TwoList[T]
GZ>{
GZ>A:list[T];
GZ>b:list[T];
GZ>TwoList(a, b){this.A=a;this.B=b;}
GZ>Revert(){TwoList[T](B,A)}
GZ>}
GZ>

GZ>То есть сделать свою немутирующую коллекцию на генериках сделать нельзя? Или я чего-то не понимаю.

можешь, конечно

только правильно запиши код
вывод типов на уровне членов класса не поддерживается...
короче внимательно прочти, что компилятор выводит (ошибки)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: GlebZ Россия  
Дата: 15.01.07 06:40
Оценка:
Здравствуйте, PhantomIvan, Вы писали:

PI>только правильно запиши код

PI>вывод типов на уровне членов класса не поддерживается...
PI>короче внимательно прочти, что компилятор выводит (ошибки)
Нету компилятора под рукой. Здесь вообще ошибки (например декларация конструктора). Вопрос простой, можно или нельзя?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re[6]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: _FRED_ Черногория
Дата: 15.01.07 07:00
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Зато аналоги — SelectMany и используемая мной SelectRecursively (имя, конечно, дурацкое, но лучшего не придумал. Занимается она тем, что преобразует произвольное дерево к IEnumerable) имеют отношение к Select.


VD>Дерево? Как это?


Примерно так:
public static class Sequence
{
  /// <summary>
  /// Функция возвращает "плоское" представление иерархии объектов.
  /// </summary>
  /// <typeparam name="T">Тип, общий для всех элементов иерархии.</typeparam>
  /// <param name="items">Набор "корневых" элементов.</param>
  /// <param name="selector">Функтор, возвращающий набор элементов, связанный с переданным ему элементом.</param>
  /// <returns>Рекурсивный набор всех элементов, включая переданный набор <paramref name="items"/>.</returns>
  public static IEnumerable<T> SelectRecursively<T>(IEnumerable<T> items, Function<T, IEnumerable<T>> selector) {
    foreach(T item in items) {
      yield return item;
      foreach(T x in SelectRecursively(item, selector)) {
        yield return x;
      }//for
    }//for
  }

  /// <summary>
  /// Функция возвращает "плоское" представление иерархии объектов.
  /// </summary>
  /// <typeparam name="T">Тип, общий для всех элементов иерархии.</typeparam>
  /// <param name="item">"Корневой", или даже "стартовый", элемент иерархии.</param>
  /// <param name="selector">Функтор, возвращающий набор элементов, связанный с переданным ему элементом.</param>
  /// <returns>Рекурсивный набор всех элементов, включая переданный элемент <paramref name="item"/>.</returns>
  public static IEnumerable<T> SelectRecursively<T>(T item, Function<T, IEnumerable<T>> selector) {
    foreach(T x in selector(item)) {
      yield return x;
      foreach(T y in SelectRecursively(x, selector)) {
        yield return y;
      }//for
    }//for
  }
}

Используется, например, тут:
public static class PageUtils
{
  /// <summary>
  /// Функция возвращает (рекурсивно) все дочернии элементы переданного ей элемента управления, имеющие тип <typeparamref name="T"/>.
  /// </summary>
  /// <typeparam name="T">Тип возвращаемых элементов управления. Так же является "фильтром" результирующего множества.
  /// Обычно, это либо тип <see cref="T:Control"/> (тогда возвращаются все дочернии элементы управления), 
  /// либо интерфейс, который должен поддерживать дочерний элемент управления для того, что бы попасть в результирующий набор.</typeparam>
  /// <param name="control">"Корневой" элемент иерархии.</param>
  /// <returns>Рекурсивный список элементов управления, являющихся дочерним для <paramref name="control"/>.</returns>
  public static IEnumerable<T> Childs<T>(Control control) where T : class {
    if(control == null) {
      throw new ArgumentNullException("control");
    }//if

    Function<Control, IEnumerable<Control>> selector = delegate(Control item) {
      if(item is T) {
        return Sequence.Empty<Control>(); // Пустая последовательность
      }//if

      return Sequence.Cast<Control>(item.Controls); // Каждый элемент преобразуется к Control
    };

    return Sequence.OfType<T>(Sequence.SelectRecursively(control, selector)); // OfType: только элементы заданного (T) типа.
  }

  /// <summary>
  /// Возвращает рекурсивный список дочерних элементов управления.
  /// </summary>
  /// <param name="control">"Корневой" элемент иерархии.</param>
  /// <returns>Рекурсивный список элементов управления, являющихся дочерним для <paramref name="control"/>.</returns>
  public static IEnumerable<Control> Childs(Control control) {
    if(control == null) {
      throw new ArgumentNullException("control");
    }//if

    Function<Control, IEnumerable<Control>> selector = delegate(Control item) {
      return Sequence.Cast<Control>(item.Controls);
    };

    return Sequence.SelectRecursively(control, selector);
  }
}

Теперь, например, я могу получить список всех chekbox-ов, находящихся "внутри" GridView не заботясь о том, на каком уровне иерархии они будут расположены.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[4]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: Андрей Хропов Россия  
Дата: 15.01.07 11:03
Оценка: 12 (1) +1
Здравствуйте, GlebZ, Вы писали:

GZ>Нету компилятора под рукой. Здесь вообще ошибки (например декларация конструктора). Вопрос простой, можно или нельзя?


Можно, правильный код:

[Record]
class TwoList[T]
{
  A: list[T];
  B: list[T];
  
  public Revert() : TwoList[T] { TwoList.[T](B,A) }
  
  public override ToString() : string { $"TwoList: A = $A, B = $B" }
}

System.Console.WriteLine($"Revert of TwoList([1],[2]) is $(TwoList([1],[2]).Revert())");
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.01.07 12:24
Оценка: 14 (1) +1
Здравствуйте, _FRED_, Вы писали:

_FR>Зато аналоги — SelectMany и используемая мной SelectRecursively (имя, конечно, дурацкое, но лучшего не придумал. Занимается она тем, что преобразует произвольное дерево к IEnumerable) имеют отношение к Select.

Гм. А почему бы не обратиться к истокам? То, что делает эта функция, называется "обход графа", а по импортному — Traversal. Так что по идее, функция должна быть такой:

  /// <summary>
  /// Функция возвращает "плоское" представление иерархии объектов.
  /// </summary>
  /// <typeparam name="T">Тип, общий для всех элементов иерархии.</typeparam>
  /// <param name="roots">Набор "корневых" элементов.</param>
  /// <param name="getChildren">Функтор, возвращающий набор элементов, связанных с переданным ему элементом.</param>
  /// <returns>Итератор, перебирающий набор всех доступных через <paramref name="getChildren"> элементов, включая переданный набор <paramref name="items"/>.</returns>
    /// <remarks>Внимание! Несмотря на то, что функция имеет ленивую семантику, крайне не рекомендуется передавать в нее структуры, содержащие циклы. Используйте подходящую версию функции Traverse* для обхода произвольных графов объектов.</remarks>
  public static IEnumerable<T> TraverseTree<T>(IEnumerable<T> roots, Function<T, IEnumerable<T>> getChildren) {
    foreach(T root in roots) {
      yield return root;
      foreach(T item in SelectRecursively(root, getChildren))
        yield return item;
    }
  }
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: chudo19  
Дата: 15.01.07 12:39
Оценка:
Здравствуйте, _FRED_, Вы писали:

На сколько я зопомнил yield нельзя было использовать рекурсивно. Я спутал счем-то ?
Re[6]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: _FRED_ Черногория
Дата: 15.01.07 12:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Гм. А почему бы не обратиться к истокам? То, что делает эта функция, называется "обход графа", а по импортному — Traversal.


Спасибо, я этого не знал

Но, в "истоках" функции с этим названием именно возвращают енумератор или же принимают функтор:
public static IEnumerable<T> TraverseTree<T>(IEnumerable<T> roots, Function<T, IEnumerable<T>> getChildren, Action<T> action) {
  foreach(T root in roots) {
    action(root);
    TraverseTree(getChildren(root), getChildren, action);
  }//for
}



По большому счёту, конечно же пофиг, но интересно…
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[8]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: _FRED_ Черногория
Дата: 15.01.07 12:42
Оценка:
Здравствуйте, chudo19, Вы писали:

C>На сколько я зопомнил yield нельзя было использовать рекурсивно. Я спутал счем-то ?


Вроде спутал. Нельзя его использовать а анонимных методах, например.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Re[9]: [Nemerle] map, filter, etc. возвращающие IEnumerable[
От: chudo19  
Дата: 15.01.07 12:53
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Вроде спутал. Нельзя его использовать а анонимных методах, например.


Тоесть получается что создается виртуальный стек ?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.