Здравствуйте, <Аноним>, Вы писали:
А>Мои 150 выполняют больше работы, но это, как я уже писал, из-за работы по памяти.
Больше? Он не делал то что от него требовалось. И друго полезного тоже ничего не делает.
А>К тому же моя иерархия, возможно (из-за незнания Nemerle), строже.
Серьезно? Ну, сделай ее менее строгой. Хотя что-то я не заметил там какой-то строгости. Недоработки вот видны сразу. Например, контроль количества параметров у фунций отсуствует. Можно такую несуразность как Min() с одинм параметром сделать.
А>Например у меня некоторые классы в иерархии абстрактные, то есть их нельзя создать.
Это проблемы твоей реализации и выбронного тбой подхода. Сделай по другому. Главное, чтобы по фунциональности было тоже самое.
VD>>Причем, заметь, я не менял весь код а добавил всего два фрагмента. Фнукцию Convert:
А>Практически аналогично и у меня.
У тебя код не делал то что нужно.
VD>>К каждому классу иерархии был добавлен соврешенно метод RemoveOneParameterMin().
VD>>Он увеличил код и сделал его плохо читаемым.
А>Спорно что плохочитаемым.
Это спорно только для тебя. И то потому что ты любиль спорить и не любишь призновать своей не правоты (сам такй, по этому знаю не по наслышке
).
Заметь, люди которые знают оба зыка откровенно помеялись над твоим кодом.
К тому же если все так хорошо, что же ты переписал код как только увидел мой вариант?
VD>>К тому же RemoveOneParameterMin не универсален, а в исходном задании было сказано о том, что требуется универсальное решение, а не для конкретного случая.
А>Зато появляется доступ к внутренним полям класса, например можно вообще обойтись без публичнных полей.
Да уж это неверотное приемущество, вот только этого не требовалось по условию задачи и не ясно что оно дает.
VD>>Не выполнено по сути и задие с добавлением фунций. Ведь у тебя количество параметров не контролируется.
А>Легко добавляется.
То-то я гляжу, все так легко, что дня не хвает на реализацию.
VD>>Теперь можно продолжить наши упраженния. Сколько тебе потребуется времени и сил чтобы добавить еще две оптимизирующие трансформации — заменять выражение max(константа, константа) на значение большей из констант. И соответственно min(константа, константа), меньшей? Мне — пол минуты. Я просто добавлю пару образцов и все.
А>После написания функции Convert для поддержки конвертации, тоже, что-то в этом духе
Что же ты ее не написал в этом же духе сразу? И как выглядит код твоих трансформаций? Заметь я привел совсем примитивные примеры образцов. Они у тебя уже порождают кучу кода. А даже небольшое их усложнение приведет к настоящей горе кода. Причем совершенно нечитаемого.
Сравни:
static Expr RemoveMaxOfLiterals(Expr expr)
{
Max max = expr as Max;
if (max != null)
{
Lit first = max.First as Lit;
Lit second = max.Second as Lit;
if (first != null && second != null)
return new Lit(Math.Max(first.Eval(), second.Eval()));
}
return expr;
}
и
| Call("max", [Lit(x), Lit(y)]) => Lit(Math.Max(x, y))
Кстати, использовать Eval() для доступа к значениям литералов плохой подход. В будущем поведение может измениться и этот код превратится в ошибочный, а компилятор снова не сможет ничего подсказать.
VD>>Заметь, по сути мне нужно было добавить две строки. Тебе же прийдется еще раз менять дизайн всего приложения.
А>Не придется.
Да? А как понимать, то что ты полностью переписал свой код и отказался от так защищаемого тбой RemoveOneParameterMin()?
Ты уже начиташь сам себе противоречить и своими же действиями опровергать свои же слова
.
VD>>С Посетителем код у тебя может и был бы несколько больше, но все же не пришлось бы каждый раз курочить все классы ради подобных вещей.
А>Да, но похоже у посетителя, таже проблема, что и с общим методом в корневом классе. При добавлении классов в иерархию, ошибка не обработки, какого-либо класса переносится в runtime.
Отнюдь. Как раз посетители отлично выявляют необработанные классы иерархии, если конечно, правильно их готовить.
VD>>Ну, и естественно, что без паттерн-матчинга как бы ты не извивался, но твой код все равно будет больше и непонятнее.
А>Все-таки вопрос привычки.
Серьезно? Ну, я почти на верняка пишу на C# дольше тебя (начал еще в 2000-ном когда первые превью появились), но вот почему-то никак не могу привыкнуть к тому, что вместо:
def expr = expr.Convert(_ => {
| Mul(x, Literal(1.0)) => x
| Call("max", [Literal(x), Literal(y)]) => Literal(Math.Max(x, y))
| Call("mix", [Literal(x), Literal(y)]) => Literal(Math.Min(x, y))
| e => e });
я вынужден писать:
static Expr Transform(Expr expr)
{
return RemoveMulToOne(RemoveMaxOfLiterals(RemoveMinOfLiterals(expr)));
}
static Expr RemoveMulToOne(Expr expr)
{
Mul mul = expr as Mul;
if (mul != null)
{
Lit lit = mul.Second as Lit;
if (lit != null && lit.Eval() == 1)
return mul.First;
}
return expr;
}
static Expr RemoveMaxOfLiterals(Expr expr)
{
Max max = expr as Max;
if (max != null)
{
Lit first = max.First as Lit;
Lit second = max.Second as Lit;
if (first != null && second != null)
return new Lit(Math.Max(first., second.Eval()));
}
return expr;
}
static Expr RemoveMinOfLiterals(Expr expr)
{
Min min = expr as Min;
if (min != null)
{
Lit first = min.First as Lit;
Lit second = min.Second as Lit;
if (first != null && second != null)
return new Lit(Math.Min(first.Eval(), second.Eval()));
}
return expr;
}
...
expr = expr.Convert(Transform);
Расскажи, как ты к такому привыкаешь?
Я даже могу тебе подсказать, как сократить еще по строчки в каждой из функий. Например, RemoveMinOfLiterals можно записать так:
static Expr RemoveMinOfLiterals(Expr expr)
{
Min min = expr as Min;
if (min != null)
{
if (min.First is Lit && min.Second is Lit)
return new Lit(Math.Min(min.First.Eval(), min.Second.Eval()));
}
return expr;
}
но это ужимки. Код можно оптимизировать до какой-то степени, но не более. Без введения в язык новых вещей вроде паттерн-матчинга ничего ничего радикально изменить нельзя!
А>Вот код:...
Ну, что же. Ты не плохо учишся. Это называется переписать код в близком к функциональному стилю. Заметь, сходу ты такой код порадить не был способен. Пришлось подглядывать за поей версией и тырить от туда идеи. Я же просто писал в выбранном стиле, что называется не думая.
Теперь еще раз разберем полеты.
Объем кода
После устранения в твоем коде совсем уж затариенных в одну строку вещей кода получилось около 200 строк. Причем он еще остался "ужатым". В реальных проетах код будет по рыхлее. Мой код занимает 75 строк.
Получается кода более чем в 2 раза больше. Его вдвое больше при любых других измерения (в словах, в символах и т.п.). Если твой код отформатировать скажем по правилам РСДН, то его станет в трое больше.
Читаемость кода
Вряд ли ты станешь спорить, что теперь наш код иделогически близок. Но вот что лучше читается? На мой взгляд действия собранные вместе и без лишних заголовков функций читается намного лучше. Его и поддерживать проще.
Код правил трансформации даже сранвивать смешно. Три ясных как божий день строчки против порядка 40 строк! И это на примитивных паттернах! Что будет при их уложнении?
Развитие кода
Если нам понадобиться добавить новую операцию обработки кода мне будет достаточно создать новый метод, а тебе придется лазить по всем классам и добавлять в каждый из них по фукнции.
Если прийдется добавить новую ветку AST, то тебе прийдется добавить один класс и реализовать в нем по методу для каждого метода обработки, а мне добавить в каждый метод обработки по записи. Причем компилятор сам подксажет где это нужно сделать.
Если для тебя вывод еще не очевиден, то я уже даже и не знаю что саазать.
... << RSDN@Home 1.2.0 alpha rev. 637>>