Futurism in action

February 20th, 2012 antonio No comments

Futurism is one of these themes / trends / disciplines – not really sure what name I should give to it – which is always in the back of my mind and continuously sparks my interest, although I tend to go in bouts of futurism.

However fancy the title sounds, to be a futurist, a future thinker, consultant or whatever, I still think we can all benefit – a lot – if we adapt and adopt some futurist thinking in our daily work. It’s not all about dreaming sci-fi cities or miracle technologies, because only some very talented and bright people can do that. But if we bring doses of future thinking in our daily approach, the system will greatly improve.

And what are those ingredients? I’d like to oppose them to what I see as current trends not only in business or big co. but also in politics and lackluster leadership.

We should have depth of vision and long term focus as opposed to the current shortsightedness and short-term planning, either in budgeting, planning or politics. In this, I think the Chinese are outpacing all of the Western world. It could be a consequence of not having to deal with elections. No electioneering seems to enable longer-term thinking, even if party survival is the ultimate goal (but that is another topic). Not that I defend not having elections, but we seem unable to have people in office capable of thinking beyond the next term and how to win it. That is the generalized sorry state of our leadership.

struct

We need more strategic thinking, instead of narrow focusing on improving processes, minute attention to detail and such streamlining with no discernible value added, other than maybe this year’s bonus for reducing stationery costs.

As humans we cannot help imagining the future in terms of the past and our experience, but let’s make an effort to emphasize other futures, other alternatives. It is just not safe or very smart to assume continuity, to assume status quo. Our current world of MSM and politicians is dominated by a paralyzing fear of being an outsider, of proposing extravagant ideas, that is, to think outside the box and maybe be seen as an outcast. We need to get rid of this stupid P.C. that permeates and debases our thinking. People who dare to speak against common thought, sanctioned ideas, are widely criticized. That is just insane. Richness of insights in invaluable.

Go back to being a child, take full-time exploration as a background running task in your brain. Don’t get lost in the details. Getting lost is easy in the daily grind, but stop for a minute and lift your neck. Lose your gaze and imagine.

We need to fight the trend in our world towards becoming more and more of an specialist. The future demands multi-skilled people. Step outside your bubble of people, job, etc. Read about many other things. Whatever sparks your fancy.

Build things or software, write down your ideas. Share them. Change minds, even if it is only yours.

Categories: Futurism, rants Tags: ,

questions about architecture…

January 27th, 2012 antonio No comments

Does you architecture…

  • Well, do you have one?
  • have a well-defined vision?
  • inspire?
  • accommodates people?
  • serve your customers?
  • have evangelists to spread the word?
  • clearly communicate the motivation behind?
  • enable you to move towards your strategic goals?
  • reflect your organization and its process model adequately?
  • support your business needs or does it reflect the vendor’s?
  • let you live in an agile and nimble enough framework?
  • allow you room for future decision-making?
  • provide increasing ROI, increasing enterprise revenue, better, faster service?
  • let you deploy with not too much pain? (no magic recipes here)
  • give you the necessary intelligence you need about your customers and your org?
  • let you adapt to changes quickly and easily?
  • let you change or update a part easily? (modularity)
  • clearly separate data from logic?
  • document itself?
  • have security built in, ignored, or thrown in as an after thought?
  • communicate security policies accurately?
  • keep you in control? or are the vendors in control?
  • have a clear path from business need to specific implementation?
  • become set in stone once implemented?
  • break down problems so that they are manageable and understandable, that is, actionable?
  • tame inherent complexity?
  • get the vital business sponsorship?
  • make clear that agility and nimbleness does not mean “no holds barred” and obeying every whim? that it also means setting constraints and trade-offs?
  • is easily learned by new hires?
  • tolerate (behave gracefully), reacts to and communicates failure adequately?
  • provide you a reusable, industrial, product line?
  • have a well-defined change process?
  • inform people about best design?
  • facilitate a way to get existing silos talk to each other?
  • provide an adequate mechanism for capturing business requirements?
  • provide a common data format? a enterprise-wide lingua franca for data exchange?
  • allow you to remove pain points that appear in the future?
  • have performance metric built in? can that data be exploited by BI tools?


