PDI^2

Note dal Ruby Social Club Milano 3

ruby, personale, rubyonrails, ruby-it September 27, 2008 1:41 pm (Save post)

Passando da milano un paio di giorni fa i rubyisti locali hanno avuto l’ottima idea di organizzare un meeting.
In fondo un po’ me lo meritavo, essendo stato presente al primo storico RSC dovevano farmi vedere come siam cresciuto in due anni :)

E cavolo se siamo cresciuti! La prima volta eravamo in cinque o sei, se non ricordo male, stavolta eravamo una trentina! Note sparse:

  • l’accoglienza di mikamai è stata ottima. Anche perché mi hanno fatto stare da loro per due giorni oltre alla sera del meeting :)
  • ben tre donne!
  • nei talk si è parlato, tra le altre cose, di tecnologie di scraping, amazon EC2, assistenti virtuali, visualizzazione di social network con Processing
  • all’ultimo momento ho scoperto di dover fare un mini-talk anche io. Come speaker faccio schifo. La micropresentazione è online, ma siccome è stata accroccata in fretta e con il takahashi method non credo ci capirete niente. Però se volete chiedere fate pure :)
  • Matteo Vaccari ha tenuto una pico-sessione al proiettore presentandoci un problema interessante:

    supponiamo di voler partizionare/ordinare un array in modo che tutti gli elementi X vengano prima di quelli Y.
    Ad esempio, ordinare [1,2,3,4,5,6,7] in modo che tutti i pari vengano prima dei dispari.
    La cosa va fatta in place, in modo che lo spazio usato sia costante (qualche variabile ausiliaria va bene). E in tempo lineare.
    Questo è facile, effettuando uno scan della lista e scambiando ogni volta l’elemento i-esimo con l’elemento j-esimo, dove i è inizialmente zero (incremento quando non scambio) e j è array.length -1 (fine array, decremento quando scambio).
    In questo algoritmo l’invariante è che ogni passo riduce la dimensione dell’array lasciando le parti esterne ordinate (l’inizio che si è già passato perché composto da elementi “minori” e la fine che si è allontanata perché composta da elementi “maggiori”).
    Come si fa con una partizione in tre (minori, medi, maggiori) ?

    Divertitevi, sulla ML c’è un thread (spezzato in due) a riguardo

  • io avevo anche promesso a un paio di persone di dargli i dati precisi di un altro problemino, ma non mi ricordo a chi l’ho detto. Beh in ogni caso il problema è il seguente:

    Dato un array A di lunghezza N vogliamo produrre in output un array B della stessa lunghezza in cui ogni a ogni elemento A[i] corrisponda il prodotto di tutti gli elementi dell’array tranne se stesso.
    Ad esempio per A= [1,2,3,4] avremmo B= [2*3*4, 1*3*4, 1*2*4, 1*2*3] = [24, 12, 8, 6].

    Ovviamente, in tempo lineare.
    Se ora state per dire “basta usare la divisione..” beh ovviamente no, senza usare divisione, modulo e similari.

  • tra le altre cose di cui mi ricordo di aver parlato: couchdb, linguaggio io, bloody mary, le cameriere, django, biologi, ungheria, irlanda, etc etc
  • è sempre bello incontrare persone che hai sempre letto sullo schermo e scoprire che hanno una terza dimensione

Mi scuso con quelli che mi son stati vicini perché credo di aver parlato troppo e ascoltato poco, ma mi ha fatto molto piacere incontrarvi, spero si possa fare di nuovo, e d’altronde sarebbe anche ora di fare un nuovo RSC meeting a roma :)

script/performance/request in rails 2

personale, rubyonrails January 13, 2008 10:27 am (Save post)

Avete visto che figa la nuva fìciur che c’è in rails2? In pratica script/performance/request permette di eseguire uno scriptino che simula un’interazione dell’utente effettuandone il profiling.

Ora, vi invito a guardare il changelog, che mostra questo fantastico esempio;

    $ cat login_session.rb
    get_with_redirect '/'
    say \"GET / => #{path}\"
    post_with_redirect '/sessions', :username => 'john', :password => 'doe'
    say \"POST /sessions => #{path}\"
    $ ./script/performance/request -n 10 login_session.rb

