Я думаю, что это просто, но я не могу этого понять.
Я хочу создать нового оператора, например. (=??) , который можно использовать как '=' для привязок полей свойств. То есть новый оператор будет использоваться следующим образом:
MyProperty =?? NewValue
Я хотел бы, чтобы оператор (=??) выполнял Option.get NewValue, чтобы либо вернуть значение в MyProperty, либо немедленно завершить работу, если NewValue не имеет опции none.
Можно ли это сделать на F#??
Спасибо за ваше внимание.
Приложение:
Я до сих пор не могу понять это правильно. Например:
Предположим, что запись под названием «пациент» инициализирована как:
{Patient.RefId = Guid.NewGuid(); PatientAccountId = m.PatientAccountId; LastName = m.LastName; FirstName = m.FirstName; Mi = m.Mi;
BirthDate = m.BirthDate}
Теперь, когда запись пациента определяет дату рождения как строку, но m.Birthdate является строковым параметром, поэтому назначение:
BirthDate = m.BirthDate
терпит неудачу.
Но если я это сделаю BirthDate = Option.get m.BirthDate
все хорошо.
Итак, как бы я определил оператор, например. =??, это делает:
BirthDate = Option.get m.BirthDate`
как
BirthDate =?? m.BirthDate
ТИА
Короткий ответ: Нет.
Если вы не согласны с моим ПРИМЕЧАНИЕМ и считаете, что у вас действительно есть вариант использования, в котором это большая победа, возможно, стоит расширить ваш вопрос более широким примером того, как вы предполагаете использовать такой механизм (не исключено, что это может быть конкретизировано в предложении fslang, если оно имеет смысл, но в нынешнем виде не похоже, что у вас есть такая проблема?)
@RubenBartelink Я не спорю, просто пытаюсь понять, как это можно сделать. (Я новичок в перегрузках операторов). Пожалуйста, ознакомьтесь с моим дополнением о том, как я хотел бы его использовать. Спасибо.
@RubenBartelink Кроме того, я просто случайно выбрал =??, не имеет значения, как оно называется. :)
Попробую перефразировать ответ, возможно это поможет. =
при инициализации записи — это не оператор, а элемент синтаксиса. Так что перегружать его нельзя. Я думаю, лучшее, что ты можешь сделать, это {... ; BirthDate = m.BirthDate.Value}
Оператор присваивания <-
нельзя заменить. Операторы обычно представляют собой функции, вычисляющие значения. Не существует эквивалента перегрузки операторов присваивания C/C++ с возможностью требовать неявной передачи аргумента по ссылке и т. д. ПРИМЕЧАНИЕ.
Итак, лучший синтаксис, который вы получите:
MyProperty <- NewValue.Value
Что функционально идентично:
MyProperty <- Option.get NewValue
Стоит отметить, что если вы создаете новый объект, вы также можете инициализировать свойства как часть создания, т.е.
let myThing = Thing(args)
myThing.MyProperty <- NewValue.Value
Можно свернуть в:
let myThing = Thing(args, MyProperty = NewValue)
ПРИМЕЧАНИЕ. На самом деле существуют различные способы передачи ссылки в функцию (ищите символ подписи типа &
, в том числе неявно IIRC). Так что на самом деле технически возможно приблизиться к этому. Однако я настоятельно не рекомендую делать это при обычном использовании, так как в этом случае код будет очень сложно сканировать, чтобы выявить места, где происходит мутация. Тот факт, что mutable
, <-
и Interlocked.Xyz(&thing, ...
) — единственные места, где могут происходить мутации, является важной особенностью языка.
Думаю, я выразился несколько расплывчато. Я бы хотел, чтобы новая функция компилировалась без ошибок и аварийно завершала работу только при фактическом выполнении. например, MyProperty =??? NewValue компилируется без ошибок. Но при выполнении =??? выдает ошибку во время выполнения, когда NewValue равен none. Спасибо.
См. также примечание к OP; =
в инициализации не может быть переопределен таким образом. Value/Option.get оба выдадут. Вы можете сделать implicit
конверсионное расширение, но это будет кошмар. Вы можете определить унарный оператор, а затем выполнить = op X
(со спаем между ними) — см. Learn.microsoft.com/en-us/dotnet/fsharp/language-reference/… (но в конечном итоге это будет довольно уродливо ). Другая проблема заключается в том, что если у вас есть более одного из них в блоке кода, вам будет трудно определить, какая нулевая проверка запущена (именно поэтому рекомендуется сопоставление с образцом).
операторы обычно представляют собой функции, которые не принимают rvalue -> Я запутался, вы имеете в виду вместо этого lvalue?
извиняюсь за путаницу lvalue/rvalue — я перестал использовать C++ в 03, и да, я имею в виду lvalue. Пошел читать stackoverflow.com/questions/3601602/… для покаяния;)
Обратите внимание: в целом
=
не подразумевает присваивания где-либо в F# — речь идет о сравнении; предлагаемое имя, следовательно, будет сильно раздражать любого, кто прошел начальный этап обучения F#, чтобы читать