LINUX.ORG.RU
Ответ на: комментарий от Zubok

> Так они так и определены. Есть произвольный список, к которому map можно сделать. В списке может быть объект любого вида: цифры, строчки, круги, квадраты, сферические кони в вакууме. Никаких ограничений. Гибкость, как карма у Будды :)

Речь шла не о этой гибкости. А о том, что common-lisp'овские map и reduce работают только для встроенных видов последовательностей: списков и массивов. Если я задам к примеру упорядоченное (мульти)множество, представленное в виде avl-дерева, то встроенные map, reduce и многие другие я применять уже не смогу.

anonymous
()
Ответ на: комментарий от anonymous

>Речь шла не о этой гибкости. А о том, что common-lisp'овские map и reduce работают только для встроенных видов последовательностей: списков и массивов. Если я задам к примеру упорядоченное (мульти)множество, представленное в виде avl-дерева, то встроенные map, reduce и многие другие я применять уже не смогу.

Ну так это к вопросу только о переименовании стандартной функции map, которое делать нельзя (не рекомендуется). А так ты спокойно можешь в LISP сделать свое дерево, написать свой map для него (который будет мэпом над стандартными мэпами и т. п.), обозвать его map-tree и вперед. Единственная проблема в твоем случае: как map-tree в map переименовать. А надо очень? Ну так сделать враппер можно. Сначала проверить аргумент на то, дерево это или нет. Если да, то выполнить map-tree, а если нет, то вызвать стандартный map. Назвать это все дело my-super-map и применять его всегда в своих программах. :)

Zubok ★★★★★
()
Ответ на: комментарий от eugine_kosenko

> Такой вопрос: можно ли в алхимии быстро включить трассировку sql-запросов? В Лиспе это очень помогло при отладке.

metadata = sqlalchemy.BoundMetaData('sqlite:///files.db', strategy='threadlocal', echo=True)

Там есть и более навороченная система, см. доку по слову echo_uow

redvasily
()
Ответ на: комментарий от cattlecoder

>does anybody know about CL implementations for PocketPC? that'd be great to have REPL on PocketPC.

Гугл? :)

Zubok ★★★★★
()
Ответ на: комментарий от bugmaker

> Можно пример, когда в лиспе понадобился бы новый тип-контейнер? А в питонос++ он нужен _всегда_,

Это наглое вранье, уж простите. Ассортимент контейнеров STL+Boost покрывает все необходимости "обычного" программиста. А в "необычных" случаях (очень много данных, особые требования по производительности и/или памяти, специфичные структуры) - все равно придется писать, на любом языке.

anonymous
()
Ответ на: комментарий от bugmaker

> дык ты покажеш как в с++ пользовать стандартные [] от массива в user-defined type не переопределяя или не?

Еще раз (десятый, примерно): _этого_никто_не_хочет_. Люди хотят, чтобы определив конечное малое количество интефрфейса для своего класса, они могли бы сделать его совместимым со стандартными алгоритмами.

В C++ для этого достатосно написать класс-итератор. Ну, чтобы прям со всеми-всеми алгоритмами работало - два класса, если не ошибаюсь (не гуру, мягко говоря, в C++): один модели forward iterator и другой - insert iterator.

Причем реализация их в большинстве случаев тривиальна.

В CL это все "наоборот", там предлагается переописывать все нужные алгоритмы для нового контейнера.

anonymous
()
Ответ на: комментарий от anonymous

> Это наглое вранье, уж простите. Ассортимент контейнеров STL+Boost покрывает все необходимости "обычного" программиста.

Дык их надо наследовать или и так работают?

> А в "необычных" случаях (очень много данных, особые требования по производительности и/или памяти, специфичные структуры) - все равно придется писать, на любом языке.

Так уж и на любом! Отлистай выше, для хранения файлов и в питоне и в с++ понадобилось сочинять свой, а в лиспе - не.

bugmaker ★★★★☆
()
Ответ на: комментарий от anonymous

> Еще раз (десятый, примерно): _этого_никто_не_хочет_. Люди хотят, чтобы определив конечное малое количество интефрфейса для своего класса, они могли бы сделать его совместимым со стандартными алгоритмами.

ещё раз, одиннадцатый примерно: стандартные алгоритмы _не_ работают с классами.

> В C++ для этого достатосно написать класс-итератор. Ну, чтобы прям со всеми-всеми алгоритмами работало - два класса, если не ошибаюсь (не гуру, мягко говоря, в C++): один модели forward iterator и другой - insert iterator.

