Pull to refresh
20
0

Пользователь

Send message
Если я правильно Вас понял, то структуры, подобные двусвязным связным спискам и прочим циклическим графам реализовать в рамках концепции владения не получится. Но как быть если такая структура нужна?
А концепция владения решает проблему замкнутых циклов? Мне казалось, что это её слабое место как раз. Разве можно реализовать в рамках концепции владения, без привлечения подсчёта ссылок какой-нибудь двусвязный список?
По моему мнению шаблоны в плюсах плохи:
1. Временем компиляции
2. Негибкостью (хороши только если одну функцию надо написать для нескольких типов, но как только начинают решаться проблемы из реального мира, приходится изобретать монструозную конструкцию из шаблонов, а то и вообще откатываться к макросам из C)
3. Сообщениями об ошибках (без парсера в них можно утонуть)

В Nim метапрограммирование на порядок лучше плюсового реализовано.
Итак, у нас есть функции, процедуры, дженерики, мультиметоды, шаблоны и макросы. Когда лучше использовать шаблон, а когда процедуру? Шаблон или дженерик? Функция или процедура? Так, а макросы?


Функции, процедуры, дженерики, мультиметоды, шаблоны, макросы.
Именно в таком порядке по приоритету. Если первого пункта недостаточно для реализации необходимого функционала, переходим к следующему и так далее. К сожалению, не могу вспомнить где в документации видел приоритетность, но она была очень похожа на эту. Разве что мультиметодов и функций там не было. Мультиметоды я бы вообще исключил, поскольку они почти всё время были сломаны.

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

Говоря «модули» я имел в виду отдельные проекты в терминах CMake. Например проблема в том, что я не могу собрать отдельно проект A, не собирая B и не используя CMakeLists.txt из корня.
А не поделитесь ли опытом, как эти модули потом находить друг относительно друга? Например есть три модуля A, B и С, при том A и B зависят от C: им нужны его инклюды и его нужно слинковать с ними. Вопрос: как организовать структуру проекта без уродливых "../" или модуля D который в правильном порядке выставляет add_subdirectory? При этом A, B и C отдельными проектами не являются (от них зависят другие модули которые потом в сумме могут использоваться в нескольких полноценных проектах), но было бы здорово собирать их в статические библиотеки для тестирования например.
В конце концов, языки программирования пишутся для программистов, а не для парсера.

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

Надеюсь, это был сарказм. Разве нагромождение символов пунктуации читабельнее обычных английских слов с редкими вкраплениями пунктуации?
Мне кажется, большая часть перечисленного в статье, уже есть в Nim. Вот несколько примеров:

Макросы поддерживают работу с синтаксическим деревом.
import macros
macro hello(x: untyped): untyped =
  result = x
  # Сакральный смысл индексов ниже:
  # Первый индекс - утверждение (у нас оно одно)
  # Второй индекс - часть утверждения (для нашего случая под номером 1 будет первый аргумент
  #      0(1, 2...)
  # 0: echo("goodbye world")
  # 1: ...
  result[0][1] = newStrLitNode("hello world")
hello:
  echo("goodbye world") # Превратится в echo "hello world"

Кортежи без предварительного объявления
proc x(): (int, int) = (4, 2)

Лямбды:
let f = (x:int)=>x*x
echo(f(2)) # 4


Удобная система сборки: nimble

Не хватает разве что ленивых вычислений из коробки (но можно сделать за счёт макросов) и хорошей интеграции с IDE, но это дело наживное. Ах, да, ещё подсветки синтаксиса хабрадвижком, чтобы не пользоваться питоновской подсветкой.
Спасибо, теперь понятно. До этого мне показалось, что Вы эмулируете полноценный объект С++ с помощью структуры AIModule.

Отличная статья! Я бы даже сказал: о наболевшем, а именно о мучениях с ABI C++.


Однако, я не смог понять, как Вам удалось справиться с соглашениями о вызовах. Если речь идёт о 32-битном коде, то просто объявления статических функций и заполнения ими таблицы виртуальных методов недостаточно, поскольку виртуальные методы используют соглашение о вызовах thiscall, тогда как функции обычно используют stdcall.


С 64-битным кодом всё несколько проще. Насколько я понял, там спасает ключ компилятора -mabi=ms. Тем не менее, мне очень интересно, что за магия происходит в wrap_handler и как Rust понимает, что нужно использовать соглашения о вызовах MSVC вместо System V без -mabi=ms.

Хорошая статья, однако, у меня есть пару идей, как можно было бы сделать её ещё лучше.

На мой взгляд, первые пункты про запись образа диска и установку CentOS можно было бы и опустить. Думаю, что человек, поставивший себе задачу поднять свой репозиторий, самостоятельно сможет справиться с установкой системы.

