

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Rodrigo Kumpera Weblog &#187; language design</title>
	<atom:link href="http://www.kumpera.net/blog/index.php/category/language-design/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kumpera.net/blog</link>
	<description>Meus achados sobre tecnologia</description>
	<lastBuildDate>Thu, 14 Jul 2011 15:45:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A beleza do sistema de tipos do C#</title>
		<link>http://www.kumpera.net/blog/index.php/2011/07/14/a-beleza-do-sistema-de-tipos-do-c/</link>
		<comments>http://www.kumpera.net/blog/index.php/2011/07/14/a-beleza-do-sistema-de-tipos-do-c/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 15:45:23 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=171</guid>
		<description><![CDATA[Outro dia me apresentaram o código abaixo com um dúvida bem boba. Esse código em C# abusa um pouco de uma das novidades da última revisão da linguagem, tipos genéricos variantes. Vamos ao código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface A&#60;in B&#62; &#123; &#125;
&#160;
interface B&#60;in A&#62; &#123; &#125;
&#160;
class X : A&#60;B&#60;X&#62;&#62; &#123; &#125;
&#160;
class Y : B&#60;A&#60;Y&#62;&#62; &#123; &#125;
&#160;
class Test
&#123;
	static void Main [...]]]></description>
			<content:encoded><![CDATA[<p>Outro dia me apresentaram o código abaixo com um dúvida bem boba. Esse código em C# abusa um pouco de uma das novidades da última revisão da linguagem, tipos genéricos variantes. Vamos ao código:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> A<span style="color: #008000;">&lt;</span><span style="color: #0600FF;">in</span> B<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">interface</span> B<span style="color: #008000;">&lt;</span><span style="color: #0600FF;">in</span> A<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> X <span style="color: #008000;">:</span> A<span style="color: #008000;">&lt;</span>B<span style="color: #008000;">&lt;</span>X<span style="color: #008000;">&gt;&gt;</span> <span style="color: #000000;">&#123;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> Y <span style="color: #008000;">:</span> B<span style="color: #008000;">&lt;</span>A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;&gt;</span> <span style="color: #000000;">&#123;</span> <span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> Test
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;</span> x <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> X <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>O código é um enrolado. A parte mais importante é entender <strong>interface A&#60;in B&#62;</strong> que é a declaração de A contravariante em B. Isso significa, a grosso modo, que <strong>A&#60;object&#62; instanceof A&#60;string&#62; == true</strong>.</p>
<p>A dúvida é se a atribuição <strong>A&#60;Y&#62; x = new X ();</strong> é válida. Vou usar <em>&#60;:</em> como notação para<br />
pode ser atribuido em, como em <em>string &#60;: object</em>.</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">X <span style="color: #008000;">&lt;:</span> A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;</span> <span style="color: #008080; font-style: italic;">//X é uma classe e A uma interface, logo verificamos as interfaces de X</span>
A<span style="color: #008000;">&lt;</span>B<span style="color: #008000;">&lt;</span>X<span style="color: #008000;">&gt;&gt;</span> <span style="color: #008000;">&lt;:</span> A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;</span> <span style="color: #008080; font-style: italic;">//Duas instâncias diferentes do mesmo tipo genérico. Por ser contravariante no primeiro parâmetro, verificamos ele</span>
&nbsp;
<span style="color: #008080; font-style: italic;">//Note que contravariância significa verificar na ordem inversa</span>
Y <span style="color: #008000;">&lt;:</span> B<span style="color: #008000;">&lt;</span>X<span style="color: #008000;">&gt;</span>  <span style="color: #008080; font-style: italic;">//Y é uma classe e B uma interface, logo verificamos as interfaces de Y</span>
B<span style="color: #008000;">&lt;</span>A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;&gt;</span> <span style="color: #008000;">&lt;:</span> B<span style="color: #008000;">&lt;</span>X<span style="color: #008000;">&gt;</span> <span style="color: #008080; font-style: italic;">//Novamente duas instancias de um tipo contravariante, verificamos o primeiro parâmetro</span>
&nbsp;
X <span style="color: #008000;">&lt;:</span> A<span style="color: #008000;">&lt;</span>Y<span style="color: #008000;">&gt;</span></pre></div></div>

<p>Calma la, voltamos a definição original! Sim, voltamos, existe um ciclo nessa verificação e ela não pode ser decidida. Tanto o compilador como o sistema de tipos são não capazes de decidir. A solução pragmática é simplesmente recusar essa atribuição.</p>
<p>Quem imaginaria que o novo sistema de tipos do C# possui casos que não decidíveis. Pois é, e não fica só nisso, existem outros problemas envolvendo variância como ambiguidade no caso de últimas interfaces que merecem outro artigo. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2011/07/14/a-beleza-do-sistema-de-tipos-do-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementando Haskell em VMs tradicionais (parte 2)</title>
		<link>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/</link>
		<comments>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 23:30:36 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=149</guid>
		<description><![CDATA[Retomando a questão sobre como implementar Haskell em VMs tradicionais, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado [...]]]></description>
			<content:encoded><![CDATA[<p>Retomando a questão sobre <a href="http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/">como implementar Haskell em VMs tradicionais</a>, vamos ver um dos aspectos mais complicados, thunking, de implementar de forma eficiente. Um dos aspectos que surpreende a maioria dos que usam Haskell pela primeira vez é o fato da linguagem ser lazy evaluated, isto é, o valor de uma expressão só é computado quando for usado, mesmo entre chamadas funções. Vejamos um exemplo simples:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;">square a <span style="color: #339933; font-weight: bold;">=</span> a <span style="color: #339933; font-weight: bold;">*</span> a
&nbsp;
square<span style="color: #339933; font-weight: bold;">_</span>of<span style="color: #339933; font-weight: bold;">_</span>sum a b <span style="color: #339933; font-weight: bold;">=</span> square <span style="color: green;">&#40;</span>a <span style="color: #339933; font-weight: bold;">+</span> b<span style="color: green;">&#41;</span></pre></div></div>

<p>Nesse exemplo, quando square_of_sum chama square, o parâmetro passado não é o resultado de a + b, mas sim algo próximo a uma closure que irá calcular a + b. Quando square for avaliada, ela precisará do valor de &#8216;a&#8217;, então usará a closure que recebeu como parâmetro para tal. Ou melhor, funciona quase assim, Haskell implementa um mecanismo chamado call-by-need, que resolve o valor uma única vez na primeira vez que for necessário memorizando o resultado. Isso significa que no caso de square &#8216;a&#8217; será avaliada uma única vez. Por conta da memorização, não usamos o termo closure, mais sim thunk para descrever o que uma função passa para outra.</p>
<p>Outro detalhe importante, chamadas de função também são lazy evaluated, então tanto square, quanto square_of_sum na verdade retornam thunks para os valores em questão. Essa coisa toda pode parecer extremamente ineficiente a primeira vista e de fato é. Tanto que o GHC gera código sem uso de thunk sempre que conseguir provar que um pedaço de código pode ser strict evaluated [1].</p>
<p>Antes de imaginar como implementar isso em uma VM como a CLR, vamos traduzir nosso exemplo para C# [2]:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
<span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	<span style="color: #FF0000;">bool</span> resolved<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> Thunk <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> closure<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>resolved<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				resolved <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_of_sum <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a_plus_b <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">+</span> b.<span style="color: #0000FF;">Value</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">return</span> square <span style="color: #000000;">&#40;</span>a_plus_b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">//Já que square produz um thunk, não precisamos criar outro.</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Bem confuso, de certo. Primeiro a implementação de Thunk, simples e direta, já square_of_sum precisa de uma variável local para ficar minimamente legível. Uma coisa é fato, C# não foi feita para ser usada com lazy evaluation.</p>
<p>Existe alguns problema quanto a eficiencia de fazer dessa forma. O maior deles é como lidar quando alguns valores já estão resolvidos e temos ainda assim criar um thunk para satisfazer o função chamada. A forma como GHC lida isso é passando todos parâmetros boxed de forma que é possível misturar thunks e valores sem problema. A função square, do nosso exemplo anterior ficaria assim:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #FF0000;">int</span> val<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>a <span style="color: #008000;">is</span> <span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>a<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">else</span>
			val <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#41;</span>a<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
		<span style="color: #0600FF;">return</span> val <span style="color: #008000;">*</span> val<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Outra forma de também lidar com esse problema é criar duas versões da mesma função, uma que recebe valores resolvidos e outra apenas thunks. Fazer dessa forma é vantagem quando podemos provar o uso estrito dos valores em questão. Por fim, acho que o maior problema ser achar uma forma de representar um thunk usando o mínimo possível de memória.</p>
<p>No nosso exemplo, em uma plataforma 32bits, Trunk<T> usa 20 bytes, Func<T> usa mais 40 e outros 8 da closure[3]. Ou seja, começa usando 68, coisa pacas. Podemos fazer algumas mudanças nisso. Dado que não existe null em Haskell podemos remover o atributo resolved e simplesmente verificar se closure é ou não null. Segundo, em vez criar 1 delegate toda vez podemos fazer caching dele e armazenar as variáveis capturadas no próprio thunk. Algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">abstract <span style="color: #FF0000;">class</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">public</span> abstract T Value <span style="color: #000000;">&#123;</span> get<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> ThunkWithVars<span style="color: #008000;">&lt;</span>T,V<span style="color: #008000;">&gt;</span> <span style="color: #008000;">:</span> Thunk<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
	T value<span style="color: #008000;">;</span>
	Func<span style="color: #008000;">&lt;</span>V, T<span style="color: #008000;">&gt;</span> closure<span style="color: #008000;">;</span>
	V vars<span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> ThunkWithVars <span style="color: #000000;">&#40;</span>Func<span style="color: #008000;">&lt;</span>V,T<span style="color: #008000;">&gt;</span> closure, V vars<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">closure</span> <span style="color: #008000;">=</span> closure<span style="color: #008000;">;</span>
		<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">vars</span> <span style="color: #008000;">=</span> vars<span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> T Value <span style="color: #000000;">&#123;</span>
		get <span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>closure <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
				value <span style="color: #008000;">=</span> closure <span style="color: #000000;">&#40;</span>vars<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				closure <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
				vars <span style="color: #008000;">=</span> <span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>V<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">return</span> value<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">static</span> Func<span style="color: #008000;">&lt;</span>Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span>, <span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square_resolve <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>a<span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> a.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">*</span> a.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> square <span style="color: #000000;">&#40;</span>Thunk <span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> a<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> ThunkWithVars<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span>, Thunk<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;&gt;</span> <span style="color: #000000;">&#40;</span>square_resolve, a<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Usando essa codificação Thunk continua usando 20 bytes porém nos livramos dos demais objetos, um ganho de 70% no final das contas. Poderíamos economizar outros 4 se juntarmos as variáveis closure e value em uma só caso T fosse do tipo referência &#8211; ou manter o resultado boxed. Mesmo sem isso, 20 bytes já é um valor razoável, conseguir o mesmo em uma JVM é basicamente impossível sem muita ginástica.</p>
<p>Qual a performance dessa solução? Segundo o pessoal do GHC, em média 95%-98% dos thunks gerados são resolvidos. Com um generational GC, a maioria vira lixo efêmero. Ou seja, não existe muita razão para uma VM tradicional ser mais lenta que a do GHC, o principal fator nesse caso é, sem dúvida, o compilador, que pode gerar pedaços de código inteiros sem uso de thunk.</p>
<p>[1] É muito comum em Haskell gerar código que não funciona sem lazy evaluation, como geradores de listas infinitas.<br />
[2] Nesse exemplo vou trapacear e tornar as funções mono-mórficas e usar int no lugar de Number para simplificar o código.<br />
[3] Nesse caso estou ignorando quanto de memória as variáveis capturadas usam.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2010/01/09/implementando-haskell-em-vms-tradicionais-parte-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementando Haskell em VMs tradicionais (parte 1)</title>
		<link>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:49:24 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[clr]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=138</guid>
		<description><![CDATA[Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir [...]]]></description>
			<content:encoded><![CDATA[<p>Outro dia uma discussão me levou a pensar se era possível implementar Haskell em cima de uma VM tradicional, tal qual JVM ou CLR, de forma eficiente. Em termos dos mecanismos que a VM precisa suportar de forma eficiente os principais são tail call, thunking, type classes e algebraic types. Nesse artigo vou apenas discutir um deles, type classes.</p>
<p>Uma type class para os acostumados com OO pode ser vista como uma interface cuja implementações são externas aos tipos que estão atrelados. Um exemplo bem simples é Eq, que permite compar objetos do mesmo tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">class</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">==</span><span style="color: green;">&#41;</span><span style="color: #339933; font-weight: bold;">,</span> <span style="color: green;">&#40;</span><span style="color: #339933; font-weight: bold;">/=</span><span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">::</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> a <span style="color: #339933; font-weight: bold;">-&gt;</span> <span style="color: #cccc00; font-weight: bold;">Bool</span>
    x <span style="color: #339933; font-weight: bold;">/=</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">==</span> y<span style="color: green;">&#41;</span>
    x <span style="color: #339933; font-weight: bold;">==</span> y <span style="color: #339933; font-weight: bold;">=</span> <span style="font-weight: bold;">not</span> <span style="color: green;">&#40;</span>x <span style="color: #339933; font-weight: bold;">/=</span> y<span style="color: green;">&#41;</span></pre></div></div>

<p>Para nos não iniciado em Haskell, linha um define a classe Eq e diz que ela possui um parâmetro polimófico; linha 2 diz que Eq tem 2 funções, &#8220;==&#8221; e &#8220;/=&#8221; cuja assinatura são dois valores do tipo &#8216;a&#8217; e retorna um booleano; por fim, linhas 3 e 4 são implementações padrão das funções. Seria o equivalente, em pseudo-C#, ao seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">==</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">!=</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
   <span style="color: #FF0000;">bool</span> <span style="color: #0600FF;">operator</span><span style="color: #008000;">!=</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> <span style="color: #008000;">!</span><span style="color: #000000;">&#40;</span>a <span style="color: #008000;">==</span> b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Uma das vantagens de type classes no Haskell é que elas podem fornecer implementações padrão para alguns de seus métodos. Bom, agora que temos Eq definida, para dizer que Listas a implementa usamos algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">instance</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> a <span style="color: #339933; font-weight: bold;">=&gt;</span> <span style="color: #cccc00; font-weight: bold;">Eq</span> <span style="color: green;">&#91;</span>a<span style="color: green;">&#93;</span> <span style="color: #06c; font-weight: bold;">where</span>
    <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#91;</span><span style="color: green;">&#93;</span> <span style="color: #339933; font-weight: bold;">=</span> True
    <span style="color: green;">&#40;</span>x:xs<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: green;">&#40;</span>y:ys<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> x<span style="color: #339933; font-weight: bold;">==</span>y <span style="color: #339933; font-weight: bold;">&amp;&amp;</span> xs<span style="color: #339933; font-weight: bold;">==</span>ys
    <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">==</span> <span style="color: #339933; font-weight: bold;">_</span> <span style="color: #339933; font-weight: bold;">=</span> False</pre></div></div>

<p>Aqui vemos uma das melhores características do Haskell é explorada, que é pattern matching &#8211; e isso também é assunto para outro artigo. Como pode se notar, uma implementação de uma dada type class não está embutida na definição do tipo em questão, ou seja, não podemos interfaces como a CLR ou a JVM suportam.</p>
<p>A idéia é representar type classes de forma semelhante a como o ghc faz, usando dictionary passing[1], que é bem simples de entender e implementar. Para cada type class que uma função recebe nos seus parâmetros, passamos junto um objeto que representa as operações em questão. Em C# teríamos:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">interface</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">class</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> dict, T a, T b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>dict.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Existe alguns problemas aqui, primeiro que estamos passando um parâmetro extra e segundo que não é possível eliminar a verificar por null pointer caso op_eq seja inlined. A solução é razoavelmente simples no caso do C#:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">struct</span> Eq_Int <span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">int</span><span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_eq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">==</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> op_neq <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> a, <span style="color: #FF0000;">int</span> b<span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #0600FF;">return</span> a <span style="color: #008000;">!=</span> b<span style="color: #008000;">;</span> <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #FF0000;">int</span> Fun<span style="color: #008000;">&lt;</span>T, TD<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#40;</span>T a, T b<span style="color: #000000;">&#41;</span> where TD<span style="color: #008000;">:</span> Eq<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">default</span> <span style="color: #000000;">&#40;</span>TD<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">op_eq</span> <span style="color: #000000;">&#40;</span>a, b<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>A grande mudança aqui é tornar a instância da typeclass um valuetype e construir um valor default para satisfazer o compilador. É uma pena que não podemos simplesmente chamar um método estático e TD, o que é uma limitação boba da CLR. Essa solução não é possível na JVM devido a inexistência de valuetypes e generics.</p>
<p>E quanto a performance dessa solução? Bom, no caso do mono, o JIT&#8217;er reconhece as chamadas como não virtuais e é capaz de fazer inline de forma bem agressiva &#8211; exatamente como desejado. Eu pensei em fazer um comparativo dessa solução com o equivalente em Java, mostrando como a CLR permite codificar tipos muito mais ricos e interessantes que a JVM &#8211; e como isso se traduz em performance. Mas realmente não estou afim de criar motivo para um flamewar por parte dos javeiros de plantão.</p>
<p>[1]Esse é o paper original que descreve type classes e a técnica utilizada: http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/09/10/implementando-haskell-em-vms-tradicionais-parte-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Limites da orientação a objetos</title>
		<link>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 20:00:06 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[plt]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[type systems]]></category>
		<category><![CDATA[typeclasses]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=136</guid>
		<description><![CDATA[Toda linguagem de programação pode ser analisada pela sua junção de três elementos distintos: forma, comportamento e taxonomia. Cada um define um aspectodistinto de como o conjunto de valores que compõe um programa é usado.
Cada um destes valores possui um forma, que é a representação concreta para o conceito abstrato que cada um significa. Um [...]]]></description>
			<content:encoded><![CDATA[<p>Toda linguagem de programação pode ser analisada pela sua junção de três elementos distintos: forma, comportamento e taxonomia. Cada um define um aspectodistinto de como o conjunto de valores que compõe um programa é usado.</p>
<p>Cada um destes valores possui um forma, que é a representação concreta para o conceito abstrato que cada um significa. Um array de bytes e uma lista de chars são duas maneiras de representar uma string &#8211; um conceito abstrato. Forma admite composição e extensão, mas isso é razoavelmente óbvio.</p>
<p>Por comportamento me refiro a um grupo que operações definido que operam em um dado conjunto de valores. Repetindo nosso exemplo, strings, podemos definir particionamento, remover espaços em branco e pois ai vai. Ou seja, nada mais simples que um conjunto de funções.</p>
<p>Por fim, taxonomia é como damos nomes a conjuntos de valores. Ruby, que usa um sistema nominal de tipos, damos um nome explicitamente a um dado conjunto de valores que irão habitar uma classe. Outro aspecto importante é que podemos usar os operadores da teoria de conjuntos para definir relações entre pares. Voltando a Ruby, a única relação é a de subconjunto, que é a herança entre duas classes.</p>
<p>São três elementos bem distintos, porém, linguagens OO misturam dois, as vezes mesmo todos. Por exemplo, classes são os três ao mesmo tempo, atributos a forma, métodos o comportamento e a taxonomia vem através da relação herança entre duas classes. Interfaces misturam comportamento e taxonomia. Mixins misturam forma e comportamento. O problema disso é quando você quer manipular apenas um e os outros vem de brinde.</p>
<p>Linguagens funcionais costumam lidar de forma mais efetiva com esse problema. Haskell separa muito bem isso, com datatypes para forma, funções lidam com o comportamento e typeclasses resolvem a questão da taxonomia. Dessa forma é possível focar apenas em um dos três sem nenhuma bagagem extra.</p>
<p>Um problema com haskell é que uma typeclass classifica todos habitantes de um dado tipo, não é possível fazer isso com uma parte apenas. Nesse sentido Qi possui um sistema de tipos muito interessante, baseado em sequent calculus, permitindo definir de forma mais precisa quais valores compõe um dado tipo.</p>
<p>Eu acredito que essa limitação da orientação a objetos é a razão pelo qual tantas pessoas preferem fugir para linguagens OO dinâmicas, que aliviam boa parte do problema dado que forma e taxonomia poder ser consideradas ad-hoc, agrada a vários, mas realmente não me agrada para construir sistema de grande escala.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/08/30/limites-da-orientacao-a-objetos/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ode ao C</title>
		<link>http://www.kumpera.net/blog/index.php/2009/01/12/ode-ao-c/</link>
		<comments>http://www.kumpera.net/blog/index.php/2009/01/12/ode-ao-c/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 02:34:40 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[anger management]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[macros]]></category>
		<category><![CDATA[type systems]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=123</guid>
		<description><![CDATA[A parte que mais odeio no C é ser minha melhor opção. Sim, sério, para aquilo que faço hoje em dia, realmente não existe linguagem melhor. E isso de deixa maluco pois se trata de uma linguagem anacrônica, cheia de problemas enormes que aparentemente toda comunidade de PLR esqueceu de tentar resolver.
Para quem já programou [...]]]></description>
			<content:encoded><![CDATA[<p>A parte que mais odeio no C é ser minha melhor opção. Sim, sério, para aquilo que faço hoje em dia, realmente não existe linguagem melhor. E isso de deixa maluco pois se trata de uma linguagem anacrônica, cheia de problemas enormes que aparentemente toda comunidade de PLR esqueceu de tentar resolver.</p>
<p>Para quem já programou em C, ou mesmo C++, e em uma linguagem de alto nível tais quais C#, Haskell ou LISP sabe o tamanho do sofrimento que é trabalhar com uma ferramenta tão primitiva. Aos incautos não estou me referindo nem me referindo as vantagens óbvias dessas linguagens como gerenciamento automático de lixo, um sistema de tipos rico ou tipagem ou dinâmica[1].</p>
<p>Quando se programa próximo do metal ter um controle e visão muito clara daquilo que é gerado é muito importante, então coisas como verificações inseridas pelo compilador, não ter controle fino sobre a representação dos dados ou simplesmente não podem burlar o sistema de tipos inviabilizam o uso de uma linguagem &#8211; por mais estranho que pareça.</p>
<p>Entretanto usar destes argumentos para defender as relíquias que são C e C++ é temerário. Ambas linguagens foram construídas sob as bases do que era avançado em termos de compiladores nos anos 70 e para a capacidade de processamos do começo dos anos 90. Muita coisa mudou de lá para cá, menos o fato de C++ demorar horrores para compilar.</p>
<p>A primeira grande falha do C, e uma que chama muito a atenção, é o sistema de módulos e compilação separada. Que realmente não existe. Em ambas as linguagens se usa inclusão textual de cabeçalhos com declarações supostamente exportadas por outros módulos do sistema e pronto. O problema disso é óbvio se já tiver trabalhado em projetos grandes. O tempo de compilação individual aumenta sem razão aparente, conflitos com o nome de símbolos ocorrem e, em geral, atrapalham a vida de todos.</p>
<p>Continuando com a questão de processamento de texto. Macros em C provavelmente são o recurso mais importante da linguagem, aquele que a tira da lista de inúteis. É bem freqüente encontrar uma infinidade de truques feitos usando macros para sanar a falta de expressividade da linguagem. Porém tão comum quanto é encontrar gente frustada com a dificuldade de depurar um sistema rico em macros. Ao mesmo tempo, programando um dia com LISP qualquer um enxerga que um grande sistema de macros faz qualquer linguagem medíocre ir muito longe.</p>
<p>Por fim, minha última reclamação é devido ao fato de estar em 2009 e ainda ser obrigado a usar uma linguagem sem inferência de tipos. O artigo do Robin Milner tem quase 31 anos e ainda assim sou obrigado a pagear o compilador com aquilo que ele consegue descobrir sozinho. Inferência de tipos é um recurso ainda mais importante quando falamos de sistemas de tipos mais ricos.</p>
<p>Ainda assim, por algum motivo que me escapa, não existe um substituto usável para C ou C++. Talvez seja pelo fato de tal linguagem não possuir muito acadêmico em termos de papers e PHDs, ou que a enorme parte da comunidade de programadores destas linguagens é cega por achar que são o último biscoito do pacote.</p>
<p>[1]Ou latente, caso tenha um fetiche pelo Fowler.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2009/01/12/ode-ao-c/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Herança não funciona, parte III</title>
		<link>http://www.kumpera.net/blog/index.php/2008/12/01/heranca-nao-funciona-parte-iii/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/12/01/heranca-nao-funciona-parte-iii/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 14:35:14 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Programming language Theory]]></category>
		<category><![CDATA[language design]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=119</guid>
		<description><![CDATA[Em artigos anteriores eu descrevi algum dos problemas associados com herança, ou subtipagem, e questões ligadas a co/contravariância. Porém outra questão me chamou muito a atenção recentemente, é o fato de classes e objetos como normalmente vemos em linguagens com tipagem explícita são uma mistura de conceitos que talvez não deveriam estar juntos.
O que exatamente [...]]]></description>
			<content:encoded><![CDATA[<p>Em <a href="http://www.kumpera.net/blog/index.php/2007/11/13/heranca-nao-funciona/">artigos</a> <a href="http://www.kumpera.net/blog/index.php/2007/12/31/heranca-nao-funciona-parte-2/">anteriores</a> eu descrevi algum dos problemas associados com herança, ou subtipagem, e questões ligadas a co/contravariância. Porém outra questão me chamou muito a atenção recentemente, é o fato de classes e objetos como normalmente vemos em linguagens com tipagem explícita são uma mistura de conceitos que talvez não deveriam estar juntos.</p>
<p>O que exatamente objetos de linguagens comuns, feito C++, oferecem? Basicamente três coisas: layout, interfaces e subtipagem. Uma classe derivada define uma estrutura de dados que é uma extensão do layout daquelas de seus parentes; o mecanismo de funções virtuais é a única forma sã de se definir interfaces; e, por fim, herança é a forma de se definir uma relação de subtipagem entre dois tipos, no caso do C++ classes.</p>
<p>As duas primeiras propriedades são realmente úteis, a terceira é questionável &#8211; mas não vamos atentar para isso agora. Não existe uma razão óbvia para deixar extensão estrutural e interfaces atadas uma a outra. De fato, é uma enorme limitação. Java e C# possuem o mecanismo de interfaces para resolver isso, porém ambas exigem que todas sejam definidas de antemão, ou seja, são uma minúscula fração do número potencial de interfaces que suportam. Ou seja, adora um modelo de interfaces prescritivo e não latente.</p>
<p>Algumas linguagens funcionais resolvem este problema adotando alguma forma de <a href="http://en.wikipedia.org/wiki/Higher-order_logic">tipos de alta ordem</a>*, que permitem uma função ser definida em termos da interface exigida de um objeto e basta este atendê-la para poder ser usado, independente de herança. Pode ser visto, a grosso modo, como um mecanismo equivalente à interfaces no Java ou C# onde cada classe não precisa definir quais suportam, basta implementar os métodos relacionados.</p>
<p>À primeira vista, tipos de alta ordem, ou <a href="http://en.wikipedia.org/wiki/Type_class">classes de tipos</a> na terminologia e implementação do Hakell, podem parecer a mesma coisa que templates do C++, porém a semelhança fica apenas na superfície, templates são um mecanismo de macro-expansão estruturada, não existe como validar uma função em sua definição ou uso, é necessário sempre fazer sua expansão para verificar sua validade. Outra diferença gritante é a ampla possibilidade de compartilhar código entre as várias instanciações de uma função que usa tipos de alta ordem. Existe uma longa literatura sobre o assunto e várias formas de favorecer uso de memória ou performance.</p>
<p>Mas voltando a questão de se subtipagem é uma propriedade interessante ou não para uma linguagem ter. Bom, teoricamente é muito interessante poder definir relações de substituibilidade, mas na prática, a maioria dos frameworks não se valem de tal princípio. Um bom exemplo é o pacote de coleções do Java, ela é toda construída em termos de interfaces e herança é usada como uma forma tosca de promover reuso de código.</p>
<p>O súbito interesse por linguagens funcionais nesses últimos anos vem trazendo a tona uma série de avanços que estas linguagens possuem e estavam até então restritos à comunidade científica. Está mais que na hora para começarmos a repensar todos os antigo erros e quimeras que as linguagens de programação de mercado promovem e começar a pensar como produzir algo que nos permita dar o mesmo salto dos anos 60 que Algol e Fortran garantiram &#8211; e dessa vez nenhum idéia pode ser refém.</p>
<p>*A wikipedia, apesar de extensão não tem uma referencia para tipos de alta ordem, então vou me valer como referencia lógica de alta ordem e deixar como exercício a aplicação do mesmo para teoria de tipos. Type classes do Haskell podem ser construídas aplicando lógica de alta ordem à um sistema de tipos básico como o descrito em &#8220;Basic Simple Type Theory &#8211; Hindley, J. Roger&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/12/01/heranca-nao-funciona-parte-iii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A Nova onda de interpretadores</title>
		<link>http://www.kumpera.net/blog/index.php/2008/09/30/a-nova-onda-de-interpretadores/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/09/30/a-nova-onda-de-interpretadores/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 05:00:33 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[Dalvik]]></category>
		<category><![CDATA[interpretadors]]></category>
		<category><![CDATA[máquinas virtuais]]></category>
		<category><![CDATA[SquirelFish]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/?p=92</guid>
		<description><![CDATA[Interpretadores voltaram a ser um assunto muito discutido devido aos resultados alcansados pela SquirrelFish (interpretador de javascript do Webkit) e ao fato da VM do Android também usar um. Curiosamente, ambas VMs são baseadas em registradores em vez de pilha, como as máquinas virtuais tradicionais como JVM e CLR.
A grande diferença está na forma como [...]]]></description>
			<content:encoded><![CDATA[<p>Interpretadores voltaram a ser um assunto muito discutido devido aos resultados alcansados pela SquirrelFish (interpretador de javascript do Webkit) e ao fato da VM do Android também usar um. Curiosamente, ambas VMs são baseadas em registradores em vez de pilha, como as máquinas virtuais tradicionais como JVM e CLR.</p>
<p>A grande diferença está na forma como valores intermediários são calculados. Em uma VM baseada em pilha, operandos são adicionados ao topo da pilha enquanto operadores os retiram e realizam alguma operação. Uma máquina baseada em registradores usa de variaveis para armazenar resultados intermediários.</p>
<p>Para exemplificar melhor, o código &#8220;a = b * c + 10&#8243; ficaria algo como:</p>
<p>Máquina de pilha:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">push_local <span style="color: #ff0000;">'b'</span>
push_local <span style="color: #ff0000;">'c'</span>
mul
push_const <span style="color: #0000dd;">10</span>
add
store_local <span style="color: #ff0000;">'a'</span></pre></div></div>

<p>Máquina de registradores:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">load_local R0 <span style="color: #339933;">&lt;=</span> <span style="color: #ff0000;">'b'</span>
load_local R1 <span style="color: #339933;">&lt;=</span> <span style="color: #ff0000;">'c'</span>
mul R2 <span style="color: #339933;">&lt;=</span> R0<span style="color: #339933;">,</span> R1
load_const R3<span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span>
add R4 <span style="color: #339933;">&lt;=</span> R2<span style="color: #339933;">,</span> R3
store_local <span style="color: #ff0000;">'a'</span> <span style="color: #339933;">&lt;=</span> R4</pre></div></div>

<p>A primeira vista a diferença é quase que estética, porém se considerarmos quanto espaço precisamos para representar o código e o número de operações de leitura e escrita à memória cada uma faz, vamos notar como são técnicas fundamentalmente diferentes.</p>
<p>Vamos assumir um formato bem simples para representar o código de ambas, que é um byte para designar a operação seguido de um byte para cada operando. Aplicando esta forma, temos.</p>
<p>Máquina de pilha:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">push_local <span style="color: #ff0000;">'b'</span> <span style="color: #666666; font-style: italic;">//2 bytes</span>
push_local <span style="color: #ff0000;">'c'</span> <span style="color: #666666; font-style: italic;">//2 bytes</span>
mul <span style="color: #666666; font-style: italic;">//1 byte</span>
push_const <span style="color: #0000dd;">10</span> <span style="color: #666666; font-style: italic;">//2 bytes</span>
add <span style="color: #666666; font-style: italic;">//1 byte</span>
store_local <span style="color: #ff0000;">'a'</span> <span style="color: #666666; font-style: italic;">//2 bytes</span></pre></div></div>

<p>Total: <strong>10 bytes</strong></p>
<p>Máquina de registradores:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">load_local R0 <span style="color: #339933;">&lt;=</span> <span style="color: #ff0000;">'b'</span> <span style="color: #666666; font-style: italic;">//3 bytes</span>
load_local R1 <span style="color: #339933;">&lt;=</span> <span style="color: #ff0000;">'c'</span> <span style="color: #666666; font-style: italic;">//3 bytes</span>
mul R2 <span style="color: #339933;">&lt;=</span> R0<span style="color: #339933;">,</span> R1 <span style="color: #666666; font-style: italic;">//4 bytes</span>
load_const R3 <span style="color: #339933;">&lt;=</span> <span style="color: #0000dd;">10</span> <span style="color: #666666; font-style: italic;">//3 bytes</span>
add R4 <span style="color: #339933;">&lt;=</span> R2<span style="color: #339933;">,</span> R3 <span style="color: #666666; font-style: italic;">//4 bytes</span>
store_local <span style="color: #ff0000;">'a'</span> <span style="color: #339933;">&lt;=</span> R4 <span style="color: #666666; font-style: italic;">//3 bytes</span></pre></div></div>

<p>Total: <strong>20 bytes</strong></p>
<p>Fica claro aqui que uma máquina de pilha admite uma representação muito mais compacta do mesmo programa. Em geral essa relação não é tão gritante, pois existe uma série de formas de diminuir o número de instruções necessárias para uma máquina de registradores.</p>
<p>Agora vamos analisar quantas operações de memória cada máquina faz, verificando cada instrução individualmente.</p>
<p>Maquina de pilha:</p>
<p><em>push_local</em> X</p>
<ol>
<li>lê a variavel local X</li>
<li>lê o endereço atual do topo da pilha</li>
<li>escreve X no topo da pilha</li>
<li>incrementa e armazena o novo valor para topo da pilha</li>
</ol>
<p><em>mul / add</em></p>
<ol>
<li>lê o endereço atual do topo da pilha</li>
<li>lê o valor do topo da pilha</li>
<li>lê o valor abaixo do topo da pilha</li>
<li>escreve o resultado no local abaixo do topo da pilha</li>
<li>decrementa e armazena o novo valor para topo da pilha</li>
</ol>
<p><em>push_const</em> X</p>
<ol>
<li>lê o endereço atual do topo da pilha</li>
<li>escreve X no topo da pilha</li>
<li>incrementa e armazena o novo valor para topo da pilha</li>
</ol>
<p>store_local X</p>
<ol>
<li>lê o endereço atual do topo da pilha</li>
<li>lê o valor no topo da pilha</li>
<li>escreve o valor em X</li>
<li>decrementa e armazena o novo valor para topo da pilha</li>
</ol>
<p>Aplicando esses valores ao programa em questão temos um total de <strong>25 operações</strong>.</p>
<p>Máquina de registradores:</p>
<p><em>load_local</em> X <= Y</p>
<ol>
<li>lê o valor da variavel local Y</li>
<li>escreve o valor no registrador X</li>
</ol>
<p><em>mul / add</em> X <= Y, Z</p>
<ol>
<li>lê o valor do registrador local Y</li>
<li>lê o valor do registrador local Z</li>
<li>escreve o valor no registrador X</li>
</ol>
<p><em>load_const</em> X <= Y</p>
<ol>
<li>escreve o valor de Y no registrador X</li>
</ol>
<p><em>store_local</em> X <= Y</p>
<ol>
<li>lê o valor do registrador Y</li>
<li>escreve o valor no registrador X</li>
</ol>
<p>Fazendo a conta, temos um total de <strong>13 operações</strong>.</p>
<p>Ironicamente neste caso, uma máquina de registradores leva uma significante vantagem em relação a uma máquina de pilha. Apesar de se tratar de uma simplificação, na prática o resultado é o mesmo. Em máquinas modernas onde o custo de acessar a memória principal é muito grande, uma máquina de registradores tem o potencial de ser mais rápida.</p>
<p>Essas dicotomia entre qual admite uma representação mais compacta e qual permite uma implementação mais eficiente é fundamental na arquitetura de qualquer máquina virtual. Apesar disso, existe muito além da simples forma de funcionar do interpretador que define a real performance da VM, ainda mais se falarmos de linguagens dinâmicas. Em um artigo futuro pretendo mostrar uma implementação de exemplo de ambos os tipos de máquinas virtuais.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/09/30/a-nova-onda-de-interpretadores/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>O futuro da programação &#8211; hoje</title>
		<link>http://www.kumpera.net/blog/index.php/2008/06/14/o-futuro-da-programacao-hoje/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/06/14/o-futuro-da-programacao-hoje/#comments</comments>
		<pubDate>Sat, 14 Jun 2008 04:26:26 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[language design]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/06/14/o-futuro-da-programacao-hoje/</guid>
		<description><![CDATA[Sempre que leio qualquer coisa feita pelo Iam Piumarta fico impressionado. Outro dia ao ler os slides sobre o progresso do grupo dele para construir uma linguagem que seja uma real evolução ao que temos hoje, me dei conta de como aquilo que eles propõem é radicalmente diferente ao que a prática de que estamos [...]]]></description>
			<content:encoded><![CDATA[<p>Sempre que leio qualquer coisa feita pelo Iam Piumarta fico impressionado. Outro dia ao ler <a href="http://piumarta.com/papers/S3-2008-slides.pdf">os slides</a> sobre o progresso do grupo dele para construir uma linguagem que seja uma real evolução ao que temos hoje, me dei conta de como aquilo que eles propõem é radicalmente diferente ao que a prática de que estamos habituados.</p>
<p>A atenção excessiva na meta-recursividade do sistema, assim como ser trivial criar e integrar novas gramáticas a linguagem, me faz pensar qual seria o limite de duas propriedade com emergence como essas. O efeito imediato é no compilador, que tem suporte direto a <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">PEG</a>s e pattern matching.</p>
<p>O compilador é capaz de se adaptar a mudanças nas regras de sintaxe e passar a usá-las instantaneamente apos serem definidas, ou seja, você pode definir uma mini linguagem em 5-10 linhas e usá-la logo em seguida. Não só isso, mas elas possuem escopo e podem operar em apenas um bloco de texto do seu fonte. Junta isso ao fato de que PEGs poderem ser  compostas facilmente e o compilador suportar staged compilation que o resultado é ter uma linguagem que é maleável ao extremo.</p>
<p>A outra é a máquina virtual, que é construída com essa nova linguagem, de forma que ela mesmo siga o modelo de protótipos e delegação na sua implementação. Isso permite que ela seja tão flexível e dinâmica quanto suas aplicações. Essa é, de longe, a característica mais interessante, pois nenhuma linguagem baseada e máquina virtual que eu conheço chega a esse ponto.</p>
<p>Mas quais seriam aplicações reais disso? Aquilo que hoje fazemos com frameworks e bibliotecas, poderíamos fazer com DSLs. Então em vez de aprender um enorme framework que precisa seguir às regras da linguagem, bastaria aprender uma pequena nova linguagem. Da mesma forma, muita coisa que hoje se traduz em referencia direta ao código de bibliotecas, poderia ser feito como uma série de modificações à gramática corrente.</p>
<p>Porém eu acho que é possível ir muito mais além, com uma VM flexível, seria possível ajustar o modelo de execução para melhor realizar a tarefa que o programa deseja. Como, por exemplo, introduzir processos leves ao estilo do Erlang simplesmente incluindo uma biblioteca.</p>
<p>Quem ainda não se ligou o que gente como Ian Piumarta e Alan Kay tem feito no <a href="http://www.vpri.org/">Viewpoints Research Institute</a> deve parar um pouco e se dedicar àquilo que um dia poderia ser o próximo passo na evolução da computação.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/06/14/o-futuro-da-programacao-hoje/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Como fazer uma linguagem dinâmica ser rápida?</title>
		<link>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/#comments</comments>
		<pubDate>Thu, 22 May 2008 05:09:16 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[mono]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/</guid>
		<description><![CDATA[Muito se fala em como as implementações de Ruby estão ficando rápidas, que estão evoluindo rapidamente. Porém não consigo pensar em como todas elas parecem mas preocupadas em repetir o caminho das pedras que outras linguagens dinâmicas passaram em décadas passadas.
Hoje a maioria ainda está no estágio de possuir um interpretador razoável e estar começando [...]]]></description>
			<content:encoded><![CDATA[<p>Muito se fala em como as implementações de Ruby estão ficando rápidas, que estão evoluindo rapidamente. Porém não consigo pensar em como todas elas parecem mas preocupadas em repetir o caminho das pedras que outras linguagens dinâmicas passaram em décadas passadas.</p>
<p>Hoje a maioria ainda está no estágio de possuir um interpretador razoável e estar começando a investir em algum mecanismo primitivo de compilação para código nativo. Talvez a única diferença seja o uso de inline caches para resolução de nomes, que foi uma contribuição significativa do pessoal do Self no começo dos anos 90. Porém os principais resultados obtivos por pesquisas a um bom tempo, como tracing, especialização e especulação não deram as caras ainda.</p>
<p>Inline caching é uma optimização no qual o resultado da resolução de nomes, para dispatch de método por exemplo, é armazenado entre ativações distintas. O truque é introduzir uma clausula de guarda que verifica o tipo do objeto seletor e sua versão. Caches devem ser invalidados sempre que alguém alterar uma classe. Temos dois tipos de cache, os monomórficos que fazem caching de apenas uma invocação e os polimórficos, que armazenam uma série de resultados. Para melhor vamos exemplificar com pseudo código:</p>
<p><code><br />
//ruby<br />
def test (a)<br />
    a.foo<br />
end</p>
<p>//pseudo-código gerado em C# para um cache monomórfico</p>
<p>class CallSite {<br />
    Type type;<br />
    MethodInfo method;<br />
    int version;<br />
}</p>
<p>static CallSite test_site_0;</p>
<p>object test(object a) {<br />
    //guarda do cache monomórfico verifica tipo e versão<br />
    if (test_site_0.type == a.Type &#038;&#038; test_site_0.version == A.Type.version)<br />
        return method (a);<br />
    else<br />
        //ResolveAndInvoke resolve o método "foo", invoca ele e atualiza o cache<br />
        return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código gerado em C# para um cache polimórfico<br />
delegate object InlineCacheNoArg (object this_);</p>
<p>static InlineCacheNoArg test_site_0;</p>
<p>object test(object a) {<br />
    return test_site_0 (a);<br />
}</p>
<p>//pseudo-código inicial do delegate de test_site_0<br />
object test_site_0_v0 (object _this) {<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código do delegate depois de chamarmos test (99)<br />
object test_site_0_v1 (object _this) {<br />
    if (_this.Type == typeof (int) &#038;&#038; _this.version == 1)<br />
        //o dispatch aqui pode ser via um delegate dependendo da resolução<br />
        return ((int)_this).foo ();<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}</p>
<p>//pseudo-código do delegate depois de chamarmos test ("str")<br />
object test_site_0_v2 (object _this) {<br />
    if (_this.Type == typeof (int) &#038;&#038; _this.version == 1)<br />
        return ((int)_this).foo ();<br />
    if (_this.Type == typeof (string) &#038;&#038; _this.version == 1)<br />
        return ((string)_this).foo ();<br />
    return ResolveAndInvoke (a, "foo", ref test_site_0);<br />
}<br />
</code></p>
<p>Como fica claro pelo exemplo, um cache polimórfico tem uma performance superior pois usa literais e funciona muito melhor no caso de não existir um tipo dominante entre as ativações. Aqui fica clara a limitação de uma das implementações, o JRuby não pode se dar ao luxo de gerar tantos métodos pois cada um precisa de uma classe e um classloader novos, ou seja, abusa da PermGen do Java.</p>
<p>Apesar de inline caches resultarem em ganho expressivo de performance, estão longe de produzirem algo razoável. O grande problema continua sendo o enorme custo de dispatch para código simples. A chave disso é fazer inferência dos tipos, de forma a conseguir eliminar por completo o overhead dos caches e resolução de nomes. As atuais implementações não implementam se quer inferência estática, ou seja, código como &#8220;123.to_s&#8221; é executado sem qualquer conhecimento prévio de 123.</p>
<p>O grande avanço ocorre se fizemos inferência em tempo de execução. Ou seja, instrumentamos o código para coletar os tipos que aparecem pelo código durante a execução e baseado nisso a máquina virtual gera versões mais eficientes do código. Existem duas técnicas bastante difundidas de como fazer isso, uma é via especialização parcial de métodos e a outra é via trace-based optimization.</p>
<p>Trace-based optimization é a tecnologia adotada pela Tamarin, a próxima VM de Javascript da Mozilla. De maneira sucinta, essa técnica consiste em gravar os trechos, e os tipos encontrados, que executam mais freqüentemente e gerar código eficiente baseado nessa informação. Os trechos gravados costumam incluir vários métodos diferentes e suas ativações juntas. Suas principais vantagens é a conseguir fazer inlining de métodos de maneira muito eficiente e normalmente gastar menos tempo no JIT. Porém existem uma enorme quantidade de problemas complexos de serem resolvidos como limitar expansão descontrolada da quantidade de código gerado.</p>
<p>Especialização parcial de métodos também leva em conta os métodos que executam mais freqüentemente. Os tipos dos parâmetros e valores de retorno<br />
são armazenados e posteriormente utilizados para gerar versões especializadas dos métodos em questão. Sua principal vantagem é a maior simplicidade<br />
e o fato de existir muito mais literatura e ferramentas para gerar código eficiente nestes casos. Para se ter uma idéia do poder dessa técnica um exemplo cai bem:</p>
<p><code><br />
//ruby<br />
def fun (a, b)<br />
    2 * a - b<br />
end</p>
<p>//fun é sempre chamada com números como argumento, "fun (1,2)" por exemplo.</p>
<p>//pseudo-código C# gerado inicialmente (sem usar caches)<br />
object fun_v0 (object a, object b) {<br />
    object tmp = Invoke (2, "*", a"); //_this, nome do método, argumentos<br />
    return Invoke (tmp, "-", b);<br />
}</p>
<p>//pseudo-ćodigo C# gerado após especialização:<br />
int fun_int_int (int a, int b) {<br />
    int tmp = 2 * a; //o método que implementava multiplicação foi inlined<br />
    return tmp - b;<br />
}</p>
<p>object fun_v1 (object a, object b) {<br />
    if (a.Type == typeof (int) &#038;&#038; b.Type == typeof (int) &#038;&#038; typeof (int).version == 1)<br />
        return fun_int_int ((int)a, (int)b);<br />
    object tmp = Invoke (2, "*", a"); //_this, nome do método, argumentos<br />
    return Invoke (tmp, "-", b);<br />
}<br />
</code></p>
<p>Não precisa ir muito longe para imaginar a diferença de performance entre as duas versões. Porém entre descobrir os métodos as serem especializados e gerar código de máquina existe um Just-In-Time compiler que é, surpresa, surpresa, muito trabalhoso de ser escrito para executar rapidamente e gerar código eficiente.</p>
<p>Possui um bom JIT é atualmente um grande dilema entre as implementações de ruby. Pois ao usar o JIT de máquinas virtuais maduras, como HotSpot ou mono, a implementação fica limitada ao que é possível a linguagens gerenciadas. Em contrapartida, ao não utilizá-las, construções de baixo nível como profiler e interpretador podem ser implementadas de forma muito mais eficiente.</p>
<p>Apesar de do futuro parecer muito legal, futuras VMs terão o trabalho adicional de educar a comunidade de desenvolvedores sobre como escrever código rápido em ruby. Coisas como monkey patching furam qualquer esquema de caching ou especialização pois cada objeto passa a ter uma singleton class distinta.</p>
<p>Não existe solução fácil e todas implementações tem muito chão pela frente até Ruby ter uma performance competitiva com outras linguagens dinâmicas. Soluções como as aqui apresentadas devem conseguir melhorias de uma ordem de magnitude tranquilamente, de acordo com os resultados já encontrados. Performance é um problema que é resolvido via muito suor, com uma contínua série de melhoras, atacando um pouco por vez.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/05/22/como-fazer-uma-linguagem-dinamica-ser-rapida/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Monkeypatching: gambiarra du-jour</title>
		<link>http://www.kumpera.net/blog/index.php/2008/03/03/monkeypatching-gambiarra-du-jour/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/03/03/monkeypatching-gambiarra-du-jour/#comments</comments>
		<pubDate>Mon, 03 Mar 2008 14:20:00 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[language design]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/03/03/monkeypatching-gambiarra-du-jour/</guid>
		<description><![CDATA[Finalmente o óbvio atingiu a comunidade de desenvolvedores de Ruby. Enfim descobriram que meta-programação sem disciplina é um engôdo. No começo produz resultados fabulosos rapidamente, só que mais adiante se torna um inferno de integração. Não falta gente calejada em Rails para te contar uma miríade de problemas ao integrar frameworks que modificam classes como [...]]]></description>
			<content:encoded><![CDATA[<p>Finalmente o óbvio atingiu a comunidade de desenvolvedores de Ruby. Enfim descobriram que meta-programação sem disciplina é um engôdo. No começo produz resultados fabulosos rapidamente, só que mais adiante se torna um inferno de integração. Não falta gente calejada em Rails para te contar uma miríade de problemas ao integrar frameworks que modificam classes como Object ou Fixnum.</p>
<p>Sistemas grandes e complexos exigem que seus componentes sejam isolados o máximo possível entre si para minimizar a interferência que um pode causar no outro. Em linguagens como Java, com um sistema de tipos simples, normalmente isso se resume a usar interfaces para delimitar fronteiras e protocolos de comunicação inter-módulo. Porém quando temos classes abertas o problema é muito maior, já que o sistema todo pode ser modificado de um único lugar. Permitir que a modificação de classes fundamentais como Kernel em um canto do sistema influencie todo o resto é um sério problema pois fica difícil controlar o estrago que essas mudanças causam.</p>
<p>O problema com Ruby pode ser entendido melhor se olharmos para ele segundo o a classificação de <a href="http://fragmental.tw/research-on-dsls/language-oriented-programming-lop/">domínios de page-jones</a>. Segundo o mesmo, podemos classificá-los em fundamental, arquitetural, negócios e aplicação; sendo que a especificidade aumenta na mesma ordem. Outro ponto é que o domínio menos específico não deve depender de um mais específico, assim como dependências laterais devem ser evitadas. Por essa ótica, código da aplicação alterando uma classe fundamental do sistema é uma clara violação desse modelo.</p>
<p>O motivo pelo qual Ruby viola o modelo de page-jones é por não ser possível definir um escopo que não seja global para alterações feitas a classes externas a código em questão. Outro problema que agrava a situação é a impossibilidade de realmente controlar o mecanismo de resolução de nomes de um bloco de código, isso é um grande problema para criação de DSLs que acabam por fazer enormes cirurgias no core da linguagem ou apelam para o monkeypatching, uma &#8220;solução&#8221; muito menos intrusiva.</p>
<p>Existem duas formas de ser realizar meta-programação; uma é a intrínseca, a qual se permite operar sobre a definição dos tipos e, uma vez feita a alteração, ela é visível a todos usuários do dado tipo, podemos dizer também que é meta-programação no ponto de definição; a outra é a extrínseca, na qual se altera o mecanismo de resolução de nomes para um dado corpo de código, isso permite realizar as mesmas operações que o método anterior, porém todo código precisa informar direta ou indiretamente se existe algo alterando tal mecanismo, podemos dizer também que é meta-programação no ponto de uso.</p>
<p>A vantagem do primeiro é simplicidade e alcance, uma vez feita a modificação nada mais precisa ser feito para sua aplicação utilizar a versão modificada do tipo, porém também é sua fraqueza, pois se uma função depender explicitamente do comportamento anterior ela não mais funcionará &#8211; Ruby é um ótimo exemplo de meta-programação intrínseca. Já a segunda técnica é quase o oposto, pois exige que as modificações sejam explicitamente ativadas, que é sua principal vantagem, pois permite facilmente compor conjuntos de alterações e restringir seu escopo, em contrapartida é sua fraqueza pois não permite que uma dada alteração seja definida por completo em um único lugar &#8211; extension methods do C# 3.0 é um exemplo simples de meta-programação extrínseca.</p>
<p>Tentar comparar ambas as técnicas e concluir qual a melhor é um exercício fútil, pois sempre existirão fartos casos no qual uma falha e a outra brilha. Assim como achar que Ruby é uma linguagem quebrada por possuir seus defeitos, pois apesar de tudo é um modelo ao mesmo tempo muito rico e simples de usar.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/03/03/monkeypatching-gambiarra-du-jour/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