потому что в с++ контейнер может полноценно хранить только один тип или классы с одним общим предком. А в лиспе внутре контейнеров может сидеть всё чё угодно. Для с++ это _костыль_ который в лиспе не нужен.

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

Только если следовать логике "шиворот навыворот": определять и наследовать контейнеры вместо тово, чёбы юзать их по назначению, для хранения чево-то. Лисп этому никак не препяцтвует, но и костылей на такой случай (почти) не предлагает.

bugmaker ★★★★☆
()
Ответ на: Фига себе! от ero-sennin

А "форматы" ещё не :( Неплохо Die-Hard зажог. Кстати, а где он? Никто не видел случяйно? Чёто он тут не отписываецо...

bugmaker ★★★★☆
()
Ответ на: комментарий от bugmaker

> Потому что в с++ (руби не знаю совсем, неведомо как там) есть примитивное типы, включяя массивы и операции с ними.

Весь STL можно описать не используя встроенных массивов - примитивных типов, указателей и аллокатора достаточно впоолне.

> user-defuned типы в с++ нагромождаются _поверх_ STL в свою очередь.

Это неправда. STL ортогонален пользовательским типам совершенно. Более того, оно не требует наследования - template progamming в С++ с ним не связан совершенно.

Короче, ты просто не понимаешь, о чем говоришь.

На плюсах есть "дополнительное измерение", с помошью которого я могу сказать "эта функция работает с любым типом, который удовлетворяет используемому интерфейсу". И если этот интерфейс состоит из operator++, operator--, operator*, и operator== - то она "поймет" и встроенные массивы, и STL-ные sequence-ы.

И не надо никуда ничего наследовать.

anonymous
()
Ответ на: комментарий от bugmaker

> а в лиспе нету видов последовательности в том смысле, в каком есть унаследованные от STL классы в с++

итак, 11-й раз -

чтобы пользоваться STL-ными алгоритмами не нужно наследоваться от STL-ных контейнеров. Более того, стандартные алгоритмы прекрасно работают на встроенных массивах (по крайней мере, когда такой массив - источник данных, insert iteratior-а для них таки нету), хотя они никакими отношениями родства ни с чем не связаны.

anonymous
()
Ответ на: комментарий от Zubok

> В языках C, C++ можно залезать в хэш на уровне указателей, но это уже (тут тонкая грань) работа не с хэшем, как с типом данных, а работа с хэшем на уровне реализации, коих может быть много разных.

По map и hash_map можно идти последовательно, получая на каждом шаге пару <ключ, значение>. На этой последовательности пар работают любые алгоритмы на последовательностях. У map даже порядок будет предсказуемый, в порядке сортировки ключей (тем отношением порядка, которое было указано при инстанциировании шаблона).

Короче, вы не владеете предметом...

anonymous
()
Ответ на: комментарий от bugmaker

> Так уж и на любом! Отлистай выше, для хранения файлов и в питоне и в с++ понадобилось сочинять свой, а в лиспе - не.

Ну-ка, покажи-ка мне в (_моей_ же ;) программе на С++ новый контейнер? Нету его там, не ищи. В питоньей - тоже нету.

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

А контейнеры и алгоритмы там все стандартные.

anonymous
()
Ответ на: комментарий от bugmaker

> потому что в с++ контейнер может полноценно хранить только один тип или классы с одним общим предком. А в лиспе внутре контейнеров может сидеть всё чё угодно. Для с++ это _костыль_ который в лиспе не нужен.

Очень хочется перейти на стиль vsl.

Врешь ты нагло, или троллишь.

Каждый экземпляр контейнера, естественно, ограничен одним типом. Но сама реализация его - да ни разу. Это называется метапрограммирование...

> Только если следовать логике "шиворот навыворот": определять и наследовать контейнеры вместо тово, чёбы юзать их по назначению, для хранения чево-то.

Никто не предлагает наследовать контейнеры. ВСего лишь - определять в своих типах стандартный интерфейс.

Например, если у тебя вдруго списки перестанут помещаться в памяти и ты сделаешь тип on-disk-list, с прозрачной подкачкой из файлов, в лисповой проге тебе придется везде поменять map на map-over-on-disk-list (аналогично с reduce и какие еще у вас там определены алгоритмы). А на плюсах все заработает "автомагически".

И для этого даже не придется наследоваться от vector/list/whatever.

anonymous
()
Ответ на: комментарий от anonymous

> Ну-ка, покажи-ка мне в (_моей_ же ;) программе на С++ новый контейнер?

typedef map< FileId, set<string>, FileId::Eq > FileDist;

Оно?

Вообще, шаблонирование -- штука приятная, конечно, но скорость компиляции убивает в усмерть. А однажды даже удалось создать шедевр на Эйфеле, компиляция которого просто не завершалась -- вис компилятор. Так что, это не проблема C++, а вообще проблема шаблонирования. Кроме того, в C++ использование шаблонов приводит к чудным результатам, когда в результате ошибки в одном месте диагностика выдается совершенно в другом, причем эти два места могут быть абсолютно не связаны. Если добавить к этому прелести несовместимости шаблонов, например, в MSVS C++ и G++, то ловить блох в кроссплатформенных приложениях становится особым экстримом. Посему я так и ниасилил ни STL ни его более ранние/поздние альтернативные замены. Просто тихо сполз на Эйфель.

> В питоньей - тоже нету.

class FileDb:

А это что? Правда, в таком примере можно было бы обойтись и без дополнительного класса (хинт -- переменная self нигде в классе не используется). Так что, это уже скорее следствие тяжелого воздействия ООП на психику программеров...

eugine_kosenko ★★★
()
Ответ на: комментарий от anonymous

>> Потому что в с++ (руби не знаю совсем, неведомо как там) есть примитивное типы, включяя массивы и операции с ними.

> Весь STL можно описать не используя встроенных массивов - примитивных типов, указателей и аллокатора достаточно впоолне.

какая наф разница? важно чё примитивных. Можно и на структурках список выстроить. И даже бес структурок обойтись, использовать например (int *)(a + ITEM_N) где a типо void *. Главное чё STL базируецо на примитивных типах а не наоборот.

> Это неправда. STL ортогонален пользовательским типам совершенно. Более того, оно не требует наследования - template progamming в С++ с ним не связан совершенно.

STL с точки зрения компилера такая же библиотека юзверовских типоф. Если оные юзверовские типы нагромождать не поверх STL то опять таки поверх базовых типоф. Примитивный тип ты недобавиш никаким естественным способом, равно как и дополнительные операторы для работы с им.

> Короче, ты просто не понимаешь, о чем говоришь.

это просто ты не понимаеш чё в лиспе просто не нужны костыли такие как в с++

> На плюсах есть "дополнительное измерение", с помошью которого я могу сказать "эта функция работает с любым типом, который удовлетворяет используемому интерфейсу". И если этот интерфейс состоит из operator++, operator--, operator*, и operator== - то она "поймет" и встроенные массивы, и STL-ные sequence-ы.

Аха, вот ты про чё. Да, чево нет тово нет, собственно по тем же причинам. Я даже не представляю как это могло бы пригодицо если бы было. Для приведённово тобой случяя выше, это можно было бы сделать на CLOS, либо делать собственную функцию, которая не замещает встроенную но работает параллельно и называецо подругому.

bugmaker ★★★★☆
()
Ответ на: комментарий от eugine_kosenko

> > Ну-ка, покажи-ка мне в (_моей_ же ;) программе на С++ новый контейнер?

> typedef map< FileId, set<string>, FileId::Eq > FileDist;

> Оно?

Ну, если _это_ называется "новый контейнер"... ;)

