레코드(F#)
업데이트: 2010년 5월
레코드는 명명된 값의 간단한 집계를 나타내며 선택적으로 멤버를 포함할 수 있습니다.
[ attributes ]
type [accessibility-modifier] typename = {
[ mutable ] label1 : type1;
[ mutable ] label2 : type2;
...
}
member-list
설명
위 구문에서 typename은 레코드 형식의 이름이고, label1과 label2는 레이블이라는 값의 이름이며, type1과 type2는 해당 값의 형식입니다. member-list는 형식의 멤버 목록으로서 선택적 요소입니다.
다음은 이를 보여 주는 몇 가지 예입니다.
type Point = { x : float; y: float; z: float; }
type Customer = { First : string; Last: string; SSN: uint32; AccountNumber : uint32; }
각 레이블을 한 줄에 하나씩 입력하는 경우 세미콜론을 생략할 수 있습니다.
레코드 식이라고 하는 식의 값을 설정할 수 있습니다. 사용되는 레이블이 다른 레코드 형식의 레이블과 충분히 구별되는 경우 컴파일러는 사용되는 레이블로부터 형식을 유추합니다. 레코드 식은 중괄호({ })로 둘러싸입니다. 다음 코드는 float 요소 세 개를 포함하는 레코드를 레이블 x, y 및 z로 초기화하는 레코드 식을 보여 줍니다.
let mypoint = { x = 1.0; y = 1.0; z = -1.0; }
다른 형식에도 동일한 레이블이 사용될 수 있는 경우에는 축약된 형식을 사용하지 말아야 합니다.
type Point = { x : float; y: float; z: float; }
type Point3D = { x: float; y: float; z: float }
// Ambiguity: Point or Point3D?
let mypoint3D = { x = 1.0; y = 1.0; z = 0.0; }
이전에 선언한 형식의 레이블보다 가장 최근에 선언한 형식의 레이블의 우선 순위가 높으므로 위 예제에서 mypoint3D는 Point3D인 것으로 유추됩니다. 다음 코드에서와 같이 레코드를 명시적으로 지정할 수 있습니다.
let myPoint1 = { Point.x = 1.0; y = 1.0; z = 0.0; }
클래스 형식의 경우와 마찬가지로 레코드 형식에 대해 메서드를 정의할 수 있습니다.
레코드 식을 사용하여 레코드 만들기
레코드에 정의되어 있는 레이블을 사용하여 레코드를 초기화할 수 있습니다. 이 초기화를 수행하는 식을 레코드 식이라고 합니다. 레코드 식을 묶는 데는 중괄호를 사용하고 구분 기호로는 세미콜론을 사용합니다.
다음 예제에서는 레코드를 만드는 방법을 보여 줍니다.
type MyRecord = {
X: int;
Y: int;
Z: int
}
let myRecord1 = { X = 1; Y = 2; Z = 3; }
레코드 식과 필드 정의에서 마지막 필드 뒤에는 세미콜론을 생략할 수 있습니다. 이때 해당 필드를 모두 한 줄에 입력했는지 여부는 중요하지 않습니다.
레코드를 만들 때는 각 필드의 값을 지정해야 합니다. 어떠한 필드에 대해서도 초기화 식에서 다른 필드의 값을 참조할 수 없습니다.
다음 코드에서 myRecord2의 형식은 필드의 이름을 통해 유추됩니다. 원하는 경우 형식 이름을 명시적으로 지정할 수도 있습니다.
let myRecord2 = { MyRecord.X = 1; MyRecord.Y = 2; MyRecord.Z = 3 }
기존 레코드를 복사하여 필드 값 중 일부를 변경해야 하는 경우에는 다른 형식의 레코드 구문을 사용하는 것이 편리할 수 있습니다. 다음 코드 줄에서는 이 구문을 보여 줍니다.
let myRecord3 = { myRecord2 with Y = 100; Z = 2 }
이와 같은 형태의 레코드 식을 복사 및 업데이트 레코드 식이라고 합니다.
레코드는 기본적으로 변경 불가능하지만, 복사 및 업데이트 식을 사용하면 수정된 레코드를 쉽게 만들 수 있습니다. 변경 가능한 필드를 명시적으로 지정할 수도 있습니다.
type Car = {
Make : string
Model : string
mutable Odometer : int
}
let myCar = { Make = "Fabrikam"; Model = "Coupe"; Odometer = 108112 }
myCar.Odometer <- myCar.Odometer + 21
레코드와 패턴 일치
패턴 일치에 레코드를 사용할 수 있습니다. 일부 필드를 명시적으로 지정하고 일치 여부를 확인할 때 다른 필드에 할당할 값을 제공할 수 있습니다. 다음 코드 예제에서는 그 구체적인 방법을 보여 줍니다.
type Point3D = { x: float; y: float; z: float }
let evaluatePoint (point: Point3D) =
match point with
| { x = 0.0; y = 0.0; z = 0.0 } -> printfn "Point is at the origin."
| { x = xVal; y = 0.0; z = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
| { x = 0.0; y = yVal; z = 0.0 } -> printfn "Point is on the y-axis. Value is %f." yVal
| { x = 0.0; y = 0.0; z = zVal } -> printfn "Point is on the z-axis. Value is %f." zVal
| { x = xVal; y = yVal; z = zVal } -> printfn "Point is at (%f, %f, %f)." xVal yVal zVal
evaluatePoint { x = 0.0; y = 0.0; z = 0.0 }
evaluatePoint { x = 100.0; y = 0.0; z = 0.0 }
evaluatePoint { x = 10.0; y = 0.0; z = -1.0 }
이 코드의 출력은 다음과 같습니다.
Point is at the origin.
Point is on the x-axis. Value is 100.000000.
Point is at (10.000000, 0.000000, -1.000000).
레코드와 클래스의 차이점
레코드 필드는 속성으로 자동 노출되며 레코드를 만들고 복사하는 데 사용된다는 점에서 클래스와 다릅니다. 레코드 구문과 클래스 구문에도 차이가 있습니다. 레코드 형식에서는 생성자를 정의할 수 없습니다. 대신 이 항목에서 설명한 구문이 적용됩니다. 클래스의 경우 생성자 매개 변수, 필드 및 속성 사이에 직접적인 관계가 없습니다.
공용 구조체 및 구조체 형식과 마찬가지로 레코드에는 구조적 같음 의미 체계가 있습니다. 클래스에는 참조 일치 의미 체계가 있습니다. 다음 코드 예제에서 이를 보여 줍니다.
type RecordTest = { X: int; Y: int }
let record1 = { X = 1; Y = 2 }
let record2 = { X = 1; Y = 2 }
if (record1 = record2) then
printfn "The records are equal."
else
printfn "The records are unequal."
클래스를 사용하여 동일한 코드를 작성하는 경우 두 클래스 개체가 같지 않게 됩니다. 클래스 형식에서 System.Object.Equals 메서드를 재정의하지 않는 한, 두 값이 힙의 두 개체를 나타내며 주소만 서로 비교되기 때문입니다.
참고 항목
참조
기타 리소스
변경 기록
날짜 |
변경 내용 |
이유 |
---|---|---|
2010년 5월 |
향상된 일부 코드 예. |
향상된 기능 관련 정보 |