Re[7]: Как сделать активные паттрены.
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.10 09:41
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Фича, мне казалось, "о том", чтобы собрать в кучку весь императивный код, спрятать его в этом самом актив паттерне, а наружу выставить красивую декларативную хрень.


Для этого есть функции (инкапсуляция). Идея инкапсуляции для паттернов мне нравится. Но это слишком сложно и не очень шустро.

Получается, что реальная проблема — рыхлый синтаксис — подменяется введением навороченного решения которое чтобы реализовать надо встать раком и при реализации которого по всей видимости не удастся обойтись без рантайм-оверхэда.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Как сделать активные паттрены.
От: WolfHound  
Дата: 20.10.10 09:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Тут еще вопрос — зачем мне писать кучу ненужного кода, когда задача — упростить синтаксис ПМ по объектам?

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

Трмоза и "не рекурсивность" это твое воображение.

И я даже и не думал встраивать это в 1.0
Там вывод типов и построитель решений придется весьма не слабо покорежить. В прочем их по любому нужно полностью переписывать.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Как сделать активные паттрены.
От: Воронков Василий Россия  
Дата: 20.10.10 10:02
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>Фича, мне казалось, "о том", чтобы собрать в кучку весь императивный код, спрятать его в этом самом актив паттерне, а наружу выставить красивую декларативную хрень.

VD>Для этого есть функции (инкапсуляция). Идея инкапсуляции для паттернов мне нравится. Но это слишком сложно и не очень шустро.

Ну я так понимаю, актив-паттерн это и есть своего рода функция — просто с некоторым слоем сахара поверх. Опять же фича с одной стороны интересная, но вот придумать для нее реальное применение не так-то просто в действительности.

Основная фишка актив паттернов, если мне не изменяет маразм, это то, что они позволяют имитировать row type полиморфизм. Опять же — с одной стороны круто. С другой — тоже неясно, насколько это востребованно. Потом, если нужен row type полиморфизм, почему бы не вводить его явно, как в OCaml? При этом ценность актив паттернов как фичи тут же падает, и ничего, кроме сахара, не остается.

VD>Получается, что реальная проблема — рыхлый синтаксис — подменяется введением навороченного решения которое чтобы реализовать надо встать раком и при реализации которого по всей видимости не удастся обойтись без рантайм-оверхэда.


Ну честно то, что Вольфхаунд предлагает, мне вообще не понятно. Может, я не "секу фишку"? Зачем мне делать:

pattern Asdasdasd
{
    | Asd { a : int; b : string; x : float; }
    | Qwe { c : string; d : int; }

    match (value : SomeType)//*
    {
    ...
    }
}


match (someTypeValue)
{
    | Asd (a, b, x) =>
    | Qwe (c, d) =>
}


Когда я могу написать:

match (ToAsdQwe <| someTypeValue)
{
    | Asd (a, b, x) =>
    | Qwe (c, d) =>
}
Re[9]: Как сделать активные паттрены.
От: WolfHound  
Дата: 20.10.10 10:18
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну честно то, что Вольфхаунд предлагает, мне вообще не понятно. Может, я не "секу фишку"? Зачем мне делать:

А попробуй вот это переписать:
pattern Asdasdasd
{
    | Asd { a : int; b : SomeType; x : float; }
    | Qwe { c : string; d : int; }

    match (value : SomeType)//*
    {
    ...
    }
}

match (someTypeValue)
{
    | Asd (a1, Asd (a2, b, x2), x1) =>
    | Asd (a, Qwe (c, d), x) =>
    | Qwe (c, d) =>
}

Это не считая того что твой вариант медленней.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Как сделать активные паттрены.
От: Воронков Василий Россия  
Дата: 20.10.10 11:01
Оценка:
Здравствуйте, WolfHound, Вы писали:

ВВ>>Ну честно то, что Вольфхаунд предлагает, мне вообще не понятно. Может, я не "секу фишку"? Зачем мне делать:

WH>А попробуй вот это переписать:

Переписать что? У тебя же внутри match троеточие У меня там тоже... эээ... "троеточие". Вернее, функция ToAsdQwe будет рекурсивной, что в принципе на объеме кода практически не скажется.

