Re[24]: Языки общего назначения не имеют смысла!
От: vdimas Россия  
Дата: 16.04.12 19:02
Оценка: :)
Здравствуйте, Sinclair, Вы писали:


V>>Дальше лень расписывать, пока было расписано подвыражение:

V>>select ManagerID, sum(Orders.Amount) from Orders where Orders.OrderDate between '20100101' and '20101231' group by ManagerID;
S>Отлично. Пока что SQL рвёт библиотеку 1 к 3м по компактности и читаемости.

Это пока нам не надо повторно использовать код. А то в итоге может оказаться наоборот 30 к 1 в итоге.


S>И это у вас ещё нет никаких попыток разрешить переписывания и оптимизации запроса внутри библиотеки — ваши предикаты это всего лишь функторы, а не Expression Trees.


V>>Можно спросить, что ты хотел узнать?

S>Да я-то ничего нового не узнал. Я хотел вам показать разницу между DSL и библиотекой, нарисованной на GPPL. Надеюсь, показал.
V>>На Клиппере пожестче было в свое время — никто не жаловался. И рвали по быстродействию любые базы, бо скомпилированный код многократно быстрее интерпретируемого работает.
S>
S>Вообще-то на клиппере как раз было помягче, т.к. всё таки это DSL, специально заточенный на обработку данных — пусть и чрезмерно императивный.

Таки я хорошо помню, что ручками делал гораздо больше, чем могу себе позволить обобщить на шаблонах С++ сегодня. И никакой оптимизации тоже не было, ес-но, было тупое сканирование файлов данных или файлов-индексов и обработка согласно самописных алгоритмов. Так же помню, что копипасты было много.


V>>>>Если же ты о перезаписи операций и прочей оптимизации — то это совсем отдельные операции, которые тоже, впрочем, достаточно формализованы.

S>>>Хотелось бы, чтобы перезапись операций и прочая оптимизация были не хуже, чем в SQL.

V>>Это нужен подход №2, когда выражение дается в виде декларации и доступно затем для аналитических вычислений. Тогда точно так же как показано выше в синтаксисе, но пусть select, from, transform и т.д. являюся не вызовами на обработку коллекций, а конструкторами узлов графа операций (аналог AST). Добавится лишь еще одна команда, нечто типа:

V>>
V>>auto resultingCollection = execute(result);
V>>

S>Что-то меня гложут тяжкие сомнения про то, что это так легко сделать, как вы пишете.

Почему? Смотрел на boost::lambda? Они почти весь синтаксис С++ умудрились сделать как генератор работающего AST. Отличный пример того, как это надо делать и стартовая точка для своих наработок.

Ес-но, для каждого выражения — свой узел. Вот здесь в двойных скобках приводил в примере именно генерацию AST, которое исполняется "потом":
( (_1.managerId=_2.first, _1.amount=sum(_2.second, &Order::amount)) )


_1, _2 — это глобальные placeholders из boost::lambda. В двойный скобках потому, что используется operator,() (оператор "запятая"), для перечисления последовательности действий в лямбде. Но синтаксис вызова ф-ии "проглотит" эти запятые в качестве разделителей нескольких аргументов, в то время как аргумент только у нас только один — это лямбда, вызываемая для построчных трансформаций.


S>Скажем, Версанту потребовалось всё-таки приделать свой парсер C++, чтобы обойти ограничения языка. Для AST недостаточно скормить в between указатель на член класса — надо каким-то образом дать возможность среде определить, что это за член класса такой, и поднять всю нужную метадату.


Как раз для приведенной мною ф-ии between ничего не нужно в отличие от генерации трансформаторов для проекций, продукций и пересечений, т.к. это просто перегрузка ее сигнатуры для случая на указателя на мембер, которая должна конструировать MemberBetweenPredicate (кстате, приведенный исключительно с целью показать, во что превратится вызов between).

Если бы я писал не торопясь, то увидел бы, что некая ф-ия приведения 'cdate' не нужна, достаточно, чтобы тип переменной-мембера имел нужный конструктор от одного аргумента, который можно вызвать как explicit.

Вот полный код для перегрузки сигнатуры between для указателя на мембер:
template<typename Entity, typename Value, typename Arg1, typename Agr2>
struct MemberBetweenPredicate<Entity, Value> between(Arg1 agr1, Value Entity::*member, Arg2 arg2) {
  MemberBetweenPredicate<Entity, Value> tmp = { member, { Value(arg1), Value(arg2) } };
  return tmp;
}


Теперь, при наличии у некоего типа, используемого для представления даты, конструктора от С-строки, можно писать еще короче:
between("20100101", &Order::orderDate, "20101231")
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.