OCaml과 같은 일부 기능 언어에는 추상 데이터 형식 을 구현하기위한 메커니즘이 내장되어있어 일부 불변성을 적용합니다 . 그러한 메커니즘을 갖지 않는 언어는 불변을 적용하기 위해 사용자가 "카펫을 보지 않고"의존합니다.
OCaml의 추상 데이터 유형
OCaml에서 모듈 은 프로그램을 구성하는 데 사용됩니다. 모듈은 구현 과 서명을 가지며 , 후자는 모듈에 정의 된 값과 유형의 요약이며, 전자는 실제 정의를 제공합니다. 이것은 .c/.h
C 프로그래머에게 친숙한 diptych와 느슨하게 비교할 수 있습니다 .
예를 들어 Fraction
다음과 같이 모듈을 구현할 수 있습니다 .
# module Fraction = struct
type t = Fraction of int * int
let rec gcd a b =
match a mod b with
| 0 -> b
| r -> gcd b r
let make a b =
if b = 0 then
invalid_arg "Fraction.make"
else let d = gcd (abs a) (abs b) in
Fraction(a/d, b/d)
let to_string (Fraction(a,b)) =
Printf.sprintf "Fraction(%d,%d)" a b
let add (Fraction(a1,b1)) (Fraction(a2,b2)) =
make (a1*b2 + a2*b1) (b1*b2)
let mult (Fraction(a1,b1)) (Fraction(a2,b2)) =
make (a1*a2) (b1*b2)
end;;
module Fraction :
sig
type t = Fraction of int * int
val gcd : int -> int -> int
val make : int -> int -> t
val to_string : t -> string
val add : t -> t -> t
val mult : t -> t -> t
end
이 정의는 이제 다음과 같이 사용될 수 있습니다 :
# Fraction.add (Fraction.make 8 6) (Fraction.make 14 21);;
- : Fraction.t = Fraction.Fraction (2, 1)
누구나 내장 된 안전망을 우회하여 유형 분수 값을 직접 생성 할 수 있습니다 Fraction.make
.
# Fraction.Fraction(0,0);;
- : Fraction.t = Fraction.Fraction (0, 0)
이를 방지하기 위해 다음 Fraction.t
과 같은 유형의 구체적인 정의를 숨길 수 있습니다 .
# module AbstractFraction : sig
type t
val make : int -> int -> t
val to_string : t -> string
val add : t -> t -> t
val mult : t -> t -> t
end = Fraction;;
module AbstractFraction :
sig
type t
val make : int -> int -> t
val to_string : t -> string
val add : t -> t -> t
val mult : t -> t -> t
end
를 만드는 유일한 방법 AbstractFraction.t
은 AbstractFraction.make
함수 를 사용하는 것입니다.
구성표의 추상 데이터 유형
Scheme 언어에는 OCaml과 동일한 추상 데이터 유형 메커니즘이 없습니다. 캡슐화를 달성하기 위해 사용자는 "카펫을 보지 않고"의존합니다.
Scheme에서는 fraction?
입력을 검증 할 수있는 기회를 제공하는 값 인식 과 같은 술어를 정의하는 것이 일반적 입니다. 내 경험상 지배적 인 사용법은 사용자가 각 라이브러리 호출에서 입력을 검증하는 대신 값을 위조하는 경우 입력을 검증하도록하는 것입니다.
그러나 적용시 값을 생성하는 클로저를 반환하거나 라이브러리가 관리하는 풀의 값에 대한 참조를 반환하는 것과 같이 반환 값의 추상화를 적용하는 몇 가지 전략이 있지만 실제로는 본 적이 없습니다.