domingo, 26 de octubre de 2008

Metaprogramación en php

En php5 han entrado nuevas posibilidades en lo que a metaprogramación se refiere, revisando el siguiente trozo de código nos encontramos un ejemplo de que construcciones se pueden realizar.

<?php

function saludo(){
return "hello";
}

$cadena = "saludo";
$cadena_funcion = "cadena";
?>

<?= $cadena() ?>

<br/>

<?= $$cadena_funcion() ?>

Primero podemos ver que si guardamos en una cadena el nombre de una función, y luego llamamos a la cadena con una lista de parámetros (en este caso vacía), se invoca dicha función. Esto puede ser bastante útil para elegir que acción ejecutar ante una entrada por parámetro.

En segundo lugar se muestra como utilizar las variables con doble '$', es decir, las variables de variables. Por cada '$' delante del nombre de la variable se hace una evaluación de la variable.

$cadena_funcion contiene la cadena "cadena", si por el contrario se referencia a $$cadena_funcion, se evaluará la variable $cadena.

martes, 21 de octubre de 2008

Programación funcional con javascript

En programación funcional se usa las funciones map, filter y reduce para manipular colecciones.

En javascript se pueden implementar fácilmente de la siguiente manera.

function map(f, a){
var r=new Array();
for(var i=0;i<a.length;i++){
r.push(f(a[i]));
}
return r;
}

function filter(f, a){
var r=new Array();
for(var i=0;i<a.length;i++){
if(f(a[i])){
r.push(a[i])
}
}
return r;
}

function reduce(f, a){
if(a.length<1){
return a
}
else{
var r=a[0].__proto__;
for(var i=0;i<a.length;i++){
r=f(r, a[i])
}
return r;
}
}

domingo, 19 de octubre de 2008

Implementación de un memory pool

En aplicaciones en las que se reserva y libera memoria con mucha frecuencia se puede sufrir fragmentación de memoria. Cuando el rendimiento no es demasiado importante este comportamiento puede ser aceptable, en cambio, si esto se produce en una aplicación de tiempo real es necesario solucionarlo.

Para evitar la fragmentación de memoria existe una técnica llamada memory pool, básicamente consiste en crear un espacio fijo de memoria para que la aplicación lo administe.

En el siguiente ejemplo se crea un pool para un conjunto de threads que lo comparten.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define BUF_SIZE 128
#define POOL_SIZE 36
#define NUM_THREADS 10

typedef struct dataStruct{
int id;
char cadena[BUF_SIZE];
} data;


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

data **dataPool;
int next_data = 0;

int get_next_memory_position(){
pthread_mutex_lock(&mutex);
next_data = (next_data + 1) % POOL_SIZE;
pthread_mutex_unlock(&mutex);
return next_data;
}

data **allocate_pool(){
int i;
data **d = (data**) malloc(sizeof(data*) * POOL_SIZE);

for(i = 0;i < POOL_SIZE; i++){
d[i] = malloc(sizeof(data));
}

return d;
}

void *thread(){
data *param = dataPool[get_next_memory_position()];

param->id = next_data;
strcpy(param->cadena, "hello");

printf("%d: %s \n", param->id, param->cadena);
}

int main(){
pthread_t t[NUM_THREADS];
dataPool = allocate_pool();
int i;

for(i = 0;i < NUM_THREADS; i++){
pthread_create(&t[i], NULL, thread, NULL);
}

for(i = 0;i < NUM_THREADS; i++){
pthread_join(t[i], NULL);
}
}

En este ejemplo se asigna automáticamente memoria a los threads conforme la piden circularmente, este planteamiento no vale siempre, para cambiar la política de asignación de bloques libres solo hay que cambiar el método get_next_memory_position.

sábado, 18 de octubre de 2008

Simulando enlaces con javascript

En algunas ocasiones necesitamos poner un enlace en un elemento del DOM de una web que no acepta la propiedad href.

Normalmente ocurre cuando se quiere añadir un hipervínculo que no estaba previsto al realizar la maquetación.