WH>Это не считая того что твой вариант медленней.


Ты, видимо, забыл главную мантру ФП — No premature optimization.

Кстати, раз уж зашла речь... Как в твоей реализации будет выглядеть вот такое:

let (|DivisibleBySeven|_|) input = if input % 7 = 0 then Some() else None

let (|IsPerfectSquare|_|) (input : int) = 
    let sqrt = int (Math.Sqrt(float input))
    if sqrt * sqrt = input then 
        Some() 
    else 
        None

let describeNumber x =
    match x with
    | DivisibleBySeven & IsPerfectSquare -> printfn "x is divisible by 7 and is a perfect square."
    | DivisibleBySeven                   -> printfn "x is divisible by seven"
    | IsPerfectSquare                    -> printfn "x is a perfect square"
    | _                                  -> printfn "x looks normal."
Re[11]: Как сделать активные паттрены.
От: WolfHound  
Дата: 20.10.10 11:27
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Переписать что? У тебя же внутри match троеточие У меня там тоже... эээ... "троеточие". Вернее, функция ToAsdQwe будет рекурсивной, что в принципе на объеме кода практически не скажется.

Выделенное
| Asd (a1, Asd (a2, b, x2), x1) =>
| Asd (a, Qwe (c, d), x) =>
| Qwe (c, d) =>

Пожалуйста читай то что тебе пишут.
Мне уже надоело говорить с людьми которые даже не пытаются читать то что я пишу.

WH>>Это не считая того что твой вариант медленней.

ВВ>Ты, видимо, забыл главную мантру ФП — No premature optimization.
Не правильно.
Не оптимизируей руками.

ВВ>Кстати, раз уж зашла речь... Как в твоей реализации будет выглядеть вот такое:

Для тех кто не читал первое сообщение показываю:
def DivisibleBySeven(input) { input % 7 = 0 }

def IsPerfectSquare(input : int)
{
    def sqrt = int (Math.Sqrt(float input));
    sqrt * sqrt = input
}

def describeNumber(x)
{
    match (x)
    {
        | DivisibleBySeven & IsPerfectSquare => WriteLine("x is divisible by 7 and is a perfect square.")
        | DivisibleBySeven                   => WriteLine("x is divisible by seven")
        | IsPerfectSquare                    => WriteLine("x is a perfect square")
        | _                                  => WriteLine("x looks normal.")
    }
}

Вот прямо так.
Обычными функциями.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: Как сделать активные паттрены.
От: Воронков Василий Россия  
Дата: 20.10.10 11:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

ВВ>>Переписать что? У тебя же внутри match троеточие У меня там тоже... эээ... "троеточие". Вернее, функция ToAsdQwe будет рекурсивной, что в принципе на объеме кода практически не скажется.

WH>Выделенное
WH>
WH>| Asd (a1, Asd (a2, b, x2), x1) =>
WH>| Asd (a, Qwe (c, d), x) =>
WH>| Qwe (c, d) =>
WH>

WH>Пожалуйста читай то что тебе пишут.
WH>Мне уже надоело говорить с людьми которые даже не пытаются читать то что я пишу.

Что выделенное? У меня своя рукописная функция ToAsdQwe, которая принимает someTypeValue и возвращает экземпляр варианта. Определение варианта может быть рекурсивным. Может быть каким угодно. Кроме такого, которое запрещает система типов.

WH>>>Это не считая того что твой вариант медленней.

ВВ>>Ты, видимо, забыл главную мантру ФП — No premature optimization.
WH>Не правильно.
WH>Не оптимизируей руками.

И чем же ты собрался оптимизировать?

WH>def describeNumber(x)

WH>{
WH> match (x)
WH> {
WH> | DivisibleBySeven & IsPerfectSquare => WriteLine("x is divisible by 7 and is a perfect square.")
WH> | DivisibleBySeven => WriteLine("x is divisible by seven")
WH> | IsPerfectSquare => WriteLine("x is a perfect square")
WH> | _ => WriteLine("x looks normal.")
WH> }
WH>}
WH>[/ocaml]

А чем это отличается от:

