типы - варианты
От: para  
Дата: 17.03.10 08:16
Оценка:
есть такой тип:
  [Record]
  internal variant V
  {
  | V1 { i : int; }
  | V2 { i : int; d : double}  
  | V3 { y : char; }    

    public s : string;  
  }

Можно ли как-нибудь обобщить варианты V1 b V2 ?
например хотелось бы типа такого:
  [Record]
  internal variant V
  {
  | variant V1 
    {
    | V2 { d : double; }
      i : int
    }
  | V3 { y : char; }    

    public s : string;  
  }

сразу отвечу на вопрос зачем:
такая схема наследования лучше отражает предметную область.
а "вариантная" нотация более наглядная и простая.
Re: типы - варианты
От: hardcase Пират http://nemerle.org
Дата: 17.03.10 08:59
Оценка:
Здравствуйте, para, Вы писали:

P>есть такой тип:

P>
P>  [Record]
P>  internal variant V
P>  {
P>  | V1 { i : int; }
P>  | V2 { i : int; d : double}  
P>  | V3 { y : char; }    

P>    public s : string;  
P>  }
P>

P>Можно ли как-нибудь обобщить варианты V1 b V2 ?

По-моему нельзя, только если вводить дополнительную варианту:
[Record]
variant SubV {
    | V1
    | V2 { d : double }
    public i : int;
}

[Record]
variant V {
    | V1 { sub : SubV; }
    | V3 { y : char; }
    public s : string;
}


Возможно было бы неплохо позволить вариантам реализовывать интерфейсы:
interface V1_2 {
    i : int { get; }
}

[Record]
variant V {
    | V1 : V1_2 { i : int; i : int implements V1_2.i { get { i } }  }
    | V2 : V1_2 { i : int; i : int implements V1_2.i { get { i } } d : double; }
    | V3 { y : char; }
    public s : string;
}


Думаю, в частности сценарий для свойств можно реализовать посредством макроса. Код будет выглядеть примерно так:
interface V1_2 {
    i : int { get; }
}

[Record]
variant V {
    | V1 { [VariantInterface(V1_2)]i : int; }
    | V2 { [VariantInterface(V1_2)]i : int; d : double; }
    | V3 { y : char; }
    public s : string;
}
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re: типы - варианты
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.03.10 10:39
Оценка: 1 (1)
Здравствуйте, para, Вы писали:

P>есть такой тип:

P>
P>  [Record]
P>  internal variant V
P>  {
P>  | V1 { i : int; }
P>  | V2 { i : int; d : double}  
P>  | V3 { y : char; }    

P>    public s : string;  
P>  }
P>


Дык когда будешь делать сопоставление с образцом, то делай два образца:
match (x)
{
  | V.V1(i) | V.V2(i, _) => DoSomethingWithI(i)
}


P>Можно ли как-нибудь обобщить варианты V1 b V2 ?


Только если ввести еще один вариант и сделать его вложенным в перый (полем первого).
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: типы - варианты
От: para  
Дата: 17.03.10 13:45
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Дык когда будешь делать сопоставление с образцом, то делай два образца:

VD>
VD>match (x)
VD>{
VD>  | V.V1(i) | V.V2(i, _) => DoSomethingWithI(i)
VD>}
VD>


кроме этого, ещё было бы интересно иметь метод, который можно применять только к определённой группе вариантов, что было бы удобно сделать, введя для этой группы суперкласс(
variant V
{
| V1 { i: int}
| V2 { ii : list[int] }
| V3 { s : string }
}
...
match(...)
{
| (как-то обобщить варианты (V1, V2)) as v
  def intList = v.GetInts();
...
}
//где 
V1.GetInts() : list[int]
{
  [i]
}
V2.GetInts() : list[int]
{
  ii
}

понимаю, что можно сделать вложенный мач, но мне кажется что так красивее
Re[3]: типы - варианты
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.03.10 15:17
Оценка:
Здравствуйте, para, Вы писали:

P>кроме этого, ещё было бы интересно иметь метод, который можно применять только к определённой группе вариантов, что было бы удобно сделать, введя для этой группы суперкласс(

P>
P>variant V
P>{
P>| V1 { i: int}
P>| V2 { ii : list[int] }
P>| V3 { s : string }
P>}
P>...
P>match(...)
P>{
P>| (как-то обобщить варианты (V1, V2)) as v
P>  def intList = v.GetInts();
P>...
P>}
P>


Ну, так и в чем проблема? Сам вариантный тип и есть тот самый супертип.
Можно сделать так:
variant V
{
  | V1 { i: int}
  | V2 { ii : list[int] }
  | V3 { s : string }
  
  public GetInts() : list[int]
  {
    match (this)
    {
      | V1(i)  => [i]
      | V2(ii) => ii
      | V3     => []
    }
  }
}

или так:
variant V
{
  | V1
    {
      i: int;
      
      public override GetInts() : list[int] { [i] }
    }
  | V2
    {
      ii : list[int];
      
      public override GetInts() : list[int] { ii }
    }
  | V3 { s : string }
  
  public virtual GetInts() : list[int] { [] }
}
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: типы - варианты
От: para  
Дата: 17.03.10 16:47
Оценка:
Здравствуйте, VladD2, Вы писали:

а можно ли сделать так, что бы
1) V3 не имел этого метода?
2) в качестве параметра передавать либо V1 либо V2 статически типизированно?
(тут впрочем, подойдет решение с интерфейсами выше)
Re[5]: типы - варианты
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.03.10 17:01
Оценка:
Здравствуйте, para, Вы писали:

