F # : let mutable vs. ref


82

첫째,이 질문이 중복 될 가능성을 인정합니다. 바로 알려주세요.

변경 가능성이 필요한 상황에 대한 일반적인 "모범 사례"가 무엇인지 궁금합니다. F #은이를 위해 두 가지 기능을 제공 let mutable하는 것 같습니다. "대부분의"언어에서 변수처럼 작동하는 것처럼 보이는 바인딩과 ref사용하려면 명시 적 역 참조가 필요한 참조 셀 ( 함수로 생성됨 )입니다.

이 하나 하나 또는 다른에 "강제"되는 경우의 커플 : .NET 상호 운용성에 변경할 수 사용하는 경향이 <-, 워크 플로우 계산 한 사용해야합니다 ref함께 :=. 따라서 이러한 경우는 매우 명확하지만 이러한 시나리오 외부에서 변경 가능한 변수를 만들 때 어떻게해야할지 궁금합니다. 한 스타일이 다른 스타일보다 어떤 이점이 있습니까? (아마도 구현에 대한 추가 통찰력이 도움이 될 것입니다.)

감사!



4
F # 버전 4에서는 ref가 필요했던 곳에 mutable을 사용할 수 있습니다. blogs.msdn.com/b/fsharpteam/archive/2014/11/12/...
제임스 무어

답변:


133

나는 gradbot이 말한 것만 지원할 수 있습니다. 뮤 테이션이 필요할 때는 let mutable.

구현 및 두 ref셀 간의 차이점과 관련하여 기본적으로 변경 가능한 레코드 필드를 포함하는 매우 간단한 레코드로 구현됩니다. 직접 쉽게 작성할 수 있습니다.

type ref<'T> =  // '
  { mutable value : 'T } // '

// the ref function, ! and := operators look like this:
let (!) (a:ref<_>) = a.value
let (:=) (a:ref<_>) v = a.value <- v
let ref v = { value = v }

두 접근 방식의 눈에 띄는 차이점 let mutable은 변경 가능한 값을 스택에 ref저장하는 반면 (C #에서는 변경 가능한 변수로) 변경 가능한 값을 힙 할당 레코드의 필드에 저장한다는 것입니다. 이것은 성능에 약간의 영향을 미칠 수 있지만 숫자가 없습니다 ...

덕분에 사용하는 변경 가능한 값을 ref별칭으로 지정할 수 있습니다. 즉, 동일한 변경 가능한 값을 참조하는 두 개의 값을 만들 수 있습니다.

let a = ref 5  // allocates a new record on the heap
let b = a      // b references the same record
b := 10        // modifies the value of 'a' as well!

let mutable a = 5 // mutable value on the stack
let mutable b = a // new mutable value initialized to current value of 'a'
b <- 10           // modifies the value of 'b' only!

2
그냥 알림 : 스택 또는 힙에있는이 구현 세부 사항 및 질문에 정확히 관련이없는 (그러나 그럼에도 불구하고 훌륭한 대답)입니다
브루노 브랜트

5
어떤 것이 힙 할당 및 수집의 오버 헤드를 유발하는지 여부를 아는 것은 모범 사례가 무엇인지 결정할 때 매우 관련이 있다고 주장합니다.
jackmott

에릭 Lippert의에 의해이 문서를 체크 아웃 @jackmott라는 스텍되는 구현 세부 정보
jaromey

5
@jaromey 예 나는 그 점에서 에릭과 근본적으로 완전히 동의하지 않는다는 것을 이해합니다. '모범 사례'를 고려할 때 성능 고려 사항을 제쳐 놓을 수 없습니다. 성능이 여전히 중요하지 않다고 주장하는 경우가 많습니다. 수천 가지 구현 세부 사항으로 인해 많은 소프트웨어가 느려집니다.
jackmott

18

관련 질문 : "로컬 변경 가능 값은 클로저에 의해 캡처 될 수 없으므로 대신 ref를 사용해야한다고 언급했습니다. 그 이유는 클로저에서 캡처 된 변경 가능한 값을 힙에 할당해야하기 때문입니다 (클로저가 힙). " 에서 F # REF-가변 바르 오브젝트 필드 대

내가 생각하는 let mutable기준 셀을 통해 바람직하다. 개인적으로 필요할 때만 참조 셀을 사용합니다.

내가 작성한 대부분의 코드는 재귀 및 꼬리 호출 덕분에 가변 변수를 사용하지 않습니다. 변경 가능한 데이터 그룹이 있으면 레코드를 사용합니다. 개체의 경우 let mutable개인 가변 변수를 만드는 데 사용 합니다. 나는 클로저, 일반적으로 이벤트에만 참조 셀을 사용합니다.


9

변경 가능한 값의 단순화 된 사용 섹션 의이 MSDN 블로그 기사 에 설명 된대로 더 이상 람다에 대한 참조 셀이 필요하지 않습니다. 따라서 일반적으로 더 이상 필요하지 않습니다.


4

Brian 의이 기사 가 답을 제공 할 수 있습니다.

mutables는 사용하기 쉽고 효율적이지만 (래핑 없음) 람다로 캡처 할 수 없습니다. 참조 셀 캡처 수 있지만 장황하고 효율성이 떨어집니다 (?-확실하지 않음).


"(...) 및 덜 효율적"-아마도 래퍼 유형은 더 많은 메모리를 사용합니다.
JMCF125 '2013

2
대부분의 경우 F # 4.0 mutable을 캡처 할 수 있고 ref의 필요성이 훨씬 적기 때문에 이것은 변경되었습니다.
Abel

3

위키 북 의 변경 가능한 데이터 섹션을 살펴볼 수 있습니다.

편의를 위해 다음은 관련 인용문입니다.

mutable 키워드는 레코드 유형과 함께 자주 사용되어 변경 가능한 레코드를 생성합니다.

가변 변수는 다소 제한적입니다. 가변 변수는 정의 된 함수의 범위 밖에서는 액세스 할 수 없습니다. 특히 이것은 다른 함수의 하위 함수에서 mutable을 참조 할 수 없음을 의미합니다.

Ref 셀은 변이의 한계를 극복합니다. 사실, 참조 셀은 레코드 유형에서 변경 가능한 필드를 감싸는 매우 간단한 데이터 유형입니다.

참조 셀은 힙에 할당되므로 여러 기능에서 공유 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.