среда, 23 апреля 2008 г.

Third

Сижу и слушаю Portishead, альбом Third, крышу сносит нипадецки, никогда ничего подобного не слышал %)

воскресенье, 20 апреля 2008 г.

Деньги

Я нормальный человек, поэтому хочу ауди А8, пентхауз и двух близняшек блондинок :-D. Но есть одна проблема... работая программистом, я вряд-ли в ближайшие лет 5 заработаю хотя-бы на нормальную квартиру. Все что я могу себе в данный момент позволить, это просто нормальный уровень жизни, как у "нормальных" людей. Я уже давно понял, что работая на "дядю", особо не разбогатеешь, "дядя" заинтересован только в том, что-бы ты от него не ушел к другому "дяде"(я не ненатурал =) и твоя зарплата будет ровно такой, насколько ты полезен(зна). Конечно можно получать и оч. много, работая на работе, но это далеко от того, что можно заработать работая на себя. Еще стоит учитывать качество жизни, дядька, к сорока пяти годам пролезший в начальственное кресло, при этом заработавший геморой от просиживания штанов и простатит от постоянного стресса, но зарабатывающий много, вряд-ли сможет жить качественно, просто фантазии не хватит =)... Одним словом жизнь несправедлива, лучшие годы жизни нужно проводить на работе, 9 часов каждый день... Поэтому я хочу занятся чем нибудь еще, я постепенно теряю интерес к программированию, просто потому, что это становится рутиной. Пока-что мой выбор пал на web-программирование, может это и требует другой квалификации, чем у меня, но тем не менее... Здесь по крайней мере я могу что-то сделать сам(+дизайнер). Главная мысль: В общем, главное что-то делать, так шансы на успех повышаются, сразу конечно ничего не бывает, но если ограничить себя одной только работой(на "дядю"), то вообще ничего особенного в твоей жизни не произойдет... если в результате я смогу просто более свободно распоряжаться своим временем(при таких-же доходах), то это уже хорошо...

пятница, 11 апреля 2008 г.

Кортежи

У меня появилась идея, как сделать распаковку tuple-ов, тех что в библиотеке boost, более удобной. Обычный синтаксис с использованием get методов
int value = boost::tuples::get<0>(mytuple);
выглядит страшновато, когда нужно часть одного кортежа скопировать в другой, короче разбить один большой кортеж, на несколько маленьких... в общем хочу я странного такого:
using namespace boost::tuples;

tuple<int, std::string> tuple1(44, "aaaaa");
tuple<double, int> tuple2(55.33f, 111);
tuple<int> tuple3(88);
tuple<int, std::string, double, int, int> tuple4(1, "'2'", 3.14159f, 4, 5);

(tuple1, tuple2, tuple3)= tuple4;

int local = 0;

(tuple1, tuple2, tie(local)) = tuple4;
результат должен быть такой, до: tuple4 = (1 '2' 3.14159 4 5) tuple1 = (44 aaaaa) tuple2 = (55.33 111) tuple3 = (88) и после: tuple4 = (1 '2' 3.14159 4 5) tuple1 = (1 '2') tuple2 = (3.14159 4) tuple3 = (5) local = 5 причем это должно работать в обе стороны, так: (tuple1, tuple2, tie(local)) = tuple4; и так: tuple4 = (tuple1, tuple2, tie(local)); это уже похоже на pattern matching в функциональных языках в общем сразу приведу результат =)
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/add_reference.hpp>


namespace boost { namespace tuples {


  template < class T , class H>
  struct split_;

  template <
      class head, class tail,
      class ex_head, class ex_tail
  >
  struct split_< cons<head, tail>, cons<ex_head, ex_tail> >
  {
      typedef cons<
          head,
          typename split_<
              tail,
              cons<ex_head, ex_tail>
          >::type
      > type;
  };

  template <
      class head,
      class ex_head, class ex_tail
  >
  struct split_< cons<head, null_type>, cons<ex_head, ex_tail> >
  {
      typedef boost::tuples::cons<
          head,
          cons<ex_head, ex_tail>
      > type;
  };




  template <class T>
  struct make_cons_ref_;

