나는 ocaml 멍청이다. int에 대한 평범한 오래된 참조 또는 다른 간단한 내장 유형을 사용하여 지금까지 모든면에서 예상대로 작동합니다. 저는 ref가 튜플의 멤버 인 튜플의 컨텍스트에서 사용했습니다. 나는 그들 역 참조의 심판을 업데이트 할 수 있습니다 등입력 된 참조 셀?
# let e = 1, ref 1;;
val e : int * int ref = (1, {contents = 1})
# snd e := 2;;
- : unit =()
# e;;
- : int * int ref = (1, {contents = 2})
# !(snd e);;
- : int = 2
하지만 최대한 빨리 (또는 내장 간단한) 일이 일반적으로 심하게 이동, 입력 다른 집계에 "심판의"명명 된 형식을 선언으로 . 나는 그들이 "ref의"유형으로 선언되지 않았을 때 이전과 달리 참조를 더 이상 변경할 수 없다는 것을 발견했다. 그! and : = 연산자가 실패합니다.
그리고 의미가 이상하게 보이는 방식으로 바뀌는 것처럼 보입니다. 아래는 단지 하나의 예입니다. 아래의 첫 번째 코드 블록을 작성하는 것이 합법적 인 이유는 무엇입니까? 그러나 맨 위 루프에서 이와 유사한 작업을하는 것은 불법입니다 (아래 참조). 첫 번째 블록은 컴파일러에 의해 받아 들여지고, 생성 된 타입 인 ref와 일치 할 수 있고! 라인 (13) 및 (14)에 오퍼레이터 이것은 모든 순환 큐의 컨텍스트 내에 있고 #use하여 상부 루프 파일을로드 : 상부 루프 유사한 노력에서
type 'a element = 'a * 'a pointer
and 'a pointer = Pointer of 'a element ref;;
let next (_,n) = n;;
type 'a queue = 'a element option ref;;
let create() = None;;
(*passes compiler and behaves well*)
let enqueue queue x =
match !queue with
None ->
let rec elem = (x, Pointer (ref elem)) in
queue := Some elem;
| Some (_, Pointer last_newest_next) -> (*Insert between newest and oldest*)
let oldest = !last_newest_next in
let elem = (x, Pointer (ref oldest)) in
last_newest_next := elem;
queue := Some elem;;
를 (이 따라 변동)하지 아래, 나는 또한 함수를 사용하여 튜플을 분해 한 후 같은 연산자를 호출 할 경우 같은 :
let rec elem = (1, Pointer (ref elem));;
let last = !(next elem);;
Characters 12-22:
let last = !(next elem);;
^^^^^^^^^^
Error: This expression has type int pointer
but an expression was expected of type 'a ref
그래, 내가 사용하고 -rectypes을하지만 약식 재귀를 사용하지 않고 한 번이를 원했고 유형과 나는 그 후 모든 붙어있어.
let last = next elem;;
val last : int pointer = (* ... *)
그리고 첫 번째 코드 블록은 라인 (14)에 변경된 경우를 사용하지 : 그것은 동일하며 내가 정말 원하는 상단 루프에서 다음 작품을 참고하지만 확실하지 않다! 연산자, 중단됩니다.
(*compiles but fails - que only ever holds one item*)
let enqueue queue x =
match !queue with
None ->
let rec elem = (x, Pointer (ref elem)) in
queue := Some elem;
| Some (_, Pointer last_newest_next) ->
let oldest = last_newest_next in
let elem = (x, Pointer oldest) in
last_newest_next := elem;
queue := Some elem;;
그것은이없는 것을해야합니다 : 다시 쓰기는 (아래) 컴파일러를 전달했지만 무례한 행동을하는 대기열 기능을 원인! 연산자 (그리고 다른 몇 가지 변경 사항), 두 번째 행에서 마지막 행까지는 실제로 원래 의도 한대로 elem을 가리 키도록 다른 포인터 (일치 항목의 분해 된 요소 내에서)를 업데이트하는 대신 elem 포인터를 자체로 가리 킵니다. 그럼에도 불구하고 필자는 typed ref의 최상위 루프 튜플 분해와 ml 파일에서 동일한 작업을하는 것과 의미가 왜 일치하지 않는지 아직 볼 수 없다. 또는 패턴 매치에서 분해가 어떻게 든 함수를 통해 튜플을 분해하는 것과 같지 않습니까?
그리고 위의 기능의 동작을 테스트 할 디큐 기능을 사용 : 나는 기능적인 언어로 심판 세포를 피해야 할 이유
let dequeue queue =
match !queue with
None -> raise Not_found
| Some (_, Pointer oldest_ref) ->
let oldest = !oldest_ref in
let (x, Pointer next_ref) = oldest in
let next = !next_ref in
if next == oldest then
queue := None
else
oldest_ref := next;
x;;
내가 이해할 수 있지만 사용하는 방법을 내가 알 필요가 그것은 필수적 일 때 (말장난 의도 없음).
회상 질문에 대한 사과; 그들이 내 이해를 대단히 도왔을 때 모든 해답 덕분에. – paul