Archivi categoria: Ruby

Ruby : cicli e iteratori – parte 2

Cos’è un iteratore?  E’ semplicemente un metodo che, per mezzo dell’operatore yield trasferisce il controllo al blocco di codice che è associato al metodo stesso quando questo viene invocato ……

Quando noi scriviamo

a.map { |i|  i*5 }

Il metodo map (che è un iteratore) trasferisce il controllo al blocco, cioè alla porzione di codice delimitata da {}.

In che senso trasferisce il controllo? perchè? quante volte? Questo dipende dal metodo.

each

l’iteratore più semplice è each. Questo metodo trasferisce il controllo al blocco per ogni elemento contenuto nella collection al quale è applicato.

[1,2,3].each { |x| puts x }

nel blocco il costrutto |x| indica che quando il controllo viene trasferito al codice contenuto nel blocco, la variabile x contiene il valore dell’elemento sul quale la funzione collect sta iterando.

E’ come scrivere:

for x in [1,2,3] do
  puts x
end

Collect Select Inject Reject

Questi quattro iteratori li troviamo in tutti i linguaggi funzionali, magari con nomi leggermente differenti.

collect aka map

Data una collection crea un’altra collection con lo stesso numero di elementi, ma alterando ogni elemento per mezzo del blocco associato.

numeri = [1,2,3,4,5]
doppi = numeri.collect { |x| x*2 }

produce [2,4,6,8,10]

select aka find_all

Data una collection crea un’altra collection contenente i valori per i quali il blocco associato ritorna true

singolo = [1,2,3,4,5]
pari = singolo.select { |x|  x % 2 == 0 }

reject

Data una collection crea un’altra collection contenente i valori per i quali il blocco associato ritorna false

singolo = [1,2,3,4,5]
dispari = singolo.reject { |x|  x % 2 == 0 }

inject aka reduce

Questo è più complicato: inject diversamente dagli altri iteratori non ritorna una collection ma semplicemente un valore, che è il risultato dell’esecuzione del blocco su tutti gli elementi della collection, accumulando i valori intermedi in un’altra variabile.

 

valori = [1,2,3,4,5]
somma = valori.select { |t, x|  t + x }

Notiamo che nel blocco il costrutto |t, x| definisce due variabili: la prima è l’accumulatore, la seconda è il valore dell’elemento della collection su cui stiamo iterando.

E’ come se avessimo scritto

t=0
for x in valori do
   t = t + x
end

Questo iteratore esiste in diverse varianti, la forma più generica è:

inject( valore_iniziale) { | accumulatore, elemento | ...... }

In cui passiamo al metodo inject un argomento che rappresenta il valore iniziale della variabile di accumulo.

Il blocco è opzionale, possiamo passare come argomento anche un simbolo che rappresenta l’operazione da eseguire da ogni iterazione:

somma = valori.inject( :+, 0)

se poi il valore iniziale dell’accumulatore è 0 anche questo può essere omesso:

somma = valori.inject( :+ )

l’iteratore è così smart che è in grado di determinare che l’elemento neutro per la somma è 0 mentre quello per il prodotto è 1.

 

per ora è tutto, restate collegati!

 

Ruby 2.1: il nuovo Garbage Collector

La versione 2.1 di Ruby introduce un nuovo Garbage Collector, vediamo come funziona!

Come tutti sapete, l’azione del GC è divisa in due fasi:

  1. la fase di Mark, in cui viene esplorato dalla radice l’albero degli oggetti e viene settato il bit FL_MARK per indicare quelli “vivi”
  2. la fase di Sweep, in cui si itera sugli slot dell’heap e gli oggetti con il flag FL_MARK non settato vengono aggiunti alla lista degli oggetti disponibili (per il riutilizzo).

Durante le fasi di Mark e di Sweep, il mondo si ferma e la nostra applicazione Ruby si congela.

Con Ruby 1.8, ad intervalli prestabiliti vengono eseguite in sequenza le due fasi e questo determina un tangibile congelamento dell’applicazione a causa della durata combinata di queste due fasi.

Dalla versione 1.9.3 di Ruby la fase di Sweep anzichè essere eseguita subito dopo quella di Mark, viene suddivisa in microfasi che sono eseguite ogni volta che è richiesta l’allocazione di un nuovo oggetti. In questo modo il tempo necessario a svolgere la fase di Sweep “scompare” dalla nostra percezione, ma rimane quello necessario alla fase di Mark.

Con Ruby 2.0 è stato introdotta la Bitmap Marking GC.
Dietro questo curioso nome si nasconde una intelligente trovata di Narihiro Nakamura: tutti sapete cos’è l’ottimizzazione Copy On Write del sistema di gestione della memoria dei sistemi Linux e Unix based; i processi che vengono forkati (per esempio per gestire più richieste contemporaneamente in un server WEB) mantengono in comune oggetti in memoria fino al momento in cui uno dei processi va ad alterare l’oggetto. Questo consente di minimizzare l’utilizzo di memoria, ma nel momento in cui la fase di Mark altera il bit FL_MARK, questo fa  venire meno la suddetta condizione e quindi l’ottimizzazione COW fallisce (limitatamente agli oggetti allocati dalla nostra applicazione Ruby). L’idea di Narihiro Nakamura è quella di spostare il bit FL_MARK in una sottostruttura (una bitmap) che diventa la sola parte che viene “sporcata” nella fase di Mark.

In Ruby 2.1 è stato introdotto un nuovo GC: questo è chiamato RGENGC (Restricted Generational GC), un GC generazionale parte dal presupposto che la maggior parte degli oggetti vengono allocati e poi “muoiono giovani”, il GC distingue tra oggetti “giovani” ed oggetti “vecchi”: gli oggetti “vecchi” sono quelli che “sopravvivono” all’n-esimo GC.

Con l’RGENGC vengono effettuati due distinti GC, il Minor GC in cui vengono trattati gli oggetti “giovani” e il Major GC (che viene eseguito solo quando la memoria scarseggia) in cui vengono trattati entrambi.

(segue)

 

 

 

RoR 4.1.0 beta 1 released!

ror

E’ Natale e il regalo di quest’anno è l’anteprima di Ruby On Rails 4.1

Spring Application Preloader

Spring velocizza lo sviluppo mantenendo l’applicazione in esecuzione in background,  evitando di riavviarla ogni volta che dovete eseguire un task di rake, una migrazione oppure un test.

config/secrets.yml

Questo files, che di default memorizza il parametro secret_key_base dell’applicazione, può essere utilizzato anche per memorizzare le chiavi di accesso per altre API externe.

Per esempio possiamo mantenere l’access key dei web services amazon

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
    aws_access_key: 09876543212345678
ed accedervi quando necessario nell’applicazione
aws_acc_key = Rails.application.secrets.aws_access_key

Action Pack Variants

I request variant  sono una specializzazione dei request format
che consentono di effettuare render differenziati in base al dispositivo da cui avviene la richiesta:

respond_to do |format|
    format.js      { ...... }
    format.desktop    { ....... }
    format.phone  { ....... }
    format.tablet   { ....... }
end

il variant deve essere impostato in una before_action

request.variant = :tablet if request.user_agent =~ /iPad/

Action Mailer Previews

Visitando uno speciale url è possibile visualizzare in anteprima l’aspetto delle email prodotto dall’Action Mailer.

Active Record Enums

Ora è possibile associare dei nomi ai valori numerici di un campo intero di una tabella.
Class Invoice < ActiveRecord::Base
        enum status: [ :suspended, :active, :payed ]
end

if status.payed? ......
………….. prosegue nel prossimo articolo …………..