  template <class head, class tail>
  struct make_cons_ref_ < cons<head,tail> >
  {
      typedef cons<
          typename add_reference<head>::type,
          typename make_cons_ref_ <tail>::type
      > type;
  };

  template <class head>
  struct make_cons_ref_ < cons<head, null_type > >
  {
      typedef cons<
          typename add_reference<head>::type,
          null_type
      > type;
  };





  template <
      class lhead, class ltail,
      class rhead, class rtail
  >
  typename make_cons_ref_<
      typename split_<
          cons<lhead, ltail>, cons<rhead, rtail>
      >::type
  >::type initialize_tie_ ( cons<lhead, ltail> &tuple_1st, cons<rhead, rtail> &tuple_2nd )
  {
      typedef cons<lhead, ltail>                    _1st;
      typedef cons<rhead, rtail>                    _2nd;
      typedef typename make_cons_ref_<
          typename split_<_1st, _2nd>::type
      >::type                                        _3rd;
      typedef typename make_cons_ref_<
          typename split_<ltail, _2nd>::type
      >::type                                        next_t;

      next_t next = initialize_tie_ (tuple_1st.tail, tuple_2nd);
      _3rd result(tuple_1st.head, next );
      return result;
  }


  template <
      class lhead,
      class rhead, class rtail
  >
  typename make_cons_ref_ <
          cons<lhead,    cons<rhead, rtail> >
  >::type initialize_tie_ ( cons<lhead, null_type> &tuple_1st, cons<rhead, rtail> &tuple_2nd )
  {
      typedef cons<lhead, null_type>
                                                  _1st;
      typedef cons<rhead, rtail>    _2nd;

      typedef typename make_cons_ref_ <
              cons<lhead,
              cons<rhead, rtail>
          >
      >::type                                        _3rd;

      typedef typename make_cons_ref_<
          cons<rhead, rtail>
      >::type                                        next_t;

      next_t next = initialize_tie_ (tuple_2nd);
      _3rd result(tuple_1st.head, next);
      return result;
  }

  template <
      class head, class tail
  >
  typename make_cons_ref_ <
      cons<head, tail>
  >::type initialize_tie_ ( cons<head, tail> &tuple_2nd)
  {
      typedef cons<head, tail>                            _2nd;
      typedef typename make_cons_ref_<_2nd>::type            _3rd;
      typedef typename make_cons_ref_<tail>::type            next_t;

      next_t next = initialize_tie_ ( tuple_2nd.tail );
      _3rd result( tuple_2nd.head, next );
      return result;
  }

  template <
      class head
  >
  typename make_cons_ref_ <
          cons<head, null_type>
  >::type

      initialize_tie_ (  
          cons<head, null_type> &tuple_2nd)
      {
          typedef cons<head, null_type>                    _2nd;
          typedef typename make_cons_ref_<_2nd>::type        _3rd;

          return _3rd( tuple_2nd.head, null_type() );
      }




  //template arg
  template <
      class lhead, class ltail,
      class rhead, class rtail
  >
  //return value
  typename make_cons_ref_ <
      typename split_<
          cons<lhead, ltail>,    cons<rhead, rtail>
      >::type
  >::type
  operator , ( cons<lhead, ltail> &tuple_1st, cons<rhead, rtail> &tuple_2nd )
  {
      return initialize_tie_(tuple_1st, tuple_2nd);
  }

}; };

#include <iostream>
#include <conio.h>
#include <boost/tuple/tuple_io.hpp>

using namespace boost::tuples;


