I'm trying to implement the C# keyword yield
with in JavaScript/TypeScript (doesn't matter which): For example, I would like to implement the code:
//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;
}
}
in JavaScript.
The end goal is to implement a function written in C# from another question I asked about on stackoverflow, in 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();
}
Any ideas?
I don't think there's a reasonable way to make this work in the context of a for
loop that preserves the C# semantics of lazy evaluation during the "move next" operation. You can simulate this reasonably with closures, though.
(TypeScript code):
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);
}
I know it's many years later, but generators & iterators now exist in TypeScript, so this is now possible. You can read more of the details here: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#typescript-23
I'm the original author of the SplitByCharacterType
, so I figured I'd also give it a stab to try and re-implement in JS. The hardest problem is the lack of a native ability to differentiate character type (ex: GetUnicodeCategory
). unicode-categories looks like it could be used to identify the character category. There is also an answer here for this. I'm going to use the second option as it looks more comprehensive. Note, that the getType()
method used here is coming from that answer.
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("");
}
This was also an interesting page on the subject: http://inimino.org/~inimino/blog/javascript_cset
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With