레코드(F#)

레코드는 명명된 값의 간단한 집계를 나타내며 선택적으로 멤버를 포함할 수 있습니다.

[ 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

DefaultValue 특성은 레코드의 필드를 사용 하지 마십시오.기본값으로 초기화 되는 필드에 있는 레코드의 기본 인스턴스를 정의 합니다. 그런 다음 복사본을 사용 하 고 기본값에서 다른 필드 집합을 레코드 식을 업데이트 하는 것이 좋습니다.

// Rather than use [<DefaultValue>], define a default record.
type MyRecord =
    { 
        field1 : int 
        field2 : int
    }

let defaultRecord1 = { field1 = 0; field2 = 0 }
let defaultRecord2 = { field1 = 1; field2 = 25 }

// Use the with keyword to populate only a few chosen fields
// and leave the rest with default values.
let rr3 = { defaultRecord1 with field2 = 42 }

레코드와 패턴 일치

패턴 일치에 레코드를 사용할 수 있습니다.일부 필드를 명시적으로 지정하고 일치 여부를 확인할 때 다른 필드에 할당할 값을 제공할 수 있습니다.다음 코드 예제에서는 그 구체적인 방법을 보여 줍니다.

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 메서드를 재정의하지 않는 한, 두 값이 힙의 두 개체를 나타내며 주소만 서로 비교되기 때문입니다.

참고 항목

참조

클래스(F#)

패턴 일치(F#)

기타 리소스

F# 형식

F# 언어 참조