Здравствуйте, alex_public, Вы писали:
_>Теперь посмотри что даёт нам голый D. Удобные массивы со срезами, итерациями, контролем памяти. Плюс ещё ассоциативные массивы. Это покрывает огромное множество задач. Т.е. я думаю что вполне возможно довольно долго работать на D, вообще не заглядывая в те разделы библиотеки.
Да какая разница куда заглядывать — в описание встроенных в язык хэш-таблиц или в описание библиотечных (причём стандартная библиотека это практически часть языка). А заглядывать в любом случае придётся — например чтобы правильно сделать хэширование для своего типа, или хотя бы как правильно удалить.
У нас же нет задачи высадится на остров взяв собой только компилятор, потому что стандартная библиотека в чемодан не помещается
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, minorlogic, Вы писали:
EP>>>Взять например те же ranges — они проигрывают итераторам по производительности by-design M>>Этого не понял , ranges же легко делать поверх итераторов , где там производительность потеряется ?
EP>Ranges действительно легко делать поверх итераторов — например Boost.Range. Но в D нет итераторов — там сразу Range.
М... могу предположить что диапазон из одного элемента вместо указателя использует Range, и в этом накладные расходы ?
Здравствуйте, jazzer, Вы писали:
J>А вот если у тебя такая задача, каким бы был идиоматичный код на D?
Эм, я не знаю какой был бы идиоматичный код на D. Я в нём пока что совсем не спец., а так присматриваюсь понемногу. )))
J>Есть массив целых чисел, нужно найти искомое число, потом отсчитать вниз 2 четных числа, а потом наверх 5 нечетных. J>Т.е. для массива 1,2,3,4,5,6,7,8,9,10,11,12 мы находим 5, потом отсчитываем 2 четных числа вниз (4,2), потом 5 нечетных вверх (3,5,7,9,11) — ответ 11.
J>Мне вот не приходит в голову, как такую задачу решать на диапазонах. А на итераторах все естественно.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Я о том, что код у std::search может содержать реализацию только для ForwardIterator, и для всего остального будет работать без дополнительных движений. Без всяких isSomeString и isRandomAccessRange, и при этом даже будет быстрее, так как не имеет лишних операций.
Ну быстрее то вряд ли, т.к. там все эти ветвления в основном времени компиляции.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Да какая разница куда заглядывать — в описание встроенных в язык хэш-таблиц или в описание библиотечных (причём стандартная библиотека это практически часть языка). А заглядывать в любом случае придётся — например чтобы правильно сделать хэширование для своего типа, или хотя бы как правильно удалить. EP>У нас же нет задачи высадится на остров взяв собой только компилятор, потому что стандартная библиотека в чемодан не помещается
Например я заглянул в std.container только в следствие нашей дискуссии тут. Хотя при этом у нас есть некий небольшой проектик на D.
Здравствуйте, minorlogic, Вы писали:
EP>>>>Взять например те же ranges — они проигрывают итераторам по производительности by-design M>>>Этого не понял , ranges же легко делать поверх итераторов , где там производительность потеряется ? EP>>Ranges действительно легко делать поверх итераторов — например Boost.Range. Но в D нет итераторов — там сразу Range. M>М... могу предположить что диапазон из одного элемента вместо указателя использует Range, и в этом накладные расходы ?
Выше уже много примеров было: лишняя работа на каждой итерации в std::find, partition, search. Плохая комбинируемость приводящая к лишним проходам, копиям, созданием новых типов range на ровном месте, пониженная категория результирующих range.
То что где-то будет хранится два итератора, вместо одного само по себе не является серьёзной проблемой. А вот то что нельзя взять вот такие два range, в каждом из которых один элемент, и получить бесплатно range содержащий все элементы между этими двумя — это уже алгоритмическая ивалидность.
Здравствуйте, alex_public, Вы писали:
EP>>Я о том, что код у std::search может содержать реализацию только для ForwardIterator, и для всего остального будет работать без дополнительных движений. Без всяких isSomeString и isRandomAccessRange, и при этом даже будет быстрее, так как не имеет лишних операций. _>Ну быстрее то вряд ли, т.к. там все эти ветвления в основном времени компиляции.
Я не про static if'ы, а например про это. В версии с итераторами этого не будет вообще, by-design.
EP>Выше уже много примеров было: лишняя работа на каждой итерации в std::find, partition, search. Плохая комбинируемость приводящая к лишним проходам, копиям, созданием новых типов range на ровном месте, пониженная категория результирующих range.
Это собственно и вытекает из избыточности.
EP>То что где-то будет хранится два итератора, вместо одного само по себе не является серьёзной проблемой. А вот то что нельзя взять вот такие два range, в каждом из которых один элемент, и получить бесплатно range содержащий все элементы между этими двумя — это уже алгоритмическая ивалидность.
Тут у меня ступор , почему нельзя бесплатно ? ну или с незначительными расходами (на откуп оптимизатору)
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, DarkEld3r, Вы писали:
DE>>Кстати, правильно ли я понимаю, что свой аналог хеш-таблицы (ассоциативного массива) с таким же синтаксисом, как встроенные (ValueType [KeyType]), сделать нельзя?
DM>По идее, ничто не мешает — описываешь структуру/класс с оператором обращения по индексу и вперед.
А всякие вещи типа "in"?
Здравствуйте, minorlogic, Вы писали:
EP>>Выше уже много примеров было: лишняя работа на каждой итерации в std::find, partition, search. Плохая комбинируемость приводящая к лишним проходам, копиям, созданием новых типов range на ровном месте, пониженная категория результирующих range. M>Это собственно и вытекает из избыточности.
Нет, это не из-за избыточности, а из-за ограниченности. Избыточность это мелкие расходы на хранение — а вот то что аналог std::find, если ему скормить bidirectional range, разбивает его на два range, понижая категорию первого до forward — это как раз ограниченность.
EP>>То что где-то будет хранится два итератора, вместо одного само по себе не является серьёзной проблемой. А вот то что нельзя взять вот такие два range, в каждом из которых один элемент, и получить бесплатно range содержащий все элементы между этими двумя — это уже алгоритмическая ивалидность. M>Тут у меня ступор , почему нельзя бесплатно ? ну или с незначительными расходами (на откуп оптимизатору)
Вообще нельзя, нет такой операции. Например у ForwardRange есть только такие операции:
R r;
if (r.empty) {}
r.popFront();
auto element = r.front;
auto copy = r.save();
Вот тебе два range из одной последовательности:
R r1, r2;
В каждом по одному элементу. То есть после popFront он сразу становится empty.
С такими операциями нельзя получить всё что между ними, by design.
А в случае итераторов всё элементарно, и даже бесплатно:
I i1, i2;
// [i1, i2) - все элементы между, включая первый
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>То что где-то будет хранится два итератора, вместо одного само по себе не является серьёзной проблемой. А вот то что нельзя взять вот такие два range, в каждом из которых один элемент, и получить бесплатно range содержащий все элементы между этими двумя — это уже алгоритмическая ивалидность.
Я бы сказал это здравый смысл и обеспечение корректности. Твои слова звучат как "А вот то что нельзя взять произвольное число, превратить в указатель и получить бесплатно итератор — это уже алгоритмическая ивалидность". Возможность лепить range из произвольных не связанных друг с другом итераторов — слишком опасная граната, слишком много ног можно ей оторвать. Так что это просто такой design choice в пользу корректности.
Только что на эту тему неплохие слова услышал: http://youtu.be/TS1lpKBMkgg?t=16m28s
Здравствуйте, DarkEld3r, Вы писали:
DE>>>Кстати, правильно ли я понимаю, что свой аналог хеш-таблицы (ассоциативного массива) с таким же синтаксисом, как встроенные (ValueType [KeyType]), сделать нельзя? DM>>По идее, ничто не мешает — описываешь структуру/класс с оператором обращения по индексу и вперед. DE>А всякие вещи типа "in"?
Это уже синтаксис, он так просто не меняется. Делай функцию. Будет вместо "x in a" "x.isIn(a)" или "a.has(x)".
Здравствуйте, -n1l-, Вы писали:
N>Пользуясь случаем хочу спросить. N>На чем в linux'e больше программируют(чистых сях или инкрементированных) и что(встраиваемые системы, десктопчики, мобилки, веб)?
Кто на чем может, на том и программирует. C++ присутствует всерьез: (кроссплатформенная) библиотека Qt — едва ли не лучшее, что есть в хозяйстве. Я тоже побаиваюсь, что выбор языка еще даст о себе знать, но пока полет нормальный. В смысле, Qt-приложения заметно выигрывают на фоне своих альтернатив на других фреймворках, в среднем по больнице. Сложно все, одним словом. С другой стороны, если пользоваться биндингами для Питона (PyQt, PySide), можно не заметить, что там внутри .
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, DarkEld3r, Вы писали:
DE>>>>Кстати, правильно ли я понимаю, что свой аналог хеш-таблицы (ассоциативного массива) с таким же синтаксисом, как встроенные (ValueType [KeyType]), сделать нельзя? DM>>>По идее, ничто не мешает — описываешь структуру/класс с оператором обращения по индексу и вперед. DE>>А всякие вещи типа "in"?
DM>Это уже синтаксис, он так просто не меняется. Делай функцию. Будет вместо "x in a" "x.isIn(a)" или "a.has(x)".
Ну я про синтаксис и спрашивал.
Возможно, это глупая придирка, просто не уверен, что мне нравится идея добавлять "настолько высокоуровневые" вещи "прямо в язык" со специальным отдельным синтаксисом. В этом плане стл больше нравится — контейнеры/алгоритмы там ведь на правах обычных классов/функций. Соответственно при переходе от стандартных вещей к сторонним библиотекам (или своим велосипедам) особо ничего и не поменяется (при желании сохранить "интерфейс").
Выигрыш в краткости ведь небольшой, но уже добавляются дополнительные ключевые слова. "in expression" ведь только для ассоциативных массивов используется?
Здравствуйте, DarkEld3r, Вы писали:
DM>>Это уже синтаксис, он так просто не меняется. Делай функцию. Будет вместо "x in a" "x.isIn(a)" или "a.has(x)". DE>Ну я про синтаксис и спрашивал.
А, вон меня рядом поправили, можно и in задействовать для своих типов. Вот насчет своих литералов уже не уверен.
DE>Возможно, это глупая придирка, просто не уверен, что мне нравится идея добавлять "настолько высокоуровневые" вещи "прямо в язык" со специальным отдельным синтаксисом. В этом плане стл больше нравится — контейнеры/алгоритмы там ведь на правах обычных классов/функций. Соответственно при переходе от стандартных вещей к сторонним библиотекам (или своим велосипедам) особо ничего и не поменяется (при желании сохранить "интерфейс").
Я думаю, при переходе к сторонним библиотекам на С++ почти всегда будет другой интерфейс у контейнеров и придется вообще все переписывать. Насколько просто проходит переход между контейнерами STL, MFC, Qt, WxWidgets? У всех свои, похожие, но тем не менее достаточно разные, чтобы пришлось переписывать код. Что до специального синтаксиса, то опыт популярных "высокоуровневых" языков вроде перла/питона/руби/похапе и пр. показал, что они во многом так удобны именно из-за наличия подобных структур данных сразу в языке, без необходимости подключения дополнительных библиотек. Это достаточно базовые вещи, чтобы иметь их в приличном языке сразу.
Здравствуйте, D. Mon, Вы писали:
EP>>То что где-то будет хранится два итератора, вместо одного само по себе не является серьёзной проблемой. А вот то что нельзя взять вот такие два range, в каждом из которых один элемент, и получить бесплатно range содержащий все элементы между этими двумя — это уже алгоритмическая ивалидность. DM>Я бы сказал это здравый смысл и обеспечение корректности. Твои слова звучат как "А вот то что нельзя взять произвольное число, превратить в указатель и получить бесплатно итератор — это уже алгоритмическая ивалидность".
в стандартной библиотеке, по которому видно к чему эта ограниченность приводит — к абсолютно ненужному коду в алгоритмах, обслуживающему только узкие специальные случаи, хотя при нормальном дизайне достаточно было бы кода для одного общего случая.
Или, например то, что по двусвязному списку нельзя пройтись в обратном направлении тому откуда мы пришли — это тоже вполне конкретная алгоритмическая инвалидность.
Это не какие-то сферические касты целых чисел в итераторы, а вполне реальные алгоритмические ограничения
DM>Возможность лепить range из произвольных не связанных друг с другом итераторов — слишком опасная граната, слишком много ног можно ей оторвать. Так что это просто такой design choice в пользу корректности.
Да нет тут ничего опасного — в большинстве кода пусть используются структура с парой итераторов, большинство даже не будет знать что там внутри, но в тех местах где есть соответствующая потребность — пусть будет возможность достать эти итераторы, а не подставлять костыли (которые ни разу не безопасны).
С тем же успехом можно вообще запретить все range/view — так как они могут протухать — и ни какой GC тут не спасёт.
DM>Только что на эту тему неплохие слова услышал: DM>http://youtu.be/TS1lpKBMkgg?t=16m28s
You have to write correct code. If you want to prove it correct — wonderful. You cannot make it correct by bizarre syntactic limitations. It's just cannot be done.
In some sense, Turing machine is fundamentaly unsafe — it could loop forever. As long as you give me while statement — I could write an unsafe program.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Или, например то, что по двусвязному списку нельзя пройтись в обратном направлении тому откуда мы пришли — это тоже вполне конкретная алгоритмическая инвалидность.
Если мы откуда-то пришли, значит мы там уже были и могли запомнить это место (.save), зачем туда опять пешком идти?
DM>>Возможность лепить range из произвольных не связанных друг с другом итераторов — слишком опасная граната, слишком много ног можно ей оторвать. Так что это просто такой design choice в пользу корректности.
EP>Да нет тут ничего опасного — в большинстве кода пусть используются структура с парой итераторов, большинство даже не будет знать что там внутри, но в тех местах где есть соответствующая потребность — пусть будет возможность достать эти итераторы, а не подставлять костыли
Достать итераторы — да, дело хорошее. Но я же про другое — про возможность слепить range из несвязанных итераторов. Это обратная операция, и она примерно настолько же ошибкоемкая как прямая работа с указателями: да, если соблюдать осторожность? написать корректный код можно, но шанс наступить на мину очень велик.
EP>С тем же успехом можно вообще запретить все range/view — так как они могут протухать — и ни какой GC тут не спасёт.
В иных языках так и сделали — зафорсили иммутабельность. Корректность еще возрасла. Однако если в каком-то одном месте мы допустили возможность ошибок, это еще не повод плодить такие места дальше. Вопрос того, насколько язык помогает или мешает писать корректный код, он не черно-белый, не 1 или 0, тут есть градации. D тут ближе к корректности, чем С++, некоторые другие языки еще ближе.
EP>Вот правильные слова (~4 минуты, [16m00s, 19m42s) ):
Да, очень правильные — при его дизайне с итераторами действительно нет возможности проверить, что два итератора относятся к одному списку. А подход с range эту задачу успешно решает. И в этом их большое преимущество. Что до следующих его слов, то языки вроде Rust и ATS отлично показывают, что подобные проверки корректности (pointer aliasing) вполне можно проводить в компайл-тайме, просто нужна хорошая система типов и несколько другой язык, не С++. Что до МТ и while, то можно и без полноты по Тьюрингу прекрасно программы писать, которые делают все что нужно и гарантированно не виснут. См. тот же ATS, а также Idris, Agda.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>You have to write correct code. If you want to prove it correct — wonderful. You cannot make it correct by bizarre syntactic limitations. It's just cannot be done. EP>In some sense, Turing machine is fundamentaly unsafe — it could loop forever. As long as you give me while statement — I could write an unsafe program. EP>[/q]
Раз нельзя сделать тотально корректным — значит ничего делать не нужно? Отличная точка зрения.
А вечные циклы теоретически можно и запретить. И так неизбежно и будет, с ростом мощи компиляторов. (Ну, останется 0,001% программ, где будет присутствовать циклы, доказать завершимость которых не удастся, такие программы напишут на Ц )
Здравствуйте, D. Mon, Вы писали:
DM>А, вон меня рядом поправили, можно и in задействовать для своих типов. Вот насчет своих литералов уже не уверен.
Да, эта "претензия" снимается.
DM>Я думаю, при переходе к сторонним библиотекам на С++ почти всегда будет другой интерфейс у контейнеров и придется вообще все переписывать. Насколько просто проходит переход между контейнерами STL, MFC, Qt, WxWidgets? У всех свои, похожие, но тем не менее достаточно разные, чтобы пришлось переписывать код.
Контейнеры Qt как раз поддерживают итераторы, так что комбинировать их с СТЛевскими алгоритмами никаких проблем нет вообще. С WxWidgets не довелось работать, но гугл показывает, что и там есть итераторы, например вот. MFC довольно старая библиотека... там, конечно, никаких итераторов нет.
Ещё буст как пример — отлично комбинируется с СТЛ.
DM>Что до специального синтаксиса, то опыт популярных "высокоуровневых" языков вроде перла/питона/руби/похапе и пр. показал, что они во многом так удобны именно из-за наличия подобных структур данных сразу в языке, без необходимости подключения дополнительных библиотек. Это достаточно базовые вещи, чтобы иметь их в приличном языке сразу.
Тут я немного не понял. Даже вот такая фигня:
int test[] = [1, 2, 3];
test.empty();
без "import std.array;" работать не будет. То есть мы всё равно вынуждены подключать библиотеку.
Насчёт иметь в языке — мне не понятно чем стандартная библиотека хуже. Вот то, что С++ довольно долго не имел хеш таблиц стандартных — это, конечно, не здорово. Но эти времена прошли.