<?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:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" version="2.0">
  <channel>
    <title>Dibi Store weblog!</title>
    <link>http://www.dibistore.com/articles.rss</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Il blog per gli sviluppatori web</description>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/DibiStoreWeblog" type="application/rss+xml" /><item>
      <title>Ruby 1.9: addio Continuation, benvenuto Fiber</title>
      <description>&lt;p&gt;&lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; è un linguaggio naturale, ma non per questo semplice, infatti offre una sintassi molto ricca e articolata. Oggi volevo parlare di due generatori non molto usati (ma non per questo inutili) che possono offrire dei grandi vantaggi al programmatore.&lt;/p&gt;

&lt;h3&gt;Fiber&lt;/h3&gt;
&lt;p&gt;Fiber è una nuova classe introdotta in ruby 1.9 che permette di effettuare delle chiamate sequenziali ad un oggetto fiber.&lt;/p&gt;

&lt;h3&gt;Continuation&lt;/h3&gt;
&lt;p&gt;La classe Continuation è già presente in Ruby 1.8, tuttavià verrà rimossa dalla prossima release, in quanto non è portabile tra le diverse versioni. Di fatto ne viene sconsigliato l'utilizzo, e se ne incoraggia quello della classe Fiber (che fa un lavoro simile).&lt;/p&gt;

&lt;h3&gt;Approfondimenti&lt;/h3&gt;
&lt;a href="http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177"&gt;The Ruby programming language&lt;/a&gt; (link non sponsorizzato).

</description>
      <pubDate>Sat, 28 Jun 2008 07:42:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:117a4032-6359-4943-91d5-c3a1271c6569</guid>
      <comments>http://www.dibistore.com/articles/2008/06/28/ruby-1-9-addio-continuation-benvenuto-fiber#comments</comments>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=ruby-1-9-addio-continuation-benvenuto-fiber&amp;month=06&amp;year=2008&amp;day=28</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/06/28/ruby-1-9-addio-continuation-benvenuto-fiber</link>
    </item>
    <item>
      <title>Consigli per migliorare il proprio lavoro da casa</title>
      <description>&lt;p&gt;Se siete alla ricerca di un elenco completo di consigli per lavorare da casa,&lt;a href="http://www.internetservicedeals.com/blog/62/because-sitting-up-is-for-suckers-70-tools-tips-and-hacks-to-work-from-bed/"&gt;questo&lt;/a&gt; articolo in lingua inglese potrebbe interessarvi.&lt;/p&gt;

</description>
      <pubDate>Fri, 20 Jun 2008 07:39:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:3f1d4388-0018-4cae-a8f5-08d7851fc890</guid>
      <comments>http://www.dibistore.com/articles/2008/06/20/consigli-per-migliorare-il-proprio-lavoro-da-casa#comments</comments>
      <category>metodologie</category>
      <category>produttivita</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=consigli-per-migliorare-il-proprio-lavoro-da-casa&amp;month=06&amp;year=2008&amp;day=20</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/06/20/consigli-per-migliorare-il-proprio-lavoro-da-casa</link>
    </item>
    <item>
      <title>La vecchia storia...</title>
      <description>There’s
the old story of the young project manager, where his senior
programmer announced she was pregnant and going to leave
the project, and he protested that this “wasn’t on the project
plan.”

</description>
      <pubDate>Wed, 04 Jun 2008 22:49:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a317cd7d-5fa0-4c4d-b0a8-b3b2e39b88dd</guid>
      <comments>http://www.dibistore.com/articles/2008/06/04/la-vecchia-storia#comments</comments>
      <category>metodologie</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=la-vecchia-storia&amp;month=06&amp;year=2008&amp;day=04</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/06/04/la-vecchia-storia</link>
    </item>
    <item>
      <title>Passenger / mod_rails per il deploy di applicazioni rails</title>
      <description>&lt;p&gt;&lt;a href="http://modrails.com/"&gt;Passenger&lt;/a&gt; è un modulo apache sviluppato di recente da &lt;a href="http://phusion.nl/about.html"&gt;phusion&lt;/a&gt; che permette il deploy di applicazioni rails anche in &lt;a href="http://blog.dreamhost.com/2008/05/13/passenger-for-ruby-on-rails/"&gt;grande&lt;/a&gt; scala.&lt;/p&gt;