dehesa

Let’s make clear one thing. I don’t claim to do most of these things right, far from it. I’ve got so much to learn and experience. These questions emerge from my readings of industry luminaries and some of my own musings. I am just trying to keep a sort of checklist, a sort of questions that we tend to forget in the daily grind or when incorporating to a new project or team, but that the aspiring enterprise architect should keep in the back of the mind.

un experto no es un consultor y viceversa

January 23rd, 2012 antonio No comments

¿Porqué los proveedores de servicio, las grandes consultoras, y también las pequeñas, en muchas, demasiadas, ocasiones acaban no satisfaciendo las expectativas del cliente? ¿Y no será que la diferencia entre lo que es un experto en una(s) tecnología(s) determinada(s) y lo que es, o lo que se vende como consultor, es la raíz del problema?


dehesa

Un experto, lo sea más o menos, al final no hace sino ejecutar las órdenes, construir lo que se le pide, etc. etc. Un consultor, guía, asesora, orienta, y en muchas ocasiones, le falta el componente clave de liderazgo; es decir, fundamentalmente responde preguntas. No es lo mismo ni lejanamente. En numerosas ocasiones, el cliente no tiene del todo claro que quiere, con lo que ese rol de asesoramiento y guía se hace bastante necesario, pero es el experto es que está deseando asumir ese rol, ofreciendo su experiencia y explotando su creatividad.

El problema es que hay muchos “expertos” acostumbrados a ser carne inerte de proyecto, esperando a recibir un “fichero batch” y ponerse a trabajar, y menos consultores de verdad de lo que nos quieren hacer creer. Para más inri, las empresas están prestas a vender una cosa por la otra, y en muchas ocasiones, los términos se utilizan como si fuesen sinónimos, cuando realmente no lo son.

En este mundo cada vez cobra más importancia la figura del especialista generalista – capaz de mantener en el radar la visión general – es crucial adoptar un rol híbrido que nos permita ejercer los dos roles. Sólo de esa forma daremos un valor real a nuestro cliente. Lo que falla es que ni uno ni otro, ni consultor ni experto, asume totalmente los mandos, o no se le permite, en muchas ocasiones. Si el ámbito de nuestro contrato es obedecer y construir lo que se nos dice, aunque esté mal, aunque veamos deficiencias u oportunidades para mejorar x aspectos, y no podemos o no queremos asumir el control, estamos fracasando en un aspecto crucial de nuestro trabajo, que es el de tener razón, el de la corrección, y no me refiero a las formas y maneras, sino a la correcta ejecución de algo. ( en el fondo estoy volviendo a esa manida palabra de proactividad, pero como está tan sucia y vacía, prefiero no usarla).



Tenemos que quitar de los hombros del cliente el peso de la “responsabilidad” de una serie de decisiones que deben ser correctas pero que muchas veces no está capacitado para tomar, y en realidad es el cliente quien debe ser nuestro consultor, al que iremos a preguntar por su conocimiento de negocio, al que acudiremos cuándo sea necesario, pero desde una perspectiva de negocio. El cliente, que en 98% de las veces, por decir un número, no tiene conocimientos técnicos, no necesita tener ese control del proyecto. Ésa es nuestra tarea, nosotros tenemos que asumir esa responsabilidad en aras del mejor interés del cliente. Dejar siempre toda la responsabilidad en los hombros del cliente es cómodo, es una metodología “cover-your-ass” sobradamente probada, pero la clave que nos enriquece a todos es trabajar juntos.

