Вопрос

Что ж, я понял, что F # может управлять ссылками (что-то вроде ссылок, подобных C ++).Это дает возможность изменять значения параметров, передаваемых в функции, а также позволяет программисту возвращать более одного значения.Однако вот что мне нужно знать:

  1. Ключевое слово ссылки:Ключевое слово ref используется для создания из значения ссылки на это значение выведенного типа.Так

    let myref = ref 10
    

    Это означает, что F# создаст объект типа Ref<int> помещая туда (в изменяемое поле) мой int 10.

    ХОРОШО.Поэтому я предполагаю, что ref используется для создания экземпляров Ref<'a> тип.Это правильно?

  2. Значение доступа:Чтобы получить доступ к значению, хранящемуся в ссылке, я могу сделать это:

    let myref = ref 10
    let myval = myref.Value
    let myval2 = !myref
    

    В то время := оператор просто позволяет мне редактировать значение следующим образом:

    let myref = ref 10
    myref.Value <- 30
    myref := 40
    

    Так ! (Бах) разыменовывает мою ссылку.И := отредактируйте его.Полагаю, это тоже правильно.

  3. Оператор:Что делает этот оператор?Следует ли применять его к ссылочному типу?Нет, я думаю, это должно быть применено к изменяемому значению, и что это возвращает?Ссылка?Адрес?При использовании интерактивного:

    let mutable mutvar = 10;;
    &a;;
    

    Последняя строка выдает ошибку, поэтому я не понимаю, что & оператор предназначен для.

  4. Автор ссылки:Как насчет byref?Для меня это очень важно, но я понимаю, что не понимаю этого.Я понимаю, что он используется в функции передачи параметров.Кто-то использует byref, когда хочет, чтобы переданное значение можно было редактировать (это немного противоречит философии функциональных языков, но f# - это нечто большее).Учтите следующее:

    let myfunc (x: int byref) =
        x <- x + 10
    

    Это странно.Я знаю, что если у вас есть ссылка let myref = ref 10 а затем сделайте это, чтобы отредактировать значение: myref <- 10 возникает ошибка, потому что должно быть так: myref := 10.Однако тот факт, что в этой функции я могу редактировать x используя <- оператор означает, что x это не отсылка, да?

    Если я предположу, что x не является ссылкой, то я также предполагаю, что в функциях при использовании byref к параметру, к этому параметру может быть применен изменяемый синтаксис.Так что это всего лишь вопрос синтаксиса, если я так предполагаю, то со мной все в порядке, и на самом деле все работает (без ошибок компилятора).Однако что такое x?

  5. Вызов функций:Как я могу использовать функцию, использующую параметры byref?

    А & В этом участвует оператор, но не могли бы вы объяснить это получше, пожалуйста?В этой статье: Параметры и аргументы MSDN приведен следующий пример:

    type Incrementor(z) =
        member this.Increment(i : int byref) =
           i <- i + z
    
    let incrementor = new Incrementor(1)
    let mutable x = 10
    // A: Not recommended: Does not actually increment the variable. (Me: why?)
    incrementor.Increment(ref x)
    // Prints 10.
    printfn "%d" x  
    
    let mutable y = 10
    incrementor.Increment(&y) (* Me: & what does it return? *)
    // Prints 11.
    printfn "%d" y 
    
    let refInt = ref 10
    incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *)
    // Prints 11.
    printfn "%d" !refInt
    
Это было полезно?

Решение

Ключевое слово ссылки Да, когда ты пишешь let a = ref 10 ты по сути пишешь let a = new Ref<int>(10) где Ref<T> тип имеет изменяемое поле Value.

Значение доступа А := и ! операторы — это просто ярлыки для записи:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

По ссылке — это специальный тип, который можно (разумно) использовать только в параметрах метода.Это означает, что аргумент должен быть по существу указателем на некоторую область памяти (выделенную в куче или стеке).Это соответствует out и ref модификаторы в C#.Обратите внимание, что вы не можете создать локальную переменную этого типа.

Оператор это способ создать значение (указатель), которое можно передать в качестве аргумента функции/методу, ожидающему byref тип.

Вызов функций пример с byref работает, потому что вы передаете методу ссылку на локальную изменяемую переменную.По ссылке метод может изменить значение, хранящееся в этой переменной.

Следующее не работает:

let a = 10            // Note: You don't even need 'mutable' here
bar.Increment(ref a)  

Причина в том, что вы создаете новый экземпляр Ref<int> и вы копируете значение a в этот экземпляр.А Increment затем метод изменяет значение, хранящееся в куче в экземпляре Ref<int>, но у вас больше нет ссылки на этот объект.

let a = ref 10
bar.Increment(a)  

Это работает, потому что a это значение типа Ref<int> и вы передаете указатель на экземпляр, выделенный в куче, Increment а затем получить значение из эталонной ячейки, выделенной в куче, используя !a.

(Вы можете использовать значения, созданные с помощью ref в качестве аргументов в пользу byref поскольку компилятор обрабатывает этот случай особым образом — он автоматически возьмет ссылку на Value поле, потому что это полезный сценарий...).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top