Ora, cosa c’è che non va in questo eempio, diranno i miei piccoli lettori? Quello che non va in tutti gli esempi che ci sono in rails dalla versione 1.2 in poi, il fatto che non funziona.

Perché? Semplicemente perché post_with_redirect e get_with_redirect non esistono. say, d’altro canto, è un puts inutuile e non si capisce perché ci sia, forse perché a jeremy kemper piace molto perl6.

I dati, che verranno generati anonimamente nella directory tmp/ del vostro progetto, senza che ci sia modo di saperlo, sono d’altronde i normali dati di ruby-prof, il che significa che vi mostreranno come il 99% del tempo sia speso da rails per definire dei metodi. Sigh sob. Ah e ad ogni esecuzione request si lamenta di non trovare un file descriptor per la console (?) .

Mi chiedo che fine abbia fatto quella pulizia e precisione che c’era in rails pre 1.0 :/

Fare casino con IRB, binding ed eval

ruby July 3, 2007 9:49 pm (Save post)

Ricordate quando parlavo del mio piccolo doctest per ruby?

Ok, continua ad essere sporco e puzzolente, ma adesso ha un paio di feature in più, tra cui la possibilità di effettuare il replay di una sessione passata.
Questo significa che se avevate un test-esempio


>> a = 10
=> 10
>> b = 20
=> 20
>> def sum(a,b)
>>  a+b
>> end
=> nil
>> sum(a,b)
=> 30

potete effettuare il replay della sessione ed andare avanti con


>> def triplesum(a,b)
>>  sum(sum(sum(a,b),b),b)
>> end
=> nil
>> triplesum(a,b)
=> 70

Che è molto carino, e utile imo.
Ora, dove sta il problema? Primo, nel modo in cui funziona eval, secondo, nel modo in cui è scritto IRB.

evil eval
Che eval sia fondamentalmente malvagio è una cosa rinomata, ma per scrivere un REPL rimane la cosa più sensata.
Quello che potreste non sapere è che in ruby eval() non può definire una variabile nello scope in cui è richiamata. O quasi.

Lasciate stare IRB e provate questo:

ruby -e \"eval('a=10');a\"

Se tutto funziona normalmente dovreste beccarvi un bel NameError. Questo perché il parser non ha mai visto nessuna a nello scope corrente.
Se però provate questo:

ruby -e \"eval('a=10');p eval('a')\"

vedrete stampato un bel 10 che dimostra che la variabile esiste solo che non è accessibile con il solito approccio.

good IRB
IRB però vi frega in questo, guardate un po’:

>> eval(\"a=10\")
=> 10
>> a
=> 10

Perché? Perché ovviamente IRB usa internamente eval, non fa il parsing come l’interprete farebbe normalmente, e quindi tutto funziona.

good require
Se caricate un file con require() le variabili locali rimangono.. beh.. locali, e quindi non sono accessibili all’esterno. Allora come facciamo a caricare le variabili locali che avevamo nella sessione precedente?
Non possiamo fare un dump del codice su un file e caricarlo con questo metodo, ma possiamo usare eval() per definirle in un oggetto Binding e poi convincere IRB che deve usare quell’oggetto come spazio di lavoro.

evil IRB
Solo che IRB, di default, non permette di effettuare questa cosa. C’è un casino di setup quando la console interattiva viene inizializzata, che va dal caricare l’encoding al verificare la configurazione di default all’impostare il nome del programma, e tutto questo è fatto tramite IRB.start che non ammette alcun parametro utile per i nostri scopi.

Soluzione
Qual’è la prima forma di riuso? Il copia&incolla, esatto. Quindi per definire la nuova funziona ci si limita a ricopiare il codice di quella originale in modo quasi identico, cambiandolo dove serve.

In attesa che qualcuno ci dia una versione di IRB che ci semplifichi la vita, potete quindi usare il mio IRB.start_in_binding che crea una console per il binding dato (o per TOPLEVEL_BINDING).
Pare funzionare, in caso non andasse potete ravanere nei sorgenti di IRB da soli o sfruttare il lavoro fatto da flgr in ruby-breakpoint

Perché Java è meglio di Ruby

ruby, java, fun June 22, 2007 4:56 pm (Save post)

Si, siamo una comunità di disturbati, e ne siamo fieri.

Ruby & rails vs J2EE, di nuovo

ruby, java, blogosfera June 13, 2007 2:44 pm (Save post)

Su TRM c’è un articoletto che ha l’intento di spiegare rails al programmatore J2EE, e da lì c’è un articoletto di risposta di uno sviluppatore J2EE, appunto.

Le mie dure lire: usate quello che è più adatto al progetto corrente, che conoscete meglio e che preferite. È il modo giusto per vivere felici :-)