def describeNumber(x)
{
    match (x)
    {
        | _ when DivisibleBySeven(x) && IsPerfectSquare(x) => WriteLine("x is divisible by 7 and is a perfect square.")
        | _ when DivisibleBySeven(x)                   => WriteLine("x is divisible by seven")
        | _ when IsPerfectSquare(x)                    => WriteLine("x is a perfect square")
        | _                                  => WriteLine("x looks normal.")
    }
}


Ты мне давай честный вариант.
Для интриги давай добавим в коллекцию такую продукцию IsRemNotZero(rem), которая должна биндить rem к остатку при делении.
Re[13]: Как сделать активные паттрены.
От: WolfHound  
Дата: 20.10.10 12:01
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Что выделенное? У меня своя рукописная функция ToAsdQwe, которая принимает someTypeValue и возвращает экземпляр варианта. Определение варианта может быть рекурсивным. Может быть каким угодно. Кроме такого, которое запрещает система типов.

То выделеное.
Там может быть использован другой паттерн.
Что еще одну функцию писать будешь?
А не озвереешь?

ВВ>А чем это отличается от:

Хотябы тем что меньше букв.
Плюс можно написать так:
| SomePattern(DivisibleBySeven, IsPerfectSquare) =>

сравни с
| SomePattern(x1, x2) when DivisibleBySeven(x1) && IsPerfectSquare(x2) =>

Больше букв. Больше конструкций. Нужно придумывать имена, а потом искать их.

Вот эта конструкция в F#
let (|DivisibleBySeven|_|) input =

Не дает ничего по сравнению с обычной функцией.
По этому я ее порезал бритвой Оккама.

ВВ>Ты мне давай честный вариант.

ВВ>Для интриги давай добавим в коллекцию такую продукцию IsRemNotZero(rem), которая должна биндить rem к остатку при делении.
Отличный пример того что ты не читаешь то что я пишу.
Я в первом же сообщении показал как это сделать.
Повторяю второй раз:
match (someString)
{
    | string.IsNullOrEmpty =>
    | int.TryParse(value) =>
    | Contains("qwe") =>
    | Contains("asd") =>
    | Contains("zxc") =>
}

