本文介绍了为什么不能的IEnumerator的克隆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在实现基本方案除preTER在C#中,我发现,我的恐惧,下面的问题:

In implementing a basic Scheme interpreter in C# I discovered, to my horror, the following problem:

IEnumerator的没有一个克隆的方法! (以上precisely,IEnumerable的不能给我提供一个可复制枚举)。

IEnumerator doesn't have a clone method! (or more precisely, IEnumerable can't provide me with a "cloneable" enumerator).

我想:

interface IEnumerator<T>
{
    bool MoveNext();
    T Current { get; }
    void Reset();
    // NEW!
    IEnumerator<T> Clone();
}

我不能想出的IEnumerable的实现,将不能够提供一个有效的可复制的IEnumerator(向量,链表,等等一切就都能够提供一个简单的实现了IEnumerator的克隆的()作为上述规定.. 。这将是比提供一个Reset()方法,反正容易!)。

I cannot come up with an implementation of IEnumerable that would not be able to supply an efficiently cloneable IEnumerator (vectors, linked lists, etc. all would be able to provide a trivial implementation of IEnumerator's Clone() as specified above... it would be easier than providing a Reset() method anyway!).

由于没有克隆方法意味着列举一个序列的任何功能/递归成语将无法正常工作。

The absence of the Clone method means that any functional/recursive idiom of enumerating over a sequence won't work.

这也意味着我不能无缝进行了IEnumerable的表现得象Lisp(您使用汽车/ CDR枚举递归)名单。即唯一的FPGA实现(CDR的部分的IEnumerable 的)将是完全不能胜任。

It also means I can't "seamlessly" make IEnumerable's behave like Lisp "lists" (for which you use car/cdr to enumerate recursively). i.e. the only implemention of "(cdr some IEnumerable)" would be woefully inefficient.

任何人都可以表明,将无法提供有效的克隆()方法将IEnumerable对象的现实的,有用的,例如?难道有会是与收益建设?问题

任何人都可以提出一个解决办法?

Can anyone suggest a workaround?

推荐答案

的逻辑是无情的! 的IEnumerable 不支持克隆,你需要克隆 ,所以你不应该使用的IEnumerable

The logic is inexorable! IEnumerable doesn't support Clone, and you need Clone, so you shouldn't be using IEnumerable.

或者更准确的说,你不应该使用它作为一个方案除preTER工作的基本依据。为什么不把一个简单的不可变的链表呢?

Or more accurately, you shouldn't be using it as the fundamental basis for work on a Scheme interpreter. Why not make a trivial immutable linked list instead?

public class Link<TValue>
{
    private readonly TValue value;
    private readonly Link<TValue> next;

    public Link(TValue value, Link<TValue> next)
    {
        this.value = value;
        this.next = next;
    }

    public TValue Value
    {
        get { return value; }
    }

    public Link<TValue> Next
    {
        get { return next; }
    }

    public IEnumerable<TValue> ToEnumerable()
    {
        for (Link<TValue> v = this; v != null; v = v.next)
            yield return v.value;
    }
}

注意 ToEnumerable 方法为您提供了方便的使用标准C#的方式。

Note that the ToEnumerable method gives you convenient usage in the standard C# way.

要回答你的问题:

任何人都可以提出一个现实的,  IEnumerable的有用的,例如  对象,将不能够  提供高效率的克隆()方法?  难道有会是一个问题  在收益构建?

将IEnumerable可以在世界任何地方的数据。下面是从控制台读取线的一个例子:

An IEnumerable can go anywhere in the world for its data. Here's an example that reads lines from the console:

IEnumerable<string> GetConsoleLines()
{
    for (; ;)
        yield return Console.ReadLine();
}

有两个问题:首先,克隆功能不会特别直接写(和重置就毫无意义)。其次,该序列是无限 - 这是完全允许的。序列是懒惰的。

There are two problems with this: firstly, a Clone function would not be particularly straightforward to write (and Reset would be meaningless). Secondly, the sequence is infinite - which is perfectly allowable. Sequences are lazy.

另外一个例子:

IEnumerable<int> GetIntegers()
{
    for (int n = 0; ; n++)
        yield return n;
}

有关这两个例子中,变通你接受就没有多大用处,因为它只是耗尽可用内存或挂断电话,直到永远。但这些序列的完全有效的例子。

For both these examples, the "workaround" you've accepted would not be much use, because it would just exhaust the available memory or hang up forever. But these are perfectly valid examples of sequences.

要了解C#和F#序列,你需要看看方案Haskell中的列表,而不是列表。

To understand C# and F# sequences, you need to look at lists in Haskell, not lists in Scheme.

如果你觉得无限的东西,是一个红色的鲱鱼,怎么样从套接字读取的字节数:

In case you think the infinite stuff is a red herring, how about reading the bytes from a socket:

IEnumerable<byte> GetSocketBytes(Socket s)
{
    byte[] buffer = new bytes[100];
    for (;;)
    {
        int r = s.Receive(buffer);
        if (r == 0)
            yield break;

        for (int n = 0; n < r; n++)
            yield return buffer[n];
    }
}

如果有正在发送向下一些字节的插座,这不会是一个无限序列。然而,写克隆的这将是非常困难的。如何将编译器生成的IEnumerable实现自动执行的呢?

If there is some number of bytes being sent down the socket, this will not be an infinite sequence. And yet writing Clone for it would be very difficult. How would the compiler generate the IEnumerable implementation to do it automatically?

只要有创建的克隆,这两种情况下将现在必须从一个缓冲系统,他们共享工作。这是可能的,但在实践中是不需要的 - 这不是如何将这些种序列被设计为可以使用。你对待他们单纯的功能性,如价值观,应用过滤器,以他们递归,而不是命令式记忆序列中的位置。这是一个有点清洁比低级别的 / CDR 操作。

As soon as there was a Clone created, both instances would now have to work from a buffer system that they shared. It's possible, but in practice it isn't needed - this isn't how these kinds of sequences are designed to be used. You treat them purely "functionally", like values, applying filters to them recursively, rather than "imperatively" remembering a location within the sequence. It's a little cleaner than low-level car/cdr manipulation.

进一步的问题:

我不知道,什么是最低水平  原语(S)我需要这样  任何事情我可能想要做的  IEnumerable的在我的计划除preTER  可在方案中实现,而  不是作为一个内建的。

简短的回答我觉得这是看在阿伯尔森和萨斯曼并且特别的部分有关流的IEnumerable 是一个流,而不是一个列表。他们描述你是如何需要的地图,过滤器,积累等特殊版本,与他们合作。他们还获得到统一名单的想法和溪流中第4.2节。

The short answer I think would be to look in Abelson and Sussman and in particular the part about streams. IEnumerable is a stream, not a list. And they describe how you need special versions of map, filter, accumulate, etc. to work with them. They also get onto the idea of unifying lists and streams in section 4.2.

这篇关于为什么不能的IEnumerator的克隆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-04 22:32