Здравствуйте, 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;
}
кроме этого, ещё было бы интересно иметь метод, который можно применять только к определённой группе вариантов, что было бы удобно сделать, введя для этой группы суперкласс(
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
}
понимаю, что можно сделать вложенный мач, но мне кажется что так красивее
Здравствуйте, 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] { [] }
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
а можно ли сделать так, что бы
1) V3 не имел этого метода?
2) в качестве параметра передавать либо V1 либо V2 статически типизированно?
(тут впрочем, подойдет решение с интерфейсами выше)
Здравствуйте, para, Вы писали:
P>а можно ли сделать так, что бы P>1) V3 не имел этого метода? P>2) в качестве параметра передавать либо V1 либо V2 статически типизированно? P>(тут впрочем, подойдет решение с интерфейсами выше)
Ну, обяви методы локальнов V1 и V2. Но тогда, естественно, ты не сможешь вызвать их у базового класса (то есть, V).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
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" не подходит для использования. Возможно это просто неправильная стратегия использования.
Здравствуйте, hardcase, Вы писали:
H>Похоже топикстартер относится к вариантам ни как к структурам данных, но как к некоторым самостоятельным сущностям, которые имеют определенные методы помимо простых полей-свойств. H>Если мыслить в этом ключе, то спецификатор вида "with ii" не подходит для использования. Возможно это просто неправильная стратегия использования.
В общем, реализация интерфейсов отдельными вхождениями варианта возможна и не сложно реализуема.
С другой стороны необходимость в этом надумана.
Если подходить к дизайну языка из соображений минимализма, то реализовывать эту фичу не надо.
Если же подходить с точки зрения "мы допускаем разное мышление", то в принципе подобная фича была бы полезной.
Короче, вопрос философский. Требует более широкого обсуждения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали: VD>В общем, реализация интерфейсов отдельными вхождениями варианта возможна и не сложно реализуема. VD>С другой стороны необходимость в этом надумана. VD>Если подходить к дизайну языка из соображений минимализма, то реализовывать эту фичу не надо. VD>Если же подходить с твочки зрения "мы допускаем разное мышление", то в принципе подобная фича была бы полезной. VD>Короче, вопрос философский. Требует более широкого обсуждения.
. У нас на проекте вылезла необходимость того что-бы вариант (и его опции) реализовывали интерфейсы. Тогда я сам начал это вкручивать в компилятор, но ещё совсем не рубил во внутренностях и быстро что-то не пошло. В итоге так как интерфейс был нужен всего один и только для одного варианта — выкрутился вроде на том что у варианта может быть базовый класс, который в свою очередь может реализовывать интерфейс.
Так что 1-2 раза на проект возможность такая нужна, но вроде во время перехода от беты к релизу фичи положено только выбрасывать а не добавлять