int main()
{
  tuple<int, std::string> tuple1(44, "aaaaa");
  tuple<double, int> tuple2(55.33f, 111);
  tuple<int> tuple3(88);
  tuple<int, std::string, double, int, int> tuple4(1, "'2'", 3.14159f, 4, 5);

  std::cout << "tuple4 = " << tuple4 << std::endl ;
  std::cout << "tuple1 = " << tuple1 << std::endl;
  std::cout << "tuple2 = " << tuple2 << std::endl;
  std::cout << "tuple3 = " << tuple3 << std::endl;

  std::cout << "(tuple1, tuple2, tuple3) = tuple4" << std::endl;

  (tuple1, tuple2, tuple3)= tuple4;

  std::cout << "tuple4 = " << tuple4 << std::endl ;
  std::cout << "tuple1 = " << tuple1 << std::endl;
  std::cout << "tuple2 = " << tuple2 << std::endl;
  std::cout << "tuple3 = " << tuple3 << std::endl;

  std::cout << "(tuple1, tuple2, tie(local)) = tuple4" << std::endl;
  int local = 0;  
  (tuple1, tuple2, tie(local)) = tuple4;

  std::cout << "local = " << local << std::endl;


  _getch();
  return 0;
}
этому коду явно не хватает комментариев)) в двух словах принцип здесь такой кортеж представляет из себя по сути экземпляр списка типов, вот такого вот
template<class H, class T>
struct cons
{
  H head;
  T tail;
};
(реально конечно не так, пример сильно утрирован) head - хранимое значение, tail - может быть либо null_type, либо другой cons. В общем так можно получить последовательность любой длины, вот такая вот последовательность:
cons<int, cons<long, cons<std::string, null_type> > >
соответствует кортежу tuple: int, long, string. boost::tuple так и реализован, с той лишь разницей, что tuple наследует от списка типов, а линеаризация достигается с помощью параметров шаблона, если заглянуть в исходники, то можно увидеть там:
template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>

class tuple :
  public detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
................
typedef cons<T0,
               typename map_tuple_to_cons<T1, T2, T3, T4, T5,
                                          T6, T7, T8, T9, null_type>::type
              > type;
в общем моя идея состоит в том, что-бы перегрузить оператор ,(comma) для кортежей так, что-бы он возвращал кортеж ссылок на элементы своих аргуметов Для этого сначала нужно вычислить тип результата. Для этого сначала кортежи объединяются метафункцией split_
typedef typename split_<
cons<int, null_type>,
cons<long, cons<double, null_type> >
>::type result;
где result будет равно
cons<int, cons<long, cons<double, null_type> > >
Метафункция make_cons_ref_ - делает параметры ссылками, то-есть после ее применения у нас будет последовательность вида:
cons<int&, cons<long&, cons<double&, null_type> > >
Теперь остается ее проинициализировать. Здесь самая большая сложность со ссылками, так как они не имеют конструктора по умолчанию и должны инициализироваться во время создания. Для этого предназначена функция initialize_tie_. Структура cons имеет конструктор cons(H head, T tail), соответственно функция initialize_tie_ вызывается рекурсивно и всегда возвращает tail. С этим кодом есть одна проблема. Он соответствует стандарту только для случая tuple3 = tuple2, tuple1; то есть для 2х кортежей, так как временный объект не может использоваться как rvalue при инициализации не константной ссылки. Но у компилятора Visual Studio на этот счет свое мнение =), там есть расширение, которое позволяет это делать, в общем в студии это отлично работает. Производительность - такая-же как и при использовании get функций, компилятор отлично справляется с оптимизацией, я проверял =) Может быть мне удастся сделать это более переносимым, посмотрим...

среда, 9 апреля 2008 г.

GoogleApp

Недавно начал работать сервис Google App. Все информационные издания делают основной акцент на том, что теперь разработчикам доступна технология BigTable. Но помимо этого Google App это первый бесплатный python хостинг, к тому-же App Engine включает в себя фреймверк Django. Еще будет очень тесная интеграция с другими сервисами google, например можно сделать авторизацию через аккаунт google для пользователей сайта. В общем все это очень здорово... Когда-нибудь я разгребу текущие дела и сделаю какое-нибудь веб-приожение, вот увидите =)

понедельник, 7 апреля 2008 г.

задумал недоброе =)

пятница, 4 апреля 2008 г.

Сегодня выяснилось что C# не содержит чего-либо похожего на boost::bind (о ужас, даже на bind1st bind2nd). Врапперы для функций нужно писать ручками. Нашел статью в Dr. Dobb's на эту тему, в общем совсем он примитивный этот C#, бейсик со скобками =) Update... вот небольшой пример на С++, здесь функция fn - принимающая один параметр типа int, используется как callback - без аргументов, при вызове callback в fn всегда будет передаваться 1.
void fn (int value) {...}

boost::function<void ()> delegate_type;

delegate_type callback = boost::bind( &fn, 1 );
    
callback();//<---- реально происходит вызов fn(1);
с делегатами в C# такое сделать нельзя :)