match (someDictionary)
{
    | TryGetValue("qwe", value) =>
    | TryGetValue("asd", value) =>
    | TryGetValue("zxc", value) =>
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: Как сделать активные паттрены.
От: Воронков Василий Россия  
Дата: 20.10.10 12:30
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Что выделенное? У меня своя рукописная функция ToAsdQwe, которая принимает someTypeValue и возвращает экземпляр варианта. Определение варианта может быть рекурсивным. Может быть каким угодно. Кроме такого, которое запрещает система типов.

WH>То выделеное.
WH>Там может быть использован другой паттерн.
WH>Что еще одну функцию писать будешь?

Я так понимаю, у меня есть определение вида:

variant AsdQwe
{
 | Asd { a : int; b : AsdQwe; x : float; }
 | Qwe { c : string; d : int; }
}
  
def val = ToAsdQwe(...);
 
match (val : AsdQwe) {
 | Asd(a1, Asd(a2, b, x2), x1) => {}
 | Asd(a, Qwe(c, d), x) => {}
 | Qwe(c, d) => {}
}


Что там внутри AsdQwe — хз. Зависит от входных данных. Как и в твоем случае, естественно. Может, придется еще одну функцию написать. Может, даже две. А может, и не придется.
Пока лишь понятно, что твой вариант должен быть как бы короче, но насколько и как короче — еще непонятно.

WH>А не озвереешь?


Не беспокойся. Я уже давно озверел. Теперь вот успокоительное пью.

WH>
WH>| SomePattern(x1, x2) when DivisibleBySeven(x1) && IsPerfectSquare(x2) =>
WH>

WH>Больше букв. Больше конструкций. Нужно придумывать имена, а потом искать их.

Ну разница в количестве букв пока не впечатляет. Да дело даже не в этом. Т.е. и это все? Тупо сахар и ничего больше?

WH>Вот эта конструкция в F#

WH>
WH>let (|DivisibleBySeven|_|) input = 
WH>

WH>Не дает ничего по сравнению с обычной функцией.
WH>По этому я ее порезал бритвой Оккама.

Она дает ровно то же самое, что ты пытаешься дать и своим "законопроектом". Скажем, partial pattern вида:

match x with
| Int 1 -> ...


Распарсит x и, в случае, если это целое, сравнит его с единицей. Если результат не равен 1, то мы переходим к следующему паттерну. Как это будет выглядеть в твоем случае? "Много букаф"?

И, кстати, тут у нас начинается интересное — все partial patterns по умолчанию irrefutable, т.е. мы можем успешно "пройти сопоставление" и с Int, и с String, и с Float и т.д. Причем у тебя судя по всему будет абсолютно та же петрушка. И вот что-то мне начинает казаться, что не все так хорошо с этим.

ВВ>>Ты мне давай честный вариант.

ВВ>>Для интриги давай добавим в коллекцию такую продукцию IsRemNotZero(rem), которая должна биндить rem к остатку при делении.
WH>Отличный пример того что ты не читаешь то что я пишу.

Ты не прав, читаю. Уже примерно половину прочитал.
Re[11]: Как сделать активные паттрены.
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.10 17:19
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Я с твоим воображение даже пытаться спорить не будут.


Мое воображение тут не причем. Это ты так объясняешь.

WH>И я даже и не думал встраивать это в 1.0


Тогда и обсуждать нечего. Я говорил о фичи которую можно добавить здесь и сейчас.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Как сделать активные паттрены.
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.10 17:21
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну честно то, что Вольфхаунд предлагает, мне вообще не понятно. Может, я не "секу фишку"?


Судя по словам того же Вольфхаунда
Автор: WolfHound
Дата: 20.10.10
мне смысл тоже не понятен.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: активные паттрены: перезагрузка :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.10 18:11
Оценка:
Не люблю абстракции, так как они обычно приводят к массе трепа без понимания происходящего.

Предлагаю перейти к конкретике. То что предлагал я (декларацию подразумеваемых конструкторов для классов), я предлагал для решения конкретной задачи — упрощению сопоставления с образцом для иерархии классов. Вопрос этот был поднят IT уже довольно давно, и поднят он был в контексте разбора деревьев выражений LINQ-а.

Так давайте разберем конкретный пример — работу с деревьями выражений.

Итак...

Дано System.Linq.Expressions.Expression и его наследники:
* BinaryExpression
* ConditionalExpression
* ConstantExpression
* InvocationExpression
* LambdaExpression
* ListInitExpression
* MemberExpression
* MemberInitExpression
* MethodCallExpression
* NewArrayExpression
* NewExpression
* ParameterExpression
* TypeBinaryExpression
* UnaryExpression

Задача:
Продемонстрировать как будет выглядеть необходимый код чтобы для данных типов можно было использовать упрощенный "конструкторный" синтаксис в сопоставлении с образцом. Например, чтобы можно было писать так:
match (someExpr)
{
  | Bin(ExpressionType.And, Const(1), Call(null, method, args)) => 
    // что-то делаем с method и args

  | _ => ...
}


В демонстрационном коде не должно быть никаких "..." и т.п. Код должен быть полным.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: активные паттрены: перезагрузка :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.10.10 18:58
Оценка: 24 (1)
Здравствуйте, VladD2, Вы писали:

VD>Задача:

VD>Продемонстрировать как будет выглядеть необходимый код чтобы для данных типов можно было использовать упрощенный "конструкторный" синтаксис в сопоставлении с образцом.

Мое решение предполагает добавление следующих объявлений:
[assembly: PMCtor(BinaryExpression,      Bin(conv=Conversion, left=Left, right=Right, method=Method))]
[assembly: PMCtor(ConditionalExpression, If(ifFalse=IfFalse, ifTrue=IfTrue, cond=Test))]
[assembly: PMCtor(ConstantExpression,    Const(value=Value))]
[assembly: PMCtor(InvocationExpression,  Invoc(lambda=Expression, args=Arguments))]
[assembly: PMCtor(LambdaExpression,      Lambda(parms=Parameters, body=Body))]
[assembly: PMCtor(ListInitExpression,    ListInit(what=NewExpression, inits=Initializers))]
[assembly: PMCtor(MemberExpression,      Member(obj=Expression, member=Member))]
[assembly: PMCtor(MemberInitExpression,  MemberInit(what=NewExpression, bindings=Bindings))]
[assembly: PMCtor(MethodCallExpression,  Call(obj=Object, method=Method, args=Arguments))]
[assembly: PMCtor(NewArrayExpression,    New(ty=Type, inits=Expressions))]
[assembly: PMCtor(NewExpression,         NewArray(ctor=Constructor, args=Arguments, bindings=Members))]
[assembly: PMCtor(ParameterExpression,   Param(name=Name, ty=Type))]
[assembly: PMCtor(TypeBinaryExpression,  Is(expr=Expression, ty=TypeOperand))]
[assembly: PMCtor(UnaryExpression,       Unary(operator=Method, operand=Operand))]


После этого мы имеем возможность использовать описанные конструкторы в паттерн-матчинге.
Можно даже немного упростить эти объявления приняв соглашение по которому параметры имя которых совпадает со свойствами без учета регистар, можно описывать сокращенно. Например, вместо "left=Left" можно просто писать "Left".

Данные описания позволят компилятору просто переписать образец вида:
Bin(conv, left, right, method)

в образец вида:
BinaryExpression where(Conversion=conv, Left=left, Right=right, Method=method)

Что приведет к формированию эффективного кода без какого-либо рантайм-оверхэда.



Собственно жду аналогичного описания для активных партернов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: активные паттрены: перезагрузка :)
От: Рысцов Денис  
Дата: 20.10.10 21:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Не люблю абстракции, так как они обычно приводят к массе трепа без понимания происходящего.