Вообще-то, это всего-лишь алиас типа, вполне себе собранного из стандартных контейнеров. Если удалить это строку, и потом заменить все вхождения FileDist на определения этого типа - то все будет работать прекрасно, только читать будет невозможно...

Это ж, блин, явная типизация.

> > В питоньей - тоже нету.

> class FileDb:

> А это что? Правда, в таком примере можно было бы обойтись и без дополнительного класса (хинт -- переменная self нигде в классе не используется). Так что, это уже скорее следствие тяжелого воздействия ООП на психику программеров...

Это, если я правильно помню, издержки реализации sqlalchemy (я не знаю питона) - в смысле, оно хочет класс-наследник с определением структуры данных.

Т.е. это сущность того же порядка, что и мой плюсовый typedef. Никто не _реализует_ новых контейнеров на каждый чих, а рассказывает стандартной библиотеке, чего конкретно от нее надо.

> Вообще, шаблонирование -- штука приятная, конечно, но скорость компиляции убивает в усмерть. А однажды даже удалось создать шедевр на Эйфеле, компиляция которого просто не завершалась -- вис компилятор. Так что, это не проблема C++, а вообще проблема шаблонирования. Кроме того, в C++ использование шаблонов приводит к чудным результатам, когда в результате ошибки в одном месте диагностика выдается совершенно в другом, причем эти два места могут быть абсолютно не связаны. Если добавить к этому прелести несовместимости шаблонов, например, в MSVS C++ и G++, то ловить блох в кроссплатформенных приложениях становится особым экстримом. Посему я так и ниасилил ни STL ни его более ранние/поздние альтернативные замены. Просто тихо сполз на Эйфель.