En ocasiones parece que un consultor “puro y duro” se limita a asesorar, y nos falta el componente de liderazgo, de asumir las riendas y dar tranquilidad al cliente. En mi humilde opinión, ese perfil híbrido entre experto y consultor, con confianza y sin miedo de tomar el control es el que a veces nos falta – bien es cierto que la cultura empresarial de algunas organizaciones no lo va a permitir tan facilmente, pero ese es otro problema – a la hora de dar servicio a nuestros clientes.

las fotos son mías y son CC
Creative Commons

Categories: General, rants Tags:

Conway’s game of life, but with a noisy twist

January 15th, 2012 antonio No comments

After the short experiment the other day in Processing, I decided i wanted to do it a bit funnier, using something better than true-false pixels. So I put yellow blocks and also made use of the easy to use functionalities in Processing’s third-party libs to make some noise.
I didn’t elaborate too far, but I feel this could become a serious sine wave noise generator. My simple goal in the beginning, was just to make a sonic footprint of the little universe’s evolution.

The looks of the thing now is like this, a bit nicer than the pixels.

20 generations of the game of life

It’s easy to modify the code if you want to have a bigger or smaller grid, the only gotchas being that the side size of the squares has to be an even number, and the height and width of the board have to yield zero if %’ed to the square side size. So basically I mean width % _sqSize = 0 and height % _sqSize = 0. I didn’t bother to perform this kind of checking. This is a quick and dirty test.

I think you guys are able to follow the Processing code easily and modify as wanted.
The code as it is will also record the noise generated for you. Exactly as for generating the animated gif file, click on the mouse whenever you want to generate both the gif and the sound bite.

Alternatively you could use the keyreleased event to have separate keys triggering each event (see here). The gif library is the same as the other example. Grab it from here. The Minim library (better be the beta) get from here. Thanks to the authors for their excellent work.

I put an array of floats with the tones of 8 octaves, which I got from here, although I must say I didn’t make much use. I guess you could introduce a lot of random variations in the algorithm. The idea is to get the closest tone to the count of live and dead cells respectively (multiplying by 200 since otherwise we would get very low numbers, therefore very low tones). Even so I commented out the lowest tones.

I don’t want to cause headaches, so I put just a short mp3. You play with the rest if you want more.

So this is the code.
rock on!

import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.ugens.*;
/* above import is for noise gen */
/* http://code.compartmental.net/tools/minim/manual-music-programming-intro/ */

import gifAnimation.*;

/* Every time you use the Minim library, you need to instantiate a
 Minim object and call its constructor with the this keyword. (in setup())*/
Minim minim;
/* we need this class for minimum audio output */
AudioOutput audioout;
SineWave sinW;
SineWave sinW2;
SineWave sinW3;    // this will signal the spawning of new cells
boolean activateMouseOverNoise =false;
Oscil osc;

AudioInput audioin;
AudioRecorder recorder;

int freq1 = 440;
int freq2 = 440;

GifMaker gifExport = null;

/* declarations of love... */
int _sqSize = 12;
int _width = 288;  // _width % _sqSize should be 0
int _height = 288; // _height % _sqSize should be 0
float frames = 2;
int genCounter;
int rowLength = _width / _sqSize;
int rowHeight = _height / _sqSize;
/* hold our universes here */

float startpop;

/* we decide this is the live color */
color _liveColor = color(235, 235, 0);

/* death gradient intervals, indicates how the cell will turn of slowly
 losing its color in certain intervals; these values will be added or
 substracted to the values that make up the live color */
/* not done yet */
int _gradIntervalR = 10;
int _gradIntervalG = 10;
int _gradIntervalB = 10;