VD>Что приведет к формированию эффективного кода без какого-либо рантайм-оверхэда.
VD>Собственно жду аналогичного описания для активных партернов.

Рантайм-оверхэд — непосредственное свойство активных парттернов, нельзя предоставить ту же мощь, что предоставляют активные партерны, но избавиться от оверхэда (а так же проблем в случае кода с побочными эффектами). Это существенная деталь реализации.

Код выше решает одну из проблем, которую так же решают активные парттерны, но не является полноценной заменой, так как не решает других. Он, действительно, является сахаром над where выражением. Если задача стоит в том, чтобы обеспечить pattern matching для обыкновенных объектов, то это хорошее решение. Если идет обсуждение о добавлении активных паттернов, то предложенное не является альтернативой.

Достаточно краткое и понятное введение в активные паттерны доступно по следующей ссылке: http://msdn.microsoft.com/en-us/library/dd233248.aspx

Ниже я привел пример на F# и "порт" на Nemerle

let (|Integer|_|) (str: string) =
   let mutable intvalue = 0
   if System.Int32.TryParse(str, &intvalue) then Some(intvalue)
   else None

let (|Float|_|) (str: string) =
   let mutable floatvalue = 0.0
   if System.Double.TryParse(str, &floatvalue) then Some(floatvalue)
   else None

let parseNumeric str =
   match str with
     | Integer i -> printfn "%d : Integer" i
     | Float f -> printfn "%f : Floating point" f
     | _ -> printfn "%s : Not matched." str



[Pattern] Integer(obj : string) : option[int]
{
  mutable intvalue = 0;
  if (int.TryParse(obj, out intvalue)) Some(intvalue) else None
}

[Pattern] Float(obj : string) : option[float]
{
  mutable floatvalue = 0;
  if (float.TryParse(obj, out floatvalue)) Some(floatvalue) else None
}

MatchExample(str : string) : string
{
  match(str)
  {
    | Integer(i) => $"str : int = $i"
    | Float(f) => $"str : float = $f"
    | _ => $"$str : Not matched"
  }
}


Реализация, я думаю, очевидна:

match(Integer(str))
{
  | Some(i) => $"str : int = $i"
  | _ => match(Float(str))
    {
      | Float(f) => $"str : float = $f"
      | _ => $"$str : Not matched"
    }
}