Ad ogni modo, nel post e nei commenti ci sono dei punti validi: la m17n in ruby è ancora debole (ma per il web cambia poco, visto che utf8 è gestito), il deploy non è ancora un’operazione banale, ruby non ha i thread nativi ed è un interprete lento, non esiste accesso a tutta la pletora di MOM che c’è in java e altro. Ricordo che io, fondamentalmente odio rails ;)

Però, siccome l’autore dice di cercare l’oggettività, per quanto ovviamente possibile, mi permetto di rettificare alcune cose sbagliate ( credo siano dovute alla mancanza di conoscenza dell’ambiente, non a un FUD intenzionale ;)

Su ruby:

  • ruby non ha le variabili dì’istanza pubbliche di default, anzi non è proprio possibile avere variabili pubbliche, si accede solo attraverso metodi.
    Le variabili d’istanza pubbliche sono una rottura dell’incapsulazione (eccezione: property alla python/C#/TP) e infatti in Smalltak, che la OO l’ha inventata, non esistono.
  • non so cosa significhi che la struttura delle classi è neogotica, perché non so qual’è l’equivalente degli archi a sesto acuto in ambito programmatorio, ma la gerarchia delle classi mi sembra abbastanza ragionevole. Non c’è neanche l’ereditarietà multipla che dovrebbe far storcere il naso ai javisti (io, essendo anche pythonista non ci vedo niente di male :)
  • sinceramente non mi pare sia possibile assegnare una variabile da sinistra a destra in ruby, a meno che non ci sia un operatore “->” che non ho mai trovato negli ultimi 6 anni
  • le variabili d’istanza vengono istanziate al volo, vero, ma puoi comunque farlo solo tramite i metodi (o la reflection) quindi non c’è problema
  • “La tipizzazione degli oggetti base è da barzelletta non esiste”. De gustibus, a me i tipi dinamici piacciono. D’altronde neanche java è type safe, e HAppS è ancora un po’ ostico per me.
  • gli errori sono più comprensibili in ruby imho. Almeno l’equivalente di NullPointerException ti dice che metodo è stato richiamato, perché nil è un oggetto
  • mai fallita l’installazione di una gemma, ma capisco possa accadere. Però il confronto con maven mi pare inappropriato, non è un package manager.

Su Rails:

  • il sistema di template (che imo pone pochi problemi) si cambia in una riga. script/plugin install liquid | haml | erubis | ya2yaml | amrita | markaby o quel che volete
  • credo che il plurale di persona (as in dramatis persona) sarebbe personae, ma si sa che gli inglese col latino fanno porcate :) . Aldilà di questo, è possibile definire le proprie inflection se si vuole un db sgrammaticato (o uno legacy)
  • non ho capito che significa che la gestione degli url viene fatta in punti diversi, io la faccio solo in routes.rb
  • non so perché non si possa usare un qualsiasi approccio allo sviluppo. In teoria si può sviluppare un’applicazione RoR anche senza modelli e controller ma grazie al cielo lo fanno in pochi ;)
  • si può usare uno schema legacy, si può fare. Ci sono pure plugin per farlo. Certo, manca JCA.
  • manca il supporto all’internazionalizzazione builtin, ma esistono plugin come globalize apposta. Rimane sempre meglio averla builtin, come in django (lo dicevo di là) e comunque il supporto a unicode è scadente, come dicevo prima, ma c’è sempre UTF-8.
  • non ho capito il problema con gli scaffolding. Quelli servono a evitare di scrivere un po’ di codice, mica sono un’interfaccia di amministrazione (django++ ma per rails ci sono, ancora, dei plugin)