// float of tones - see here http://www.phy.mtu.edu/~suits/notefreqs.html
float tones[] = new float [] {
  /*16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87, 32.7, 34.65, 36.71, 38.89, 41.2, 43.65, 46.25, 49, 51.91, 55, 58.27, */
  61.74, 65.41, 69.3, 73.42, 77.78, 82.41, 87.31, 92.5, 98, 103.83, 110, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 
  196, 207.65, 220, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88, 523.25, 
  554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880, 932.33, 987.77, 1046.5, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 
  1567.98, 1661.22, 1760, 1864.66, 1975.53, 2093, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520, 3729.31, 
  3951.07, 4186.01, 4434.92, 4698.64, 4978.03
};

void setup()
{
  size(_width, _height);

  frameRate(frames);
  startpop = .18 * rowLength * (rowHeight/1.2);

  setupAudioShite();

  println("----------------------------------------------------------------------------------------------");
  println("STARTPOP " + startpop);
  background(0);    // set bg to black
  smooth();

  gifExport = new GifMaker(this, "life.gif");
  gifExport.setRepeat(0); // make it an "endless" animation
}

void draw()
{

  println(" --------- GENERATION: " + genCounter + " --------------------------------------------------");

  if (genCounter == 0)
  {
    for (int i = 0; i < startpop; i++ )
    {
      drawCell(int(random(rowLength))*_sqSize, int(random(rowHeight))*_sqSize, 255);
    }
    recorder.beginRecord();
  }

  for (int x = 0; x < rowHeight * _sqSize; x+=_sqSize ) {
    for (int y = 0; y < rowLength * _sqSize; y+=_sqSize ) {
      //println("X:" + x + "Y:" + y);
      int _neighs = getNeighbours(x+(_sqSize/2), y+(_sqSize/2));
      //println("NUMBER OF NEIGHS: " + _neighs);
      // get color first
      boolean islive = isPixelAlive(x+(_sqSize/2), y+(_sqSize/2));  // get color of cell center

      // -----------------------------------
      if (islive)
      {
        if (_neighs < 2 || _neighs > 3) {
          freq1++;  
          killCell(x, y);
        }

        if (_neighs == 2) {  // keep alive
          drawCell(x, y, _liveColor);
          freq2++;
        }
        // if(genCounter % 3 == 0)
        //  killCell(int(random(rowLength))*_sqSize, int(random(rowHeight))*_sqSize);
      }
      else
      {
        if (_neighs == 3) {
          drawCell(x, y, _liveColor);
        }
      }
      // -----------------------------------

      // uncomment if you want further chaos
      //     if(genCounter % 3 == 0)
      //     drawCell(int(random(rowLength))*_sqSize, int(random(rowHeight))*_sqSize, _liveColor);
    }  // inner for
  }  // outer for

    ++genCounter;

  sinW.setFreq(findNearestTone(freq2*200) / genCounter);
  sinW2.setFreq(findNearestTone(freq2*200) / genCounter);

  gifExport.setDelay(500);
  gifExport.addFrame();
}  // method

void mouseMoved() {
  if (activateMouseOverNoise) {
    sinW.setFreq(map(mouseX/2, mouseY, height, 500, 60));
    sinW2.setFreq(map(mouseX/2, mouseY, height, 500, 60));
  }
}

void mousePressed() {
  if ( recorder.isRecording() )
  {
    recorder.endRecord();
    recorder.save();
  }

  gifExport.finish(); // write file
}

int getNeighbours(int x, int y)
{
  int _n = (y + height - _sqSize) % height;
  int _s = (y + _sqSize) % height;
  int _e = (x + _sqSize) % width;
  int _w = (x + height - _sqSize) % width;

  /* we must exclude from evaluating as alive those nearby cells 
   that are in the process of losing color */

  return (isPixelAlive(x, _n) ? 1 : 0) +
    (isPixelAlive(_e, _n) ? 1 : 0) + 
    (isPixelAlive(_e, y) ? 1 : 0) + 
    (isPixelAlive(_e, _s) ? 1 : 0) + 
    (isPixelAlive(x, _s) ? 1 : 0) + 
    (isPixelAlive(_w, _s) ? 1 : 0) + 
    (isPixelAlive(_w, y) ? 1 : 0) + 
    (isPixelAlive(_w, _n) ? 1 : 0);
}

