F # оператор "?" - PullRequest
       13

F # оператор "?"

15 голосов
/ 21 мая 2009

Я только что прочитал информацию на этой странице , а пока новая? упоминается оператор, мне совершенно неясно, каким будет его использование.
Может ли кто-нибудь дать краткое объяснение, опубликовать отрывок кода о том, как будет использоваться этот оператор, и, возможно, упомянуть вариант использования? Редактировать : это действительно неловко, я заметил, что? Оператор больше не упоминается в заметках о выпуске Дона. Есть идеи, почему это так?

Ответы [ 3 ]

31 голосов
/ 23 мая 2009

В этом выпуске F # есть два новых «специальных» оператора, (?) И (? <-). Они не определены, но доступны для перегрузки, поэтому вы можете определить их самостоятельно. Специальный бит - это то, как они обрабатывают свой второй операнд: они требуют, чтобы он был действительным идентификатором F #, но передают его функции, реализующей оператор, в виде строки. Другими словами: </p>

a?b

соответствует:

(?) a "b"

и

a?b <- c

соответствует:

 (?<-) a "b" c

Очень простое определение этих операторов может быть:

let inline (?) (obj: 'a) (propName: string) : 'b =
    let propInfo = typeof<'a>.GetProperty(propName)
    propInfo.GetValue(obj, null) :?> 'b

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) =
    let propInfo = typeof<'a>.GetProperty(propName)
    propInfo.SetValue(obj, value, null)

Обратите внимание, что поскольку тип возвращаемого значения для gettor является универсальным, в большинстве случаев вам придется указывать его на сайте использования, т. Е .:

let name = foo?Name : string

хотя вы все еще можете использовать цепочечный вызов (?) (Поскольку первый аргумент (?) Также является общим):

let len = foo?Name?Length : int

Другая, более интересная реализация - это повторное использование метода CallByName, предоставляемого VB:

open Microsoft.VisualBasic    

let inline (?) (obj: 'a) (propName: string) : 'b =
    Interaction.CallByName(obj, propName, CallType.Get, null) :?> 'b //'

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) =
    Interaction.CallByName(obj, propName, CallType.Set, [| (value :> obj) |])
    |> ignore

Преимущество заключается в том, что он будет правильно обрабатывать как свойства, так и поля, работать с COM-объектами IDispatch и т. Д.

4 голосов
/ 21 мая 2009

Звучит как "?" Оператор относится к динамическому языку исполнения (DLR). То есть вы используете его, когда хотите связать с элементом объекта (методом, свойством) во время выполнения, а не во время компиляции.

Забавно, потому что я надеялся, что так будет работать динамический вызов члена в C #. Увы, C # предоставляет эту функциональность через «псевдо» тип («динамический» IIRC). На мой взгляд, это делает код несколько менее понятным (потому что вы должны отследить объявление переменной, чтобы узнать, является ли вызов ранним или поздним).

Я не знаю точного синтаксиса, но если бы мне пришлось угадывать, он либо заменяет, либо увеличивает "." (точка) оператор. Как в:

let x = foo?Bar()

или, может быть:

let x = foo.?Bar()
1 голос
/ 29 июля 2011

Существует модуль FSharp.Interop.Dynamic , в nuget, который реализует динамический оператор с использованием dlr.

let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";

Это открытый исходный код, лицензия Apache, вы можете посмотреть на реализацию , и она включает в себя модульное тестирование пример кейсов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...