&lt;p&gt;La cosa interessante è che questa soluzione sta già diventando la de-facto per una buona parte di sviluppatori &lt;a href="http://rubyonrails.org/"&gt;rails&lt;/a&gt;. Avrò occasione di provare questo prodotto al più presto, e quindi di darvi maggiori info e feedback, nel frattempo vi lascio alcuni link utili per iniziare a darci un occhiata.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://modrails.com/"&gt;modrails.com&lt;/a&gt;: sito ufficiale.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.rubyinside.com/28_mod_rails_and_passenger_resources-899.html"&gt;28 mod_rails / Passenger Resources To Help You Deploy Rails Applications Faster&lt;/a&gt;: link utili per iniziare da subito.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nubyonrails.com/articles/ask-your-doctor-about-mod_rails"&gt;Ask Your Doctor About mod_rails&lt;/a&gt;: interessante articolo scritto da Geoffrey Grosenbach.&lt;/p&gt;


</description>
      <pubDate>Mon, 26 May 2008 07:38:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:145e0af5-0086-421a-80c1-a6dcd9acf893</guid>
      <comments>http://www.dibistore.com/articles/2008/05/26/passenger-mod_rails-per-il-deploy-di-applicazioni-rails#comments</comments>
      <category>ruby on rails</category>
      <category>deploy</category>
      <category>passenger</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=passenger-mod_rails-per-il-deploy-di-applicazioni-rails&amp;month=05&amp;year=2008&amp;day=26</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/05/26/passenger-mod_rails-per-il-deploy-di-applicazioni-rails</link>
    </item>
    <item>
      <title>Aggiungere supporto readline a ruby</title>
      <description>&lt;p&gt;&lt;a href="http://tiswww.case.edu/php/chet/readline/rltop.html"&gt;Readline&lt;/a&gt; è una libreria che vi permette di usare alcune interessanti funzioni da shell, come ^R per la reverse search oppure il supporto ai caratteri accentati. Sarebbe utile poter usare questo supporto anche all'interno di irb, tuttavia nella versione per mac osx non ci viene permesso. Tuttavia, &lt;a href="http://henrik.nyh.se/2008/03/irb-readline"&gt;questo&lt;/a&gt; articolo ci spiega come abilitare la libreria in meno di 5 minuti.&lt;/p&gt;

</description>
      <pubDate>Sat, 24 May 2008 11:01:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:80ce7c8e-0147-43b0-8b13-df9cad7d53e1</guid>
      <comments>http://www.dibistore.com/articles/2008/05/24/aggiungere-supporto-readline-a-ruby#comments</comments>
      <category>ruby</category>
      <category>irb</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=aggiungere-supporto-readline-a-ruby&amp;month=05&amp;year=2008&amp;day=24</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/05/24/aggiungere-supporto-readline-a-ruby</link>
    </item>
    <item>
      <title>Finalmente Rails on Rubinius</title>
      <description>&lt;p&gt;E' &lt;a href="http://blog.fallingsnow.net/2008/05/17/rails-on-rubinius/"&gt;notizia&lt;/a&gt; di ieri sera che &lt;a href="http://rubini.us/"&gt;rubinius&lt;/a&gt; è finalmente in grado di eseguire applicazioni &lt;a href="http://www.rubyonrails.org"&gt;rails&lt;/a&gt;. Entro la fine dell'anno, come &lt;a href="http://www.chadfowler.com/2008/5/17/ruby-on-rails-on-rubinius"&gt;detto&lt;/a&gt; da Fowler, saremo in grado di assistere al deploy di applicazioni commerciali su questa piattaforma.&lt;/p&gt;

</description>
      <pubDate>Sun, 18 May 2008 11:32:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:b2153da4-02c9-4255-95a4-0ec928a838f4</guid>
      <comments>http://www.dibistore.com/articles/2008/05/18/finalmente-rails-on-rubinius#comments</comments>
      <category>ruby</category>
      <category>rubinius</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=finalmente-rails-on-rubinius&amp;month=05&amp;year=2008&amp;day=18</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/05/18/finalmente-rails-on-rubinius</link>
    </item>
    <item>
      <title>Analisi del modello sostitutivo per applicazioni procedurali</title>
      <description>&lt;p&gt;
  Il modello sostitutivo, in ambito informatico, è il più semplice di una serie incrementale di modelli che descrivono come un interprete analizza il programma. L'uso del modello sostitutivo è quotidianamente usato anche dagli utenti per capire come una determinata procedura funziona.
  Per cogliere al volo il concetto analizziamo il seguente listato:
&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;
  pi: 3.14159
  
  circonferenza(x): x * x * pi
  
  somma_di_circonferenze(x, y): circonferenza(x) + circonferenza(y)
  
  somma_di_circonferenze(4, 7) = ?
  
&lt;/pre&gt;&lt;/code&gt;




&lt;p&gt;
  Ipotizzando di possedere un interprete in grado di comprendere la sintassi di questo codice attraverso il modello sostitutivo, esso performerà le seguenti operazioni:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    valuterà il risultato dei parametri (&lt;em&gt;arity&lt;/em&gt;) della funzione, producendo il seguente risultato: &lt;code&gt;circonferenza(4) + circonferenza(7)&lt;/code&gt;
  &lt;/li&gt;
  &lt;li&gt;Il processo di sostituzione verrà ora eseguito per entrambe le funzioni circonferenza (questo processo può avvenire attraverso l'uso di una struttura ad albero), ottenendo così &lt;em&gt;(4 * 4 * pi) + (7 * 7 * pi)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;L'interprete provvederà a questo punto alla sostituzione della &lt;em&gt;variabile&lt;/em&gt; &lt;code&gt;pi&lt;/code&gt; con il relativo valore, e performerà le operazioni di moltiplicazione e somma (sempre il principo del &lt;em&gt;modello sostitutivo&lt;/em&gt;, ma applicato alle definizioni interne del linguaggio o del sistema operativo).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Nonostante il processo sia banale e alla base di ogni semplice ragionamento, esso rappresenta un elemento fondamentale del processo di elaborazione di una procedura più sofisticata, ed è necessario averlo compreso perfettamente se si vogliono poi padroneggiare principi più complessi.
&lt;/p&gt;

&lt;h3&gt;Differenza tra ordine normale e ordine applicativo di valutazione&lt;/h3&gt;

&lt;p&gt;
  Nell'esempio precedente, abbiamo valutato il risultato di ogni singolo parametro prima di valutare il corpo della funzione. Questo processo viene chiamato &lt;em&gt;ordine applicativo di valutazione&lt;/em&gt;; tuttavia possiamo ottenere lo stesso risultato usando un altra tecnica, chiamata &lt;em&gt;ordine normale di valutazione&lt;/em&gt;, che consiste nel &lt;strong&gt;non&lt;/strong&gt; calcolare il valore dei parametri, fino a ché ciò non sia strettamente necessario. Consiglio vivamente di approfondire l'argomento attraverso il seguente articolo (in lingua inglese): &lt;a href="http://people.csail.mit.edu/jastr/6001/spring06/r23.pdf"&gt;http://people.csail.mit.edu/jastr/6001/spring06/r23.pdf&lt;/a&gt;.
&lt;/p&gt;

</description>
      <pubDate>Wed, 07 May 2008 15:12:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:4a1376e2-3b9d-4df9-8005-f837bfeba14b</guid>
      <comments>http://www.dibistore.com/articles/2008/05/07/analisi-del-modello-sostitutivo-per-applicazioni-procedurali#comments</comments>
      <category>programmazione</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=analisi-del-modello-sostitutivo-per-applicazioni-procedurali&amp;month=05&amp;year=2008&amp;day=07</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/05/07/analisi-del-modello-sostitutivo-per-applicazioni-procedurali</link>
    </item>
    <item>
      <title>Principi base della gestione di memoria</title>
      <description>
&lt;p&gt;
  Quando programmiamo in alcuni linguaggi di alto livello, come ad esempio in &lt;a href="http://www.ruby-lang.org/en/" title="Ruby Programming Language"&gt;ruby&lt;/a&gt;, non abbiamo bisogno di preoccuparci di come viene gestita la memoria da parte del computer. Tuttavia è interessante (oltre che utile) conoscere almeno a livello superficiale cosa avviene dietro le quinte. Questo articolo ha l'obiettivo di descrivere in maniera generale il processo di lettura e scrittura della memoria.
&lt;/p&gt;

&lt;h3&gt;Registri&lt;/h3&gt;
&lt;p&gt;I registri sono la parte più performante della memoria, ma sono anche molto costosi, infatti nei processori 80x86, abbiamo a disposizione solo 8 registri da 32 bit (più altri di minore capacità). Quando lavoriamo a basso livello ci conviene sempre utilizzare i registri (se possibile) in modo di sfruttare appieno la velocità della nostra &lt;em&gt;cpu&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;Cache&lt;/h3&gt;

&lt;p&gt;La cache è quella parte della memoria che memorizza i valori corrispondenti a diversi indirizzi fisici di memoria. In ogni computer può esser presente uno o più livelli di cache, ad esempio L1 e L2. Prendendo come esempio L1, esso è costituito da diverse &lt;em&gt;cache lines&lt;/em&gt; (linee di cache) che a loro volta contengono delle sequenze di byte.&lt;/p&gt;

&lt;h4&gt;In che modo vengono memorizzati i dati in cache?&lt;/h4&gt;

&lt;p&gt;Solitamente vengono usate tre strategie per determinare in quale &lt;em&gt;cache line&lt;/em&gt; inserire il valore presente in memoria:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;strategia a mappatura diretta: da ogni indirizzo di memoria viene ricavata la relativa linea di cache attraverso un algoritmo. Tuttavia essendo le linee di cache un numero molto inferiore rispetto agli indirizzi di memoria, è probabile che si creino dei conflitti qualora si tenti di sovrascrivere una linea di cache già usata in precedenza.&lt;/li&gt;
  &lt;li&gt;strategia a mappatura associativa: in questo caso il controller di cache, ha la possibilità di decidere arbitrariamente quale linea di cache utilizzare. Questo metodo è poco usato in quanto molto dispendioso a livelli di performance.&lt;/li&gt;
  &lt;li&gt;memoria associativa n-volte (&lt;em&gt;n-way set associative cache&lt;/em&gt;): In questo caso il blocco di cache che abbiamo a disposizione viene suddiviso n volte (per esempio 2 o 4), e queste suddivisioni vengono chiamate &lt;em&gt;set&lt;/em&gt;. Questo ci permette di usare la strategia a mappatura diretta direttamente sui set, mentre al loro interno possiamo usare la strategia a mappatura associativa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;E quando tentiamo di sovrascrivere una linea di cache utilizzata in precedenza?&lt;/h4&gt;
&lt;p&gt;
  Nel caso in cui tentiamo di sovrascrivere una porzione di memoria attraverso una mappatura diretta, viene semplicemente dovrascritta la parte interessata, mentre nel caso stiamo usando una mappatura associativa, il discorso diventa più complesso: in alcuni casi viene sostituita la linea di cache usata meno recentemente, mentre altre volte la sostituzione avviene in modo randomico oppure attraverso il meccanismo &lt;em&gt;fifo&lt;/em&gt; (first in first out).
&lt;/p&gt;

&lt;h3&gt;Cosa succede quando scriviamo dati in memoria principale?&lt;/h3&gt;
&lt;p&gt;Ma soprattutto: quando tento di salvare un dato in un indirizzo di memoria, il livello di cache che si occupa di memorizzare il valore, come interagisce con questo processo?&lt;br /&gt;
Anche qui le scelte più usate sono due:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;write through policy&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;write back policy&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Write through policy; ogni volta che memorizziamo un dato in memoria, dapprima viene salvato in cache, subito dopo nella memoria principale. Write back policy invece salva prima il dato in memoria, e dopo un certo lasso di tempo lo salva nella memoria principale. Qualora stiamo salvando grosse quantità di memoria, nel primo caso il BUS che trasporta i dati dalla cache alla memoria principale finisce per intasarsi, analogamente nel secondo caso se tentiamo di memorizzare un dato nella stessa linea di cache, dobbiamo attendere che venga trasferito il rispettivo valore nella memoria principale. Nel caso la performance sia un elemento essenziale, &lt;strong&gt;è compito del programmatore&lt;/strong&gt; (nei limiti del possibile) assicurarsi di utilizzare la cache in maniera propria.
&lt;/p&gt;

&lt;h4&gt;NUMA&lt;/h4&gt;

&lt;p&gt;Questo livello di memoria viene usato generalmente da dispositivi quali schede video, schede di interfaccia, ecc, che ovviamente hanno un tempo di accesso maggiore rispetto alla memoria principale.&lt;/p&gt;


&lt;h3&gt;Memoria virtuale&lt;/h3&gt;
&lt;p&gt;
La memoria virtuale simula la memoria principale utilizzando lo spazio su disco ed è responsabile del trasferimento di dati dall'hard disk alla memoria principale. E' inoltre responsabile della gestione dei processi del sistema, ad esempio ipotizzando di avere in attivo 10 servizi contemporaneamente, come può la &lt;em&gt;CPU&lt;/em&gt; decidere quale memoria far utilizzare a ciascun servizio? La risposta è il &lt;em&gt;paging&lt;/em&gt;.&lt;br /&gt;
Il &lt;em&gt;paging&lt;/em&gt; consiste nel suddividere la memoria in porzioni (per esempio da 32 bit) le quali vengono affidate ai vari processi. In questo modo ogni processo avrà i suoi indirizzi di memoria riservati (nota che per il processo 1, l'indirizzo $F è diverso dal rispettivo $F nel processo 2). La &lt;em&gt;CPU&lt;/em&gt; userà poi in seguito una tabella di &lt;em&gt;lookup&lt;/em&gt; per conoscere l'effettivo indirizzo, che a sua volta contiene un meccanismo di cache per evitare problemi di performance.
&lt;/p&gt;



&lt;h3&gt;Esempio pratico per l'ottimizzazione del software in C&lt;/h3&gt;

&lt;code&gt;&lt;pre&gt;
  int arr[123][123]
  ...
  for(i = 0; i &lt; 123; i++)        arr[0][0] = ..
  {                               arr[1][0] = ..
    for(j = 0; j &lt; 123; j++)      arr[2][0] = ...
    {
      arr[j][i] = i + j;
    }
  }
  
vs

  int arr[123][123]
  ...
  for(i = 0; i &lt; 123; i++)        arr[0][0] = ..
  {                               arr[0][1] = ..
    for(j = 0; j &lt; 123; j++)      arr[0][2] = ...
    {
      arr[i][j] = i + j;
    }
  }
&lt;/pre&gt;&lt;/code&gt;


&lt;p&gt;In questi due esempi l'unica differenza risiede nell'ultima istruzione. Il &lt;code&gt;C&lt;/code&gt; usa l'&lt;a href="http://en.wikipedia.org/wiki/Row-major_order" title="Row-major order - Wikipedia, the free encyclopedia"&gt;ordinamento a colonne&lt;/a&gt; per gestire gli array di dimensione multipla, per cui vengono salvati gli indici in posizioni continue nella cache di memoria. Tuttavia nel primo esempio l'accesso avviene in modo non naturale, causando un fenomeno descritto come &lt;a href="http://en.wikipedia.org/wiki/Thrash_%28computer_science%29" title="Thrash (computer science) - Wikipedia, the free encyclopedia"&gt;trashing&lt;/a&gt;, mentre nel secondo caso sfruttiamo appieno le capacità della &lt;em&gt;CPU&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La chiave qui sta nel fatto che è sempre meglio studiare come avviene l'accesso alla memoria qualora si stia tentando di ottimizzare il proprio codice a questi livelli (anche se sarebbe sempre da prendere come regola generale).&lt;/p&gt;


&lt;h3&gt;Conclusioni&lt;/h3&gt;
&lt;p&gt;
  Nella lista non è stata inclusa la gestione della memoria su disco fisso, dispositivi esterni e network.&lt;br /&gt;
  Approfondimenti:
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/CPU_cache" title="CPU cache - Wikipedia, the free encyclopedia"&gt;http://en.wikipedia.org/wiki/CPU_cache&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://it.wikipedia.org/wiki/Non-Uniform_Memory_Access" title="Non-Uniform Memory Access - Wikipedia"&gt;NUMA&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://webster.cs.ucr.edu/WriteGreatCode/index.html" title="Write Great Code"&gt;Write great code series&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/p&gt;

</description>
      <pubDate>Sat, 29 Mar 2008 23:11:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:6565c3f5-adb5-4619-82ce-2df4ff068f6f</guid>
      <comments>http://www.dibistore.com/articles/2008/03/29/principi-base-della-gestione-di-memoria#comments</comments>
      <category>programmazione</category>
      <category>memory</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=principi-base-della-gestione-di-memoria&amp;month=03&amp;year=2008&amp;day=29</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/03/29/principi-base-della-gestione-di-memoria</link>
    </item>
    <item>
      <title>Principi base di input/output (I/O) in ruby</title>
      <description>&lt;p&gt;Una domanda legittima che un programmatore può farsi nel corso dei suoi studi è: dov'è che esattamente viene rediretto l'output dei miei comandi?&lt;br /&gt;Ad esempio in ruby, il metodo &lt;code&gt;puts&lt;/code&gt; viene chiamato senza ricevente esplicito, quindi da qualche parte deve essere definito dove stampare la stringa.&lt;/p&gt;

&lt;p&gt;Quando avviamo un programma in ruby, ci vengono fornite tre costanti, &lt;code&gt;STDIN&lt;/code&gt;, &lt;code&gt;STDOUT&lt;/code&gt; e &lt;code&gt;STDERR&lt;/code&gt;, che indicano rispettivamente da dove prendere l'input, dove stampare l'output e infine gli errori. Queste variabili contengono degli indirizzi di memoria, possiamo verificarlo con un semplice inspect delle costanti.&lt;br /&gt;A dire il vero, ruby ci mette a disposizione anche tre variabili globali ($stdin, $stdout e $stderr), che possono essere gestite direttamente da noi all'interno del programma per modifica il flusso I/O. Vediamo un esempio:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;
  file = File.new('foo', w)
  puts 'standard output'
  
  $stdout = file
  puts 'sto scrivendo all\'interno del file'
  
  $stdout = STDOUT
  puts 'sono nuovamente nel flusso standard'
  
&lt;/pre&gt;&lt;/code&gt;

</description>
      <pubDate>Sat, 22 Mar 2008 19:01:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:d08182a1-f972-4e08-8e13-af60f90347b3</guid>
      <comments>http://www.dibistore.com/articles/2008/03/22/principi-base-di-input-output-i-o-in-ruby#comments</comments>
      <category>ruby</category>
      <category>io</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=principi-base-di-input-output-i-o-in-ruby&amp;month=03&amp;year=2008&amp;day=22</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/03/22/principi-base-di-input-output-i-o-in-ruby</link>
    </item>
    <item>
      <title>Usare acts_as_taggable con will_paginate</title>
      <description>&lt;p&gt;Il plugin &lt;a href="http://agilewebdevelopment.com/plugins/acts_as_taggable_on_steroids" title="Plugins - Acts As Taggable On Steroids - Agile Web Development"&gt;acts_as_taggable_on_steroids&lt;/a&gt; è molto utile quando abbiamo bisogno di taggare i nostri modelli in &lt;a href="http://rubyonrails.org/" title="Ruby on Rails"&gt;rails&lt;/a&gt;. Recentemente mi sono trovato a dover implementare una funzionalità di paginazione che tenesse conto dei risultati della ricerca per tag. Come plugin per la paginazione &lt;a href="http://www.zooppa.com/" title="ZOOPPA &amp;mdash; Home"&gt;usiamo&lt;/a&gt; &lt;a href="http://errtheblog.com/posts/56-im-paginating-again" title="I'm Paginating Again &amp;mdash; err.the_blog"&gt;will_paginate&lt;/a&gt; e per aggiungere la funzionalità mi è bastato inserire questo pezzo di codice alla fine del file &lt;code&gt;environment.rb&lt;/code&gt;.&lt;/p&gt;



&lt;code&gt;&lt;pre&gt;
  module ActiveRecord
    module Acts
      module Taggable
        module SingletonMethods
          def paginate_tagged_with(*args)
            options = find_options_for_find_tagged_with(*args)
            options.blank? ? WillPaginate::Collection.new(1, 1, 0) : paginate(:all, options)
          end        
        end
      end
    end
  end
&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;Dietro le quinte stiamo definendo un metodo che usa paginate al posto di file, &lt;code&gt;WillPaginate::Collection.new(1, 1, 0)&lt;/code&gt; serve invece per evitare di ricevere l'errore &lt;code&gt;undefined method `page_count' for []:Array&lt;/code&gt; quando l'array di risultati è vuoto.&lt;/p&gt;

</description>
      <pubDate>Thu, 20 Mar 2008 15:28:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:a6e9ba32-cb39-4356-84c2-c2d138722a3e</guid>
      <comments>http://www.dibistore.com/articles/2008/03/20/usare-acts_as_taggable-con-will_paginate#comments</comments>
      <category>ruby on rails</category>
      <trackback:ping>http://www.dibistore.com/trackbacks?article_id=usare-acts_as_taggable-con-will_paginate&amp;month=03&amp;year=2008&amp;day=20</trackback:ping>
      <link>http://www.dibistore.com/articles/2008/03/20/usare-acts_as_taggable-con-will_paginate</link>
    </item>
  </channel>
</rss>