Угу, есть такая проблема. Но в лиспе, насколько я успел понять в процессе своих попыток прорешать Practical CL, она тоже стоит - эксепшены вываливают программу в REPL с 6..12 слойным стеком, и где конкретно ты сделал что-то не так - столь же непонятно неопытному глазу.

anonymous
()
Ответ на: комментарий от bugmaker

> какая наф разница? важно чё примитивных. Можно и на структурках список выстроить. И даже бес структурок обойтись, использовать например (int *)(a + ITEM_N) где a типо void *. Главное чё STL базируецо на примитивных типах а не наоборот.

И что? А CLOS базируется на defgeneric, который тоже, насколько я понимаю, встроенный, и переопределить который нельзя. И уже точно оно все базируется на вызовах функций и cons cell-ах, которые зашиты в компилятор. В чем аргумент-то заключается? Что С++ - статически типизированный и это плохо? Ну, это твои заморочки, мне кажется, что это хорошо.

> STL с точки зрения компилера такая же библиотека юзверовских типоф. Если оные юзверовские типы нагромождать не поверх STL то опять таки поверх базовых типоф. Примитивный тип ты недобавиш никаким естественным способом, равно как и дополнительные операторы для работы с им.

Угу, да. А ты не сможешь изменить семантику cons cell-ов, или удалить из лисп-машины сборщик мусора. Наличие и состав базовых концепций - это ни в коем разе не аргумент в "сферически-вакуумном" сравнении языков, все равно какие-то везде есть.

> это просто ты не понимаеш чё в лиспе просто не нужны костыли такие как в с++

> Я даже не представляю как это могло бы пригодицо если бы было. Для приведённово тобой случяя выше, это можно было бы сделать на CLOS, либо делать собственную функцию, которая не замещает встроенную но работает параллельно и называецо подругому.

Я тебе привел пример. Чтобы на лиспе сделать библиотеку, которая оперирует как всроенными списками (для маленьких задач), так и самодельными списками-на-диске для больших, и предлагала пользователю сделать свой тип (скажем, подкачку данных по сети для _совсем_ больших задач), тебе придется сделать массу телодвижений, сводящихся, в основном, к повторной реализации того, что уже есть в стандартной библиотеке.

anonymous
()
Ответ на: комментарий от anonymous

> Ну-ка, покажи-ка мне в (_моей_ же ;) программе на С++ новый контейнер?

typedef map< FileId, set<string>, FileId::Eq > FileDist;

оно?

> Нету его там, не ищи.

нашед, нашед! :P

> В питоньей - тоже нету.

class FileDb(dict):

а эт чево?

> достаточно будет поменять только определение этого

а в лиспе и без определения всё ладно.

bugmaker ★★★★☆
()
Ответ на: комментарий от anonymous

> Очень хочется перейти на стиль vsl.

нет, только не это!!!

> Каждый экземпляр контейнера, естественно, ограничен одним типом. Но сама реализация его - да ни разу. Это называется метапрограммирование...

какая разница? тип нужен переопределять или не?

>> Только если следовать логике "шиворот навыворот": определять и наследовать контейнеры вместо тово, чёбы юзать их по назначению, для хранения чево-то.

> Никто не предлагает наследовать контейнеры. ВСего лишь - определять в своих типах стандартный интерфейс.

дык а зачечем переопределяют?

> Например, если у тебя вдруго списки перестанут помещаться в памяти и ты сделаешь тип on-disk-list, с прозрачной подкачкой из файлов, в лисповой проге тебе придется везде поменять map на map-over-on-disk-list (аналогично с reduce и какие еще у вас там определены алгоритмы). А на плюсах все заработает "автомагически".

а фих ево знает как оно в лиспе будет в таком разе, там понятия памяти ваще как такового нету.

bugmaker ★★★★☆
()
Ответ на: комментарий от anonymous