/* this func returns whether a pixel is exactly of the color defined as 
 alive for our purposes here or not. the color considered valid, or live,
 is defined globally (see declaration block) */
boolean isPixelAlive(int x, int y)
{
  color _c = get(x, y);
  // print("Color for " + x + "," + y + " is " + _c);
  return (_c == _liveColor);
}

/* x and y are the center coordinates */
void drawCell(int x, int y, color c)
{
  // println("ENTERING drawCell " + x + ", " + y);
  stroke(235, 235, 0, 0);
  fill(235, 235, 0);
  rect(x, y, _sqSize, _sqSize);
}

void killCell(int x, int y)
{

  color _c = get(x, y);

  stroke(0, 0, 0, 0);
  fill(0, 0, 0);
  rect(x, y, _sqSize, _sqSize);
}

void stop()
{
  // always close Minim audio classes when done
  audioout.close();
  audioin.close();
  minim.stop();

  super.stop();
} 

/* ------------------------------------------------------------ */

void setupAudioShite()
{

  minim = new Minim(this);
  /* Without calling the getLineOut() method, none of the audio data generated by the
   xWave classes will be routed correctly to the sound card */
  audioout = minim.getLineOut(Minim.STEREO, 2048);
  audioin = minim.getLineIn(Minim.STEREO, 2048);
  recorder = minim.createRecorder(audioin, "lifesound.wav", true);

  sinW = new SineWave(0, 1, 44100);
  sinW2 = new SineWave(0, 1, 44100);
  // sinW3 = new SineWave(0, 1, 44100);
 
  sinW.portamento(300);
  sinW2.portamento(300);
  // sinW3.portamento(300);

  /* add the waves to the audio output channel */
  audioout.addSignal(sinW);
  audioout.addSignal(sinW2);
}

float findNearestTone(int freq)
{
  /* taken from here http://stackoverflow.com/questions/519881/finding-closest-number-in-an-array
   hey I just ran 12 kms...too tired for this */
  float nearest = 0.0;
  float bestDistanceFoundYet = -1;
  // We iterate on the array...
  for (int i = 0; i < tones.length; i++) {
    // if we found the desired number, we return it.
    if (tones[i] == freq) {
      return tones[i];
    } 
    else {
      // else, we consider the difference between the desired number and the current number in the array.
      float d = Math.abs(freq - tones[i]);
      if (d < bestDistanceFoundYet) {
        // For the moment, this value is the nearest to the desired number...
        nearest = tones[i];
      }
    }
  }
  return nearest;
}

recordatorio pasos instalación mongodb

January 8th, 2012 antonio No comments

Para instalar mongodb y trastear un poco, lo primero bajarlo, claro, bien sea via web o bien con curl.
Descomprimimos el paquete.
Lo movemos a /usr/local/mongodb o similar.
Creamos el directorio para datos, que no lo crea por defecto y el de los logs. Por defecto mongodb intentará ir a leer en /data/db, pero ahora veremos cómo configurarle un directorio diferente.
Finalmente, le damos permisos al usuario con el que estemos trabajando ahora, el que tiene la terminal abierta.


tar xzf mongodb-osx-x86_64-2.0.3.tgz
sudo mv mongodb-osx-x86_64-2.0.3 /usr/local/mongodb
sudo mkdir /usr/local/mongodata /var/log/mongodb
sudo chown -R sexyrichuser /user/local/mongodata

Antes de arrancar nos falta crear el archivo de configuración. Para mi lo más cómodo es tenerlo dentro del /bin.
Así que navegamos hasta el /bin de dónde hayamos instalando mongo, que sería la ruta que vemos abajo y creamos un archivo llamado mongod.conf.


ls /usr/local/mongodb/bin
touch mongod.conf

