Loops
Loops (반복문)
F#에서는 반복을 위해 세 가지 루프 표현식을 쓸 수 있어요. 리스트·시퀀스·배열 같은 열거 가능한 컬렉션을 훑을 땐 for...in, 정수 구간을 하나씩 세어가며 반복할 땐 for...to, 조건이 참인 동안 계속 반복할 땐 while...do를 사용합니다. 이 세 가지를 차례로 살펴볼게요.
출처
본문
for...in Expression
for...in은 열거 가능한 컬렉션(구간 표현식, 시퀀스, 리스트, 배열, 그리고 열거를 지원하는 다른 어떤 구성)에서 패턴과 매치되는 요소들을 하나씩 반복할 때 쓰는 루프 구조예요.
구문
for pattern in enumerable-expression do
body-expression
알아두기
for...in은 열거 가능한 컬렉션의 값들을 순회하기 때문에, 다른 .NET 언어의 for each 문과 비교할 수 있어요. 다만 for...in은 컬렉션 전체를 그냥 순회하는 것에 더해 컬렉션에 대해 패턴 매칭까지 지원한다는 점이 달라요.
열거 가능한 표현식은 열거 가능한 컬렉션으로 지정하거나, .. 연산자를 써서 구간으로 지정할 수 있어요. 열거 가능한 컬렉션에는 리스트, 시퀀스, 배열, 집합(set), 맵(map) 등이 있고, System.Collections.IEnumerable을 구현하는 어떤 타입이든 사용할 수 있어요.
.. 연산자로 구간을 표현할 때는 다음 구문을 써요.
start .. finish
증분값(이를 skip 이라고 해요)을 포함한 버전도 쓸 수 있어요.
start .. skip .. finish
skip 값을 지정하지 않으면 컬렉션에서 다음으로 생성되는 값이 1씩 증가해요. skip을 지정하면 그 값만큼 증가하지요.
패턴에서 매치된 값은 본문 표현식 안에서 그대로 사용할 수 있어요.
이어지는 코드 예시들이 for...in의 다양한 쓰임을 보여줄게요.
// Looping over a list.
let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
printfn "%d" i
출력은 다음과 같아요.
1
5
100
450
788
다음 예시는 시퀀스를 순회하면서, 단순 변수 대신 튜플 패턴을 쓰는 모습을 보여줘요. 이 시퀀스 표현식의 -> 연산자는 시퀀스 표현식과 다른 계산 표현식에서 do yield의 줄임말이에요. -> 연산자 덕분에 그 값이 시퀀스의 일부가 되는 표현식을 지정할 수 있죠. 자세한 내용은 Sequences와 Computation Expressions를 참고해요.
let seq1 = seq { for i in 1 .. 10 -> (i, i*i) }
for (a, asqr) in seq1 do
printfn "%d squared is %d" a asqr
출력은 다음과 같아요.
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
6 squared is 36
7 squared is 49
8 squared is 64
9 squared is 81
10 squared is 100
다음 예시는 간단한 정수 구간을 순회하는 방법이에요.
let function1() =
for i in 1 .. 10 do
printf "%d " i
printfn ""
function1()
function1의 출력은 다음과 같아요.
1 2 3 4 5 6 7 8 9 10
이번에는 skip이 2인 구간을 순회해요. 구간의 하나 걸러 요소만 포함되지요.
let function2() =
for i in 1 .. 2 .. 10 do
printf "%d " i
printfn ""
function2()
function2의 출력은 다음과 같아요.
1 3 5 7 9
문자 구간도 사용할 수 있어요.
let function3() =
for c in 'a' .. 'z' do
printf "%c " c
printfn ""
function3()
function3의 출력은 다음과 같아요.
a b c d e f g h i j k l m n o p q r s t u v w x y z
음수 skip 값을 써서 역순으로 반복할 수도 있어요.
let function4() =
for i in 10 .. -1 .. 1 do
printf "%d " i
printfn " ... Lift off!"
function4()
function4의 출력은 다음과 같아요.
10 9 8 7 6 5 4 3 2 1 ... Lift off!
구간의 시작과 끝도 표현식(예를 들어 함수)이 될 수 있어요. 아래 코드에서 확인해 볼게요.
let beginning x y = x - 2*y
let ending x y = x + 2*y
let function5 x y =
for i in (beginning x y) .. (ending x y) do
printf "%d " i
printfn ""
function5 10 4
이 입력값으로 function5를 실행한 출력은 다음과 같아요.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
다음 예시는 루프에서 요소가 필요하지 않을 때 와일드카드 문자(_)를 쓰는 모습을 보여줘요.
let mutable count = 0
for _ in list1 do
count <- count + 1
printfn "Number of elements in list1: %d" count
출력은 다음과 같아요.
Number of elements in list1: 5
참고로, for...in은 시퀀스 표현식이나 다른 계산 표현식 안에서도 쓸 수 있는데, 그 경우 for...in의 맞춤형 버전이 사용돼요. 자세한 내용은 Sequences, Async expressions, Task expressions, Computation Expressions를 참고해요.
for...to Expression
for...to 표현식은 루프 변수의 값 범위를 순회하며 반복할 때 쓰는 루프 구조예요.
구문
for identifier = start [ to | downto ] finish do
body-expression
알아두기
identifier의 타입은 start와 finish 표현식의 타입으로부터 추론돼요. 이 두 표현식의 타입은 32비트 정수여야 해요.
엄밀히는 표현식이지만, for...to는 명령형 프로그래밍 언어의 전통적인 문장에 가까워요. body-expression의 반환 타입은 반드시 unit이어야 해요. 다음 예시들이 for...to의 다양한 쓰임을 보여줄게요.
// A simple for...to loop.
let function1() =
for i = 1 to 10 do
printf "%d " i
printfn ""
// A for...to loop that counts in reverse.
let function2() =
for i = 10 downto 1 do
printf "%d " i
printfn ""
function1()
function2()
// A for...to loop that uses functions as the start and finish expressions.
let beginning x y = x - 2*y
let ending x y = x + 2*y
let function3 x y =
for i = (beginning x y) to (ending x y) do
printf "%d " i
printfn ""
function3 10 4
앞선 코드의 출력은 다음과 같아요.
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
while...do Expression
while...do 표현식은 지정한 테스트 조건이 참인 동안 반복 실행(루핑)을 수행할 때 쓰는 루프 구조예요.
구문
while test-expression do
body-expression
알아두기
test-expression을 평가해서 참이면 body-expression을 실행하고, 다시 테스트 표현식을 평가해요. body-expression의 타입은 반드시 unit이어야 해요. 테스트 표현식이 거짓이 되면 반복이 끝나요.
다음 예시가 while...do의 쓰임을 보여줄게요.
open System
let lookForValue value maxValue =
let mutable continueLooping = true
let randomNumberGenerator = new Random()
while continueLooping do
// Generate a random number between 1 and maxValue.
let rand = randomNumberGenerator.Next(maxValue)
printf "%d " rand
if rand = value then
printfn "\nFound a %d!" value
continueLooping <- false
lookForValue 10 20
앞선 코드의 출력은 1과 20 사이의 무작위 숫자들의 흐름이며, 마지막 숫자는 10이에요.
13 19 8 18 16 2 10
Found a 10!
참고로, while...do도 시퀀스 표현식이나 다른 계산 표현식 안에서 쓸 수 있으며, 그 경우 while...do의 맞춤형 버전이 사용돼요. 자세한 내용은 Sequences, Async expressions, Task expressions, Computation Expressions를 참고해요.