Sui punti generali non posso commentare.. non uso capistrano, ViM è il mio IDE e Rails forse non scala ma non per colpa di FastCGI (che è concettualmente molto diverso da CGI). Yahoo, Google, Digg, reddit, Flickr, livejournal etc scalano infinitamente senza servlet. <flamebait>e poi vorrei vederla questa mega applicazione in java che scala come slashdot, che è fatto con mod_perl </flamebait>

Ancora, right tool for the job, KISS, long life & prosperity, io domani parto per l’heineken jammin festival dove non mi preoccuperò di queste cose :)

ruby, doctest e lo pseudofile DATA

ruby June 12, 2007 8:33 am (Save post)

Sono un maestro del tosare yak.
Ovvero, di quella antica e nobile pratica per cui devi risolvere un problema, che però dipende da un altro, il quale porta a un altro che porta a un altro e a un certo punto ti trovi a depilare uno yak per far funzionare il tuo blog.

Nel mio caso il processo è stato

  1. mephisto non ha la feature X (che ho dimenticato cosa fosse)
  2. cavolo dovrei scrivermi il mio blog engine..
  3. beh posso farlo usando ramaze
  4. peccato non abbia una gui di amministrazione automatica
  5. beh posso sempre farla se ho un buon ORM
  6. ma non mi va di usare ActiveRecord, oltretutto son sempre stato un fan del Data Mapper
  7. oddio c’è la v0.50 di Og.. no ancora non è rilasciata e non hanno tolto tutti i rescue Object… brrr
  8. vabè, potrei scrivermene uno io, piccolino, ma ben testato
  9. cavolo se son brutti sti test..
  10. ah beh posso usare test/spec
  11. cavolo sti test fanno schifo..
  12. e poi non son capace di azzeccare una descrizione..
  13. ah avessi doctest come in python..
  14. beh potrei scrivermi il mio..

Ed è a questo punto che ci ritroviamo, circa una settimana dopo, 1400 righe più tardi, e con SLOCCount che per questo progetto stima 4 mesi di lavoro e una spesa di 38.581 dollari, da investire in 0.83 sviluppatori (?).

1400 righe? Ma sei scemo?? diranno ora i miei piccoli lettori.
In verità si, ma non per questo, in quanto solo un quinto di queste sono la libreria, mentre il resto sono i miei test unitari & doctest.
La mia libreria è piccina, se considerate che SLOCCount su ActiveRecord trova 22941 linee di codice :) .

Ed il bello è che metà di queste righe sono doctest, che nella mia microimplementazione significa: apri irb, prova cose, copincolla.

Come funziona test/doc

La “libreria” che fa funzionare il tutto è lunga ben 30 righe, perché è mal scritta e scorretta, ma io le voglio bene lo stesso.

L’idea è semplice: ogni operazione in un REPL come irb è composta da due parti: il codice, e il risultato. Se usate irb con l’opzione –simple-prompt si tratta di una cosa come questa:


>> codice()
=> risultato

dunque se le righe sono in un oggetto enumerabile basta usare grep per trovarle e ignorare le altre linee, nelle quali potrete aggiungere utili commenti o, nel mio caso, i modeltest di django ancora da tradurre :)

Una volta che avete la lista ordinata in coppie input/output basta fare l’eval del primo e confrontrarlo con il secondo. Facile, no?

In realtà no, definendo un metodo o una classe in irb questo non va perché vi trovate con input multilinea, ma io mi limito a ignorare il problema, e i miei test sono abbastanza carini.

Ora: dov’è il posto migliore per mettere i doctest? Nei commenti, potreste dire voi. Concordo in generale, ma in questo caso, visto che le cose da fare sono molte e le righe del modello molto poche, sembrava più conveniente mettere i test nello pseudofile DATA.