>Короче, вы не владеете предметом...

Перейдем на ругань или повременим? Повторю еще раз: обход по хэш-таблице -- это деталь ее *реализации*. Хэш-таблица как тип данных -- это набор пар "ключ"-"значение". В общем случае *неупорядоченный*. Детали реализации хэш-таблицы как типа данных не определены самим понятием. Есть только понятие ключ, хэш-функция и значение. Как он там эти пары ищет -- дело реализации. Поэтому еще раз утверждаю, что хэш-таблица -- это не последовательность. Последовательностью он может быть только в смысле конкретной реализации. Вот maphash в CL и ходит в хэше на низком уровне. Индекс -- это не свойство хэш-таблицы, как у массива. Смотри реализацию chaining, например. Одному индексу может соответствовать два, три, четыре и т. д. значения. То есть нет однозначного соответствия индекс-значение в общем случае. А еще используют самобалансирующиеся деревья для реализации хэш-таблиц. А завтра я сделаю хэш-функцию, которая из ключа генерирует не индекс, а сразу указатель. Выделю память по этому указателю и запишу туда данные. Как тут обходить хэш-таблицу? Индекса же нет? Но от этого она хэш-таблицей быть не перестает! Так что общем случае хэш-таблица -- это не последовательность. Давай контраргументы.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

> Перейдем на ругань или повременим?

Мы столько времени держались в рамках... ;)

> А завтра я сделаю хэш-функцию, которая из ключа генерирует не индекс, а сразу указатель.

Этот указатель и будет хэш-ключом.

> Так что общем случае хэш-таблица -- это не последовательность.

Это _неупорядоченная_ последовательность. И операция обхода всех ее элементов с получением ключей - хорошо определена и полезна. Только не нужно рассчитывать на упорядоченность - но никто и не рассчитывает.

tailgunner ★★★★★
()
Ответ на: комментарий от eugine_kosenko

> шаблонирование -- штука приятная, конечно, но скорость компиляции убивает в усмерть.

Просто реализации такие

> ниасилил ни STL ни его более ранние/поздние альтернативные замены.

А можно подробнее - что является "альтернативной заменой" STL?

> class FileDb:

> это уже скорее следствие тяжелого воздействия ООП на психику программеров

Считай это комментарием. Впрочем, без комментариев тоже можно обойтись :D

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Этот указатель и будет хэш-ключом.

Ну а я про что? Как ты обойдешь последовательно такую хэш-таблицу? Всю память будешь сканировать в поисках данных? Или генерировать все возможные ключи? :) Я соглашусь, что реализация, возможно, несколько непрактичная, но хэш-таблица работать будет нормально! Или это уже не хэш-таблица будет?

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

> реализация, возможно, несколько непрактичная, но хэш-таблица работать будет нормально! Или это уже не хэш-таблица будет?

Я не могу представить себе реализацию такой хэш-таблицы, при которой хоть где-нибудь не хранился бы список ключей. Хотя бы для того, чтобы проверять коллизии ;)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> А можно подробнее - что является "альтернативной заменой" STL?

В 96 году пытались использовать YACL (Yet Another Class Library). Тоже содержала комплект контейнеров и прочих вкусных абстрактных типов. Не смогли собрать. Насколько я понял, BOOST тоже позиционирует себя аналогичным образом. Но за нее я уже не брался, потому как уже имел негативный опыт.

eugine_kosenko ★★★
()
Ответ на: комментарий от eugine_kosenko

>> Это _неупорядоченная_ последовательность.

>Горячий лед.

Буквоедство.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

> В чем аргумент-то заключается?

в том чё примитивные типы используются для построения а не видоизменяюцо

> Что С++ - статически типизированный и это плохо? Ну, это твои заморочки, мне кажется, что это хорошо.

а типизация тут не причём совсем.

> Угу, да. А ты не сможешь изменить семантику cons cell-ов, или удалить из лисп-машины сборщик мусора. Наличие и состав базовых концепций - это ни в коем разе не аргумент в "сферически-вакуумном" сравнении языков, все равно какие-то везде есть.

в данном случяе мы сравниваем не языки а разницу в методах работы с ними.

> Я тебе привел пример. Чтобы на лиспе сделать библиотеку, которая оперирует как всроенными списками (для маленьких задач), так и самодельными списками-на-диске для больших, и предлагала пользователю сделать свой тип (скажем, подкачку данных по сети для _совсем_ больших задач), тебе придется сделать массу телодвижений, сводящихся, в основном, к повторной реализации того, что уже есть в стандартной библиотеке.