В принципе из реализации виден еще один юзкейс — это декомпозиция вложенных match.
Re[3]: активные паттрены: перезагрузка :)
От: IT Россия linq2db.com
Дата: 21.10.10 04:00
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Мое решение предполагает добавление следующих объявлений:

VD>
VD>[assembly: PMCtor(BinaryExpression,      Bin(conv=Conversion, left=Left, right=Right, method=Method))]
VD>[assembly: PMCtor(ConditionalExpression, If(ifFalse=IfFalse, ifTrue=IfTrue, cond=Test))]
VD>[assembly: PMCtor(ConstantExpression,    Const(value=Value))]
VD>[assembly: PMCtor(InvocationExpression,  Invoc(lambda=Expression, args=Arguments))]
VD>[assembly: PMCtor(LambdaExpression,      Lambda(parms=Parameters, body=Body))]
VD>[assembly: PMCtor(ListInitExpression,    ListInit(what=NewExpression, inits=Initializers))]
VD>[assembly: PMCtor(MemberExpression,      Member(obj=Expression, member=Member))]
VD>[assembly: PMCtor(MemberInitExpression,  MemberInit(what=NewExpression, bindings=Bindings))]
VD>[assembly: PMCtor(MethodCallExpression,  Call(obj=Object, method=Method, args=Arguments))]
VD>[assembly: PMCtor(NewArrayExpression,    New(ty=Type, inits=Expressions))]
VD>[assembly: PMCtor(NewExpression,         NewArray(ctor=Constructor, args=Arguments, bindings=Members))]
VD>[assembly: PMCtor(ParameterExpression,   Param(name=Name, ty=Type))]
VD>[assembly: PMCtor(TypeBinaryExpression,  Is(expr=Expression, ty=TypeOperand))]
VD>[assembly: PMCtor(UnaryExpression,       Unary(operator=Method, operand=Operand))]
VD>


Думаю, указание базового класса тоже понадобится, т.к. иерархии не всегда плоские. Ну и для одного типа желательна возможность указывать более одного шаблона.
Если нам не помогут, то мы тоже никого не пощадим.
Re[14]: Как сделать активные паттрены.
От: Jack128  
Дата: 21.10.10 05:57
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Вот эта конструкция в F#

WH>
WH>let (|DivisibleBySeven|_|) input = 
WH>

WH>Не дает ничего по сравнению с обычной функцией.

он избавляет от вложенных матчей. представь, что DivisibleBySeven возвращает какой нить сложный объект, который тоже нужно отматчить..
Re[4]: активные паттрены: перезагрузка :)
От: Воронков Василий Россия  
Дата: 21.10.10 07:09
Оценка:
Здравствуйте, Рысцов Денис, Вы писали:

РД>
РД>let (|Integer|_|) (str: string) =
РД>   let mutable intvalue = 0
РД>   if System.Int32.TryParse(str, &intvalue) then Some(intvalue)
РД>   else None

РД>let (|Float|_|) (str: string) =
РД>   let mutable floatvalue = 0.0
РД>   if System.Double.TryParse(str, &floatvalue) then Some(floatvalue)
РД>   else None

РД>let parseNumeric str =
РД>   match str with
РД>     | Integer i -> printfn "%d : Integer" i
РД>     | Float f -> printfn "%f : Floating point" f
РД>     | _ -> printfn "%s : Not matched." str
РД>


Это мы уже обсуждали. Partial patterns хорошо, но ведь по сути что это как не сахар над when? Код вида

| Integer i ->

Полностью аналогичен

| _ when int.TryParse(val) => ...

Код вида

| Integer 42 ->

Полностью аналогичен

| _ when int.TryParse(val) && val == 42 => ...

Т.е. это все равно сахар. И решение Влада — это простое решение для сахара. Оно именно такое, какое и должно быть. Т.е. сахар не пытается прикидываться этакой мегафичей.

