Desidero una funzione che mantiene lo stato locale in Ruby.
Quella parola "funzione" dovrebbe immediatamente sollevare un grosso segnale rosso lampeggiante che sta utilizzando un linguaggio di programmazione errato. Se vuoi funzioni, dovresti usare un linguaggio di programmazione funzionale, non un linguaggio orientato agli oggetti.In un linguaggio di programmazione funzionale, le funzioni di solito vicino sul loro ambiente lessicale, che ti fa ciò che si sta cercando di fare assolutamente banale:
var state;
function incMult(factor) {
if (state === undefined) {
state = 0;
}
state += 1;
return factor * state;
}
print(incMult(2)); // => 2
print(incMult(2)); // => 4
print(incMult(2)); // => 6
Questo particolare esempio è in ECMAScript, ma sembra più o meno lo stesso in qualsiasi linguaggio di programmazione funzionale.
[Nota: Mi rendo conto che non è un buon esempio, perché ECMAScript è in realtà anche un linguaggio orientato agli oggetti, sia perché ha rotto la semantica di ambito atually dire che state
perdite in questo caso, anche. In una lingua con una semantica di ambito appropriata (e in un paio di anni, ECMAScript sarà uno di questi), funzionerà come previsto. Ho usato ECMAScript principalmente per la sua sintassi familiare, non come esempio di un buon linguaggio funzionale.]
Questo è il modo in cui lo stato è incapsulato in linguaggi funzionali poiché, beh, poiché ci sono linguaggi funzionali, tutto il ritorno a calcolo lambda.
Tuttavia, negli anni '60 alcune persone intelligenti hanno notato che si trattava di uno schema molto comune, e hanno deciso che questo modello era così comune a che meritava la propria lingua. E così, l'oggetto è nato.
Quindi, in un linguaggio orientato agli oggetti, anziché utilizzare le chiusure funzionali per incapsulare lo stato, usereste gli oggetti. Come avrai notato, i metodi in Ruby non si chiudono nel loro ambiente lessicale, a differenza delle funzioni nei linguaggi di programmazione funzionale. E questo è precisamente il motivo: perché l'incapsulamento dello stato è raggiunto attraverso altri mezzi.
Così, in Ruby si usa un oggetto come questo:
inc_mult = Object.new
def inc_mult.call(factor)
@state ||= 0
@state += 1
factor * @state
end
p inc_mult.(2) # => 2
p inc_mult.(2) # => 4
p inc_mult.(2) # => 6
[Sidenote: Questa corrispondenza 1: 1 è quello che i programmatori funzionali stanno parlando quando dicono "gli oggetti sono solo le chiusure di un uomo povero" . Naturalmente, i programmatori orientati agli oggetti di solito contrastano con "le chiusure sono solo oggetti di un povero uomo". E la cosa divertente è che entrambi hanno ragione e nessuno di loro lo comprende.]
Ora, per completezza, voglio sottolineare che mentre i metodi non si chiudono nel loro ambiente lessicale, c'è un costrutto in Ruby, che fa: blocchi. (È interessante notare che i blocchi non sono oggetti.) E, dato che è possibile definire i metodi utilizzando i blocchi, è anche possibile definire i metodi che sono le chiusure:
foo = Object.new
state = nil
foo.define_singleton_method :inc_mult do |factor|
state ||= 0
state += 1
factor * state
end
p foo.inc_mult(2) # => 2
p foo.inc_mult(2) # => 4
p foo.inc_mult(2) # => 6
Io non sono troppo familiarità con loro, ma isn' t questo quali sono le continuazioni? Guarderei in 'callcc' per maggiori informazioni. –