Per chi non lo sapesse, ruby mette a disposizione del programmatore una variabile, DATA appunto, che si comporta come un oggetto File, ovvero è possibile leggere le linee, fare seek etc etc.

Il contenuto dell’oggetto non è però un vero file, ma il pezzo del file .rb corrente che sta dopo dopo la keyword __END__.

Sembrava perfetto per il mio scopo. Nessun require strano, nessun problema per fare parsing, codice
& esempi nello stesso file ma separati e dovendo aggiungere una singola linea di codice.

Senonché, e qui viene il problema, DATA non funziona come mi ricordavo io.
Ovvero, la variabile è globale e rappresenta la relativa sezione non del file corrente (cioè di __FILE__) ma dello script in esecuzione (cioè $0 o $PROGRAM_NAME).

Ergo eseguire i miei doctest tramite rcov è impossibile, perché DATA è inizializzato, male, in rcov stesso. Vabè, torniamo al parsing a mano, in fondo basta leggere il file in un array di linee e poi scorrerlo finché non si trova __END__

Però dovrei ridurmi a specificare il nome del file ogni volta che voglio creare un doctest.

Soluzione: filename ||= caller[0][ /^.*?(?=:)/ ].

Lasciando stare la Regexp, significa che usiamo come nome del file quello in cui c’è il codice che crea il DocTest.

Quindi se ho una riga DocTest.new in test/sample.rb non c’è bisogno che usi degli argomenti, perché usando caller posso scoprire automaticamente qual’è il file chiamante (appunto, test/sample.rb.

Ora i miei test funzionano, sono gradevoli e posso usare quelli di django praticamente copincollandoli (come noterete ci son pure gli stessi commenti).
Trentottomila dollari ben spesi!

Post Archivio n° 17

ruby, personale, blogosfera, web, ruby-it June 4, 2007 6:06 pm (Save post)

Sono in quel momento dell’anno un cui decido che diventerò una persona migliore.

Studiare qualcosa di completamente ignoto, andare a trovare i parenti, telefonare a amici che non sento da un sacco di tempo, fare attività fisica, scrivere codice che serva minimamente a qualcosa/qualcuno, ripulire l’hard disk, farmi la barba con regolarità, fumare di meno.

Ergo sono stremato, mi limito a buttare qua qualche link nella peggiore tradizione dei link dump di del.icio.us, scusate, ma ricordate che l’archivio serve più a me che a voi.

  • il più bel captcha di sempre
  • federico, 1: convertitore pdf -> ipod
  • federico, 2: doubtr.com, gli amici che ti danno consigli, 2.0
  • giovanni, 1: se siete giocatori apprezzerete questo blog che aggrega video sul poker. Ricordate che il vero giocatore non ricorda mai quando perde.
  • io che smanetto per aggiungere le Atom Thread Extension a mephisto, il che mi ricorda che non ci sono ancora notizie se la mia patch sia accettata, ritenuta inutile, o se quantomeno integrino i miei test che cavolo sono migliori di quelli esistenti e almeno passano. La commit bit anarchy è l’unica soluzione per lo sviluppo open source, son sempre più convinto.
  • nel frattempo mi hanno reddit’ato. Risultato: un migliaio di visite in più del normale. Nota interessante: >60% dei client sono firefox, 15% IE (più 7 che 6).
  • venerdì incontro rubyista. Siccome l’ambiente stavolta è casalingo magari fate un fischio in anticipo.
  • e mercoledì 6 giugno ci state per una seratina a roma tra nerd^Wgeek^Wtecnici^Wblogger^Wgente che vuole stare insieme? Dobbiamo solo berci qualche birra e fare due chiacchiere potenzialmente informatiche. Lo so, sarà difficile, senza neanche chiamarlo \w+camp, aprire un wiki o un blog sull’argomento, scroccare da mangiare da San Lorenzo o stampare magliette, ma ci proviamo.
YARV supporta callcc :)

ruby May 24, 2007 1:07 pm (Save post)

il commento del commit è bellissimo:

cont.c: support callcc which everyone love. incomplete. please give me bug reports.

