Mar 6 2010

Code Monkey like Fritos

blaxter

Until now I've never heard about this song, about a code monkey, funny and nice at the same time. The same songwriter, Jonathan Coulton, has a lot more of similar (geek) songs. Awesome.

Code Monkey get up get coffee
Code Monkey go to job
Code Monkey have boring meeting with boring manager Rob
Rob say Code Monkey very diligent
but his output stink
his code not functional or elegant
what do Code Monkey think
Code Monkey think maybe manager want to write goddamn login page himself
Code Monkey not say it out loud
Code Monkey not crazy just proud

Code Monkey like Fritos
Code Monkey like Tab and Mountain Dew
Code Monkey very simple man
with big warm fuzzy secret heart
Code Monkey like you
Code Monkey like you

Code Monkey hang around at front desk
tell you sweater look nice
Code Monkey offer buy you soda
bring you cup bring you ice
you say no thank you for the soda cause
soda make you fat
anyway you busy with the telephone
no time for chat

Code Monkey have long walk back to cubicle
he sit down pretend to work
Code Monkey not thinking so straight
Code Monkey not feeling so great

Code Monkey like Fritos
Code Monkey like Tab and Mountain Dew
Code Monkey very simple man
with big warm fuzzy secret heart
Code Monkey like you
Code Monkey like you a lot

Code Monkey have every reason
to get out this place
Code Monkey just keep on working
to see your soft pretty face
Much rather wake up eat a coffee cake
Take bath, take nap
This job fulfilling in creative way
such a load of crap
Code Monkey think someday he have everything even pretty girl like you
Code Monkey just waiting for now
Code Monkey say someday, somehow

Code Monkey like Fritos
Code Monkey like Tab and Mountain Dew
Code Monkey very simple man
with big warm fuzzy secret heart
Code Monkey like you
Code Monkey like you


Dic 20 2009

boost::asio, synchronous read with timeout

blaxter

The boost::asio (which means asynchronous input/output) library, is quite powerful library for asynchronous i/o, but it could be a bit difficult at first to figure out how to do a normal synchronous read. So, as a reminder for my future-me, and for you, this snippet it'll be very useful to accomplish that. Probably there will be another ways for doing that, but this is how I managed to do it:

using namespace boost::asio;
using namespace boost::system;
using boost::optional;
 
ip::tcp::socket _socket; // it could be another kind of socket, not only ip::tcp
 
/**
 * Dumb function to be used as handler argument and save the error_code
 * into a pointer
 *
 * e.g.: boost::bind( &set_result, some_pointer, _1 )
 */
void set_result( optional<error_code>* a, error_code b )
{
  a->reset( b );
}
 
#define TIMEOUT 60
/**
 * it uses _socket
 * if timeout happends throw a system_error exception
 */
template<typename MutableBufferSequence>
optional<error_code> read_with_timeout(
    const MutableBufferSequence& buffer
  ) throw( system_error )
{
  optional<error_code> timer_result;
  optional<error_code> read_result;
 
  deadline_timer timer( _socket.io_service() );
 
  timer.expires_from_now( seconds(TIMEOUT) );
  timer.async_wait( boost::bind(&set_result, &timer_result, _1) );
 
  boost::asio::async_read(
      _socket,
      buffer,
      boost::asio::transfer_at_least( buffer_size_helper(buffer) ),
      boost::bind( &set_result, &read_result, _1 )
    );
 
  _socket.io_service().reset();
 
  while ( _socket.io_service().run_one() )
  {
    if ( read_result )
    {
      timer.cancel();
    }
    else if ( timer_result )
    {
      _socket.cancel();
      throw system_error(
          error_code( errc::timed_out, get_generic_category() )
        );
    }
  }
  return read_result;
}
 

I hope it will be useful, have fun.


Nov 23 2009

How to know, in ruby, which methods have been added and by whom?

blaxter

If you are not very careful, monkeypatching could be very harmful. One thing to remember is that you should never override a method to add funcionality, for those kind of thinks you must use alias chain method pattern, a safer way of doing that.

For the rest of the monkeypatching, i.e. add new methods, you could debug them really easy with something like this:

class Class
   def method_added(method_name)
      puts "#{method_name} added to #{self}, callstack:"
      puts caller.map{|line| "\t#{line}" }.join("\n")
   end
end

You can always add more code to filter by class or by method's name. Let's see an example:

$ more example.rb
require 'date'
require 'time'
 
class Class
   def method_added(method_name)
      return if %w(method_added).include? method_name.to_s
      puts "#{method_name} added to #{self}, callstack:"
      puts caller.map{|line| "\t#{line}" }.join("\n")
   end
end
 
class Time
   def to_date
      Date.ordinal self.year, self.yday
   end
end
 
class Date
   def to_time
      Time.parse self.to_s
   end
end
 
raise "to_date not working" unless
   Time.now.to_date == Date.today
raise "to time not working" unless
   Time.now.to_date.to_time == Date.today.to_time

The output will be:

$ ruby example.rb
to_date added to Time, callstack:
	example.rb:13
to_time added to Date, callstack:
	example.rb:19

Nice, isn't it?. Remember to be carefull with your monkeypatching, with great power comes great responsibility, it's just a tool, neither magic nor the panacea.


Ago 24 2009

A new gem: rubygems is it jruby?

blaxter

A few days ago after seeing this tweet, I've decided to migrate the gem rubygems-isit19 to jruby. Thanks to this, when you install another gem you'll be able to read about compability of this gem with jruby, the information is fetched from isitjruby.com website.

