Ir al contenido principal

This is my blog, more about me at marianoguerra.github.io

🦋 @marianoguerra.org 🐘 @marianoguerra@hachyderm.io 🐦 @warianoguerra

llega el momento en la vida de toda persona

en la que se cansa de mostrar código en slides que se ven feas y escribe su propio programa para hacer presentaciones en la web basado en json.

Una idea que se me ocurrió hace un tiempo y a la cual fui un poco obligado ante la necesidad de mostrar bastante código y pelear por horas con oo impress, mas que mis slides son siempre similares y tengo que aplicar el mismo estilo a todo.

si, se que hay formas, pero las formas son mas complicadas de lo que desearía, ahora puedo tener mi código resaltado con pygments en archivos aparte, cargarlos a voluntad desde cualquier parte de la interwebs, cambiar el color del resaltado de sintaxis cambiando una archivo css, reusar estilos y slides a diestra y siniestra etc.

si lo quieren ver esta acá:

http://github.com/marianoguerra/pepete

unos slides introductorios (no podría ser de otra forma) acá, entra y apreta load:

http://marianoguerra.github.com/pepete/

disclaimer: los slides los hice a las patadas (no me gusta hacer slides :D)

pynerl

tras unas horas de codear, tengo la primera version de pynerl, un modulo en erlang que permite ejecutar python y obtener los resultados en erlang.

mas facil si lo explica xzibit.



el proyecto esta hosteado en github aca:

http://github.com/marianoguerra/pynerl

un ejemplo:

1> pynerl:eval("t = 1", "t").
1
2> pynerl:eval("t = 1 * 2", "t").
2
3> pynerl:eval("import time;t = time.time()", "t").
1274236802.877999
4> pynerl:eval("import random;t = random.random()", "t").
0.45102117275294684
5> pynerl:eval("t = print('hello erlang or python')", "t").
hello erlang or python
none
6> pynerl:call("time", "time", []).
1274236859.510859
7> pynerl:call("random", "random", []).
0.9623136682858975
8> pynerl:eval("t = True", "t").
true
9> pynerl:eval("t = 2.3", "t").
2.3


como ves las dos funciones principales son eval y call, que hacen lo que esperarias, eval evalua una expresion y devuelve el valor de la variable que pases como segundo parametro. call llama a la funcion dentro del modulo pasandole los parametros del tercer argumento y devuelve el resultado.

El estado actual es alpha, el mapeo de tipos funciona solo para los tipos basicos y el paso de parametros en call todavia no esta implementado (simplemente porque lo empece hace 2 horas :P).

Como es la primera vez que programo python y erlang internamente seguro que estoy leakeando por todos lados, se va a resolver cuando lea un poco mas.

evaluando python desde erlang

y el secreto se develo, como tener algo como eval de python pero corriendolo desde erlang.

el codigo no es lo mas bonito de la tierra pero ya va a ir mejorando.

primero que todo bajate erlang R13B04 para tener la ultima version de la API de NIF.

crea un archivo pynerl.c

/* pynerl.c */
#include <stdio.h>
#include "erl_nif.h"
#include <Python.h>

#define STR_SIZE 1024
char code[STR_SIZE];

static ERL_NIF_TERM pyeval(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
Py_Initialize();

if (enif_get_string(env, argv[0], code, STR_SIZE, ERL_NIF_LATIN1) < 0) {
return enif_make_string(env, "code too long", ERL_NIF_LATIN1);
}
else {
PyRun_SimpleString(code);
}

Py_Finalize();

return argv[0];
}
static ErlNifFunc nif_funcs[] =
{
{"pyeval", 1, pyeval}
};

ERL_NIF_INIT(pynerl,nif_funcs,NULL,NULL,NULL,NULL)


y uno llamado pynerl.erl

-module(pynerl).
-export([init/0, pyeval/1]).

-on_load(init/0).

init() ->
erlang:load_nif("./pynerl", 0).

pyeval(_Str) ->
"NIF library not loaded".


despues compila ambos:


gcc -fPIC -shared -o pynerl.so pynerl.c -I $ERL_INCLUDE -I/usr/include/python3.1/ -D_THREAD_SAFE -lpthread -ldl -lutil -lpython3.1 -lm
$ERLC pynerl.erl


