AVK>Что такое атомарный api и как он должен выглядеть?
Фактически — это то, как ты сейчас для себя определяешь правильный дизайн системы.
Для меня — это лишь фундамент, на котором строится большая часть системы.
Надеюсь мы друг друга поняли, и можно не расписывать это детально.
DG>> наворачивается несколько уровней объектной оболочки, которые приближают объектную модель программы к понятийной модели пользователя
AVK>Зачем? И с какой стати ты решил, что в понятийной модели пользователя хозоперация является частью кредитного счета?
потому что для меня как для руководителя, знающего фин. менеджмент — каждая операция тесно связана с каким-то из счетов в момент совершения.
DG>>, позволяя ему единообразным способом работать — с GUI, CLI
AVK>Что такое CLI?
command-line interface, командная строка
DG>> и скриптами
AVK>Пользователю со скриптами? Ты ничего не перепутал?
Конечно, любой сотрудник с высшим образованием должен уметь (или как минимум должен способен научиться) автоматизировать свою работу, в том числе с помощью скриптов. Иначе непонятно за что ему выдали диплом о высшем образовании..
DG>>, а также разгововарить на едином языке с программистами при постановке задач по разработке.
AVK>Пользователю разговаривать напрямую с программистами? Все страньше и страньше.
Всё тот же вопрос: зачем мне как руководителю платить деньги еще кому-то за испорченный телефон, если эффективнее напрямую соединить пользователя и программиста?
Или зачем мне держать программиста который не может поговорить с пользователем, или зачем нужен сотрудник, который не может объяснить программисту что он хочет?
DG>>В идеале — объектная оболочка строится автоматически, требуя минимальных трудозатрат.
AVK>Ух ты. Автоматически на основании чего? И зачем какая то оболочка, не привносящая в систему новой информации?
Потому что способности человека по комбинированию и запоминанию информации сильно ограничены, в отличии — от компьютера.
Соответственно, такая объектная оболочка — уменьшает временные затраты человека за счет того, что все необходимые данные для конкретной операции собраны вместе, а также благодаря тому — что большинство настроек выставлены автоматически на основе лучших рекомендаций от лучших консультантов. И соответственно, человек вводит только ту информацию и принимает только те решения, которые действительно необходимы в этот момент.
DG>> На практике — смешивается автоматическое построение объектной оболочки с ручным заданием.
AVK>Продемонстрируй. Пока что я вижу только лозунги, что все круто и никакой конкретики.
каким образом тебе это можно продемонстрировать?
AVK>Начни с описания одной подобной задачи. Реальной, а не "сижу, примус починяючеки разбираю". Потому что если реальной задачи нет — все это превращается в очередной бредогенератор типа ветки про открывание двери.
1. На основе данных за год из учетных систем (бухгалтерской и тайм-менеджмента) выдать рекомендации, что выгоднее: заключить контракт (и по какому тарифу?) на курьерское обслуживание с компанией "Скороход" или выгоднее продолжать в качестве курьера гонять Смирнова из отдела продаж и доплачивать ему за бензин?
2. Заказчик прочухался и шандарахнул на счет сразу куча бабла. Получить рекомендации от бух. системы, как эти деньги лучше дальше распределить и оформить, чтобы минимизировать расходы на налоги и минимизировать "заморозку" денег.
3. На основе данных из учетных систем посчитать норму прибыли для каждого сотрудника за последний год, и сравнить ее с нормой прибыли сотрудников в других компаниях из той же отрасли.
Здравствуйте, Ikemefula, Вы писали: I>Вобщем расслабься, больше от тебя ничего не нужно, все жосткие данные уже получены от AVK и DarkGray.
Ну и к тому же видно, кто из участников понимает, что он делает. AVK возвращает пустой массив, который иммутабелен по определению.
А коллега vdimas предлагает глупость отдавать наружу разделяемый экземпляр мутабельного ArrayList<T>.
Это грабли, заботливо разложенные на пустом месте: однажды в каком-то углу кода кто-то сделает someArbitraryArg.Add(42) и пипец наступит повсеместно. Такую багу можно искать неделями.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
I>>Вобщем расслабься, больше от тебя ничего не нужно, все жосткие данные уже получены от AVK и DarkGray. S>Ну и к тому же видно, кто из участников понимает, что он делает. AVK возвращает пустой массив, который иммутабелен по определению.
Зато использование IList в коде сжирает любой предполагаемый профит. А что надо делать с иммутабельностью — я тебе уже говорил там, где скипаешь неудобные аргументы. IList по дизайну нифига не иммутабельный.
S>А коллега vdimas предлагает глупость отдавать наружу разделяемый экземпляр мутабельного ArrayList<T>. S>Это грабли, заботливо разложенные на пустом месте: однажды в каком-то углу кода кто-то сделает someArbitraryArg.Add(42) и пипец наступит повсеместно. Такую багу можно искать неделями.
Ох, уже не знаем что на ровном месте изобрести. Поздно, все ходы записаны.
1. В исходном примере вообще null, то бишь сценарий изначально подразумевал только чтение.
2. В твой вариант можно точно так же вставить someArbitraryArg.Add(42), всё-равно это будет бага, и всё-равно это может быть сколько угодно далее распространяемая бага, т.к. вопрос относительно того, насколько бага пойдет далеко за пределы примера — вопрос исключительно спекуляционый.
3. Конкретные типы могли быть вполне иммутабельные, т.е. что автор примера, что ты, что я — все показывали только принцип. Теперь же тебя дважды ткнули носом и тебе банально обидно... Но с этим детсадом к доктору, а не ко мне.
Здравствуйте, Ikemefula, Вы писали:
I>Это попытка в десятке сообщений выдавить из тебя то, чего Avk выдал одной строчкой.
Сказано было именно это с самого начала, просто конкретно ты неадекватно вопринимаешь информацию.
I>В твоей модельке издержки на GC и близко не являются основным, она у тебя ни разу не адекватная, т.к. ошибся ты примерно на два порядка, вдобавок ко всему прочему добавил кучку дезы вроде "интрузивный список" и "должны обрабатываться после линии задержки".
Да лан, что тебе надо делать — я уже сказал. Но ты испарился там и материализовался здесь. Давай-ка лучше наоборот.
I>Вобщем расслабься, больше от тебя ничего не нужно, все жосткие данные уже получены от AVK и DarkGray.
Это ровно такие же жосткие данные, как и мои. Если ты не понял, что были упомянуты разные сценарии и поэтому наблюдали разный результат — то это опять твои проблемы.
Но, чтобы мне показать эту разницу (ключевое выделил), давай свой вариант решения "в лоб", чтобы было с чем сравнить. Хотя, собсно, ты бегаешь уже 3-й пост... И я даже знаю, почему, бо уже показывал здесь похожие трюки не раз, вызывая недовольство "высокоуровневых программистов"... Не боись, набираться опыта не так страшно, как кажется.
Здравствуйте, vdimas, Вы писали:
V>Ты не ответил ни здесь, ни на пред топик. Где сама-то сортируемая коллекция? Где аннотации как минимум еще двух типов? V>Ну и каша...
Это абсолютно неважно, но раз ты так хочешь:
interface IOperation<T, TR>
{
TR Apply(T t);
// остальные методы для простоты опущены
}
Mod modifier = GetSalt();
Ctx ctx = GetContext();
var operation = modifier[ctx]; // надеюсь тебя это не испугает
Order(x => operation.Apply(x)) // ты должен понимать, что это частный случай, то есть контекст сводится к готовому экземпляруprivate void Order(Func<Item, int> => selector)
{
_precachedResult = _items.OrderBy(selector).ToList();
}
V>А вопрос был ключевой лишь потому, что речь идет о статически-типизированном языке, то бишь, что бы не возвращал modifier[ctx] (скажем, SortModifier), и что бы не возвращаел затем Apply(x), — независимо от исходного модификатора это будет значение одного и того же типа. А я не вижу аннотаций в примере.
Это неважно.
V>Итого, в твоем примере я даже не вижу по какому критерию происходит сортировка. Полный мрак и непонятки. Вот причина "ключевых вопросов" — из-за нечитабельности кода.
Не ври, видишь — по значению возвращаемому Apply. На счет нечитаемости — так это твой С++ бекграунд даёт знать, раз уж ты одну строчку с лямбдойпрочесть ен можешь.
V>Ну ок, буду разгребать твою кашу. V>Помнишь, я писал тебе тебе, что есть замыкание? Вот часть инфраструктуры вне примера:
Мусор скипнул и это ни разу не процедурное программирование, но уже целая инфраструктура
V>Имеем некую обобщенную процедуру сортировки (показываю ключевые моменты): V>
И это мусор, см выше
V>Далее, я из головы дополню отсутствующие нотации типов в твоем примере.
Мусор скипнул, см выше
V>А теперь само решение. Смотрим на твой код и отделяем мух от котлет, то бишь свободные переменные от связанных в замыкании: V>
V>int CompareUsingModifier(SaltedModifier * sm, X * a, X * b) {
V> return CompareByModifiedX(sm->Apply(a), sm->Apply(b));
V>}
Вот, появляется инфраструктура, ВНИМАНИЕ, для частного случая ! :)))
V>Mod modifier = GetSalt();
V>Ctx ctx = GetContext();
V>SaltedModifier sm = modifier[ctx];
V>qsort(collectionOfX, make_fn(CompareUsingModifier, &sm));
V>
Итого — тебе понадобилась целая инфраструктура только для того, что бы сэмулировать один случай использования лямбды и передачи её в функцию сортировки
Если вызова будет два, тебе надо будет написать два метода,
Если вызова будет три, тебе надо будет написать три метода,
Если ...
При чем это частный случай, когда контекст сводится к уже имеющемуся экземпляру, опаньки...
А теперь, внимание, меняются требования и критерий сортировки будет другой. Для тебя это бедствие — надо переписать N-методов и N-мест, но это еще не все, потому что ...
Order(x => operation.Apply(Mask(x)))
Вот оно, бедствие — Mask это метод того же класса что и Order, а значит тебе надо еще накидать N-структур, то есть пары {SaltedModifier, SomeClass}.
Требования меняются снова:
Order(x => operation.Apply(Mask(x, code)))
Снова бедствие — перегрузка Mask приняла параметром значение параметра из вызывающего метода... И значит тебе снова надо переписать сигнатуры методов, изменить структуры {SaltedModifier, SomeClass, SomeParameter} и поменять связывание
Мне же надо поправить N-мест на каждый случай изменений. Итого — трудоемкость твоего подхода по скромной оценке на порядок выше.
Ты хорошо понимаешь, чего предлгаешь ? В твоем вариант надо метод, структуру и связывание, делать руками для каждого случая лямбды и метода который её принимает
На примере, смотри внимательно:
group.PullAction((a) =>
{
a.Location.Logical = new VectorD(dmGroup.OffsetX + dmGroup.PhysicalX, dmGroup.OffsetY + dmGroup.PhysicalY); // просто тянем из локального контекста
a.Caption = dmGroup.Name;
a.CustomGlyph = GetTypeIcon(propertyCache, dmGroup.GroupType); // снова локальный контекст но уже другой
... целая пачка свойство обновляется по требованию —
});
Так настраивается обновление и это очень, очень скромный пример, хотя экономит вагон кода и добавление нового свойства делается ровно в одну строчку, методов PullAction несколько штук...
Вот посложнее:
case PaintMode.Routing:
return (s1, services, a) =>
{
var query = new Collector(Properties.DepthMode);
query.Run(s1, services, (es, rt) => a(es, ToCategories(rt))); // лямбда принимает лямбду и это экономит вагон кода
};
А вот вещь которая тебя убьёт,
public void MergeGroupsCategories(ObjectCategories mergeMask)
{
var mergeResult = ObjectCategories.None;
Children
.Apply( When:x => x.Visible && x as Group != null, // не твой день, целых три лямбды и две из них рекурсивные
visitOpen => x => // обычная лямбда-рекурсия
{
if((x as Group).IsOpen)
{
visitOpen(x);
return;
}
mergeResult = 0;
group.Nested
.Apply(When:y => y.Visible
merge => y => // снова лямбда-рекурсия
{
mergeResult |= y.State.CheckCategories(mergeMask);
y.Children.Apply(merge);
});
group.State.SetCategories(mergeMask, mergeResult);
});
}
Чисто императивный аналог по скромным оценкам в 10...100 раз больше, теперь представь, что такие функции на каждом шагу... Конечно, встроив всякие композиты-итераторы, получится сократить код, но все равно будет намного, намного больше и будут проблемы разных сортов.
Теперь заметь, мне надо ввести еще один параметр для обхода, опаньки, ничего сложного. А твоей эмуляции надо перепахать всё, вообще всё!
V>Ты показал плохой пример. Ничего не понятно. В отличие от моего конечного варианта, который отличается одной доп. ф-ей CompareUsingModifier.
Ты снова забыл, что обещал показать процедурное, а показал ООП+ФП. Если тебе нечего добавить, то будем считать что твоя ТЗ про процедурное неверна.
I>>Ну и снова ты отошел от структурного программирования.
V>А в какую сторону я отошел-то? Тебя идентификатор lambda смутил? А если бы я назвад его object? V>Например, куда здесь отошла ф-ия драйвера, которой сам драйвер подается как контекст? V>
V>void ioctl(IODriver * driver, int param, void * arg);
V>
V>В какую сторону ты видишь тут "отход от структурного программирования" (С)? В ФП или ООП? V>Заметь, отход-то равнозначный... что как бэ намекает на истоки озвученного мною мнения. Я ведь не с потолка утверждение сделал, а после изготовления пары интерпретаторов ф-х языков.
Ты похоже не пониаешь, что в процедурном нет указателей на функции, потому даже ООП уже мягко говоря сильно затруднено.
I>>Покажи внятный аналог моего кода и не соскакивай со стурктурного .
V>Т.е. тебе опять нечего ответить? ЧТД.
Я так и не увидел "практически полный аналог процедурной декомпозиции". Пока что ты для честного случая задействовал почему то ФП и ООП, хотя обещал процедурное
I>>Покажи общий случай IoC а не вырожденый, мой пример выше.
V>Общий случай в qsort и есть. Похоже, ты не понимаешь, где в твоем собственном примере IoC, а где ФП. См внимательно мой вариант твоего примера.
Частный. Потому что лямбды используются повсеместно и тебе везде придется проектировать взаимодейтсвие. см мой пример про метод Mask
I>>"реально в дизайне видна только декомпозиция на составные ф-ии, которая практически полный аналог процедурной декомпозиции"
V>Именно, твой пример — тому пример. Твоего замыкание в дизайне не видно.
ну да — не надо сотни классов генерить, не надо сотни методов писать — в дизайне не видно
I>>В другой технике у тебя просто нет аналога, потому что I>>1. связывание придется делать вручную
V>Да похрен, это глубокие подробности кода, которые из дизайна не торчат ни разу. Абсолютно ничего не изменилось от того, что я прилепил локальную ф-ию CompareUsingModifier. Ну разве что сэкономил тебе немного на исходнике и осводил тебя от надобности писать комменты из-за самодокументирумости моего варианта.
Ну да, целая инфраструктура что бы сортировке передать параметр. Теперь вернись и посмотри состальные мои примеры.
I>>2. управлять контекстом придется вручную
V>Ну да. Подавать "контекст" придется вручную. Более того, у контекста теперь появится... оп-па! Экземпляр!
А толку ? Вместо одной строчки у тебя будет десяток другой на каждую лямбду и метод который её принимает.
I>>3. проектировать структуры данных для взаимодейтсвия придется вручную
V>Структура данных нужна будет для отображения контекста, а не дляя взаимодействия.
Неважно, её надо проектировать
V>============================ V>Кстати, у тебя, походу, проблемы с оперативной памятью: I>>Покажи внятный аналог моего кода.
Ты так и не показал "практически полный аналог процедурной декомпозиции", как только покажешь, поговорим про твой пример
S> Там в верёвках и концах — сплошной косяк. Начиная с того, что у вашей верёвки произвольное количество концов.
согласен, замечание принимается.
что в следующем коде не так с identity?
class Rope
{
public Rope()
{
this.Points = new double[100];
}
public double[] Points;
public RopeEnd Start
{
get { return new RopeEnd(this, true); }
}
public RopeEnd End
{
get { return new RopeEnd(this, false); }
}
}
class RopeEnd
{
public RopeEnd(Rope rope, bool isStart)
{
this.Rope = rope;
this.IsStart = isStart;
}
public readonly Rope Rope;
public readonly bool IsStart;
public override bool Equals(object obj)
{
var ropeEnd = obj as RopeEnd;
if (ropeEnd == null)
return false;
return object.Equals(this.Rope, ropeEnd.Rope)
&& IsStart == ropeEnd.IsStart;
}
public override int GetHashCode()
{
return this.Rope.GetHashCode() ^ this.IsStart.GetHashCode();
}
static Random rnd = new Random();
public void Change(double x)
{
var points = this.Rope.Points;
if (!IsStart)
points = points.Reverse().ToArray();
var len = rnd.Next(30);
points = points.Select((v, i) => {var r = len - i; return r > 0 ? v + x * r / len : v;}).ToArray();
if (!IsStart)
points = points.Reverse().ToArray();
this.Rope.Points = points;
}
}
S>Если непонятно, почему для непрерывно переходящих друг в друга объектов нельзя ввести identity, то я — пас.
а вот тут ты передернул: я говорил о том, что границы объектов могут быть нечеткие, а не о том, что они непрерывно переходят друг в друга — это два совершенно ортогональных друг друга свойства.
вот, например, объект RopePoint с нечеткой границей и нечетким положением относительно Rope, какие у него проблемы с identity?
class RopePoint
{
static readonly Random rnd = new Random();
public RopePoint(Rope rope, int index)
{
this.Rope = rope;
this.Index = index;
}
public readonly Rope Rope;
public readonly int Index;
public override bool Equals(object obj)
{
var other = obj as RopePoint;
if (other == null)
return false;
return object.Equals(this.Rope, other.Rope) && this.Index == other.Index;
}
public override int GetHashCode()
{
return Rope.GetHashCode() ^ Index.GetHashCode();
}
public void Change(double x)
{
var center = Index * 10 + rnd.Next(16) - 8;
var len = rnd.Next(20);
Rope.Points = Rope.Points.Select((v, i) => { var r = Math.Abs(i - center); return r < len ? (v + x * (len - r) / len) : v; }).ToArray();
}
}
Здравствуйте, vdimas, Вы писали:
I>>Это попытка в десятке сообщений выдавить из тебя то, чего Avk выдал одной строчкой.
V>Сказано было именно это с самого начала, просто конкретно ты неадекватно вопринимаешь информацию.
Если почистить от дезы и скорректировать цифры которые отличаются на два порядка, то да Дальше я скипнул, извини, буду считать что ты ничего не писал, а это мне привиделись твои сообщения.
S>Я, наверно, вас разочарую, но OOUI сейчас несколько вышло из моды.
и по какой модели построен, например, интерфейс gmail-а, интерфейс редактора Drawing из google docs, интерфейс Visual Studio, интерфейс инет-банка СберБанка?
или это всё устаревшие примеры GUI? что тогда не устаревший GUI?
Здравствуйте, Ikemefula, Вы писали:
I>Ну-ка, подробнее про зависимость затрат на уробрку мусора от количества типов.
Да, кстати.
Отвечу и покажу, когда проберемся через уровень 0 по кол-ву объектов. На их кач-во зайдем на след. итерации.
В двух словах — речь об т.н. эффекте "протухания кеша". Воспроизводится только на примере де-факто большого кол-ва пробегаемого кода и различных структур данных на каждом шаге алгоритма. Этот эффект, к слову, хорошо показывает такое удивительное на несведущий взгляд отличие в эффективности синтетических тестов и реального кода. Т.е. тот самый случай, когда результат не равен сумме слагаемых.
Здравствуйте, vdimas, Вы писали:
V>Да, кстати. V>Отвечу и покажу, когда проберемся через уровень 0 по кол-ву объектов. На их кач-во зайдем на след. итерации. V>В двух словах — речь об т.н. эффекте "протухания кеша". Воспроизводится только на примере де-факто большого кол-ва пробегаемого кода и различных структур данных на каждом шаге алгоритма. Этот эффект, к слову, хорошо показывает такое удивительное на несведущий взгляд отличие в эффективности синтетических тестов и реального кода. Т.е. тот самый случай, когда результат не равен сумме слагаемых.
Не напрягайся, я лучше подожду когда про протухание кеша будет говорить ктото другой
Здравствуйте, Ikemefula, Вы писали:
V>>Сказано было именно это с самого начала, просто конкретно ты неадекватно вопринимаешь информацию.
I>Если почистить от дезы и скорректировать цифры которые отличаются на два порядка, то да Дальше я скипнул, извини, буду считать что ты ничего не писал, а это мне привиделись твои сообщения.
Таки струсил. ))
Кстате, твой тест, судя по твоему же описанию, всё еще некорректен, то бишь исходные 2 порядка надо делить не на 8, а на 16? То бишь, 100/16=~6, так? Итого, ты даже не смог вложиться в разницу быстродействия техники 5-тилетней давности и современной. Твой голый пример на той технике даже не взлетит, хотя пока не начинал делать ничего полезного.
Здравствуйте, Ikemefula, Вы писали:
I>Не напрягайся, я лучше подожду когда про протухание кеша будет говорить ктото другой
ОК, а я подожду пока ты наберешься смелости показать пример, который на 2 порядка отличается от моих цифр. Ну или пока что-то другой сможет аналогичное.
Здравствуйте, vdimas, Вы писали:
V>Зато использование IList в коде сжирает любой предполагаемый профит. А что надо делать с иммутабельностью — я тебе уже говорил там, где скипаешь неудобные аргументы. IList по дизайну нифига не иммутабельный.
Не любой, он только инлайниться не будет, зато этот интерфейс поддерживается во всяких оптимизациях например в Linq2Objects. Иммутабельный не IList, а пустой массив, это именно то что говорил Синклер
.
Здравствуйте, vdimas, Вы писали:
V>Таки струсил. ))
V>Кстате, твой тест, судя по твоему же описанию, всё еще некорректен, то бишь исходные 2 порядка надо делить не на 8, а на 16? То бишь, 100/16=~6, так?
Здравствуйте, vdimas, Вы писали:
I>>Не напрягайся, я лучше подожду когда про протухание кеша будет говорить ктото другой
V>ОК, а я подожду пока ты наберешься смелости показать пример, который на 2 порядка отличается от моих цифр. Ну или пока что-то другой сможет аналогичное.
Надеюсь твоё ожидание не будет потреблять твои ресурсы.
> I>Ну-ка, подробнее про зависимость затрат на уробрку мусора от количества типов. > > Да, кстати. > Отвечу и покажу, когда проберемся через уровень 0 по кол-ву объектов. На их кач-во зайдем на след. итерации. > В двух словах — речь об т.н. эффекте "протухания кеша". Воспроизводится только на примере де-факто большого кол-ва пробегаемого кода и различных структур данных на каждом шаге алгоритма. Этот эффект, к слову, хорошо показывает такое удивительное на несведущий взгляд отличие в эффективности синтетических тестов и реального кода. Т.е. тот самый случай, когда результат не равен сумме слагаемых.
Тоже очень интересно про зависимость уборки мусора от количества типов и протухание кэша. Новые для меня концепции.
Здравствуйте, Ikemefula, Вы писали:
V>>Итого, в твоем примере я даже не вижу по какому критерию происходит сортировка. Полный мрак и непонятки. Вот причина "ключевых вопросов" — из-за нечитабельности кода. I>Не ври, видишь — по значению возвращаемому Apply.
Чего-чего???
I>На счет нечитаемости — так это твой С++ бекграунд даёт знать, раз уж ты одну строчку с лямбдойпрочесть ен можешь.
При чем тут С++, если вырезанный кусок не поймет ни я, ни компилятор? У меня нет остальных исходников, чтобы восстановить контекст происходящего.
V>>Ну ок, буду разгребать твою кашу. V>>Помнишь, я писал тебе тебе, что есть замыкание? Вот часть инфраструктуры вне примера:
I>Мусор скипнул и это ни разу не процедурное программирование, но уже целая инфраструктура
Это та самая процедурная декмопозиция по всем правилам процедурного искусства.
Мне уже любопытно, а как ты себе вообще представлял процедурную декомпозицию?
V>>Имеем некую обобщенную процедуру сортировки (показываю ключевые моменты): V>>
Хорошо себя чувствуешь? Это тот самый целевой аналог твоего _items.OrderBy(), ради которого всё. Т.е. оно мусор только если _items.OrderBy() тоже мусор... Хотя не, вру, _items.OrderBy() мусор заведомо, т.к. не позволяет выбрать алгоритм сортировки. Сравни с qsort, выполненным в лучших традициях слабой связанности + IoC.
V>>А теперь само решение. Смотрим на твой код и отделяем мух от котлет, то бишь свободные переменные от связанных в замыкании: V>>
V>>int CompareUsingModifier(SaltedModifier * sm, X * a, X * b) {
V>> return CompareByModifiedX(sm->Apply(a), sm->Apply(b));
V>>}
I>Вот, появляется инфраструктура, ВНИМАНИЕ, для частного случая !
Мде... Это это локальная ф-ия. С каких пор локальные ф-ии стали инфраструктурой?
I>Итого — тебе понадобилась целая инфраструктура только для того, что бы сэмулировать один случай использования лямбды и передачи её в функцию сортировки
Да лан, целая инфраструктура — это целый дотнет, где 50 метров зависимых бинарников грузятся в память, чтобы сделать простейший чих.
А моя "инфраструктура", как ты выразился:
— однократная;
— обощенная;
— поместится в 1к исходников. )))
На ней можно эмулироватьи твой случай с сортировкой и вообще любой другой, который ты только сможешь изобрести.
I>Если вызова будет два, тебе надо будет написать два метода,
Нет.
I>Если вызова будет три, тебе надо будет написать три метода,
Нет.
I>Если ...
Если бы ты понимал, где свободные переменные, а где связанные, ты бы понимал, где когда и сколько вызовов надо произвести. Реально на каждое замыкание со свободными переменными по одному вызову. То бишь замыкание легко заменяется процедурой. Собсно, именно это от меня и требовалось.
А замыкание без свободных переменных можно реализовывать как часть вышестоящих замыканий (процедур) без изменения семантики. То бишь, в реальном коде одной процедурой можно заменить сразу несколько замыканий.
I>При чем это частный случай, когда контекст сводится к уже имеющемуся экземпляру, опаньки... I>А теперь, внимание, меняются требования и критерий сортировки будет другой. Для тебя это бедствие — надо переписать N-методов и N-мест, но это еще не все, потому что ...
Гы, у меня-то как раз даже ф-ию сортировки протянуть не проблема через Fn, а у тебя надо всё раздезайнить заново. Ты ведь, сдуру отнес CompareUsingModifier к инфраструктуре, хотя это локальный метод на стороне вызывающего. Вернись и посмотри на код внимательней еще раз. CompareUsingModifier никогда не вызывается явно, а передается как адрес ф-ии. То бишь, если тебе надо другой критерий — подай адрес другой локальной ф-ии.
I>
I>Order(x => operation.Apply(Mask(x)))
I>
I>Вот оно, бедствие — Mask это метод того же класса что и Order, а значит тебе надо еще накидать N-структур, то есть пары {SaltedModifier, SomeClass}.
Беда только в голове. Поскольку кол-во замыканий сосвободными переменными у нас не изменилось, то кол-во элементов программы в моем примере не изменится. Изменится тело локальной ф-ии CompareUsingModifier точно так же, как изменился твой локальный код. Вместо sm->Apply(a) будет sm->Apply(Mask(a)).
I>Требования меняются снова:
I>
I>Order(x => operation.Apply(Mask(x, code)))
I>
I>Снова бедствие — перегрузка Mask приняла параметром значение параметра из вызывающего метода... И значит тебе снова надо переписать сигнатуры методов, изменить структуры {SaltedModifier, SomeClass, SomeParameter} и поменять связывание
SaltedModifier — это твой тип, который ты НЕ указал, я придумал ему имя сам.
Связывание измениться НЕ может, т.к. кол-во свободных переменных не поменялось, у тебя поменялось количество связанных переменных. Поэтому code уйдет в context. Будь хоть мильон связанных переменных, они все пойдут в один и тот же контекст. Единственное заметное изменение — это когда в контексте была одна переменная, а стало две. Вот тут для контекста потребуется ваять локальную структуру, вот тут уж дааааа... Особенно это будет "дааа" если я исопльзую заготовки обощенных структур, и назову эти структуры, скажем, Tuple. Но от второй переменной и дальше — никаких изменений кроме тех, которые будут и в твоем коде.
I>Мне же надо поправить N-мест на каждый случай изменений. Итого — трудоемкость твоего подхода по скромной оценке на порядок выше.
Ты просто опять подтверждаешь, что не знаешь как работает ФП и поэтому не понял моего примера. Еще раз, крупным по-белому: CompareUsingModifier никогда не вызывается явно, а передается как адрес ф-ии. Итого, ровно в стольки же N-местах я внесу такие же изменения в тела локальных ф-ий CompareUsingXXX, какие ты внесешь в свой код. См. свой пример насчет sm->Apply(Mask(a)).
I>Ты хорошо понимаешь, чего предлгаешь ? В твоем вариант надо метод, структуру и связывание, делать руками для каждого случая лямбды и метода который её принимает
Да, именно, я руками делаю то, что за тебя делает сахарок. Я это где-то отрицал? Да я же наоборот, вызвался так сделать. Похоже, ты же совсем уже в своем соку сварился, я тебя освежу:
в дизайне видна только декомпозиция на составные ф-ии, которая практически полный аналог процедурной декомпозиции (напомню, что процедурный подход допускает декомпозицию на процедуры и ф-ии). Возвращаясь к декомпозиции по замкнутому контексту — этот вид декомпозиции присутствует в подробностях кода, то бишь на уровне дизайна им можно пренебречь.
В общем, если единственно за что ты меня ругаешь, что где-то глубоко в подробностях кода у меня будет не так посахарено как у тебя, то большое спасибо, это означает полное и бесповоротное согласие с моей точкой зрения.
В остальном... я почитал ниже и, не побоюсь этого слова, с удовольствием подтверждаю твою правоту относительно того, то с синтаксическим сахарком получше чем без. Жаль, что ты не понимаешь кол-во полученного мною фана и удовлетворения в этой беседе. ))
Правда, вот эти моменты:
В твоем вариант надо метод, структуру и связывание, делать руками для каждого случая лямбды
конкретно для C# вызывают у меня жуткое неудовлетворение... При всёй красоте и удостве сахарка, техника автоматического захвата контекста безопасна только в условиях иммутабельности. А что происходит в случае захвата мутабельного контекста — видно было на этом форуме в профильных разделах, когда обсуждали мильон комбинаторно накладывающихся побочных эффектов, с которыми народ выходил жаловаться на жисть еще со времен появления анонимных делегатов в старом синтаксисе во 2-м дотнете.
I>Чисто императивный аналог по скромным оценкам в 10...100 раз больше,
Гы-гы-гы... Мож хоть раз с тобой на что-то конкретное поспорить? Ты же даже функциональной декомпозицией не владеешь, пишешь и не понимаешь свой собственный код... Ты даже не понимаешь, что показал мне в скипнутых примерах сценарии использование всего двух (ДВУХ!) базовых комбинаторов. Не стыдно??? На самом деле их ровно три, этих комбинатора. То бишь, что произойдет с моей т.н. "инфраструктурой", которую я, ес-но, на голубом глазу вынесесу из конечного решения и внесу в некий фреймворк, скажем, "Прелюдный", ты уже прямо сейчас можешь догадаться.
I>теперь представь, что такие функции на каждом шагу...
Да хоть десять на шаг. Важно понимать, что происходит.
I>Конечно, встроив всякие композиты-итераторы, получится сократить код, но все равно будет намного, намного больше и будут проблемы разных сортов.
Проблемы разных сортов бывают лишь от захвата контекста по мутабельной ссылке. А если ручкамми аккуратно захватывать копии значений в опасных местах (а я смогу этим управлять, в отличие от тебя), то проблем будет на-а-а-амного меньше.
Ды, кода будет ес-но больше. Основная масса лишнего кода будет занята строками объявлениями сигнатур локальных ф-ий и лишней парой фигурных скобок после этого объявления. Тела этих ф-ий будут отличаться по размеру не особо от исходного варианта. Остальное будет решено через комбинаторы, как через базовые, так и производные. Но ни о каких 10 раз и тем более 100 речь идти не будет, ес-но.
I>Теперь заметь, мне надо ввести еще один параметр для обхода, опаньки, ничего сложного. А твоей эмуляции надо перепахать всё, вообще всё!
Дык, если ты принцип действия IoC не понимаешь (смотри свой перл, что qsort это не IoC), если для тебя акты DI — темный лес, то ес-но тебе всё надо перепахать. А если я зависимости разнес, то пахать буду не больше тебя. Просто тебе дали такой инструмент... такой инструмент... где ты пишешь код и даже не понимаешь, какими приёмами пользуешься. Ты научился этому коду по образу и подобию на примерах более опытных товарищей, а не потому что сам понял, что так тоже можно... xz: Ей-богу, не ожидал таких перлов-комментариев на показанные мною кишки реально происходящего. Видишт ли... оно принципиально не могло отличаться от твоего решения, т.к. я его дословно эмулировал. Но ты, увы, этого не разглядел.
И да. Проблема на самом деле в моем решении есть и она серьезная, скажем, в координатах С++. Эта проблема — отсутствие GC, то бишь речь о времени жизни контекста. Проблема возникнет тогда, когда мы его используем не оперативным образом как в твоих примерах, а сохраняем для последующего использования. Скажем так, я же вижу, что ты из-зо всех сил лезешь подковырнуть оппонента, а как это сделать задешево — не понял. Надо было чуть подкорректировать свои примеры так, чтобы стал нужен GC и мне было бы сложнее отстреливаться. )) Но, справедливости ради, эта проблема ортогональна ООП/ФП/ПП. Например, в D есть GC, будет считать, что примеры можно было бы с минимальными телодвижениями переписать на нем, бо он тоже позволяет глобальные процедуры и ф-ии.
I>Ты так и не показал "практически полный аналог процедурной декомпозиции", как только покажешь, поговорим про твой пример
В том-то и дело, что показал в точности. А ты показал непонимание относительно устройства и механики работы ФП, даже когда эту механику воспроизвели на твоих собственных примерах. Это полный П.
Здравствуйте, AndrewVK, Вы писали:
V>>Дык, именно в этом соль. AVK>Соль в том, что ты неверно трактуешь понятие чистоты функции, не смотря на довольно простое и однозначное определение.
Потому что не в этом определении соль, а в том, что само простое определение опирается на определение побочного эффекта, а вот оно уже вызывает постоянные споры. Потому что некоторые спешат ставить знак равенства м/у мутабельностью и побочными эффектами. Собсно, поэтому мне понятие ссылочной прозрачности нравится больше, что оно более конкретное.
В данном же случае речь шла о таком забавном замеченном моменте:
чистая ф-ия -> порядок вычисления аргументов не важен, так?
Для Хаскеля порядок вычисления аргументов важен -> чистая ли ф-ия??? )))
Ну т.е. прикол-оксюморон и ничего больше... А ты, как всегда, с ликбезом.
То бишь юмор был в том, что программа на Хаскеле, составленная из чистых ф-ий, на самом деле НЕ МОЖЕТ быть выполнена в чистой манере. И даже не потому, что в main подается IO, а потому что вычислитель конечный, и этот конечный вычислитель ОБЯЗАН упорядочивать вычисления, невзирая на то, что порядок якобы не важен. Механизм упорядочивания в Хаскеле автоматический — на ленивости, мемоизации и гарантиях порядка вычислений аргументов при if-then-else и в конструкциях ПМ. Вот то надо выучить, чтоб от зубов отскакивало, это принципиально. Так вот, принципиально, что порядок этот гарантируется и программист может на него можно полагаться в "чистой" программе. То бишь, если бы программы на Хаскеле писали исходя из предположения, что они будут выполняться абстрактным вычислителем, который вычисляет аргумнты ф-ий в произвольном порядке, согласно их чистоты, то эти программы надо было бы писать по-другому. Вот всё что было сказано, не надо было изборетать лишнего.
V>>Мало ли, что компилятор в процессе оптимизации переписывает? AVK>Он, такие дела, и порядок вычислений тоже меняет. Так что в общем случае нет, порядок вычислений определить по Ф-программе нельзя.
Я уже сказал, для каких конструкций этот порядок заведомо известен при любом виде вычслений, что на IO, что на чистых. Без этих гарантий программы уходили бы в вечную рекурсию. Если помнишь, был здесь такой thesz, большой любитель Хаскеля, он подробно объяснял этот момент на примере комбинаторных парсеров. Я ХЗ что в этих объясениях могло быть непонятно...
V>>Точно так же и компилятор ФП, он может переписать много, но семантика результата должна быть точно такая же, как я получаю, пробегаясь по коду глазами... Иначе, как программировать-то? AVK>Порядок вычислений в семантику чистого Ф-кода не входит, в отличие от императивного.
Для Хаскеля именно что входит. Ты можешь на него полагаться в конструкциях if и ПМ.
V>>>>Фортран, ес-но. AVK>>>Это все? V>>Если речь об истоках, должно было хватить.
AVK>Т.е. это все. ЧТД.
Здравствуйте, vdimas, Вы писали:
V>>>Итого, в твоем примере я даже не вижу по какому критерию происходит сортировка. Полный мрак и непонятки. Вот причина "ключевых вопросов" — из-за нечитабельности кода. I>>Не ври, видишь — по значению возвращаемому Apply.
V>Чего-чего???
Это шутка такая, все ты понял.
I>>На счет нечитаемости — так это твой С++ бекграунд даёт знать, раз уж ты одну строчку с лямбдойпрочесть ен можешь.
V>При чем тут С++, если вырезанный кусок не поймет ни я, ни компилятор? У меня нет остальных исходников, чтобы восстановить контекст происходящего.
Да ладно, на поверку ты все правильно восстановил. Так шта...
V>Это та самая процедурная декмопозиция по всем правилам процедурного искусства.
Я давно понял, что ООП и ФП ты называешь процедурным программированием хотя там нет указателей на функции.
I>>Вот, появляется инфраструктура, ВНИМАНИЕ, для частного случая !
V>Мде... Это это локальная ф-ия. С каких пор локальные ф-ии стали инфраструктурой?
Инфраструктура это весь твой код который ты привел здесь.
V>Да лан, целая инфраструктура — это целый дотнет, где 50 метров зависимых бинарников грузятся в память, чтобы сделать простейший чих. V>А моя "инфраструктура", как ты выразился: V>- однократная; V>- обощенная; V>- поместится в 1к исходников. )))
и она будет только для сортировок и только для тех случаев, где контекст сводится к уже имеющемуся экземпляру.
V>На ней можно эмулироватьи твой случай с сортировкой и вообще любой другой, который ты только сможешь изобрести.
I>>Если вызова будет два, тебе надо будет написать два метода,
V>Нет.
Обоснования нет и не будет ?
I>>Если вызова будет три, тебе надо будет написать три метода,
V>Нет.
Обоснования нет и не будет ?
I>>Если ...
V>Если бы ты понимал, где свободные переменные, а где связанные, ты бы понимал, где когда и сколько вызовов надо произвести. Реально на каждое замыкание со свободными переменными по одному вызову. То бишь замыкание легко заменяется процедурой. Собсно, именно это от меня и требовалось.
Ты утверждаешь выше, что тебе на все случаи не нужно писать разные версии этой процедуры. А я утрвеждаю, что надо. И это уже проблема, даже без того, что надо еще и структуры и связывание описывать.
V>А замыкание без свободных переменных можно реализовывать как часть вышестоящих замыканий (процедур) без изменения семантики. То бишь, в реальном коде одной процедурой можно заменить сразу несколько замыканий.
Ну да и разбираться где в каком случае надо создавать новые экземляры, а где реюзать контекст. Я дал три примера, ты их скипнул. Попробуй предложить хотя бы похожий аналог...
I>>При чем это частный случай, когда контекст сводится к уже имеющемуся экземпляру, опаньки... I>>А теперь, внимание, меняются требования и критерий сортировки будет другой. Для тебя это бедствие — надо переписать N-методов и N-мест, но это еще не все, потому что ...
V>Гы, у меня-то как раз даже ф-ию сортировки протянуть не проблема через Fn, а у тебя надо всё раздезайнить заново.
Мне как раз все что надо это лямбду поправить. Правка лямбды это уже смена дизайна ? А ты не простой.
>Ты ведь, сдуру отнес CompareUsingModifier к инфраструктуре, хотя это локальный метод на стороне вызывающего. Вернись и посмотри на код внимательней еще раз. CompareUsingModifier никогда не вызывается явно, а передается как адрес ф-ии. То бишь, если тебе надо другой критерий — подай адрес другой локальной ф-ии.
Внимательнее читай.
I>>
I>>Order(x => operation.Apply(Mask(x)))
I>>
I>>Вот оно, бедствие — Mask это метод того же класса что и Order, а значит тебе надо еще накидать N-структур, то есть пары {SaltedModifier, SomeClass}.
V>Беда только в голове. Поскольку кол-во замыканий сосвободными переменными у нас не изменилось, то кол-во элементов программы в моем примере не изменится. Изменится тело локальной ф-ии CompareUsingModifier точно так же, как изменился твой локальный код. Вместо sm->Apply(a) будет sm->Apply(Mask(a)).
Локальные функции есть во всех языках ? Это новость Замыкания контекстов вдруг перекочевали в процедурное программирование. А ты, не простой.
V>Ты просто опять подтверждаешь, что не знаешь как работает ФП и поэтому не понял моего примера. Еще раз, крупным по-белому: CompareUsingModifier никогда не вызывается явно, а передается как адрес ф-ии. Итого, ровно в стольки же N-местах я внесу такие же изменения в тела локальных ф-ий CompareUsingXXX, какие ты внесешь в свой код. См. свой пример насчет sm->Apply(Mask(a)).
Локальные функции я так поянял есть во всех процедурных языках ? Это новость
V>Да, именно, я руками делаю то, что за тебя делает сахарок. Я это где-то отрицал?
Ты отрицаешь наличие преимуществ которые дает эта возможность и пытаешься назвать ООП и ФП процедурным программированием.
V>
V>в дизайне видна только декомпозиция на составные ф-ии, которая практически полный аналог процедурной декомпозиции (напомню, что процедурный подход допускает декомпозицию на процедуры и ф-ии). Возвращаясь к декомпозиции по замкнутому контексту — этот вид декомпозиции присутствует в подробностях кода, то бишь на уровне дизайна им можно пренебречь.
Нет этого аналога, ты демонстрируешь ООП и ФП особенности.
V>В общем, если единственно за что ты меня ругаешь, что где-то глубоко в подробностях кода у меня будет не так посахарено как у тебя, то большое спасибо, это означает полное и бесповоротное согласие с моей точкой зрения.
Ты демонстрируешь ООП и ФП а не процедурное программирование. Нет в процедурном тех вещей которые ты использовал в своем коде.
I>>Чисто императивный аналог по скромным оценкам в 10...100 раз больше,
V>Гы-гы-гы... Мож хоть раз с тобой на что-то конкретное поспорить? Ты же даже функциональной декомпозицией не владеешь, пишешь и не понимаешь свой собственный код... Ты даже не понимаешь, что показал мне в скипнутых примерах сценарии использование всего двух (ДВУХ!) базовых комбинаторов.
А мы договаривались что я покажу тебе все комбинаторы ? Или ты просто решил намекнуть непойми на что ?
Ты обещал что покажешь лямбды в процедурном программировании и пока что у тебя примеры ФП и ООП. то есть, тебе просто хочется сменить тему.
>Не стыдно??? На самом деле их ровно три, этих комбинатора. То бишь, что произойдет с моей т.н. "инфраструктурой", которую я, ес-но, на голубом глазу вынесесу из конечного решения и внесу в некий фреймворк, скажем, "Прелюдный", ты уже прямо сейчас можешь догадаться.
Мы вообще не говорили про комбинаторы, не надо соскакивать на другую тему.
V>Проблемы разных сортов бывают лишь от захвата контекста по мутабельной ссылке. А если ручкамми аккуратно захватывать копии значений в опасных местах (а я смогу этим управлять, в отличие от тебя), то проблем будет на-а-а-амного меньше.
Вагона кода еще ни разу не приводили к чему то хорошему.
V>Ды, кода будет ес-но больше. Основная масса лишнего кода будет занята строками объявлениями сигнатур локальных ф-ий и лишней парой фигурных скобок после этого объявления. Тела этих ф-ий будут отличаться по размеру не особо от исходного варианта. Остальное будет решено через комбинаторы, как через базовые, так и производные. Но ни о каких 10 раз и тем более 100 речь идти не будет, ес-но.
Будет. У меня всей инфраструктуры — один метод Apply и ничего больше, всё остальное работает само.
>А если я зависимости разнес, то пахать буду не больше тебя.
Гарантировано больше и ты это продемонстрировал.
>Просто тебе дали такой инструмент... такой инструмент... где ты пишешь код и даже не понимаешь, какими приёмами пользуешься. Ты научился этому коду по образу и подобию на примерах более опытных товарищей, а не потому что сам понял, что так тоже можно... xz:
Не расстраивайся, я учусь на чужих ошибках, в отличие от тебя
>Ей-богу, не ожидал таких перлов-комментариев на показанные мною кишки реально происходящего. Видишт ли... оно принципиально не могло отличаться от твоего решения, т.к. я его дословно эмулировал. Но ты, увы, этого не разглядел.
Ты вообще говоря так и не показал того, что обещал.
V>И да. Проблема на самом деле в моем решении есть и она серьезная, скажем, в координатах С++. Эта проблема — отсутствие GC, то бишь речь о времени жизни контекста.
Я тебе пять раз говорил про это и два из моих примеров это как раз и демонстрируют, разуй глаза.
>Проблема возникнет тогда, когда мы его используем не оперативным образом как в твоих примерах, а сохраняем для последующего использования. Скажем так, я же вижу, что ты из-зо всех сил лезешь подковырнуть оппонента, а как это сделать задешево — не понял.
Вообще говоря два из моих примеров как раз и демонстрирует это, разуй глаза.
>Надо было чуть подкорректировать свои примеры так, чтобы стал нужен GC и мне было бы сложнее отстреливаться. ))
Если бы ты читал внимательно, то сам заметил бы, что в двух из примеров нужен GC.
V>В том-то и дело, что показал в точности. А ты показал непонимание относительно устройства и механики работы ФП, даже когда эту механику воспроизвели на твоих собственных примерах. Это полный П.
Процедурное программирование не умеет указатели на функции, не умеет замыкать контексты. Когда ты пишешь make_fn это обычное ФП. То есть, нападая на ФП ты прибег к помощи ФП Когда ты используешь локальные фукнции — это все не процедурное, в процедурном ничего этого нет.