Обновить
15
Воеводин Дмитрий@DamonV79

Программист

1
Подписчики
Отправить сообщение
Писать на плюсах также как на шарпе или яве не выйдет.

Так как на Шарпах или Жабе — не выйдет. Можно изобрести свой путь. Вообще, монада (в самом первом приближении) — функция принимающая 2 ф-ции и вызывающая их последовательно. А уж как ее оформить, дело десятое. Хоть так:
or_(isMultipleOf2, isMultipleOf3)

Хоть, завернув
isMultipleOf2
в класс обертку и реализовав у нее метод
or_(...)
и тогда писать так:
isMultipleOf2Wrapper.or_(isMultipleOf3)

Как это было, так и останется монадой. Во втором случае, аллокаций просто больше будет.
Вообще, суть моего посыла была в том, что прикольно наблюдать, как паттерны из ФП изобретаются (проникают) и в других языках, не более того.
Хех, забавно наблюдать, как монады расползаются из функциональщины и начинают просачиваться везде!
image
Собственно, wiki утверждает, что монада — «это абстракция линейной цепочки связанных вычислений. Монады позволяют организовывать последовательные вычисления.». Что мы здесь и наблюдаем:
or_(isMultipleOf2, isMultipleOf3))

Шашкель и Шкалка для программистов на Плюсах заходят плохо (синтаксис категорически разный), может эта статья более понятно объяснит использование монад в языках, не являющихся функциональными…
Всю функциональность по применению Proguard обеспечивает android-sdk-plugin. Включается в build.sbt:
    proguardScala in Android := true

Т.ч. стоит посмотреть на исходники плагина.
Не так уж и много. У меня с akka.actor.FSM и Slick демка демонстрирующая работоспособность уложилась в 2.4 МБайта (*.apk). Впрочем, все относительно.
Единственный недостаток всего выше описанного в том, что используется достаточно старая версия akka'и, а последняя, увы, требует 8-й java'ы.

Буквально на днях возник вопрос портирования приложения, использующего свежую akka'у на андроид. В принципе справился. Постараюсь черкануть статейку о процессе заведения свежей akka'и.
М-м-м… А смысл? В том варианте весьма активно используются std::string и std::map, а значит, нужно управлять памятью. Нужен менеджер памяти, причем, многопоточный, т.к. использовалась операционка с вытесняющей многозадачностью. Я же обошелся только глобальной памятью и стеком. Причем в глобальной памяти у меня лежала только фабрика, очереди потоков и ивенты, дергаемые из прерываний.

Можно конечно использовать что-то вроде uSTL, например. Использовать STL, ради STL'я? Тем более, что я вполне обошелся своими силами.
Не, не боюсь :-). Чтож, надо будет попробовать. Спасибо за ссылку.
Давно слышал про Радар, но все руки не доходят попробовать. Как он в сравнении с IDA'ой? В смысле удобства реверс-инжиниринга: восстановления перекрестных ссылок, создания структур, восстановления стековых переменных и прочего? Понятно, что дизассемблировать можно во многих IDE от производителя, но сие не очень-то и удобно.
Хотелось бы уйти от IDA'ы в сторону чего-нибудь опенсорсного. Насколько адекватно Радар заменит IDA'у?
Есть такое дело. Почему это не попытаться исправить? Все в наших силах.
Да не, 6.6 после купили. Только процесс покупки затянулся на пару-тройку месяцев. Быстрее оказалось написать свое. Собственно, по этому и не стал дорабатывать модуль до конца (поддержка разных семейств, автообзывание SFR и прочее).
Да и здесь, скорее подходом к написанию анализатора поделиться хотел. Впрочем, может кому и пригодиться. Да и вообще, статей по написанию модулей для IDA в рунете не густо.
Увы, не могу сказать — секретно.
А зачем Вам, если не секрет? Может смогу ответить по другому.
На контроллере нет. Я уже уволился от-туда, где всем этим занимался. В принципе, собрать, дизассемблировать и проанализировать простенькое приложение можно. Что бы не терять время, скажите, Вас устроит разбор полетов на архитектуре x86_64 или принципиален контроллер (например, arm)?
Никаких.