en mi caso


$ echo $ERL_INCLUDE
/home/mariano/Software/otp_src_R13B04/erts/emulator/beam
$ echo $ERLC
/home/mariano/Software/otp_src_R13B04/bin/erlc


despues de eso lo probamos


$ $ERL
Erlang R13B04 (erts-5.7.5) [source] [rq:1] [async-threads:0] [kernel-poll:false]

Eshell V5.7.5 (abort with ^G)
1> pynerl:pyeval("print('hello python 3.1 from erlang!')").
hello python 3.1 from erlang!
"print('hello python 3.1 from erlang!')"


observaciones:

uso $ERL porque tengo dos versiones de erlang instalando, esa variable apunta al erlang mas nuevo que tengo compilado.

la primera linea de salida es la ejecucion de la linea, la segunda es el string que le pase como parametro, que es lo que devuelve por ahora pyeval, algun dia va a devolver el objeto que devolvio la evaluacion (mientras sea algo que pueda ser convertido a un tipo de erlang).

implementar una function en C y llamarla en erlang

Si leiste el post anterior y este podes empezar a formarte una idea de lo que quiero hacer.

para poder llamar codigo de C en erlang hay que hacer un NIF (native implemented functions), estoy siguiente el ejemplo del manual de erlang pero como tiene un error pongo el codigo aca.

creamos un archivo niftest.c y ponemos el siguiente codigo

/* niftest.c */
#include "erl_nif.h"
static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return enif_make_string(env, "Hello world!");
}
static ErlNifFunc nif_funcs[] =
{
{"hello", 0, hello}
};
ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)



creamos niftest.erl (tranquilamente se podria hacer en efene :D)

-module(niftest).
-export([init/0, hello/0]).
init() ->
erlang:load_nif("./niftest", 0).
hello() ->
"NIF library not loaded".


compilamos


gcc -fPIC -shared -o niftest.so niftest.c -I/usr/lib/erlang/erts-5.7.4/include/


y lo probamos


$ erl
cErlang R13B03 (erts-5.7.4) [source] [rq:1] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4 (abort with ^G)
1> c(niftest)
1> .
{ok,niftest}
2> niftest:hello().
"NIF library not loaded"
3> niftest:init().
ok
4> niftest:hello().
"Hello world!"
5>


vamos avanzando

Embebiendo python en otra aplicacion

tengo una idea en la cabeza que requiere embeber python en otro lado, como seguro la voy a dejar a la mitad no te voy a contar que es :P pero si voy a documentar los pasos por si me olvido o a alguien le sirve.

Estoy siguiendo la documentacion oficial

Elegi empezar con python 3.1 porque estoy jugando y porque si anda me gustaria no tener que portarlo a la larga.

el primer ejemplo es bastante simple

ponelo en un archivo llamado one.c y corre lo siguiente


gcc one.c -I/usr/include/python3.1/ -D_THREAD_SAFE -lpthread -ldl -lutil -lpython3.1 -lm -o one


una vez compilado, si lo ejecutamos:


$ ./one
Today is Tue May 18 18:25:59 2010


bien para empezar, si sigo, vas a ver mas posts como este.

Frases en aleman

hojeando un libro me encontré con frases de viajes en alemán, rescato 2 que están buenas.

Die Welt ist ein Buch, von dem man nur die erste Seite gelesen hat, wenn man nur sein Land gesehen hat.


-- Fougeret de Moubron (1706-1760)

Lo que se traduciría a

El mundo es un libro, del cual uno solo ha leído la primera pagina, cuando solo su tierra a visto.



otra

Wenn ein Reisender nach Hause zurückkehrt, soll er nicht die Bräuche seiner Heimat eintauschen gegen die der Fremden Landes. Nur einige Blumen, von dem, was er in der Ferne gelernt hat, soll er in die Gewohnheiten seines eigenen Landes einpflanzen.


Mas duro de traducir, pero intentemos :P

Si un viajero vuelve a casa, no debe cambiar las costumbres de su patria por las del país extranjero. Sólo unas pocas flores, las cuales ha aprendido en la lejania, debe plantar en las costumbres de su propio país.


-- Francis Bacon (1561 - 1626)

