Обновить
38

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

0,5
Рейтинг
11
Подписчики
Отправить сообщение

Сначала шло вполне приемлемое изложение теории множеств, но потом внезапно

Предположим, что гравитация нарушает полноту пространственно-временного континуума.

и на это месте я сломался. Какая ещё "полнота"? Перед этим вы под полнотой понимали свойства множеств, а тут что, из пространства выпадают точки? Переход от математики к физике получился резковат.

Первая часть статьи содержала мало нового: загрузить и исполнить байткод несложно и на .NET, и на JVM. А вот загрузка и исполнение нативного когда - это интересно: там же релокации, и вызов функций из DLL. Посмотрел генераторы шеллкода, упомянутые в статье, это мощные инструменты, очень интересные, спасибо автору, что познакомил.

Нууу противоречиво. Блокирующие вызовы с одной стороны блокируют поток выполнения на неопределённое время, с другой стороны - упрощают структуру кода, он остаётся линейным. С другой стороны, тому потоку, который заблокирован, точно есть что делать, если бы он не был заблокирован? И те же самые вопросы возникают, если брать оконные приложения. Автор с одной стороны ожидает, что когда он кликает, то приложение прореагирует, с другой стороны - не хочет видеть курсор ожидания. Ну дык курсор сменился на ожидание - это приложение прореагировало. Не очень хорошо, что заблокировался UI-поток, в нём происходит отрисовка. Но интерфейс приложения всё равно придётся заблокировать, каким-нибудь модальным диалогом, разве что добавив кнопку "Cancel".

Ну неплохо. Я вброшу пару советов:

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

  2. В коде совместно (вперемешку) используются макросы .IF и инструкции cmp, выглядит странно. Вы в начале статьи задаётесь вопросом: зачем писать на ассемблере, и даёте на него риторические ответы. Мой ответ другой: иногда нужно хакнуть или отреверсить программу, и для этого приходится читать дизассемблированный код, и чтобы его понимать, нужно натренировать глаз читать ассемблер. Для такой тренировки лучше не пользоваться макросами.

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

  4. Процедура CalculateTileRect сделана не очень. Я бы из CalculateTileRectPos убрал бы второй параметр additionalTileSize. Тогда из CalculateTileRect можно будет сделать только два вызова CalculateTileRect, а не четыре, как сейчас, и добавлять вот этот additionalTileSize только для нижней и правой граней.

я думаю, что имелось ввиду наоборот: удалённый отлаживаемый начинает контролировать процесс-отладчик

Извиняюсь за тупой вопрос, но вот в декомпилированном коде непосредственно перед вызовом SetEnvironmentVariableA есть цикл, в котором в строке ищется "=", чтобы разбить строку на имя переменной окружения и значение. А если этого "=" не будет, то он так и будет сканировать память, пока не повезёт?

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

описавший дифракцию и её частный случай — интерференцию

Наоборот, дифракция - частный случай интерференции

Когда прочитал примерно треть статьи, почувствовал, что меня грузят хреновой тучей информации, заправленной бурлящими эмоциями (обида, "справедливое" возмущение, ...). Остальное прокрутил мышкой. Мне такое читать не хочется, новой информации я не верю, что почерпну. Независимо от того, что написано в статье, я не верю, что "Эльбрус" станет самоокупаемым коммерчески успешным продуктом, тупо потому что стоит дохрена при так себе производительности. Сомневаюсь, что в статье приведены обратные факты.

Зашёл почитать про лексеры и парсеры, и, хоть я и не Scala-разработчик, имею много замечаний по прочитанному коду.

Первое - в BinaryOperation/UnaryFunction не надо делать equals(), который принимает String. Гораздо лучше будет для хранения операций использовать не List, а Map (она же есть в Scala, я верю в это), тем более что вы потом по содержимому List-а делаете операции map()/filter().

Во-вторых, и бинарные операции, и унарные, и константы имеют очень много общего: они имеют обозначение (ваше getDesignation), и могут быть вычислены (ваше calc()/getValue), поэтому вместо того, чтобы объявлять эти методы в трейтах по-отдельности, вполне подошёл бы родительский трейт (я верю, что такое есть в Scala). При этом сильно убавится кода, который делает одно и то же для разных трейтов (например, токенизация).

