<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Hyperreals *R</title>
	
	<link>http://ch3m4.org/blog</link>
	<description>quarks, bits y otras criaturas infinitesimales</description>
	<lastBuildDate>Sat, 12 May 2012 16:11:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Hyperreals" /><feedburner:info uri="hyperreals" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><item>
		<title>Lingua Franca</title>
		<link>http://ch3m4.org/blog/2012/05/12/lingua-franca/</link>
		<comments>http://ch3m4.org/blog/2012/05/12/lingua-franca/#comments</comments>
		<pubDate>Sat, 12 May 2012 16:11:31 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Pensamientos]]></category>
		<category><![CDATA[CompSci]]></category>
		<category><![CDATA[computing science]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=419</guid>
		<description><![CDATA[Este mes de mayo, el conocido y muchas veces criticado índice tiobe comenta que, tras 8 años, las posiciones en este índice de los lenguajes de programación no han sufrido demasiado altibajos, con excepciones notables como el &#8220;Objective C&#8221; empleado por el ecosistema Apple (iPhone/iPad/MacOS). Achaca esta inmovilidad a lo costoso de trasladar todo el [...]]]></description>
			<content:encoded><![CDATA[<p>Este mes de mayo, el conocido y muchas veces criticado <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" title="TIOBE Programming Community Index">índice tiobe</a> comenta que, tras 8 años, las posiciones en este índice de los lenguajes de programación no han sufrido demasiado altibajos, con excepciones notables como el <em>&#8220;Objective C&#8221;</em> empleado por el <em>ecosistema Apple</em> (<em>iPhone/iPad/MacOS</em>).  Achaca esta inmovilidad a lo costoso de trasladar todo el código base que hemos acumulado de un lenguaje a otro, optando por mantenerse fiel a lenguaje que está utilizando.</p>

<p>Desde mi punto de vista, ésta no es una razón de peso hoy en día. Los distintos lenguajes de programación pueden compartir librerías sin demasiados problemas. Tecnologías como <code>.Net</code> o <code>JVM</code> facilitan bastante esta tarea, de modo que la mezcla de lenguajes es posible, sin obligar a elegir un único lenguaje al inicio de un desarrollo.</p>

<p>Pienso, por ejemplo, en todos los lenguajes de programación existentes para JVM (groovy, scala, clojure, jython, jruby,&#8230;). Todos ellos pueden usar las mismas librerías que usa java, aportando a su vez opciones con las que no cuenta java. Tal vez en esa proliferación de lenguajes alternativos se encuentre la explicación de porqué java ha perdido posiciones con respecto a C++. La evolución de Java se ha quedado algo estancada, tardando demasiado en incorporar características tan demandadas como las <em>&#8220;clausuras&#8221;</em> o <em>tipos dinámicos</em> que ofrecen los otros lenguajes.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p>Porque es la evolución de los lenguajes de programación lo que realmente es interesante. No hace muchos años, creo que en la revista DrDobb&#8217;s, existía una sección fija dedicada al <em>&#8220;lenguaje exótico del mes&#8221;</em> que pretendía mostrar lenguajes más expresivos, muchos de dominio específico orientados a resolver problemas concretos, pero donde a veces se veían pequeñas joyas como el APL. Los lenguajes de uso habitual se consideraban limitados, y muchas veces la evolución en los algoritmos fallaba en el preciso momento de tener que codificarlo en un programa de ordenador. El lenguaje máquina dejó paso a otros modo de entenderse con la máquina.</p>

<p>Con el tiempo, cuando la programación se convirtió en ciencia, aparecieron los <strong>&#8220;paradigmas&#8221;</strong> y las <strong>&#8220;metodologías&#8221;</strong>. La programación se volvió bastante más abstracta y la ingeniería impuso sus reglas de eficiencia que terminó por relegar los lenguajes de programación a un segundo plano. La <em>&#8220;expresividad&#8221;</em> se conseguía ahora mediante herramientas CASE e IDEs inteligentes que imponían sus lenguajes de programación.</p>

<p>Estamos en una época que poco va a cambiar en cuanto a lenguajes, tal como afirma <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" title="TIOBE Programming Community Index">Tiobe</a>. La razón de peso son las herramientas que usamos, que no las librerías. Los lenguajes más populares (los que aparecen en el índice tiobe) poseen un proceso evolutivo por el que adaptan los aciertos de los otros y se desprenden de lo obsoleto. No aumenta el número de lenguajes, pero las versiones de los lenguajes aumentan sin parar. Una estrategia evolutiva en el más amplio sentido que hace que los lenguajes se parezcan cada vez más entre sí, con formas muy similares para resolver los mismo problemas que llamamos &#8220;patrones de diseño&#8221; y concepciones similares.</p>

<p>¿El inicio de una <em>&#8220;Lingua Franca&#8221;</em>?</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>En la literatura, se suele mencionar al lenguaje Scala como &#8220;lo que debería haber sido la evolución de Java&#8221;.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2012/05/12/lingua-franca/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problemas con los nombres largos en NTFS</title>
		<link>http://ch3m4.org/blog/2012/04/04/problemas-con-los-nombres-largos-en-ntfs/</link>
		<comments>http://ch3m4.org/blog/2012/04/04/problemas-con-los-nombres-largos-en-ntfs/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 12:07:16 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[ntfs]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=394</guid>
		<description><![CDATA[Un buen día comenté a un compañero de trabajo que en su carpeta compartida del servidor de ficheros pronto iba a tener problemas al usar nombres de carpetas demasiado largos. El explorador de ficheros ya se negaba a listas algunas carpetas y el problema iba a más con algunas herramientas (backups, antivirus,&#8230;). La respuesta fue [...]]]></description>
			<content:encoded><![CDATA[<p>Un buen día comenté a un compañero de trabajo que en su carpeta compartida del servidor de ficheros pronto iba a tener problemas al usar nombres de carpetas demasiado largos. El explorador de ficheros ya se negaba a listas algunas carpetas y el problema iba a más con algunas herramientas (backups, antivirus,&#8230;).</p>

<p>La respuesta fue una pregunta: <em>¿Sería posible sacar un listado de todos los ficheros con ruta absoluta demasiado larga?</em></p>

<p>Después de dudar un rato (y comprobar que el comando <code>dir</code> no era válido para esta labor) , me decidí a averiguar si python sería capaza de realizar dicha tarea. Éste es el resultado de ése estudio.</p>

<h2>Problema con los nombres largos</h2>

<p>Resulta bastante chocante que la API de windows limite la máxima longitud para una ruta al valor de <strong>MAX_PATH</strong>, definido como 260 caracteres. Se trata únicamente de una limitación en la API, ya que el kernel de windows está preparado para manejar rutas muchísimo más largas. Como consecuencia, muchas aplicaciones fallan con rutas largas, desde los comandos de terminal hasta las utilidades gráficas del sistema.</p>

<p>Para evitar en parte este problema, podemos usar en nuestras aplicaciones las versiones <em>unicode</em> de las funciones <em>ANSI</em> de la API. Estas versiones unicode admiten como parámetros rutas de hasta 32.767 caracteres, suficientemente largas para un uso normal.</p>

<p>En en caso de la librería estándar de python, el módulo <code>os.path</code> (sinónimo de <code>os.ntpath</code> en windows) tiene buena cuenta de qué API invocar, según sea el caso. De un modo transparente, <strong>con sólo codificar las rutas en unicode evitaremos la limitación <code>MAX_PATH</code> en la longitud de las rutas</strong>.</p>

<h2>Codificación de rutas extendida</h2>

<p>Además de codificar las rutas en unicode, tenemos que indicar que se trata de una <em>ruta extendida</em> añadiendo el prefijo <code>'\\?\'</code> a una ruta absoluta. Por ejemplo, <code>"\\?\D:\ruta\muy\muy\larga"</code>. Como gran limitación, no se puede usar esta nomenclatura con rutas relativas, por lo que las rutas relativas siempre estarán limitadas a <code>MAX_PATH</code> como máxima longitud.</p>

<p>Es posible, también, indicar una ruta <abbr title="Universal Naming Convention">UNC</abbr> (<em>Universal Naming Convention</em>) como <em>ruta extendida</em> como <code>\\?\server\share</code>, donde <code>server</code> sería el nombre del servidor y <code>share</code> el nombre de la carpeta compartida.</p>

<p>Para más información sobre las rutas extendidas, visitar la página web <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx" title="Naming Files, Paths, and Namespaces">Naming Files, Paths, and Namespaces</a> de MSDN.</p>

<h2>Script para listar ficheros de nombres muy largos</h2>

<p>Por último, sólo queda lo más fácil: codificar el script <img src='http://ch3m4.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<p>Es común que la codificación que lleva por defecto la cónsola de comandos falle con las cadenas unicode. Si pensamos sacar por cónsola los nombres de ficheros, lo recomendable es cambiar la codificación por una más apropiada, como la <code>cp1252</code>, lo más aproximado a <code>utf-8</code> que podemos encontrar:</p>

<pre><code>    C:\&gt; chcp 1252
</code></pre>

<p>Para hacer nuestro script, podríamos haber usado cualquiera de las funciones <code>os.walk</code> de la librería estándar; pero, no sé porqué, fallan a crear la lista de directorios. Ésto nos obliga a crear nuestro propio método para recorrer la jerarquía de directorios.</p>

<p>Por comodidad, voy a lanzar el script en una máquina distinta de la que hace de servidor de ficheros ya que no dispongo de python en los servidores. Usaré la nomenclatura <abbr title="Universal Naming Convention">UNC</abbr> para identificar los recursos compartidos.</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#-*- coding: utf-8 -*-</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span><br />
<br />
MAX_PATH<span style="color: #66cc66;">=</span><span style="color: #ff4500;">260</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> longnames<span style="color: black;">&#40;</span>dirpath<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;Iterador que devuelve las rutas largas (&gt;=MAX_PATH)&quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#Hay que forzar unicode para evitar el límite MAX_PATH</span><br />
&nbsp; &nbsp; dirpath<span style="color: #66cc66;">=</span><span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>dirpath<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> dirpath.<span style="color: black;">endswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; dirpath+<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><br />
<br />
&nbsp; &nbsp; dirs<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>dirpath<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; name <span style="color: #66cc66;">=</span> dirpath+f<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span><span style="color: #66cc66;">&gt;=</span>MAX_PATH:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">yield</span> name<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#poblar la lista de directorios</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#para recorrer en orden</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dirs.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> d <span style="color: #ff7700;font-weight:bold;">in</span> dirs:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> longnames<span style="color: black;">&#40;</span>d<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">yield</span> f<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> listshare<span style="color: black;">&#40;</span>server<span style="color: #66cc66;">,</span> share<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;Crea un UNC para el recurso compartido.<br />
&nbsp; &nbsp; &nbsp; &nbsp;Devuelve un iterador para las rutas largas (&gt;=MAX_PATH)<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span> &nbsp; &nbsp;<br />
&nbsp; &nbsp; dirpath<span style="color: #66cc66;">=</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>?<span style="color: #000099; font-weight: bold;">\U</span>NC<span style="color: #000099; font-weight: bold;">\%</span>s<span style="color: #000099; font-weight: bold;">\%</span>s&quot;</span>%<span style="color: black;">&#40;</span>server<span style="color: #66cc66;">,</span> share<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> longnames<span style="color: black;">&#40;</span>dirpath<span style="color: black;">&#41;</span></div></div>

<p>Su uso simple podía ser:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#-*- coding: utf-8 -*-</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">codecs</span><br />
<br />
<span style="color: #808080; font-style: italic;">#PARÁMETROS</span><br />
SERVER<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;MiServidor&quot;</span><br />
SHARE<span style="color: #66cc66;">=</span>r<span style="color: #483d8b;">&quot;Usuario<span style="color: #000099; font-weight: bold;">\d</span>ir1&quot;</span><br />
<br />
fOut<span style="color: #66cc66;">=</span><span style="color: #dc143c;">codecs</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;longnames.txt&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;utf-8&quot;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> listshare<span style="color: black;">&#40;</span>SERVER<span style="color: #66cc66;">,</span>SHARE<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> name<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span>fOut<span style="color: #66cc66;">,</span> name.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>DIRPATH<span style="color: #66cc66;">,</span><span style="color: #483d8b;">&quot;.<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
fOut.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2012/04/04/problemas-con-los-nombres-largos-en-ntfs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programación. ¿Ciencia o Ingeniería?</title>
		<link>http://ch3m4.org/blog/2012/03/09/programacion-ciencia-o-ingenieria-2/</link>
		<comments>http://ch3m4.org/blog/2012/03/09/programacion-ciencia-o-ingenieria-2/#comments</comments>
		<pubDate>Fri, 09 Mar 2012 21:21:32 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Ciencia]]></category>
		<category><![CDATA[Pensamientos]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=390</guid>
		<description><![CDATA[Cuando inicié este blog, además de servir de soporte a algunos artículos técnicos sobre programación que fueran más o menos novedosos, también me movió la idea de aportar reflexiones sobre algunos temas interdisciplinares que constantemente me hacía debido a mi formación científica y que he ido acumulando durante todos estos últimos años. Creo que es [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando inicié este blog, además de servir de soporte a algunos artículos técnicos sobre programación que fueran más o menos novedosos, también me movió la idea de aportar reflexiones sobre algunos temas <em>interdisciplinares</em> que constantemente me hacía debido a mi formación científica y que he ido acumulando durante todos estos últimos años. Creo que es momento de empezar con ellos&#8230;</p>

<h2>En busca de la materia gris</h2>

<p>Todavía persiste el mito de considerar que un informático es una especie de chamán que con unos cuantos pases mágicos delante de una pantalla es capaz de hacer que un ordenador tome vida. Muy pocos asumen que un informático pueda tener una formación científica o técnica seria que se encuentre al mismo nivel que un médico o un ingeniero. Y así nos van las cosas.</p>

<p>No tomarse en serio la formación de un informático está llevando a que muchas empresas del sector no valoren suficientemente la destreza de sus empleados. Asumen que siempre podrán encontrar nuevos empleados a los que poder darles una pequeña formación suficiente para encargarse de cualquier proyecto que tengan en marcha. Si supieran un mínimo de ingeniería, sabrían que siempre hay un límite en todo proyecto en el que añadiendo más recursos nunca se consigue acelerar el desarrollo, si no más bien lo contrario. Momentos de dificultad que desemboca en una crisis<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, donde prima más la experiencia que la cantidad de manos disponibles.</p>

<p>La actual crisis económica ha venido a agravar más el panorama al minusvalorar aún más a los profesionales de informática. Los buenos profesionales optan por emigrar a otros países donde sean mejor considerados, mientras que aquí las empresas compiten bajando más y más los precios, sin tener en consideración ni la calidad ni la idoneidad del producto que desarrollan.</p>

<p>Estamos inmersos entre sistemas informáticos y de telecomunicaciones que se están colapsando debido a malos diseños y falta de mantenimiento, con usuarios que asumen por normal que un sistema pueda fallar, que los virus puedan entrar hasta las entrañas del ordenador, o que un <em>hacker</em> pueda bloquear cualquier sistema gubernamental y robar identidades,&#8230; y lo único que importa a los responsables es que alguna empresa sin escrúpulos asuma la culpa por el menor precio posible.</p>

<h2>El fin de la ley de Moore</h2>

<p>Es sabido que por la <a href="http://es.wikipedia.org/wiki/Ley_de_moore" title="Ley de Moore">Ley de Moore</a> en estos 50 años pasados, se estaba cumpliendo que cada dos años los ordenadores doblaban su velocidad, mientras se hacían cada vez más y más baratos. Como consecuencia, las aplicaciones mal diseñadas aún se podían sobrellevar gracias a la reducción de costes y mejoras de velocidad que ofrecían los nuevos sistemas.</p>

<p>Lamentablemente, la ley de Moore llega a su final. Se intenta prorrogar su vigencia metiendo más <em>cores</em> en cada cpu, pero si bien se sigue contando con procesadores más baratos y más rápidos, un sistema multicore no es aprovechable por una aplicación mal diseñada. Para aprovechar una cpu multicore, se requiere de nuevas aplicaciones diseñadas específicamente para ellos. Hoy en día, muchos sistemas operativos sólo son capaces de aprovechar un core de todos los disponibles, lo que no deja de ser un engaño para el usuario que piensa que debería ir todo más rápido. Estamos muy cerca de una nueva crisis similar a la crisis del software, pero con hardware esta vez.</p>

<p>Es una burbuja que pronto va a estallar como tantas otras antes.</p>

<h2>Poner en valor al programador</h2>

<p>Hace tiempo que se perdió el significado de ser un <strong>&#8220;programador&#8221;</strong>. Con ese nombre se ha pasado a denominar un puesto técnico de trabajo que está por debajo de analista y un poco por encima de reparador de hardware. Nada que tenga qué ver con un trabajo metodológico y, en cierta medida, creativo.</p>

<p>Y, sin embargo, contar con buenos programadores debería ser parte del activo de una empresa que la ponga en valor. No es entendible que haya empresas que busquen programadores después de haberse comprometido con un proyecto de desarrollo. Debería ser más bien al revés, que para conseguir un proyecto se haya valorado antes qué programadores dispone la empresa en nómina.</p>

<p>Puedo asegurar que hay alguna empresa que cuenta con un núcleo de buenos programadores, normalmente gente joven que montan su propia empresa, que nunca les falta trabajo. Pero son mucho más numerosas las empresas vacías que se dedican a quemar sistemáticamente a toda su plantilla en proyectos difíciles de asumir sin la gente y los medios adecuados.</p>

<p>Contar con programadores experimentados no es tarea fácil. Toda empresa debería asegurar a sus programadores más valiosos, nunca deberían considerarlos inferiores a analistas, ya que asumen roles distintos. Un buen programador puede ser un pésimo analista y viceversa. Un buen programador debería estar bien pagado simplemente como programador, y no verse presionado para ser analista si quiere ascender y cobrar más.</p>

<h2>Programación. ¿Ciencia o Ingeniería?</h2>

<p>Según donde busques, la programación es parte de la <em>Ciencia de la Computación</em> o es parte de la <em>Ingeniería del Software</em>. Personalmente, me inclino más por que sea una ciencia.  Un buen programador siempre intenta comprender el funcionamiento de un programa con el fin de crear nuevos y mejores programas. Usa un ciclo de análisis, desarrollo, prueba y refactorización que tanto se parece al <em>&#8220;método científico&#8221;</em>, experimentando hipótesis hasta dar con una solución. La ingeniería entraría cuando se requiere que la aplicación se ajuste a determinados requisitos, donde a veces no importa tanto la optimización del programa como el que se ajuste su funcionamiento a los parámetros requeridos.</p>

<p>¿Es posible buscar la belleza entre líneas de código? ¿Evolucionamos hacia mejores lenguajes de programación?</p>

<p>Temas para próximos artículos.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>véase <a href="http://es.wikipedia.org/wiki/Crisis_del_software">Crisis del Software</a>&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2012/03/09/programacion-ciencia-o-ingenieria-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Estudio función factorial en scala – Revisión funcional</title>
		<link>http://ch3m4.org/blog/2012/02/07/estudio-funcion-factorial-en-scala-revision-funcional/</link>
		<comments>http://ch3m4.org/blog/2012/02/07/estudio-funcion-factorial-en-scala-revision-funcional/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 12:41:32 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Scala]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[factorial]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=382</guid>
		<description><![CDATA[Como programador de python que todavía anda algo despistado estudiando scala, ahora empiezo a captar la filosófía que hay detrás de este lenguaje de programación. Mientras que python empienza a erradicar poco a poco la programación funcional, en scala su influencia es cada vez mayor hasta el extremo de considerar precindibles la mayoría de los [...]]]></description>
			<content:encoded><![CDATA[<p>Como programador de python que todavía anda algo despistado estudiando scala, ahora empiezo a captar la filosófía que hay detrás de este lenguaje de programación. Mientras que python empienza a erradicar poco a poco la programación funcional, en scala su influencia es cada vez mayor hasta el extremo de considerar precindibles la mayoría de los bucles. Aún asi, ambos lenguajes soportan la <em>&#8220;compresión de listas&#8221;</em> como técnica a medio camino entre funcional y bucle estándar, aunque esta técnica está más orientada a obtener listas a partir de otras listas, y no para realizar cálculos sobre un conjunto de números.</p>

<p>Voy a completar el anterior artículo que trataba del <a href="http://ch3m4.org/blog/2011/10/17/estudio-funcion-factorial-en-scala/">&#8220;Estudio función factorial en scala&#8221;</a> con algunas formas más <em>&#8220;funcionales&#8221;</em> de definir el factorial:</p>

<p>La forma más simple de definir la función factorial:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span> to n<span style="color: #F78811;">&#41;</span>.<span style="color: #000000;">product</span></div></div>

<p>En realidad, <code>1 to n</code> no es un elemento sintáctico del lenguaje, si no más bien la forma <em>alternativa</em> de escribir la invocación del método <code>1.to(n)</code>. Este método nos genera una secuencia de números desde el 1 al n (equivalente en python a range(1,n+1)).</p>

<p>Curiosamente, también está definido <code>fact(0)</code> gracias a que <code>product</code> da como resultado el elemento neutro <code>1</code> en secuencias vacías <sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.</p>

<p>Esta forma concisa de calcular el producto es común a todas las secuencias en scala. Faltaría, tan sólo, que operara con BigInts para que fuera perfecta:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span>BigInt<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span> to n<span style="color: #F78811;">&#41;</span>.<span style="color: #000000;">product</span></div></div>

<p>No es necesario indicar el tipo devuelto por la función puesto que el compilador es capaz de inferirlo de la expresión.</p>

<p>Otra forma funcional sería usando el método <code>reduce</code>, donde se indica <em>explícitamente</em> la operación binaria a realizar entre pares de elementos:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span>BigInt<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span> to n<span style="color: #F78811;">&#41;</span>.<span style="color: #000000;">reduce</span><span style="color: #F78811;">&#40;</span><span style="color: #000080;">_*_</span><span style="color: #F78811;">&#41;</span></div></div>

<p>Como operación se pone una especie de <em>plantilla</em> (<em>pattern</em>) que representa la operación binaria de multiplicación. Por comparar, en python se puede hacer algo así:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">operator</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #0000cd;">__mul__</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> fact<span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp;<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #0000cd;">__mul__</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span>n+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></div>

<p>Lamentablemente, el operador funcional <code>'reduce'</code> está desapareciendo de python por considerarlo complejo de entender en su funcionamiento <sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>.</p>

<p>Por último, aún existe otra forma funcional de expresar el factorial en scala. Son los <em>&#8220;plegados&#8221;</em> (<em>folds</em>), similar en funcionamiento a <code>reduce</code>, pero con control sobre la dirección del recorrido y la posibilidad de dar un valor inicial:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span> to n<span style="color: #F78811;">&#41;</span>.<span style="color: #000000;">foldLeft</span><span style="color: #F78811;">&#40;</span>BigInt<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#40;</span><span style="color: #000080;">_*_</span><span style="color: #F78811;">&#41;</span></div></div>

<p>Seguro que pronto se me ocurrirán más formas.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>En el caso del método <code>sum</code> daría el elemento neutro para la suma, o sea, el <code>0</code>.&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

<li id="fn:2">
<p>Personalmente, considero que la desaparición de la programación funcional se debe más a la corta visión de quién sólo ve un encadenamiento de sentencias, en lugar de ver <em>&#8220;actores&#8221;</em> interaccionando en libre concurrencia.&#160;<a href="#fnref:2" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2012/02/07/estudio-funcion-factorial-en-scala-revision-funcional/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Codificando en binario</title>
		<link>http://ch3m4.org/blog/2012/01/26/condificando-en-binario/</link>
		<comments>http://ch3m4.org/blog/2012/01/26/condificando-en-binario/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 19:24:23 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[tip]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=375</guid>
		<description><![CDATA[A raiz de la consulta de un colega, me ha llamado la atención el módulo binascii. Este módulo se encarga de la codificación y decodificación de cadenas binarias para su transmisión en mensajes de texto. Lo habitual es que sea usado por otros módulos como uu, base64 o binhex, por lo que no es nada [...]]]></description>
			<content:encoded><![CDATA[<p>A raiz de la consulta de un colega, me ha llamado la atención el módulo <code>binascii</code>. Este módulo se encarga de la codificación y decodificación de cadenas binarias para su transmisión en mensajes de texto. Lo habitual es que sea usado por otros módulos como <code>uu</code>, <code>base64</code> o <code>binhex</code>, por lo que no es nada frecuente ver su uso directo en una aplicación.</p>

<p>Sin embargo, <code>binascii</code> posee algunas funciones que pueden sernos bastante útiles a la hora de simplificar el empaquetado de datos que requieren determinadas APIs, en lugar de usar estructuras más complejas como <code>array</code> o <code>struct</code>. También se revela muy útil a la hora de crear batería de tests donde necesitemos chequear valores binarios.</p>

<h2>Estructuras array y struct</h2>

<p>Por ejemplo, imaginemos que nuestra API nos pide que empaquetemos un número entero como cuatro bytes. Antes de python3 no existía una forma para controlar el tamaño en bytes de un objeto sin tener que recurrir a alguna estructura especializada. Por ejemplo:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">array</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">array</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> numpack<span style="color: black;">&#40;</span>num<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; a<span style="color: #66cc66;">=</span><span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; a.<span style="color: black;">append</span><span style="color: black;">&#40;</span>num<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> a.<span style="color: black;">tostring</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>::-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><br />
<br />
n<span style="color: #66cc66;">=</span>numpack<span style="color: black;">&#40;</span><span style="color: #ff4500;">0xffeeddcc</span><span style="color: black;">&#41;</span> &nbsp;<span style="color: #808080; font-style: italic;"># res: \xff\xee\xdd\xcc</span></div></div>

<p>En el resultado final ha hecho falta invertir el orden de los bytes debido a que nos estaba usando un orden <em>&#8220;little-endian&#8221;</em> para su codificación. El orden puede depender del sistema donde estemos trabajando, con lo que no es nada seguro usar este método. Es preferible el uso más especializado de <code>struct</code> donde tendremos algo más de control sobre éste y muchos otros aspectos:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">struct</span> <span style="color: #ff7700;font-weight:bold;">import</span> pack<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> numpack<span style="color: black;">&#40;</span>num<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> pack<span style="color: black;">&#40;</span><span style="color: #483d8b;">'!L'</span><span style="color: #66cc66;">,</span> num<span style="color: black;">&#41;</span><br />
<br />
n<span style="color: #66cc66;">=</span>numpack<span style="color: black;">&#40;</span><span style="color: #ff4500;">0xffeeddcc</span><span style="color: black;">&#41;</span> &nbsp;<span style="color: #808080; font-style: italic;"># res: \xff\xee\xdd\xcc</span></div></div>

<p>Nota que en la cadena de formato que se pasa a <code>pack()</code> tiene un indicador <code>'!'</code> al principio, con el que indicamos que queremos una ordenación <em>&#8220;network (=big-endian)&#8221;</em>.</p>

<p>El proceso inverso es tan fácil como usar la función complementaria <code>unpack</code>:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">unpack<span style="color: black;">&#40;</span><span style="color: #483d8b;">'!L'</span><span style="color: #66cc66;">,</span> n<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span></div></div>

<h2>Codificando mensajes</h2>

<p>Lo visto hasta ahora funciona bien cuando tenemos que interaccionar con una API que use tamaños fijos para los datos. Pero, ¿qué pasa cuando los datos son de longitud variable, por ejemplo, un mensaje largo de decenas de bytes? En el mejor de los casos, tendríamos que ir byte a byte, tal vez apoyándonos en <code>array</code> o <code>struct</code> para realizar las conversiones, algo a todas luces resulta bastante tedioso.</p>

<p>Como ya adelanté, el módulo <code>binascii</code> nos va a ayudar en este cometido, en concreto la función <code>b2a_hex</code> y su contraparte <code>a2b_hex</code>.</p>

<p>Por ejemplo, nos envían en un mensaje un entero codificado en multibyte. No sabemos si son 2, 4 u 8 bytes, o incluso podrían ser más bytes de tratarse de un <code>BigInt</code> (entero muy largo). Con <code>binascii</code> podríamos resolverlo así:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">binascii</span> <span style="color: #ff7700;font-weight:bold;">import</span> b2a_hex<span style="color: #66cc66;">,</span> a2b_hex<br />
<br />
num <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>b2a_hex<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">16</span><span style="color: black;">&#41;</span></div></div>

<p>Para el proceso contrario, codificar un entero en una cadena binaria, usaríamos <code>a2b_hex</code>:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">h <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;%x&quot;</span>%num<br />
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>h<span style="color: black;">&#41;</span>%<span style="color: #ff4500;">2</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">1</span>:<br />
&nbsp; &nbsp; h <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;0&quot;</span> + h<br />
<br />
msg <span style="color: #66cc66;">=</span> a2b_hex<span style="color: black;">&#40;</span>h<span style="color: black;">&#41;</span></div></div>

<p>Hemos tenido cuidado de que la cadena hexadecimal tenga longitud par ya que <code>a2b_hex</code> codifica siempre cada byte a partir de una pareja de dígitos hexadecimales.</p>

<h2>Estudio codificaciones unicode</h2>

<p>También es posible usar <code>binascii</code> para estudiar las codificaciones de cadenas unicode, lo que hace más sencillo crear tests automáticos para funciones que empleen unicode. Sin muchos adornos, haríamos algo así:</p>

<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">#-*- coding: utf-8 -*-</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">binascii</span> <span style="color: #ff7700;font-weight:bold;">import</span> b2a_hex<span style="color: #66cc66;">,</span> a2b_hex<br />
<br />
cadena <span style="color: #66cc66;">=</span> u<span style="color: #483d8b;">&quot;Peón <span style="color: #000099; font-weight: bold;">\N</span>{BLACK CHESS PAWN}&quot;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">print</span> b2a_hex<span style="color: black;">&#40;</span>cadena.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf-8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;">#res: 5065c3b36e20e2999f</span></div></div>

<p>Comparando el resultado obtenido con la cadena unicode, vemos que la <em>ó</em> acentuada se codifica en &#8216;utf-8&#8242; como <code>0xc3b3</code>, o que la figura de peón negro se codifica como <code>0xe2999f</code>.</p>

<p>Si cambiamos la codificación por &#8216;utf-16&#8242; obtenermos como resultado <code>fffe50006500f3006e0020005f26</code>. Además de ser más larga, vemos que se añade al principio <code>fffe</code>, que es lo que se denomina <abbr title="Byte Order Mark">BOM</abbr>, y que nos indica qué ordenación de bytes se ha usado en la codificación (<code>'FEFF'</code> para <em>Big Endian</em> / <code>'FFFE'</code> para <em>Little Endian</em>). Con <code>fffe</code> nos indica concretamente que se ha usado la codificación &#8216;UTF-16 Little Endian&#8217;, con lo que tenemos los bytes invertidos para cada caracter codificado (ver más info en el <a href="http://es.wikipedia.org/wiki/Marca_de_orden_de_bytes_(BOM)">artículo sobre <abbr title="Byte Order Mark">BOM</abbr></a> de la wikipedia).</p>

<p>De no desear que se nos añada la marca <abbr title="Byte Order Mark">BOM</abbr>, podríamos haber forzado la codificación mediante <code>'utf-16be'</code> ó <code>'utf-16le'</code> para <em>Big Endian</em> y <em>Little Endian</em>, respectivamente.</p>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2012/01/26/condificando-en-binario/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web2py, con pilas incluidas</title>
		<link>http://ch3m4.org/blog/2011/12/01/web2py-con-pilas-incluidas/</link>
		<comments>http://ch3m4.org/blog/2011/12/01/web2py-con-pilas-incluidas/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 18:34:12 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[web2py]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/2011/12/01/web2py-con-pilas-incluidas/</guid>
		<description><![CDATA[He estado últimamente trabajando en varios proyectos que me han hecho descuidar un poco el blog. En próximos días espero publicar algunos artículos relacionados que creo serán de interés. Lo último que estoy haciendo es un desarrollo de aplicación de escritorio con web2py, a pesar de tratarse de un framework para crear aplicaciones web. Corre [...]]]></description>
			<content:encoded><![CDATA[<p>He estado últimamente trabajando en varios proyectos que me han hecho descuidar un poco el blog. En próximos días espero publicar algunos artículos relacionados que creo serán de interés.</p>

<p>Lo último que estoy haciendo es un desarrollo de aplicación de escritorio con <a href="http://www.web2py.com">web2py</a>, a pesar de tratarse de un framework para crear aplicaciones web. Corre desde un navegador cualquiera, interaccionando con [jQuery] para la presentación, y con python corriendo por debajo para dar soporte a la capas de datos y lógica de negocio.</p>

<h2>¿Por qué web2py?</h2>

<p>Como indico en el título, web2py lleva las <em>&#8220;pilas incluidas&#8221;</em>, que tratándose de python significa que incluye todo lo puedas necesitar. ¡Y no exagero! La selección de <a href="http://www.web2py.com/book/default/chapter/04#Libraries">librerías</a> que incluye es extensa, permitiendo desarrollar casi cualquier aplicación web que necesites, con herramientas administrativas tanto para el modelo de datos como para editar los ficheros vistas y controladores. Vamos, que con descomprimir el fichero con web2py y un navegador ya tienes todo lo necesario para desarrollar la aplicación, desde una simple aplicación estática, hasta una completa aplicación que funcione en el Google AppEngine. Además posee un sistema de plugins que permite cambiar fácilmente el diseño de la web o añadir funcionalidades.</p>

<p>Hasta ahora, había probado algunos GUIs graficos como pyqt o wxpython que incluyeran algún <em>widget</em> html para renderizar páginas webs y poder controlarlas desde el programa python, algo bastante costoso de programar y con serias incompatibilidades a la hora de presentar la página web. Con web2py, la aplicación de escritorio se orienta a una aplicación web con el servidor web corriendo directamente en el cliente. Web2py permite abstraer algunas facilidades ajax y jquery habituales, aunque no resulta difícil usar el resto de funcionalidades de jquery en las aplicaciones sin tener que ser un experto en programación javascript.</p>

<p>Uno de los problemas que también había tenido hasta ahora era en la distribución de aplicaciones python para windows. Habitualmente, hace falta instalar varias herramientas en el sistema, desde el intérprete python hasta todas las librerías necesarias, algunas complicadas de hacerlas funcionar. Bien es cierto que existen formas de empaquetar una aplicación usando py2exe (py2app en MacOS), pero casi siempre hay alguna cosa que no funciona bien del todo. Web2py viene con todo empaquetado para su uso en windows y macOS, incluyendo el intérprete python y resto de librerías necesarias. Basta descomprimir el fichero y, sin intalación, ejecutar el servidor web y abrir un navegador. Las aplicaciones web son carpetas que podemos copiar de una instalación a otra o, aún más sencillo, usar el interface administrativo para empaquetar e instalar aplicaciones (al estilo <em>tomcat</em>).</p>

<p>Échale un vistazo, y no te dejes las <a href="http://www.web2py.com/book/default/chapter/04#Libraries">&#8220;pilas&#8221;</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2011/12/01/web2py-con-pilas-incluidas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Estudio función factorial en scala</title>
		<link>http://ch3m4.org/blog/2011/10/17/estudio-funcion-factorial-en-scala/</link>
		<comments>http://ch3m4.org/blog/2011/10/17/estudio-funcion-factorial-en-scala/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 19:49:15 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Scala]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[factorial]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=356</guid>
		<description><![CDATA[Como continuación al artículo que dediqué al estudio del factorial, voy a explicar cómo se haría este famoso algoritmo usando scala. Tengo que añadir que tan sólo llevo una semana con el lenguaje scala, por lo que es muy probable que haya algún aspecto de este lenguaje que me haya dejado por el camino. Versión [...]]]></description>
			<content:encoded><![CDATA[<p>Como continuación al artículo que dediqué al <a href="http://ch3m4.org/blog/2011/06/06/estudio-funcion-factorial/">estudio del factorial</a>, voy a explicar cómo se haría este famoso algoritmo usando <a href="http://scala-lang.org" title="Scala programming language">scala</a>. Tengo que añadir que tan sólo llevo una semana con el lenguaje scala, por lo que es muy probable que haya algún aspecto de este lenguaje que me haya dejado por el camino.</p>

<h2>Versión recursiva (y <em>one-line</em>)</h2>

<p>La forma básica de la función sería:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">==</span><span style="color: #F78811;">0</span><span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">1</span><br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> n<span style="color: #000080;">*</span>fact<span style="color: #F78811;">&#40;</span>n-<span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span></div></div>

<p>Si se compara con la función recursiva en python, no parece que haya mucha diferencia, con excepción de que en scala existe el tipado de datos.</p>

<p>Esta función es en realidad una sóla línea, por lo que podíamos haberla escrito de esta manera:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">==</span><span style="color: #F78811;">0</span><span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">1</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> n<span style="color: #000080;">*</span>fact<span style="color: #F78811;">&#40;</span>n-<span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span></div></div>

<p>Es una clara señal de la orientación funcional que tiene scala.</p>

<p>Al igual que python, esta función recursiva se corta cuando se sobrepasa un cierto límite de llamadas recursivas para proteger la memoria del sistema.</p>

<p>El compilador de Scala posee una optimización especial denominda de <em>&#8220;LLamada Terminal&#8221;</em> (<a href="http://en.wikipedia.org/wiki/Tail_call" title="Tail Call">Tail Call</a>)<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> (optimización que no existe en JVM). Este tipo de optimizaciones son posibles cuando la última línea a ejecutar de la función es únicamente la llamada recursiva a sí misma, con lo cuál hace innecesario guardar el stack de ejecución puesto que no quedarían más líneas para ejecutar.</p>

<p>Para que sea posible aplicar esta optimización de &#8220;llamada terminal&#8221;, tenemos que reescribir nuestra función de modo que la última línea sea una llamada a sí misma. Para ello usaremos una función acumuladora que se encargue de realizar la multiplicación previamente a la llamada. Casi mejor si vemos el código:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> factAcc<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int, acc<span style="color: #000080;">:</span>BigInt<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">&lt;=</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span> acc <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> factAcc<span style="color: #F78811;">&#40;</span>n-<span style="color: #F78811;">1</span>, n<span style="color: #000080;">*</span>acc<span style="color: #F78811;">&#41;</span><br />
<br />
&nbsp; &nbsp; factAcc<span style="color: #F78811;">&#40;</span>n,<span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span><br />
<span style="color: #F78811;">&#125;</span></div></div>

<p>En las últimas versiones de scala existe una <em>&#8220;anotación&#8221;</em> especial para indicar al compilador de scala que intente aplicar la optimización de &#8220;LLamada Terminal&#8221;, o que nos dé un aviso de no poder hacerlo. Finalmente, así quedaría el código de nuestra función recursiva:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">import</span></a> scala.<span style="color: #000000;">annotation</span>.<span style="color: #000000;">tailrec</span><br />
<br />
<a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">@</span>tailrec<br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> factAcc<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int, acc<span style="color: #000080;">:</span>BigInt<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt<span style="color: #000080;">=</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">&lt;=</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span> acc <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> factAcc<span style="color: #F78811;">&#40;</span>n-<span style="color: #F78811;">1</span>, n<span style="color: #000080;">*</span>acc<span style="color: #F78811;">&#41;</span><br />
<br />
&nbsp; &nbsp; factAcc<span style="color: #F78811;">&#40;</span>n,<span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span><br />
<span style="color: #F78811;">&#125;</span></div></div>

<h2>Versión iterativa</h2>

<p>Es la versión más sencilla:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>BigInt <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">var</span></a> res<span style="color: #000080;">=</span>BigInt<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">1</span><span style="color: #F78811;">&#41;</span><br />
&nbsp; &nbsp; <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">for</span></a> <span style="color: #F78811;">&#40;</span>i <span style="color: #000080;">&lt;</span>- <span style="color: #F78811;">1</span> to n<span style="color: #F78811;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; res<span style="color: #000080;">*=</span>i<br />
&nbsp; &nbsp; res<br />
<span style="color: #F78811;">&#125;</span></div></div>

<h2>Fórmula de Stirling</h2>

<p>Para completar el estudio, podemos ver cómo sería la función de Stiling en Scala, bastante similar, como puede verse, a su versión en python:</p>

<div class="codecolorer-container scala dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="scala codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">import</span></a> math.<span style="color: #000080;">_</span><br />
<br />
<a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> fact<span style="color: #F78811;">&#40;</span>n<span style="color: #000080;">:</span>Int<span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span>Double <span style="color: #000080;">=</span><br />
&nbsp; &nbsp; sqrt<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">2</span><span style="color: #000080;">*</span>Pi<span style="color: #000080;">*</span>n<span style="color: #F78811;">&#41;</span><span style="color: #000080;">*</span>pow<span style="color: #F78811;">&#40;</span>n/E,n<span style="color: #F78811;">&#41;</span></div></div>

<div class="footnotes">
<hr />
<ol>

<li id="fn:1">
<p>Existe algún intento para implementar esta optimización de &#8220;Tail Call&#8221; en python, con algunos decoradores más o menos funcionales. Si quieres ver motivos en contra, visita el artículo que escribió Guido sobre el tema: <a href="http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html">http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html</a>&#160;<a href="#fnref:1" rev="footnote">&#8617;</a></p>
</li>

</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2011/10/17/estudio-funcion-factorial-en-scala/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rentrée (nueva temporada)</title>
		<link>http://ch3m4.org/blog/2011/10/08/rentree-nueva-temporada/</link>
		<comments>http://ch3m4.org/blog/2011/10/08/rentree-nueva-temporada/#comments</comments>
		<pubDate>Sat, 08 Oct 2011 17:22:33 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Pensamientos]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[pyday]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/2011/10/08/rentree-nueva-temporada/</guid>
		<description><![CDATA[Desconectado de mis tareas habituales depués de algunas semanas viajando por Francia, veo que me quedaron varios proyectos y artículos en dique seco que pretendo recuperar. Con la &#8220;reentrada&#8221; (o, como dirían los franceses, &#8220;rentrée&#8221;) me he propuesto algunas metas para esta nueva temporada (por llamarla de algún modo) que ahora empiezo. Junto a los [...]]]></description>
			<content:encoded><![CDATA[<p>Desconectado de mis tareas habituales depués de algunas semanas viajando por Francia, veo que me quedaron varios proyectos y artículos en dique seco que pretendo recuperar. Con la <em>&#8220;reentrada&#8221;</em> (o, como dirían los franceses, <em>&#8220;rentrée&#8221;</em>) me he propuesto algunas metas para esta nueva <em>temporada</em> (por llamarla de algún modo) que ahora empiezo.</p>

<p>Junto a los artículos que tengo previstos, intentaré incorporar al blog más comentarios sobre temas técnicos que me vayan surgiendo en el día a día, preferiblemente relacionados con la programación. Sin llegar a la extensión de un artículo, espero que sirvan como gérmen de desarrollos posteriores más extensos.</p>

<p>Como primeras ideas para esta <em>rentrée</em>, he tomados dos decisiones: centrar mis desarrollos en la <a href="http://es.wikipedia.org/wiki/Máquina_virtual_Java">máquina virtual java</a> (plataforma <abbr title="Java Virtual Machine">JVM</abbr>) y aprender a programar con <a href="http://www.scala-lang.org/" title="Lenguaje Scala">scala</a>.</p>

<h2>Máquina Virtual Java (<abbr title="Java Virtual Machine">JVM</abbr>)</h2>

<p>Hoy en día, la <abbr title="Java Virtual Machine">JVM</abbr> está omnipresente para casi cualquier dispositivo y sistema operativo. Su uso empresarial es muy extendido, tanto para desarrollo en el lado servidor como para clientes móviles. Librerías y paquetes suficientemente robustos y probados completan una gran plataforma donde desarrollar cualquier tipo de aplicativo que podamos pensar.</p>

<p>Al evaluar la robustez de las librerías java, hay que tener en cuenta que java y su <abbr title="Java Virtual Machine">JVM</abbr> están en constante evolución. El paso de Java5 a Java6 sido muy lento debido a las pocas ventajas que ofrecía el cambio frente al coste de tener que adaptar el código; pero con Java7 se incorpora a la máquina virtual el poder trabajar con tipos dinámicos de datos, lo que mejorará bastante el rendimiento de los lenguajes de scripting como jython, jruby ó groovy, por poner algunos ejemplos. Este cambio parece independizar el desarrollo de la <abbr title="Java Virtual Machine">JVM</abbr> del lenguaje java para pasar a ser una plataforma común para la ejecución de aplicaciones, sea cual sea el lenguaje que se haya usado (objetivo similar a lo que tenía que haber sido .Net).</p>

<p>En lo personal, desde hace mucho tiempo que estoy programando en jython, tal como comenté en otro <a href="http://ch3m4.org/blog/2011/05/30/porque-uso-jython/">artículo</a>. La llegada de los dispositivos android hace aún más interesante la programación para <abbr title="Java Virtual Machine">JVM</abbr>, así como que las numerosas herramientas de software libre que estoy usando estén para esta plataforma. No quiero decir con ésto que renuncie a utilizar la CPython, la máquina virtual <em>&#8220;nativa&#8221;</em> que lleva python, siempre que sea necesario. Tan sólo priorizo la plataforma, <abbr title="Java Virtual Machine">JVM</abbr>, frente a las últimas implementaciones del lenguaje python. Espero que el proyecto <a href="http://pypy.org/">PyPy</a> facilite un único camino para el desarrollo del lenguaje, independiente de la máquina virtual empleada.</p>

<h2>Lenguaje Scala</h2>

<p>Poco conozco de este lenguaje, la verdad. En el índice [tiobe] de septiembre de 2011 figura en la posición 50, la última posición que entra en valoración. Pero los comentarios que he leído sobre este lenguaje me han picado tanto la curiosidad que he decidido darle un vistazo. Si quieres un consejo: no te limites a un sólo lenguaje de programación. Sólo comparando con otros lenguajes descubrirás las virtudes y limitaciones de los lenguajes que uses. Sobre todo, intenta aprender algún lenguaje <em>&#8220;exótico&#8221;</em>, si por exótico se entiende aquél que no se ve en los estudios oficiales de informática. Siempre que te pidan mostrar tus conocimientos de programador, saber programar en un lenguaje &#8220;exótico&#8221; será visto como que te entusiasma la programación y que tienes capacidad para aprender cosas nuevas por tu cuenta (Python sigue siendo un excelente ejemplo de lenguaje para estas demostraciones).</p>

<p>Algunas características interesantes de Scala:</p>

<ul>
<li>Lenguaje funcional orientado a objeto similar a java, pero superando a éste en simplicidad. Incorpora clausuras y tipado perezoso de datos.</li>
<li>Escalable (como indica su nombre: <strong>sca</strong>lable <strong>la</strong>nguage)</li>
<li>Emplea la <abbr title="Java Virtual Machine">JVM</abbr>, aunque también hay versión para .Net. Puede usarse en cualquier sitio que se use java como, por ejemplo, para programación en android.</li>
<li>Preparado para la programación concurrente. Sigue el modelo &#8220;Actor&#8221;, o lo que es lo mismo, todos los objetos son &#8220;actores&#8221; con su propio entorno de ejecución.</li>
</ul>

<h2>Asociacionismo en torno a python</h2>

<p>Tangencialmente, he empezado a meterme en la organización de un evento relacionado con python. Creo importante que todos retomemos los contactos personales e intentar hacer reflotar las ilusiones perdidas por esta crisis que estamos viviendo. Si todo va bien, espero vernos en el <a href="http://python-hispano.org/DiaPythonZGZ">Día Python 2011</a> en Zaragoza dentro de la LSWC&#8217;11.</p>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2011/10/08/rentree-nueva-temporada/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bitbucket soporta también git</title>
		<link>http://ch3m4.org/blog/2011/10/04/bitbucket-soporta-tambien-git/</link>
		<comments>http://ch3m4.org/blog/2011/10/04/bitbucket-soporta-tambien-git/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 01:38:08 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Novedad]]></category>
		<category><![CDATA[bitbucket]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=345</guid>
		<description><![CDATA[Relacionado con el anterior artículo en el que contaba cómo usar mercurial para acceder a repositorios git, la noticia de hoy es que bitbucket soporta también git (además de mercurial). Unido a las herramientas para importar cualquier proyecto de github, SourceForge, Google Code y Codeplex convierten a bitbucket en el lugar ideal para alojar nuestros [...]]]></description>
			<content:encoded><![CDATA[<p>Relacionado con el <a href="http://ch3m4.org/blog/2011/08/30/mercurial-como-cliente-dcvs-universal/">anterior artículo</a> en el que contaba cómo usar mercurial para acceder a repositorios git, la noticia de hoy es que <a href="http://bitbucket.org">bitbucket</a> soporta también git (además de mercurial). Unido a las herramientas para importar cualquier proyecto de github, SourceForge, Google Code y Codeplex convierten a <a href="http://bitbucket.org">bitbucket</a> en el lugar ideal para alojar nuestros proyectos, usando cualquier DCVS que elijamos.</p>

<p>Noticia en el blog de bitbucket: <a href="http://blog.bitbucket.org/2011/10/03/bitbucket-now-rocks-git/">http://blog.bitbucket.org/2011/10/03/bitbucket-now-rocks-git/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2011/10/04/bitbucket-soporta-tambien-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial como cliente DCVS universal</title>
		<link>http://ch3m4.org/blog/2011/08/30/mercurial-como-cliente-dcvs-universal/</link>
		<comments>http://ch3m4.org/blog/2011/08/30/mercurial-como-cliente-dcvs-universal/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 12:14:13 +0000</pubDate>
		<dc:creator>Chema Cortés</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[bitbucket]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://ch3m4.org/blog/?p=341</guid>
		<description><![CDATA[Uso de mercurial como cliente para acceso a repositorios git.]]></description>
			<content:encoded><![CDATA[<h2>Introducción</h2>

<p>Con la llegada de los <a href="http://en.wikipedia.org/wiki/Distributed_Concurrent_Versions_System" title="Distributed Concurrent Versions System">DCVS</a> (<em>Distributed Concurrent Versions System</em>), se ha convertido en habitual el uso de un sistema de control de versiones en todo desarrollo. La popularización de sitios webs basados en estos sistemas como <a href="http://github.com">github</a>, <a href="http://gitorious.org/">gitorious</a>, <a href="http://bitbucket.org">bitbucket</a> o <a href="http://code.google.com/">googlecode</a> como foros públicos donde compartir código entre programadores hasta el punto de convertirse en auténticas <em>redes sociales</em>, ha hecho de estos sistemas una necesidad para todo desarrollador que se precio, con el consabido dilema de cuál de los sistemas elegir.</p>

<p>Gracias a las extensiones que podemos añadir, cada día es menos transcendente la elección de un DCVS, pudiendo usar cualquier cliente con cualquier otro servidor.</p>

<h2>Comparando git y mercurial</h2>

<p>Sin entrar en mucho detalle, podemos comparar estos dos sistemas DCVS populares para hacernos una idea:</p>

<h3>git</h3>

<ul>
<li><span style="text-decoration: line-through;">Desarrollado en</span> <em>Depende de</em> perl y está pensado para linux (mal soporte en windows)</li>
<li>Velocidad: muy rápido</li>
<li>Comandos: algo complejo</li>
<li>Interface gráfico: no tiene</li>
<li>Popularidad muy alta</li>
<li>Repositorio público <em>estrella</em>: <a href="http://github.com">github</a></li>
</ul>

<h3>mercurial (hg)</h3>

<ul>
<li>Desarrollado en python, con versiones para linux, windows y mac</li>
<li>Velocidad: rápido</li>
<li>Comandos: sencillo (similar a subversion)</li>
<li>Interface gráfico: <a href="http://tortoisehg.bitbucket.org/">tortoiseHG</a> para gnome y windows</li>
<li>Popularidad alta</li>
<li>Repositorio público <em>estrella</em>: <a href="http://bitbucket.org">bitbucket</a></li>
</ul>

<p>Éstos son algunos apuntes rápidos. Evidentemente, hay algunos interfaces gráficos para git y es posible emplear git en windows, pero en mi opinión tiene algunos problemas que necesitan pulirse. Por otro lado, existen varios IDEs como netbeans o eclipse que pueden usar cualquiera de estos DCVS, abstrayendo su uso interno a través de un interface común.</p>

<p>Para un programador de <strong>python</strong>, la elección debería ser clara: <strong>mercurial</strong>. Realizado en python y con numerosas extensiones, también desarrolladas en python, parece sin duda la mejor elección. Además, es el sistema de control de versiones más utilizado en proyectos python, incluyendo el desarrollo del lenguaje en si, por lo que se uso es casi obligado si queremos colaborar con otros desarrolladores python.</p>

<p>Pero no hace falta renunciar a nada: desde mercurial también se puede usar repositorios git o subversion. Basta con añadir la extensión adecuada.</p>

<p>En el resto del articulo, me centreré sólo en la extensión <a href="http://hg-git.github.com/">hg-git</a>, con la que se posibilita el uso de repositorios git desde mercurial, sin necesidad de instalar ningún cliente de git adicional (no existen dependecias con ningún ejecutable <code>git</code>).</p>

<h2>hg-git</h2>

<h3>Instalación</h3>

<p>La última versión de mercurial a la hora de escribir este artículo es la 1.9. Como la versión <em>&#8220;estable</em>&#8221; de hg-git tiene problemas con esta versión en concreto de mercurial, voy a explicar aquí lo que sería el método <em>manual</em> de instalación, bastante más seguro.</p>

<p>Suponemos que tenemos ya instalado <code>mercurial</code> por lo medios habituales (autoinstalador en windows/instalador de paquetes en linux). Nos será de gran ayuda tener instalado <a href="http://tortoisehg.bitbucket.org/">tortoiseHG</a> como interface gráfico para manejar los repositorios. Para windows, la instalación de <a href="http://tortoisehg.bitbucket.org/">tortoiseHG</a> incluye todo lo necesario al empotrar un intérprete de python, mercurial y varias extensiones, algunas de ellas necesarias para transformar rutas y nombres de ficheros codificados en MBCS. Los siguientes pasos a ejecutar con mercurial serán más fáciles de aplicar desde la interface de tortoiseHG.</p>

<p>En el emplazamiento que queramos, empezamos por clonar un repositorio con <strong>hg-git</strong> desde mercurial:</p>

<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>hg clone http:<span style="color: #000000; font-weight: bold;">//</span>bitbucket.org<span style="color: #000000; font-weight: bold;">/</span>durin42<span style="color: #000000; font-weight: bold;">/</span>hg-git hg-git</div></div>

<p>Normalmente, yo suelo usar un mismo directorio para agrupas todos los repositorios clonados. Ése podría ser el lugar adecuado para guardar este repositorio.</p>

<p>Añadimos esta extensión a la configuración de mercurial. Normalmente, se hace en el fichero <code>mercurial.ini</code> (windows) o en <code>~/.hgrc</code> (linux). Si usamos tortoiseHG, desde las <code>"opciones globales"</code> podemos editar directamente este fichero.</p>

<p>Para añadir la extensión:</p>

<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[extensions]<br />
hggit = &lt;ruta-al-repositorio&gt;\hg-git\hggit</div></div>

<p>Como anotación, en alguna documentación se recomienda añadir también la extensión <em>opcional</em> <code>bookmarks</code> a la configuración; pero a partir de la versión 1.8 de mercurial, el comando <code>bookmark</code> es parte propia de los comandos de mercurial, por lo tanto este paso ya no es necesario.</p>

<p>Como dependencia, hace falta instalar el módulo de python <code>dulwich</code> para manejo de repositorios git con python. En windows ya viene incluído en tortoiseHG, por lo que no hay que hacer nada más. En linux, viene como paquete instalable (<code>python-dulwich</code> en ubuntu), pero también se podría haber instalado mediante <code>easy_install</code> sin mayor problema. Lo que sí hay que tener cuidado es en asegurarnos que no tenemos instalado el paquete <code>python-git</code> para que no interfiera con el módulo <code>hg-git</code> que estamos configurando.</p>

<p>Como lista final, estas serían las versiones probadas:</p>

<ul>
<li>mercurial (hg) <code>1.9</code></li>
<li>hg-git <code>0.2.4</code></li>
<li>dulwich <code>0.6.1</code></li>
</ul>

<h2>Utilización</h2>

<p>Con hg-git instalado ya podemos acceder, por ejemplo, a los repositorios de github directamente desde mercurial. Basta con especificar que se trata de un repositorio git:</p>

<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>hg clone git:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>django<span style="color: #000000; font-weight: bold;">/</span>django.git django.git</div></div>

<p>Para realizar un <code>push</code> a github con conexión codificada con SSH:</p>

<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">$ </span>hg push <span style="color: #c20cb9; font-weight: bold;">git</span>+ssh:<span style="color: #000000; font-weight: bold;">//</span>user<span style="color: #000000; font-weight: bold;">@</span>github.com<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span>myrep.git</div></div>

<p>Así mismo, si partimos de un repositorio mercurial también podemos <em>&#8220;convertirlo&#8221;</em> para su uso en git con el siguiente proceso:</p>

<div class="codecolorer-container bash dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ <span style="color: #7a0874; font-weight: bold;">cd</span> myrep <span style="color: #666666; font-style: italic;"># (dentro del repositorio mercurial)</span><br />
$ hg bookmark <span style="color: #660033;">-r</span> default master <span style="color: #666666; font-style: italic;"># marcamos 'default' como 'master'</span><br />
$ hg push <span style="color: #c20cb9; font-weight: bold;">git</span>+ssh:<span style="color: #000000; font-weight: bold;">//</span>user<span style="color: #000000; font-weight: bold;">@</span>github.com<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span>myrep.git<br />
$ hg push</div></div>

<p>Al marcar con el nombre <code>master</code> a <code>default</code> facilitamos la conversión de los datos de mercurial a objetos git. Este proceso sólo es necesario hacerlo la primera vez.</p>

<h2>github o bitbucket</h2>

<p>En cuanto a elegir entre github o bitbucket, es más una cuestión de gustos. <strong>github</strong> se ha posicionado como el sistema predilecto para darse a conocer, sobre todo como referencia en los <em>curriculo</em> a la hora de solicitar empleo. En cambio, <strong>bitbucket</strong> permite el uso de repositorios privados, muy útil para pequeños grupos de trabajo y para colaboraciones en la <em>&#8220;nube&#8221;</em> (dispositivos móviles).</p>

<p>Ambos son gratuitos, por lo que no debes dejar de probarlos tan sólo por lo que haya podido decir aquí. Es una nueva forma de conocer y darse a conocer entre programadores, algo que sin duda hace de nuestro pequeño mundo algo mucho más grande.</p>
]]></content:encoded>
			<wfw:commentRss>http://ch3m4.org/blog/2011/08/30/mercurial-como-cliente-dcvs-universal/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