P>а можно ли сделать так, что бы

P>1) V3 не имел этого метода?
P>2) в качестве параметра передавать либо V1 либо V2 статически типизированно?
P>(тут впрочем, подойдет решение с интерфейсами выше)

Ну, обяви методы локальнов V1 и V2. Но тогда, естественно, ты не сможешь вызвать их у базового класса (то есть, V).
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: типы - варианты
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.03.10 18:13
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Возможно было бы неплохо позволить вариантам реализовывать интерфейсы:...


Это не поддерживается, как я понимаю. Реализовать конечно не сложно. Парсер подправить немного только.

Но сама идея подобного подхода мне как-то неочень нравится. Ведь в итоге будут точно такие же рантайм-проверки типов как если бы просто написать:
match (x)
{
  | V1(i) with ii = [i] 
  | V2(ii) => используем ii
  | _ => ()
}

Чем это лучше:
match (x)
{
| y is ISomeInterface with ii = y.GetList() => используем ii
| _ => ()
}
[/c#]
?
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: типы - варианты
От: hardcase Пират http://nemerle.org
Дата: 17.03.10 20:02
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>
VD>match (x)
VD>{
VD>  | V1(i) with ii = [i] 
VD>  | V2(ii) => используем ii
VD>  | _ => ()
VD>}
VD>

VD>Чем это лучше:
VD>match (x)
VD>{
VD> | y is ISomeInterface with ii = y.GetList() => используем ii
VD> | _ => ()
VD>}
VD>[/c#]
VD>?

Похоже топикстартер относится к вариантам ни как к структурам данных, но как к некоторым самостоятельным сущностям, которые имеют определенные методы помимо простых полей-свойств.
Если мыслить в этом ключе, то спецификатор вида "with ii" не подходит для использования. Возможно это просто неправильная стратегия использования.
http://nemerle.org/Banners/?t=Developer!&g=dark /* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: типы - варианты
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.03.10 21:56
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Похоже топикстартер относится к вариантам ни как к структурам данных, но как к некоторым самостоятельным сущностям, которые имеют определенные методы помимо простых полей-свойств.

H>Если мыслить в этом ключе, то спецификатор вида "with ii" не подходит для использования. Возможно это просто неправильная стратегия использования.

В общем, реализация интерфейсов отдельными вхождениями варианта возможна и не сложно реализуема.

С другой стороны необходимость в этом надумана.

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

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

Короче, вопрос философский. Требует более широкого обсуждения.
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: типы - варианты
От: hi_octane Беларусь  
Дата: 18.03.10 03:06
Оценка: +1
Здравствуйте, VladD2, Вы писали:
VD>В общем, реализация интерфейсов отдельными вхождениями варианта возможна и не сложно реализуема.
VD>С другой стороны необходимость в этом надумана.
VD>Если подходить к дизайну языка из соображений минимализма, то реализовывать эту фичу не надо.
VD>Если же подходить с твочки зрения "мы допускаем разное мышление", то в принципе подобная фича была бы полезной.
VD>Короче, вопрос философский. Требует более широкого обсуждения.

Этот вопрос уже поднимался один раз
Автор: hi_octane
Дата: 06.06.08
. У нас на проекте вылезла необходимость того что-бы вариант (и его опции) реализовывали интерфейсы. Тогда я сам начал это вкручивать в компилятор, но ещё совсем не рубил во внутренностях и быстро что-то не пошло. В итоге так как интерфейс был нужен всего один и только для одного варианта — выкрутился вроде на том что у варианта может быть базовый класс, который в свою очередь может реализовывать интерфейс.

Так что 1-2 раза на проект возможность такая нужна, но вроде во время перехода от беты к релизу фичи положено только выбрасывать а не добавлять
вариант интерфейс variant interface
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.