Para esos casos se puede simular el comportamiento de un enlace mediante javascript.

Supongamos que el div con id 'texto' es el que queremos que tenga un enlace a otra página, con el evento onclick y cambiando el document.location podemos irnos a la página que queremos al pinchar en el elemento.

El problema es que al pasar por encima el ratón nada nos indica que es un enlace, con el evento onmouseover y cambiando la propiedad css cursor podemos hacer que parezca un enlace.

Un ejemplo de como quedaría.

<html><body>

<div id="texto" onclick="document.location='http://google.com'" onmouseover="this.style.cursor='pointer'">lorem ipsum</div>

</body></html>

domingo, 12 de octubre de 2008

Transacciones en rails

En esta entrada expliqué como usar las transacciones a nivel de base de datos (MySQL), ahora lo haré a nivel de aplicación con rails.

Si usamos MySQL debemos recordar que por ahora el único motor que soporta transacciones es InnoDB.

Los objetos que heredan de ActiveRecord tienen un método transaction que acepta un bloque, las operaciones que se ejecuten dentro se realizarán indivisiblemente.

Imaginemos que tenemos un modelo llamado Post, con los campos title y content, el campo title no puede ser nulo.

Si hacemos esto.

Post.transaction do
Post.create(:title => 'en la transaccion', :content => 'texto')
Post.create(:content => 'texto')
end

Como la segunda operación no es válida (el campo title es nulo) ninguna de las operaciones se reflejará en base de datos, por el contrario, si le asignamos un title a la segunda operación se ejecutarán normalmente y tendremos dos entradas nuevas en la tabla de posts.

sábado, 11 de octubre de 2008

Ejecutar comandos linux sobre múltiples ficheros

Para ejecutar comandos masivamente sobre una lista de ficheros en linux se pueden combinar los comandos find y xargs.

find es bastante conocido, básicamente lo que hace es buscar archivos según los criterios que le indiquemos.

xargs coge una lista y ejecuta el comando que le pasemos a cada elmento de esa lista.

La sintaxis es la siguiente.

find . -name "*.txt" | xargs echo

Con eso listaríamos los ficheros con extensión txt.

find . -name "*.php" | xargs -I fichero cat fichero >> acumulado.php

El parámetro -I hace que podamos darle un nombre a la entrada del comando que queremos ejecutar para realizar operaciones más complejas.

find . -name "*.cpp" | xargs -t -I fichero mv fichero fichero.old

Al realizar operaciones masivas con ficheros es posible que cometamos algún error, para comprobarlo se puede utilizar el parámetro -t que hace que se indiquen en la salida todos y cada uno de los comandos que xargs ejecuta.

lunes, 6 de octubre de 2008

Búsquedas fulltext en mysql

Las búsqueda fulltext son un tipo de búsqueda especial para los campos de texto, en MySQL solo está disponible para el motor MyISAM. Incluso los resultados se ordenan por relevancia.

Se pueden indexar en modo fulltext los campos de tipo char, varchar y text.

Para crear un índice fulltext la sintaxis es la siguiente.

alter table tabla add fulltext(campo);

Se pueden combinar varios campos para el índice.

alter table tabla add fulltext(campo1,campo2);

La sintaxis para las consultas fulltext.

select * from tabla where match(campo) against('contenido');

Hay que tener en cuenta ciertas condiciones al realizar búsquedas, las más importantes:

1) Si la consulta aparece en la mitad de los registros se toma como 'común', se ignoran los resultados
2) Se ignoran palabras demasiado cortas

Si no nos viene bien la regla 1), podemos hacer las búsquedas en 'modo booleano' aunque en este caso los resultados no se ordenan por relevancia.

select * from tabla where match(campo) against('contenido' in boolean mode);

En 'modo booleano' se pueden aplicar también modificadores, por ejemplo, si queremos las tuplas con contenido 'texto' y sin 'basura'.

select * from tabla where match(campo) against('+texto -basura' in boolean mode);

También se puede utilizar el wildcard '*'.

select * from tabla where match(campo) against('text*' in boolean mode);