Инструкция в виде готового рецепта неплоха, но всегда лучше, когда для каждого действия объяснена причина, последствия, а также случаи, когда можно этим действием пренебречь.

Также, для улучшения восприятия, в примерах хотелось бы видеть большую сфокусированность именно на процессе сборки, а не на особенностях конфигурации tmux'а. Но это уже так, придирки.

Не уверен, что подстановка 0 вместо именованной константы в общем случае хорошая идея. Думаю, что было бы правильнее изучить аналогичные вызовы irequest_irq в других драйверах чтобы найти аналогичную по смыслу именованную константу для нового ядра (если она существует).

Я выкладывал ссылку на github проекта на reddit и один раз это делали за меня. Это, конечно, не профильные сообщества, но хоть какие-то попытки донести информацию. Если у кого-нибудь возникнет желание сделать перевод статьи и опубликовать его (со ссылкой на оригинал, естественно) — я не буду против. Мой английский пока ещё слишком беден для такого, как мне кажется.


К тому же, для реализации библиотеки была проведена обратная разработка, что прямо запрещено соглашением подписчика Steam. Не думаю, что они будут в восторге. Похожая разработка — SteamBridge (которая упоминается в статье) благополучно игнорировалась службой поддержки Valve. Они даже отказывались ответить на вопрос о легальности подобного подхода. Насколько я понял из ответов на запросы в багтрекере Steam для Linux, политика Valve в отношении Wine весьма однозначна: они не слишком стремятся поддерживать запуск игр для Windows из Steam в Linux в таком виде. Тем более, что о возможности собирать steam_api.dll.so для Wine им рассказывали в комментариях (а при наличии исходных кодов им это сделать намного проще).

Безусловно. Правда, если бы проблемы совсем не существовало, то не было бы таких запросов.
Вот и я о том же. Соглашусь, что имело место некоторое преувеличение, но в любом случае установка нескольких копий одной программы не очень удобна. Особенно если есть привычка устанавливать каждую игру в отдельный префикс, чтобы исключить взаимное влияние.
А если у Вас больше одного префикса?
Ну надо же, я как раз недавно писал библиотеку для сериализации/десериализации с похожим принципом действия для Nim. Если кому интересно, вот она + краткий мануал.
Пусть обилием поддерживаемых форматов она не может похвастаться, но принцип действия, если я правильно всё понял, тот же. Структура, которую нужно сериализовать передается на вход макросу, а он генерирует соответствующие функции для сериализации/десериализации.
Большое спасибо за Вашу статью. После прочтения её и статьи от Commandos, я стал понимать, почему мой лучший результат был таким не радужным (удалось войти в первую сотню, и то не надолго, в основном на 100-200 местах болтался).

Моя стратегия была намного проще.
Ключевым местом в механизме принятия решений была цепочка правил, которые срабатывали в зависимости от ситуации вокруг или передавали управление дальше по цепочке.
Первые несколько версий вообще не умели в поиск пути, а обход препятствий осуществлялся по факту застревания. Волшебник просто ходил за союзными миньонами, пока не натыкался на противников и не срабатывало более приоритетное правило.
После был прикручен обход препятствий по касательной. Т. е. если луч, построенный от центра волшебника до цели пересекал окружность с центром в центре препятствия и радиусом равном сумме радиусов волшебника и препятствия, то результирующий угол поворота волшебника отклонялся минимальную величину, при которой траектория волшебника шла по касательной к препятствию.
Через несколько игр я обнаружил, что подбор бонусов дает ощутимое преимущество, после чего пришлось реализовывать полноценный поиск пути по путевым точкам в дополнение к обходу препятствий. За основу был взят алгоритм Ли, с добавлением к нему возможности учет веса вершин и ребер графа (вес ребер зависел от длины ребра и наличия на ребре врагов, а вершины только от наличия врагов). Граф состоял всего из 5 точек: углы карты и центр. Для реализации плавного движения, в окрестностях точек результирующее направление движения получалось сложением углов до ближайшей точки и до следующей.

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

Не уверен, что кому-то интересны подробности реализации работы моей стратегии, потому, если кому интересно, можете поковырять код по ссылке. За боль в области глаз при взляде на этот код, ответственности не несу. Вы были предупреждены.
Использую awesome на своей машине и xfce4 на домашней.
Awesome выбран из-за его минимализма и сумасшедшей расширяемости.
В xfce4 привлекает сочетание все того же минимализма (пусть и несколько уступающего awesome) и привычного большинству пользователей окружения.

Information

Rating
Does not participate
Registered
Activity