F # Изменить и вернуть - PullRequest
       24

F # Изменить и вернуть

0 голосов
/ 16 ноября 2011
type Tag(Kids) =
    member this.Kids = Kids

    static member (-) (this: Tag, that: list<obj>) = 
        Tag(that::this.Kids)

Смысл этого кода в том, чтобы создать новый объект на основе существующего, но изменить одно (или несколько) полей объекта.По сути, это прокси для метода-мутатора thing.setX(...), за исключением использования неизменяемых данных.

Это выглядит невероятно уродливо и многословно, и я уверен, что должен быть лучший способ сделать это, сохраняя неизменность данных, но я не понял, как это сделать.Есть какой-то синтаксически хороший способ сделать это?

РЕДАКТИРОВАТЬ: Просто для ясности, у меня также есть другие классы в иерархии:

type HTMLTag(s, Classes, Kids, Styles) = 
    inherit Tag(Kids)

    member this.NominalTag = s
    member this.Classes = Classes
    member this.Styles: list<String * String> = Styles

    static member (-) (this: HTMLTag, that: list<obj>) = 
        HTMLTag(this.NominalTag, this.Classes, that::this.Kids, this.Styles)

Помимо того, что это очень многословно, - функция «копировать с модификацией» функции совершенно не является универсальной: хотя я делаю одно и то же каждый раз (копирую с изменением в одну и ту же переменную), мне приходится переписывать все заново, что не очень приятно,

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

static member (-) (this: Tag, that: list<obj>) = 
    this.Kids = that :: this.Kids
    this

Но я стараюсь сделать все неизменным насколько возможно

1 Ответ

6 голосов
/ 16 ноября 2011

Копировать и обновить выражения записи [MSDN] предназначены для обработки именно этого случая. Если вы можете использовать вместо этого тип записи, вы можете сделать

type Tag = 
  { NominalTag : obj
    Classes : obj
    Kids : list<obj>
    Styles : list<String * String> }
  static member (-) (this: Tag, that: list<obj>) = 
    { this with Kids = this.Kids @ that }

Скомпилированные формы этого и вашего кода практически идентичны.

Кстати, странно, что оператор (-) используется для добавления ... но я предполагаю, что это надуманный случай.

UPDATE

Теперь, когда вы обновили свой вопрос, я запутался в том, что вы хотите сделать. Если вы хотите вернуть новый объект, я не вижу, как мутация помогает вам.

Более функциональный подход (против наследования) состоит в том, чтобы отделить ваши данные и поведения, данные, являющиеся записями, и функции поведения, сгруппированные в модуле. Если вы хотите, чтобы поведение разделялось между типами, используйте интерфейсы. Записи могут реализовывать интерфейсы.

...