В-третьих, нафига BinaryOperactionFabric? Вместо того, чтобы императивно клеить символ к функции и кешировать, проще в коде декларативно наобъявлять статических экземпляров трейта, а "фабрика" по-английски будет "Factory".

Тут я, наконец, добрался до токенизации. Ну, это где символы обрамляются сепараторами через string.replace(), и потом всё нарезается через string.split(). Мощно. Я долго искал себе оправдание, почему я не додумался до такого? Потом придумал искусственный случай, когда это сломается (если обозначение операции является подстрокой обозначения другой операции), и успокоился.

А где же парсер? А его тут нет. Тут сразу считалка, которая выполняет операции в том порядке, в котором они объявлены. Прикольно, если бы токенизатор понимал пробел как разделитель, то считалка понимала бы сразу и префиксную нотацию, и инфиксную, и постфиксную! (И любую кашу из них).

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

Я вообще не хотел насмехаться ни над кодом, ни над автором (хотя скорее всего звучит именно так), я хотел мозг свой размять.

Жду от автора статью "Почему Java должна быть единственным языком программирования в образовательном процессе".

Чёрт, целая статья, и ни слова про LD_LIBRARY_PATH.

Рисовать спрайты на клетчатой бумаге - это мы делали, прямо в школьных тетрадках. А вот рисовать спрайты на миллиметровке - это интересно, до такого мы не додумывались. Может, потому что миллиметровка была дороже.

Это в полной мере относится к Renegade 3, заставка красивая, игра - и некрасивая, и играется плохо. И первый уровень "prehistoric" ещё самый визуально чистый, следующие уровни, средневековый и футуристичный - это просто каша из пикселей

Я сходил в github-репозиторий автора. Я нифига не UI-разработчик, но что за бардак? Какие-то lock-файлы, какие-то конфиги среды разработки, gradle wrapper целым jar-ником лежит. Я догадываюсь, что автор тупо закоммитил всё, что у него было, но так не надо

Для этой игры тоже можно сделать подобное. Поскольку пишутся байты не последовательно, а читаются - последовательно, то стек можно использовать для чтения. Пока я вижу, что для отрисовки монстров используется много копипастного кода, для каждого монстра свои процедуры. Есть надежда это оптимизировать и выиграть место для отрисовки всего экрана, оставаясь в 48 кб

Эмуляция - она на то и эмуляция, что игра не знает, что еë эмулируют на повышенной скорости. Но то, что вы хотите, возможно, хотя для этого игру надо не ускорить, а замедлить. Механика игры работает так: между каждым кадром координаты кораблей изменяются в соответствии с их скоростями. Если разделить эти приращения координат на 2, то при вдвое увеличенной скорости эмуляции вы получите ту же динамику боя. Но придётся иметь несколько версий игры, под разные множители

Прикольно. Байт-код, похоже, фиксированного размера, чтобы проще было для переходов находить инструкцию по индексу. Виртуальная машина регистровая, и приходится указывать регистр-получатель результата. Я так понял, что идентификатор курсора - это r[0], используется, когда нужно значения колонки прочитать. Столбцы идентифицируются индексами, значит компилятор зачитывает схему таблицы для кодогенерации. Оптимизация так себе: столбец "favorite_color" зачитывается из курсора дважды, второй раз только для того, чтобы ResultsRow мог сформировать результат из последовательного набора регистров. Интересно, почему не скопировать регистр-регистр в этом случае.

Н.Носов "Фантазёры"

Я не знаю питон совсем, и верю автору, что R лучше для обработки таблиц. Но в восхвалении R автора периодически заносит.

Что представляет собой data.frame в классическом Computer Science? Это список указателей на массивы. Массивы — это колонки. Так было на ассемблере, так было на С/С++, Паскале и т.д

какой "классический Computer Science" имеет тут в виду автор - я не знаю, думаю, просто выпендривается. С и Паскаль содержат такие типы данных как структуры/записи, и таблицы реализуются массивом структур. Это одинаково компактно по памяти по сравнению с колоночным хранением.

Механизм NSE (Non-Standard Evaluation) вкупе с пайпами позволяет упомянуть имя датафрейма только в первой строчке и больше его не использовать

NSE - жуткая штука, работает магически, отлаживать её страшно. Но я соглашусь с тем, что компактный язык запросов в функциональном языке можно сделать только макросами или специальным парсером.

Информация

В рейтинге
2 379-й
Зарегистрирован
Активность