А по поводу, являются ли актив паттерны чем-то большим чем сахаром — вернее, скажем, так, позволяют ли они сделать что-то такое, что нельзя десахаризировать в when — есть по кр. мере у меня лично большие сомнение. По-моему актив паттерны — это сахар и есть.
Re[5]: активные паттрены: перезагрузка :)
От: Jack128  
Дата: 21.10.10 07:54
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>А по поводу, являются ли актив паттерны чем-то большим чем сахаром — вернее, скажем, так, позволяют ли они сделать что-то такое, что нельзя десахаризировать в when — есть по кр. мере у меня лично большие сомнение. По-моему актив паттерны — это сахар и есть.


При такой постановке — любой язык программирования — сахар над машинным кодом.

Кстати — ТОЛЬКО через when актив патерны ты не рассахаришь, нужен еще набор вложенных match'ей.
Re[6]: активные паттрены: перезагрузка :)
От: Воронков Василий Россия  
Дата: 21.10.10 07:59
Оценка:
Здравствуйте, Jack128, Вы писали:

J>При такой постановке — любой язык программирования — сахар над машинным кодом.


Не совсем. Скажем, обычные паттерны можно представить через when, однако тогда компилятор не будет строить дерево достижимости, проверять, является ли match exhaustive, и все его вхождения станут irrefutable. Т.е. у нас изменится поведение.

Когда мы актив паттерны представляем через when мы с т.з. исполнения не теряем ничего, т.к. они уже имеют все эти болячки, т.е. являются как бы "ненастоящими" паттернами. Поэтому, извините, но на мой взгляд от них несет сахарной пудрой.

J>Кстати — ТОЛЬКО через when актив патерны ты не рассахаришь, нужен еще набор вложенных match'ей.


Вложенные паттерны — без проблем. В when может быть любой expression. К тому же вариант Влада поддерживает вложенные паттерны, но прекрасно рассахаривается в when.
Вопрос — что конкретно в актив паттернах на самом деле не является сахаром? Какие случаи вариант Влада покрывать не будет? У меня есть большое подозрение, что такие случаев нет.
Re[7]: активные паттрены: перезагрузка :)
От: Jack128  
Дата: 21.10.10 08:49
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, Jack128, Вы писали:


J>>При такой постановке — любой язык программирования — сахар над машинным кодом.


ВВ>Не совсем. Скажем, обычные паттерны можно представить через when, однако тогда компилятор не будет строить дерево достижимости, проверять, является ли match exhaustive, и все его вхождения станут irrefutable. Т.е. у нас изменится поведение.


ВВ>Когда мы актив паттерны представляем через when мы с т.з. исполнения не теряем ничего, т.к. они уже имеют все эти болячки, т.е. являются как бы "ненастоящими" паттернами. Поэтому, извините, но на мой взгляд от них несет сахарной пудрой.


J>>Кстати — ТОЛЬКО через when актив патерны ты не рассахаришь, нужен еще набор вложенных match'ей.


ВВ>Вложенные паттерны — без проблем. В when может быть любой expression. К тому же вариант Влада поддерживает вложенные паттерны, но прекрасно рассахаривается в when.


ВВ>Вопрос — что конкретно в актив паттернах на самом деле не является сахаром?

ну если "настоящим паттерном" считать только те, для которым компилер может дерево достижимости, то ничего. Хотя и вообще ПМ это тоже сахар, потому что ничто не мешает компилятору проверить достижимость цепочки аналогичной цепочки if'ов.

ВВ>Какие случаи вариант Влада покрывать не будет? У меня есть большое подозрение, что такие случаев нет.

Э-э-э. Вариант Влада — это матч по свойствам объекта. Для любого варианта, где у объекта нету свойства, по которому мы хотим матчить, придется городить when.
Ну и как реюзать конкретный паттерн — не очень понятно.

match (someExpr)
{
| Bin(ExpressionType.And, Const(1), Call(null, method, args)) =>
// что-то делаем с method и args

| _ => ...
}

допустим мне нужно заюзать в другом месте аналогичный паттерн, мне его полностью копировать??
в F# можно было бы так написать:

let (|ExpressionOneAndStaticMethodCall|_|) = function
| Bin(ExpressionType.And, Const(1), Call(null, method, args)) -> Some (method, args)
| None

И потом юзать где нуно:
match exp
| ExpressionOneAndStaticMethodCall (method, args) ->
| ... -> ...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.