Вовсе нет. Я использовал бы готовые и на их основе - свои.

bugmaker ★★★★☆
()
Ответ на: комментарий от tailgunner

Да, ну и что касается итератора над хэшами, то и в CL есть макра (with-hash-table-iterator ...)

Zubok ★★★★★
()
Ответ на: комментарий от eugine_kosenko

> class FileDb: 
 
> А это что? Правда, в таком примере можно было бы обойтись и без
> дополнительного класса (хинт -- переменная self нигде в классе не 
> используется). Так что, это уже скорее следствие тяжелого 
> воздействия ООП на психику программеров...

И ты, Брут? :-)

Я то думал что FUD здесь только лисперы распростаняют.

Смотрим внимательно:

class FileDb(dict):
    def push(self, name, dir, value):
        try:
            self[(name, dir)].append(value)
        except KeyError:
            self[(name, dir)] = [value]

Всё ещё не видно self?

FileDb это потомок стандартного словаря. У него определён дополнительный метод push(), принимающий аргументы в терминах задачи:
имя файла, директорию и размер файла. 

Здесь абстрактный словарь из питона преврвщается в специализированный
для данной задачи контейнер. Можно пользоваться стандартным контейнером, как это делает bugmaker, но тогда мне бы каждый раз
пришлось бы городить этот огрод как в теле метода push().

А по поводу психики покарёженной ООП, в итоге я пишу:

filedb.push('file.txt', 777, '/foo') что тебе здесь не нравится?

Абсолютно все слова здесь из предметной области задачи.

Ну можно было обойтись без класса, описать функцию, которая первым
аргументом принимала бы словарь в который надо добавить файл, и что
это было бы труъ функциональное программирование? Нахуа?

Типа так

def add_to_file_db(file_db, name, dir, value):
    try:
        file_db[(name, dir)].append(value)
    except KeyError:
        file_db[(name, dir)] = [value]

И потом вместо filedb.push('file.txt', 777, '/foo') писать
add_to_file_db(filedb, 'file.txt', 777, '/foo')

Труъ?

И лично я на этом примере вижу то что на всех трёх языках решения
одинаковы. Различия обусловлены только статической типизацией в C++
и разницей стандартных контейнеров в разных языках.

Кстати, автор С++ примера, респект. Хорошо написал.

To anonymous: в этом примере не было sqlalchemy, с sqlalchemy 
был другой пример.

redvasily
()

Боже, дух того великого изобретателя биореактора вернулся на ЛОР, и с ним вернулись 30-ти страничные топики, и Лисп, (а может и сама, та, воспетая в веках, рекурсИя хвостОваЯ).

Да придаст же нам этот священный дух, сил, победить и сделать лучше и свободнее нашу жисьть... Мы снова на верном пути....

Даёшь комменты тышшами...даёёёш!!!

Kwintruder
()
Ответ на: комментарий от tailgunner

>Я не могу представить себе реализацию такой хэш-таблицы, при которой хоть где-нибудь не хранился бы список ключей. Хотя бы для того, чтобы проверять коллизии ;)

Да в принципе любые разрозненные данные в хеш-таблице можно дополнительно связать как минимум списком направленным. От одного entry к другому. И тогда по этому списку запускается итератор. В принципе, все просто. Я здесь в споре просто прицепился к словам. То есть что хэш-таблица без итератора может быть. Главное, чтобы она свою основную функцию исполняла: связывала ключ и значение. Итерация, согласен тут, реализуется дополнительно. И тут спорить не буду. Все. Не хочу больше по хешам.

Пошел писать программы на Си. Вчера поддержка новой архитектуры 2D-акселерации (EXA) в драйвере видяхи подала признаки жизни (с забавными глюками, однако). Пошел ковыряться в исходниках xorg.

Чтобы ночью было 2048 постов! :)

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

> данные в хеш-таблице можно дополнительно связать как минимум списком

ИМХО, не "можно", а "по-любому придется". Это природа контейнера, любого. Отсюда естественно следует наличие итератора.

> хэш-таблица без итератора может быть.

Если задаться целью повредничать :)

tailgunner ★★★★★
()
Ответ на: комментарий от redvasily

> Смотрим внимательно:

Это была _другая_ программа на питоне. Я тщательно разбирался только с "алхимической" версией, а там достаточно только синглетона-алхимии, которая и так выполняет всю необходимую работу. Там FileDB и в самом деле лишний. Об что и написал.

eugine_kosenko ★★★
()
Ответ на: комментарий от redvasily

> А по поводу психики покарёженной ООП, в итоге я пишу:

апять бугоганахъ. в итоге я пишу (зделать-всё-песдато) ичё?

bugmaker ★★★★☆
()
Ответ на: комментарий от eugine_kosenko

В основном здесь идёт обсуждение контейнеров и версий программы 
без БД.

Но даже если рассматривать версию с БД, то self тоже используется
и в конструкторе и в __unicode__():

class File(object):
    def __init__(self, **kwargs):
        # Кстати, это итерация по словарю / хэшу :-) 
        for key, value in kwargs.iteritems():
            setattr(self, key, value)

    def __unicode__(self):
        s = [ unicode(self.__class__.__name__) + u': ' ]
        for c in self.c:
            s.append(u'%s=%s ' % (c.key, getattr(self, c.key)))
        result = u''.join(s)
        return result

Класс необходим из-за того что sqlalchemy это ORM. Т.е. это для людей
поражённых ООП до мозга костей типа меня. В простейшем случае можно
считать что таблица отображается на класс, т.е. класс необходим.

А это просто мой стандартный шаблон класса для sqlalchemy, в нём
конструктору передаётся набор keyword аргументов, которые сразу
устанавливаются на объекте и определено преобразование в строку
(вернее в юникод) для вменяемого вывода на печать.

redvasily
()
Ответ на: комментарий от eugine_kosenko

> Насколько я понял, BOOST тоже позиционирует себя аналогичным образом. Но за нее я уже не брался, потому как уже имел негативный опыт.

Нет, буст позиционируется как расширение STL и полигон для обкатки того, что предлагается внести в STL в новых версиях стандарта.

anonymous
()
Ответ на: комментарий от redvasily

> Но даже если рассматривать версию с БД, то self тоже используется и в конструкторе и в __unicode__():

> class File(object):

Речь идет не о File, а о FileDB. Единственная его функция -- это контейнер для целевых функций. По сути, он синглетон. Можно было бы возложить на него функции инициализации базы данных, создания таблицы и алхимического картирования (а это скорее к File, об этом дальше). Но Вы ведь этого не сделали, предпочтя выполнить все эти телодвижения за пределами класса. Собсно, я споткнулся об это, когда писал свою версию для Лиспа. Я не умею хорошо работать с классами в Лиспе, потому создание еще одного класса мне показалось нецелесообразным. У меня получилось сделать всю функциональность FileDB простыми функциями. То же самое можно было бы сделать и в Питоне. Можно, конечно, спорить о масштабировании, но ведь это явно не тот случай. А даже если и помнить о масштабировании, то Вы слишком непоследовательно к нему подготовились.

> Класс необходим из-за того что sqlalchemy это ORM. Т.е. это для людей поражённых ООП до мозга костей типа меня. В простейшем случае можно считать что таблица отображается на класс, т.е. класс необходим.

Еще раз подчеркну: это именно File, не FileDB. Так ведь, и у меня такой класс понадобился, потому как CLSQL -- это тоже ORM (ну, плюс pysqlite в том же флаконе, и это особенно воодушевляет). Посему у меня определяется класс file. Только вот закавыка, у меня на Лиспе этот класс несет серьезную смысловую нагрузку -- он определяет картирование класса в таблицу. А в питоньей проге этот файл "зависает" -- у него при определнии даже явная атрибутика не задается. Это, опять же, делается отдельным вызовом за пределами класса. То есть, опять непоследовательно.

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

eugine_kosenko ★★★
()
Ответ на: комментарий от anonymous

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

Тебе придётся _только_ использовать имеющиеся функции для существующих типов и написать свои для новых.

Посмотрите реализацию map-ов в различных лиспах. Там, как правило, идёт проверка типа и разделение зависимого от типа кода. Теоретически - да, два хода до дженериков. Практически - 1) нфиг не надо (разве только "си++"-нутым); 2) в случае действительной надобности - легко реализуется; 3) даёт возможность компилировать довольно быстрый код.

yyk ★★★★★
()
Ответ на: комментарий от yyk