Once you have installed the gem you will have two main features, it's easier if I just show you. First the messages when you install gems:

 
$ jgem install daemons
 
daemons 1.0.10 probably might not work, blaxter says 1.0 fails
Update http://isitjruby.com/daemons with your experiences!
 
Successfully installed daemons-1.0.10
1 gem installed
$ jgem install cucumber
 
cucumber 0.3.97 might work, 100% say 0.3.11.3 works on jruby
Update http://isitjruby.com/cucumber with your experiences!
 
Successfully installed cucumber-0.3.97
1 gem installed
$ jgem install faker
 
faker 0.3.1 is 100% verified jruby
Update http://isitjruby.com/faker with your experiences!
 
Successfully installed faker-0.3.1
1 gem installed
 

And also we have an explicit gem command:

 
$ jgem isitjruby faker
faker 0.3.1:    http://isitjruby.com/faker
    Blaxter says 0.3.1 works on GNU/Linux
        it works perfectly, and it passes all test.
$ jgem isitjruby daemons
daemons 1.0.10:    http://isitjruby.com/daemons
    blaxter says 1.0 fails on GNU/Linux
        Daemons use fork, jruby doesn't support fork, so it doesn't work and
        never will
 

And that's it. The code is on github be free of fork me or open any issues. The important thing is populate with relevant information isitjruby.com for benefit of all jruby community. Oh I forgot to tell you how to install it, very easy, I've uploaded the gem to gemcutter so you can install it with something like

$ jgem install rubygems-isitjruby -s http://gemcutter.org

It's also in github, but I think (and I hope) gemcutter will be the next rubyforge, so better gemcutter :) .


Jun 13 2009

C++, cadenas multilínea de forma clara

blaxter

Según el estándar c++98 (sección 2.13.4) las cadenas literales tienen como propiedad que durante el análisis léxico del código fuente (la primera fase que realiza el compilador, convirtiendo texto de entrada a tokens y símbolos) se concatenarán cadenas adyacentes.

In translation phase 6 (2.1), adjacent narrow string literals are concatenated and adjacent wide string literals are concatenated.

Esto viene a decir que podemos partir nuestras cadenas en cualquier momento sin poner ningún signo de concatenación entre ellas, de esta forma:

 
const char s1* = "dum" "de" "dum";
const char s2* = "dum"
                 "de"
                 "dum"
;

Lo cual viene realmente bien para formar código bien indentado y formateado, pues aunque también podemos usar "\" para saltar de línea, el texto a continuación no puede estar indentado pues significaría incluir esos espacios/tabuladores en la cadena que estamos definiendo. Y lo realmente interesante es que todo esto está en la propia definición del lenguaje, no es ninguna ayuda concreta del compilador, a los ojos del programa todas las siguientes definiciones son idénticas:

 
#include <string>
#include <iostream>
 
const char * cmp( const char *s1, const char *s2 );
 
int main()
{
 
    const char * s1 = "My spoon is too big"
                      "My spoon is TOO BIG"
                      "I AM A BANANA";
    const char * s2 = "My spoon is too big\
My spoon is TOO BIG\
I AM A BANANA";
    const char * s3 = ( std::string("My spoon is too big") +
                        std::string("My spoon is TOO BIG") +
                        std::string("I AM A BANANA") ).c_str();
 
    std::cout << "s1 and s2 are " << cmp( s1, s2 ) << std::endl;
    std::cout << "s1 and s3 are " << cmp( s1, s3 ) << std::endl;
    std::cout << "s2 and s3 are " << cmp( s2, s3 ) << std::endl;
 
    return 0;
}
 
const char * cmp( const char *s1, const char *s2 );
{
    while( *s1 && *s2 && *s1++ == *s2++ );
    if ( ( *s1 != *s2 ) || ( *s1 || *s2 ) )
        return "different";
    return "equal";
}
$ c++ const_char_declaration_sample.cpp && ./a.out
s1 and s2 are equal
s1 and s3 are equal
s2 and s3 are equal

May 31 2009

Visualización de la documentación de todas las gemas instaladas

blaxter

La documentación de las gemas de ruby se genera a partir del código fuente mediante rdoc. Después de eso puedes optar por ver individualmente cada una o usar gem server.

Para poder mejorar todo esto podemos usar par de útiles herramientas: (1) la plantilla para rdoc, hanna; y (2)bdoc como alternativa a gem server para visualizar la documentación.

Hanna es una plantilla para rdoc que mejora notablemente el formato por defecto. Podemos ver la diferencia fácilmente, por ejemplo, en la documentación de rspec con el formato típico vs la documentación hecha con hanna. La instalación es simple:

$ sudo gem sources -a http://gems.github.com
$ sudo gem install mislav-hanna

Para que a partir de ahora se generar la documentación con esta plantilla, puede añadir a tu .gemrc la siguiente línea:

rdoc: --inline-source --line-numbers --template=hanna

Y para convertir la documentación de todas tus gemas instaladas, puedes hacer algo como esto:

$ sudo gem list | awk '{print $1}' | xargs sudo hanna --gems

Por otro lado, gracias a bdoc podremos navegar fácilmente entre todas las documentaciones.

$ sudo gem install manalang-bdoc
$ bdoc

bdoc
Ejecutando bdoc se nos abrirá en nuestro navegador por defecto listo para poder leer la documentación y poder movernos fácilmente entre las diferentes gemas (y versiones). Muy útil.