Beh andate e scaricate ruby 1.9.
Stressatelo su, che la release stabile deve essere una roccia ;)

Ragioni per cui amo ruby numero 1004, 1005

ruby May 17, 2007 3:13 pm (Save post)

Ogni tanto finisco sui blog di ugidotnet, e su quello di Adrian Florea ho trovato questa cosa carina: le cose che non si possono fare con le classi statiche.

Leggete la lista, è così incredibilmente fico che nessuna di quelle cose abbia senso in ruby (o python) :) .

(Siete liberi di pensare che un linguaggio non è serio se non ha classi static, non ereditabili etc etc. De gustibus)

La ragione 1005 è Module#instance_methods(include_super=true) cioè la possibilità di chiedere a un modulo (e a una classe, perché Class.superclass == Module) quali siano i metodi disponibili in una sua istanza. E usando come argomento false si ottiene la lista dei soli metodi definiti lì, senza considerare quelli ereditati.

Ne parlavo l’altro giorno con massimiliano, e oggi mi avrebbe fatto comodo sapere come farlo in python (problema poi completamente aggirato). Coincidenza curiosa.

Auguri (Chrisblogs|Anarchaia) !

ruby, personale, web March 30, 2007 8:03 am (Save post)

Nella comunità ruby (che ahimé, non seguo come un tempo) c’è sempre stata un sacco di gente interessante. Oddio, il SNR è peggiorato molto negli ultimi due anni ma sorvoliamo.

Tra questa gente interessante, c’è chris, che:

  • programma da dio
  • in una dozzina di linguaggi
  • mi ha fatto scoprire che si può implementare call/pc con call/cc in un linguaggio imperativo
  • ha sense of humor
  • è dannatamente più giovane di me e ne sa il quadruplo, di tutto

Oggi, innalzo le lodi di chris blogs, il suo blog che compie tre anni, e dei due anni di Anarchaia, l’insalata mista più bella della rete.

Eh già, perché è stato lui ha inventare i tumblelog, per quanto credo che il nome l’abbia inventato _why. D’altronde ora c’è tumblr che ha un sacco successo, ma io ho sempre pensato che il tuo tumblelog devi scriverlo da te ;)

E siccome io ne ho scritt una dozzina e poi non li ho mai pubblicati, e siccome ne avevo uno che mi son dimenticato di postare nel’ultimo anno, eccovi il mio tumblelog minimale, che si ottiene mettendo questo codice in rub.rb in un’applicazione nitro.
Non so se funzioni ancora. Forse funziona con Ramaze.


require \'nitro_and_og\'
require \'glue/timestamped\'
require \'skin\'
require \'nitro/helper/feed\'
require \'part/admin\'
	
class Thing
  is Og::SchemaInheritanceBase, TimestampedOnCreate
  property :text, :control=>:textarea
  property :title
  def to_href
    \"/thing/#{oid}\"
  end
  def to_html
    %(<p class=\"thing\">#{text}</p>)
  end
end
	
def thing(p, &block)
  Class.new(Thing) do
    property p, String
    define_method :to_html, block
  end
end
	
Quote      = thing(:author)    {\"<blockquote>%s</blockquote>\"%text}
Irc        = thing(:channel)   {\"<pre>%s</pre><p>on %s</p>\"%[text,channel]}
Snippet    = thing(:language)  {\"<pre>%s</pre>\"%text}
Image      = thing(:url)       {\'<img src=\"%s\" alt=\"%s\"/><p>   %s</p>\'%[url,title,text]}
Link       = thing(:url)       {\'<a href=\"%s\">%s</a>, %s\'%[url,title,text]}
	
Og.setup # default sqlite
	
class Home < Nitro::Controller
  helper :feed, :pager
  def atom
    response.content_type = "application/atom+xml"
    build_atom  Thing.latest,
                :title => "Tum! Atom Feed",
                :base=> "http://my.domain.info"
  end
  def login(pass)
    session[:ADMIN]=true if pass == 'password'
  end
end
	
Nitro.run(Home)

Get free blog up and running in minutes with Blogsome
Theme designed by Janis Joseph