Dentro del archivo metemos por ejemplo (el archivo lo podemos editar fácilmente con nano mongod.conf)


# Store data alongside MongoDB instead of the default, /data/db/
dbpath = /usr/local/mongodata
# Only accept local connections
bind_ip = 127.0.0.10

Y le indicamos dónde tiene que ir a trabajar con los datos.
Ahora ya estamos listos para arrancar, indicándole el archivo de configuración que debe leer.


mongod --config mongod.conf

Ahora en http://localhost:28017/ debemos ver la consola del bicho.

Para un uso en productivo convendría meter un job que haga que esto se arranque solo.

Categories: General Tags:

Conway’s game of life in Processing – very simple

January 2nd, 2012 antonio No comments

I always wanted to dabble a little bit in Processing. Since I first heard about it, quite a few years ago, I was piqued. However, it was one of these things you keep in the back of your mind and never get around to play with. However, today I did a quick and crappy version of the Conway’s game of life, although I changed the rules a little bit. I liked the output better.

All is organized around a big 2D array holding boolean values. A pixel – cell – can be true (alive) or false (dead). And that’s it. We use Processing’s draw event to evaluate the next generation. The code is pretty easy to follow along and to modify to your heart’s content. I guess you can do more complex simulations, with better graphics or stuff. It was also nice to experiment with creating random cells sometimes, painting them in a different color, etc. but I leave here the normal implementation with slightly changed rules.

This is an animated gif with 20-something generations of the game.

20 generations of the game of life

And this is the code. If you want to run it, install processing, obviously, which is quite a simple thing to do and the proceed to install the library that allows to generate the animated gif. Alternatively, just delete the lines dealing with the gifMaker if you don’t want to have the gif generated in the first place.

import gifAnimation.*;

boolean [][] grid, nextGrid;
int genCounter;

GifMaker gifExport = null;

void setup() {
  size(500, 500);
  frameRate(2);
  grid = new boolean[width][height]; //500,500 as in size() instruction
  nextGrid = new boolean[width][height]; //500,500 as in size() instruction
  // initial random config
  float startpop = 0.12 * width * height;
  print(startpop);
  for ( int i = 0; i < startpop; i++) {
    grid[int(random(width))][int(random(height))] = true;
  }
  background(255);
  gifExport = new GifMaker(this, "life.gif");
  gifExport.setRepeat(0); // make it an "endless" animation
  // gifExport.setTransparent(0, 0, 0); // black is transparent
}

void draw() {

  for (int x = 1; x < width-1; x++) {
    for (int y = 1; y < height-1; y++) {
      // get number of neighbours
      int _neighs = getNeighbours(x, y);
      if ( grid[x][y] && _neighs < 2 ) {
        killCell(x, y);
      }
      if (grid[x][y] && _neighs >= 5) {
        // death by over population
        killCell(x, y);
      }
      if (!grid[x][y] && _neighs == 3) {
        // thou shall be reborn
        nextGrid[x][y] = true;
        set(x, y, color(120));
      }
      if (grid[x][y] && ( _neighs == 2 || _neighs == 3)) {
        nextGrid[x][y] = grid[x][y];
      }
    }
  }

  // swap
  boolean[][] temp = grid;
  grid = nextGrid;
  nextGrid = temp;
  gifExport.setDelay(500);
  gifExport.addFrame();
  println("GENERATION " + genCounter++);
}

int getNeighbours(int x, int y) {
  // use modulo so that the last pixel on a row takes the first 
  int north = (y + height-1) % height;
  int south = (y + 1) % height;
  int east = (x + 1) % width;
  int west = (x + width-1) % width;
  return (grid[x][north] ? 1 : 0) +
    (grid[east][north] ? 1 : 0) + 
    (grid[east][y] ? 1 : 0) + 
    (grid[east][south] ? 1 : 0) + 
    (grid[x][south] ? 1 : 0) + 
    (grid[west][south] ? 1 : 0) + 
    (grid[west][y] ? 1 : 0) + 
    (grid[west][north] ? 1 : 0);
}

