+TypeScript 예제
Playlist는 항목을 보관하고, 순회할 때 만든 반복자는 현재 위치를 보관한다. 위치를 컬렉션 하나에 저장하지 않아야 두 순회가 서로의 진행을 바꾸지 않는다.
// 내부 배열을 감추고 항목을 순회하는 약속만 제공한다.
class Playlist implements Iterable<string> {
private readonly tracks: readonly string[];
constructor(tracks: readonly string[]) { this.tracks = [...tracks]; }
// 새 호출마다 별도 순회 위치를 가진 생성기를 반환한다.
*[Symbol.iterator](): Generator<string, void, unknown> {
for (const track of this.tracks) yield track;
}
}
function step(iterator: Iterator<string>): string {
const result = iterator.next();
return result.done ? "(end)" : result.value;
}
const playlist = new Playlist(["intro", "outro"]);
const first = playlist[Symbol.iterator]();
const second = playlist[Symbol.iterator]();
console.log("first: " + step(first));
console.log("first: " + step(first));
console.log("second: " + step(second));
console.log("second: " + step(second));
first: intro
first: outro
second: intro
second: outro
C#의 GetEnumerator()에 대응하는 진입점이 Symbol.iterator다. 생성기 함수를 호출할 때마다 별도 반복자가 만들어지며, 끝난 뒤에는 next()의 done을 확인한다.
조회·변환만 필요하면 LINQ로
이미 순회 가능한 컬렉션에서 일부 항목을 고르고 변환하려는 것이라면 새 이터레이터 클래스를 만들 필요가 없다. C#의 LINQ는 Where에 고르는 조건을, Select에 변환 함수를 받아 순회를 조합한다. 다음 코드는 in으로 시작하는 곡 이름만 대문자로 바꾸며 입력 배열은 그대로 둔다.
C#
using System;
using System.Linq;
var tracks = new[] { "intro", "outro", "interlude" };
// Where는 조건, Select는 변환을 맡고 ToArray가 지금 순회해 결과를 저장한다.
string[] labels = tracks
.Where(track => track.StartsWith("in", StringComparison.Ordinal))
.Select(track => track.ToUpperInvariant())
.ToArray();
Console.WriteLine(string.Join(",", labels));
Console.WriteLine(string.Join(",", tracks));
TypeScript
const tracks = ["intro", "outro", "interlude"];
// 배열의 filter와 map은 호출할 때 바로 계산하며 새 배열을 반환한다.
const labels = tracks
.filter(track => track.startsWith("in"))
.map(track => track.toUpperCase());
console.log(labels.join(","));
console.log(tracks.join(","));
INTRO,INTERLUDE
intro,outro,interlude
여기서는 메모리 안의 문자열을 다룬다. LINQ의 Where·Select는 결과를 순회할 때 실행되고 ToArray가 그 시점을 정하지만, TypeScript 배열의 filter·map은 즉시 실행된다. 여기에 쓴 ASCII 곡 이름에서는 같은 항목을 고르고 대문자로 바꾸며 입력은 그대로 둔다. 함수형 스타일이라고 외부 호출이나 공유 상태 변경이 자동으로 없어지는 것은 아니다.
Microsoft: Introduction to LINQ queries