Пример.
  template < typename D, typename H >
  bool operator()( uint32_t hash, D &deserializer, H &handler ) {
    if ( Head::HASH == hash ) {
      bool ret = true;

       // Здесь создаем объект и заполняем его

      return ret;
    } else
      return Base_t::operator()( hash, deserializer, handler );
  }

Здесь четко видна рекурсия, но компилятор преобразует этот кусок к виду:

400997:	81 f9 53 c1 b0 53    	cmp    $0x53b0c153,%ecx
40099d:	0f 84 84 00 00 00    	je     400a27 <main+0x247>
4009a3:	81 f9 5f 14 b3 b1    	cmp    $0xb1b3145f,%ecx
4009a9:	74 15                	je     4009c0 <main+0x1e0>

А по поводу рекурсии и переполнения стека я перестал беспокоится после курса по скалке на Coursera'е. Я там тоже стек переполнял порой (и это в функциональном языке!). Как оказалось, не всякую рекурсию можно оптимизировать. Тем не менее каких-то страшилок нам не рассказывали, так слегка затронули вопрос оптимизации хвостовой рекурсии. Я это к тому, что народ, походу, на эту тему особенно не парится. Но помнить об этом, конечно, надо.

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

Впрочем, если у кого-то будет желание провести более развернутые тесты был бы рад посмотреть результат. Я, всеж, лицо заинтересованное. Да и с даблами (первое, что под руку подвернулось, а потом переписывать бенчмарки не лень стало) мне могло повезти.
Использовал так
#include <jsmincpp/deserialize/Deserializer.h>

#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <stdint.h>
#include <iostream>

using namespace std;
using namespace rapidjson;

struct Data {
  double First;
  double Second;

  Data( )
      :
          First( 0.0 ),
          Second( 0.0 ) {
  }

  void Deserialize( Document &d ) {
    First = d [ "First" ].GetDouble( );
    Second = d [ "Second" ].GetDouble( );
  }
};

int main( ) {
  cout << "It's work!" << endl;

  double realResult = 0.0;
  double testResult = 0.0;

  char json [ ] =
      "{\"First\":X0.01,\"Second\":X0.01}";

  for ( uint32_t i = 0; i < 1000000; ++i ) {
    uint8_t t = i % 3;

    json [ 9 ] = '2' + t;
    json [ 24 ] = '3' + t;

    Document d;
    d.Parse( json );

    Data data;
    data.Deserialize( d );

    realResult += 20.01 + 30.01 + t * 20;
    testResult += data.First + data.Second;
  }
  cout
      << "RealResult = " << realResult << ", TestResult = " << testResult
      << endl;

  return 0;
}

Если есть идеи, готов проверить.
Ответил выше.
С DOM-style API получились следующие результаты:
Наилучшее время исполнения, с — 0.932,
Отношение к лидеру теста — 4.255708,
Среднее время исполнения, с — 0.95836,
Отношение к лидеру теста — 4.306849.

Я не думаю что SAX-style API что-то изменит, т.к. сообщение я парсю (паршу?) полностью.

В случае SAX-style API судя по example/messagereader/messagereader.cpp там все мрачно в плане юзабельности. В том смысле, что получаешь просто огрызки строк, следовательно, приводить их к значениям и проверять соответствие типам придется «в ручную».
В моем случае это делается автоматом.

Тем неменее у него есть преимущество — полная поддержка юникода. За свою библиотечку я пока не поручусь. Допилить возможно, но пока небыло необходимости.
Я его и использовал (QJsonDocument).
Потоком (если я правильно понял, что Вы имели в виду) десериализовать не получиться из-за текущей реализации парсера. Я глубоко не копал, но складывается впечатление, что для этого придется переписывать почти всю реализацию.
М-да… Забыл указать местоположение самой библиотеки. Здесь она.
Я вообще сериализацию не сравнивал. Не интересно, ибо сериализатор пишется тривиально. Так что сравнение было только десериализаторов.

Информация

В рейтинге
7 102-й
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность