6

我正在尝试yield在 JavaScript/TypeScript 中实现 C# 关键字(不管是哪个):例如,我想实现代码

//using System.Collections;  
//using System.Diagnostics; 
public static void Process()
{
    // Display powers of 2 up to the exponent of 8:  
    foreach (int number in Power(2, 8))
    {
        Debug.Write(number.ToString() + " ");
    }
    // Output: 2 4 8 16 32 64 128 256
}


public static IEnumerable Power(int baseNumber, int highExponent)
{
    int result = 1;

    for (int counter = 1; counter <= highExponent; counter++)
    {
        result = result * baseNumber;
        yield return result;
    }
}

在 JavaScript 中。

最终目标是在 JavaScript 中实现我在 stackoverflow 上提出的另一个问题中用 C# 编写的函数:

public static IEnumerable<string> SplitByCharacterType(string input)
{
    if (String.IsNullOrEmpty(input))
        throw new ArgumentNullException(nameof(input));

    StringBuilder segment = new StringBuilder();
    segment.Append(input[0]);
    var current = Char.GetUnicodeCategory(input[0]);

    for (int i = 1; i < input.Length; i++)
    {
        var next = Char.GetUnicodeCategory(input[i]);
        if (next == current)
        {
            segment.Append(input[i]);
        }
        else
        {
            yield return segment.ToString();
            segment.Clear();
            segment.Append(input[i]);
            current = next;
        }
    }
    yield return segment.ToString();
}

有任何想法吗?

4

5 回答 5

6

我认为没有一种合理的方法可以在循环的上下文中进行这项工作,该for循环在“移动下一个”操作期间保留惰性求值的 C# 语义。不过,您可以使用闭包合理地模拟这一点。

(打字稿代码):

function getPowers(base: number, maxExponent: number) {
    var currentExponent = 1;
    return function() {
        if(currentExponent > maxExponent) {
            return undefined;
        } else {
            return Math.pow(base, currentExponent++);
        }
    }
}

// Simple test
var p = getPowers(2, 8);
var n: number;
while((n = p()) !== undefined) {
    console.log(n);
}

// Demonstrate that multiple instances work
var p2 = getPowers(2, 3);
var p3 = getPowers(3, 3);
while(true) {
    var n2 = p2();
    var n3 = p3();
    if((n2 || n3) === undefined) break;

    console.log(n2 + ", " + n3);
}
于 2012-12-01T21:31:58.227 回答
2

我知道这是多年以后的事了,但是 TypeScript 中现在存在生成器和迭代器,所以现在这是可能的。您可以在此处阅读更多详细信息:https ://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#typescript-23

我是 的原作者SplitByCharacterType,所以我想我也会尝试在 JS 中重新实现它。最困难的问题是缺乏区分字符类型的本机能力(例如:)GetUnicodeCategoryunicode-categories看起来可以用来识别字符类别。这里也有一个答案。我将使用第二个选项,因为它看起来更全面。请注意,getType()此处使用的方法来自该答案。

function* splitByCharacterType(input) {
    if (!input || !input.length) 
        return;

    var segment = [input[0]];
    var current = getType(input[0]);

    for (var i = 1; i < input.length; i++) {
        var item = input[i];
        var next = getType(item);
        if (next == current) {
            segment.push(item);
        } else {
            yield segment.join("");
            segment = [item];
            current = next;
        }
    }
    yield segment.join("");
}

这也是一个关于这个主题的有趣页面:http: //inimino.org/~inimino/blog/javascript_cset

于 2017-05-15T06:53:04.223 回答
0

某些版本的 JavaScript 包括yield但未得到广泛支持(尽管 Firefox 确实支持它)。

尽管真正的“yield”的标志是多个活动的调用堆栈,它需要线程(这就是可以在 Java 中模拟 yield 的原因),但您也许可以即兴发挥,但标准 JS 也没有线程。

您可以查看 Web Workers http://en.wikipedia.org/wiki/Web_worker,但我怀疑这对于大多数受益于产量的应用程序来说过于重量级和限制性。

于 2012-12-01T21:23:15.327 回答
0

@Lajos Arpad:拥有一个数组与拥有一个 IEnumerable 不同。该接口的核心是按需评估迭代中的下一个元素。

为瑞安+1。

从某种意义上说,该示例可能会更好,即对 getPowers 函数的调用不应具有 maxExponent 参数。这对于惰性求值 IEnumerable 来说根本不是必需的。消费者可以选择任意数量的权力。

Ryan 的示例也适用于无界场景,而任何使用数组的实现都必须失败。

于 2012-12-01T21:49:51.933 回答
0

因此,这里有一个示例,展示了枚举如何在其定义中不受限制,但通过仅读取几个元素来限制消费者端:

        function getPowers(base) {
            var currentExponent = 1;
            return function () {
                return Math.pow(base, currentExponent++);
            }
        }

        function test() {
            // Simple test
            var p = getPowers(2);
            var elem = document.getElementById("a");
            elem.innerHTML = "<p>" + p() + "<p>" + p() + "<p>" + p() + "<p>" + p() + "<p>" + p() + "<p>" + p() + "<p>" + p();
        }
于 2012-12-03T22:09:27.587 回答