La prueba de la teoria de la evolucion? el primer chico pokemon?

titulo de La Nación:

Evoluciona el chico que sobrevivió a la tragedia aérea en Libia

Evoluciona favorablemente sera?

El copete:

El niño permanece estable tras ser operado por fracturas en sus dos piernas; viajaba con su familia; revelan más detalles sobre su identidad


Si permanece estable entonces no evoluciona.

De la RAE:

1. intr. Dicho de un organismo o de otra cosa: Desenvolverse, desarrollarse, pasando de un estado a otro.

hola mundo web con mochiweb y simplebridge

a falta de buenos ejemplos de como hacer un hola mundo web en erlang hago uno yo aca

para el ejemplo vamos a usar mochiweb y simplebridge

de sus paginas, saco lo siguiente

mochiweb:

MochiWeb is an Erlang library for building lightweight HTTP servers.

simplebridge:


SimpleBridge takes the pain out of coding to multiple Erlang HTTP servers by creating a standardized interface. It currently supports Mochiweb, Inets, and Misultin, with Yaws coming soon.


para usarlos tenemos que tener ambos instalados, asi que empezemos por bajarlos y compilarlos


# creemos una carpeta
mkdir erlweb
cd erlweb
# descargamos simplebridge
git clone http://github.com/rklophaus/SimpleBridge.git

# lo compilamos
cd SimpleBridge/
make

# volvemos a la base
cd ..

# descargamos mochiweb
svn checkout http://mochiweb.googlecode.com/svn/trunk/ mochiweb

# lo compilamos
cd mochiweb/
make

# volvemos a la base
cd ..



bueno, ya tenemos los componentes necesarios, vamos con el ejemplo, crea un archivo hello.erl y pega el siguiente codigo:

-module(hello).
-export([start/0, loop/1]).

start() ->
Options = [{ip, "127.0.0.1"}, {port, 8000}],
Loop = fun loop/1,
mochiweb_http:start([{name, mochiweb_example_app}, {loop, Loop} | Options]).

response(Req, Root) ->
simple_bridge:make_response(mochiweb_response_bridge, {Req, Root}).

response_ok(Req, Root, ContentType, Data) ->
Response = response(Req, Root),
Response1 = Response:status_code(200),
Response2 = Response1:header("Content-Type", ContentType),
Response3 = Response2:data(Data),
Response3:build_response().

loop(Req) ->
HTML = ["<h1>Hello, World!</h1>"],
response_ok(Req, "./wwwroot", "text/html", HTML).


ahora abrimos una consola interactiva incluyendo en el path los modulos que vamos a usar (mochiweb y simplebridge)


erl -pa ./mochiweb/ebin/ -pa ./SimpleBridge/ebin/


en la consola:


Eshell V5.7.4 (abort with ^G)
1> c(hello).
{ok,hello}
2> hello:start().
{ok,}


abrimos nuestro navegador apuntando a http://localhost:8000/ y deberiamos ver nuestro hola mundo

obviamente que te voy a dar la version en efene ;) pero esta ves en ifene (la diferencia es que ifene define bloques por indentacion en lugar de llaves)

@public
start = fn ()
Options = [(ip, "127.0.0.1"), (port, 8000)]
Loop = fn loop:1
mochiweb_http.start([(name, mochiweb_example_app), (loop, Loop) : Options])

response = fn (Req, Root)
simple_bridge.make_response(mochiweb_response_bridge, (Req, Root))

response_ok = fn (Req, Root, ContentType, Data)
Response = response(Req, Root)
Response1 = Response.status_code(200)
Response2 = Response1.header("Content-Type", ContentType)
Response3 = Response2.data(Data)
Response3.build_response()

@public
loop = fn (Req)
HTML = ["<h1>Hello, World!</h1>"]
response_ok(Req, "./wwwroot", "text/html", HTML)


lo guardamos en hello.ifn y lo compilamos


fnc hello.ifn


lo ejecutamos desde la consola de erlang (mas facil ;)


erl -pa ./mochiweb/ebin/ -pa ./SimpleBridge/ebin/


en la consola:


Eshell V5.7.4 (abort with ^G)
1> hello:start().
{ok,}


deberiamos obtener el mismo resultado.