>Посмотрите реализацию map-ов в различных лиспах. Там, как правило, идёт проверка типа и разделение зависимого от типа кода. Теоретически - да, два хода до дженериков. Практически - 1) нфиг не надо (разве только "си++"-нутым); 2) в случае действительной надобности - легко реализуется; 3) даёт возможность компилировать довольно быстрый код.

Точно. Я думаю, что причина того, что не сделали один универсальный map -- это забота о производительности. В процессе выполнения откуда заранее узнаешь, какой тип будет передан в map. Соответсвенно, потребовалась бы диспечеризация по типам. А нафига мне такой празник в высокопроизводительных программах? :) Поэтому и сделали для списков map, а для хэш-таблицы maphash. И это правильно. А вот в generic уже есть диспечеризация, которая разными способами оптимизируется в реализациях, но она все-равно есть.

В C++ это можно сделать без penalty, потому что тип аргументов определяется еще до компиляции. Но только опять непонятно, радоваться или огорчаться по этому поводу. Если я увижу, например, в трех участках кода универсальный (map бла-бла var), то сразу и не пойму, какой тип у var. И это только запутает. А если я вижу maphash, то сразу знаю, что там дальше хэш-таблица. Если увижу map, то знаю, то там дальше некий список. Сделаю maptree и сразу буду знать, что там дерево. И людям, которые будут читать мой код, будет легче. Так что выгода от тотальной универсализации стандартных функций в независимости от типов -- это вопрос спорный.

Zubok ★★★★★
()
Ответ на: комментарий от eugine_kosenko

> Речь идет не о File, а о FileDB

Всё, наконец дошло о чём идёт речь.

В первой версии (не зарелизенной) у этой программы metadata и files_table были атрибутами FileDb, мне это не понравилось и я их оттуда выкинул на верхний уровень модуля (т.к. при этом получалось) меньше буков, а мне не хотелось провоцировать дополнительный флейм по этому поводу :-)

В реальной задаче я думаю всё было бы подругому, начиная с того что я бы использовал не BoundMetaData, определённый на уровне модуля, а DynamicMetadata и т.д, и т.п.

Главным критерием при написании этой программы были минимальные затраты времени на её написание :-)

redvasily
()
Ответ на: комментарий от redvasily

> я их оттуда выкинул на верхний уровень модуля (т.к. при этом получалось) меньше буков, а мне не хотелось провоцировать дополнительный флейм по этому поводу :-)

Выкинули бы класс целиком -- буков было бы еще меньше. А флейма вообще не было бы.

eugine_kosenko ★★★
()
Ответ на: комментарий от Zubok

> Я точно не смотрел, разрешена ли перегрузка стандартных операторов в стандарте или это implementation feature. Изначально в SBCL и CLISP (где я попробовал) это заблокировано (что правильно), но можно разблокировать принудительно

Это стандарт, принудительно можно разблокаровать ЕМНИП (with-packge-unlock ...

Darkman ★★★
()
Ответ на: комментарий от Zubok

> Я точно не смотрел, разрешена ли перегрузка стандартных операторов в стандарте или это implementation feature. Изначально в SBCL и CLISP (где я попробовал) это заблокировано (что правильно), но можно разблокировать принудительно

Это стандарт, принудительно можно разблокаровать ЕМНИП (with-packge-unlock ...

Darkman ★★★
()
Ответ на: комментарий от Zubok

> В C++ это можно сделать без penalty, потому что тип аргументов определяется еще до компиляции. Но только опять непонятно, радоваться или огорчаться по этому поводу. Если я увижу, например, в трех участках кода универсальный (map бла-бла var), то сразу и не пойму, какой тип у var

Гм. А зачем это знать, если алгоритм все равно работает по последовательности? Интересно знать, скорее, тип содержимого контейнера.

И, если уж _очень_ хочется такого документирования - можно инстанциировать шаблоны явными параметрами, типа

copy< list<int>::const_iterator, ostream_iterator<int> >(ambigous_list.begin(), ambigous_list.end(), ostream_iterator<int>(cout, "-");

(Да, да, оно очень длинно и тавтологично - поэтому никто так не делает).

anonymous
()
Ответ на: комментарий от redvasily

> Кстати, автор С++ примера, респект. Хорошо написал.

Спасибо. Хотя, как я сам же и говорил, можно было и лучше. Но это ж думать надо было бы.

> To anonymous: в этом примере не было sqlalchemy, с sqlalchemy был другой пример.

Ну, ээ (это был я же). Я не вчитывался, я питон не знаю толком. Перлисты мы...

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.