void killCell(int x, int y) {
  nextGrid[x][y] = false;
  //set(x, y, color(222, 22, 122));
  set(x, y, color(255));
}

void mousePressed() {
  gifExport.finish();
}

Next, I want to generate some sounds along with the generation, to have some sort of sonic footprint of the ecosystem, but then I need to learn a little bit about the libraries Processing has for sound generation.
enjoy!

threads en Ruby – jugando un poco

December 2nd, 2011 antonio No comments

Ayer, jugando un poco con threads en Ruby, lenguaje que hacía tiempo al que le quería hincar el diente, noté un patrón curioso que no se si tendrá nombre, y que me imagino que ya será conocido por los expertos, claro. Estaba viendo en la documentación un ejemplo clásico de pasar la ejecución de un thread a otro (enlace):

a = Thread.new { print "a"; Thread.pass;
print "b"; Thread.pass;
print "c" }
b = Thread.new { print "x"; Thread.pass;
print "y"; Thread.pass;
print "z" }
a.join
b.join

Este snippet produce este resultado


axbycz

Lo que quizás no es aparente en este ejemplo lo es al ejecutar un ejemplo igual, pero con 4 o 5 hilos.

t1 = Thread.new { print "1"; Thread.pass; print "2"}
t1 = Thread.new { print "3"; Thread.pass; print "4"}
t1 = Thread.new { print "5"; Thread.pass; print "6"}
t1 = Thread.new { print "7"; Thread.pass; print "8"}
t1 = Thread.new { print "9"; Thread.pass; print "10"}

t1.join

puts; puts "execution ended"

Estamos creando 5 hilos con el mismo patrón, aunque en realidad, podemos ir volcando la referencia siempre en la misma variable ya que al final hacemos join sobre la última referencia con lo que no nos vamos a perder la ejecución de ningún thread porque el propio programa salga antes que el último hilo.

El resultado de esta ejecución es

rubyconsole

Veis el patrón de cómo se gestiona el paso de ejecución entre los hilos?
No es que sea el descubrimiento del siglo, pero me ha parecido curioso y agradable que el patrón sea predecible. Recuerdo haber hecho otros experimentos en otros lenguajes y las ejecuciones de este estilo no siempre son predeterminadas.
Tengo que dedicarle un ratillo al problema de los filósofos en Ruby.

¿Cómo rellenariais las comillas de los hilos para producir el resultado de la consola de debajo?


t1 = Thread.new {
print "1";
Thread.new { print ""; Thread.pass; print ""};
Thread.new { print ""; Thread.pass; print ""};
Thread.new { print ""; Thread.pass; print ""};
print "6";
}

t1.join

puts; puts "execution ended"


rubyconsole


saludos

Categories: coding, languages, ruby Tags: , ,

editar el fichero hosts en mac

November 22nd, 2011 antonio No comments

Como es normal, estamos corriendo con una cuenta limitada habitualmente, pero si queremos hacer este tipo de tareas administrativas, por ejemplo, para actualizar el hosts y que nos bloquee todas esos dominios de tracking, popups, anuncios porno y demas zarandajas, tenemos, cómo no, que impersonal al su. Los pasos son

Vamos a la terminal, como siempre y hacemos

su “cuenta admin”

Nos pedirá la password, que introduciremos y luego tecleamos

sudo nano /private/etc/hosts

nano es un mini-editor que basta para estas cosas. Pegamos el archivo o las lineas de aquellos dominios ingratos que queramos bloquear y salvamos, cuando termine haciendo Ctrl+O.

Mas sobre nano, si teneis curiosidad, en la wikipedia.

Hosts con urls ya metidas para bloquear sitios ingratos hay bastantes, por ejemplo éste.

Categories: cookbook, General, macos Tags: , , ,