6

JavaScript/TypeScript でC# キーワードを実装しようとしています (どちらでも構いません): たとえば、コードyieldを実装したいと思います:

//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 で。

最終的な目標は、stackoverflow で尋ねた別の質問から C# で記述された関数を JavaScript で実装することです。

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# セマンティクスを保持するループのコンテキストでこれを機能させる合理的な方法はないと思います。ただし、クロージャーを使用してこれを合理的にシミュレートできます。

(TypeScript コード):

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 に答える
0

一部のバージョンの JavaScript には含まれていますyieldが、広くサポートされているわけではありません (ただし、Firefox ではサポートされています)。

真の「yield」の特徴は複数のアクティブなコールスタックであり、これにはスレッドが必要ですが (Java で yield をシミュレートできるのはそのためです)、標準の JS にもスレッドがありませんが、代替案を即興で作成できる場合があります。

Web Workers http://en.wikipedia.org/wiki/Web_workerを見ることができますが、yield の恩恵を受けるほとんどのアプリケーションにとって、これは重すぎて制限が厳しすぎるのではないかと思います。

于 2012-12-01T21:23:15.327 に答える
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 に答える
0

@Lajos Arpad: 配列を持つことは、IEnumerableを持つことと同じではありません。このインターフェースの中核は、反復内の次の要素のオンデマンド評価です。

ライアンに+1。

getPowers 関数の呼び出しに maxExponent パラメーターを指定しないという意味では、この例の方が優れている可能性があります。これは、IEnumerable の遅延評価には必要ありません。消費者は、必要な数の権限を選択できます。

Ryans の例は無制限のシナリオでも機能しますが、配列を使用した実装は失敗する必要があります。

于 2012-12-01T21:49:51.933 に答える