Domanda

Di recente ho provato a fare qualcosa di simile a questo:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval b

Che dà l'errore:

TAYEERROR: Impossibile convertire Proc in String

Ma questo funziona:

def b(&block)
  "some string".instance_eval &block
end

b{ upcase }

Un ulteriore sguardo con questo metodo:

def b(&block)
  "some string".instance_eval block
end

Produce lo stesso Proc to String errore.

Quindi ... la mia comprensione dei blocchi è che sono solo proc. Ma ovviamente c'è qualcosa di speciale nel avere questo & ampersand ...

Qualcuno può spiegarmi questo? È possibile convertire un normale proc per essere qualunque cosa sia speciale in questo &block oggetto?

modificare

Ho appena capito la mia seconda domanda, preparare un & Al proc ... è stato facile, ma cosa sta davvero facendo?

È stato utile?

Soluzione

Tutto quello che devi fare per il tuo primo esempio per lavorare è questo:

>> a.instance_eval &b #=> "SOME STRING"

Il motivo è quello instance_eval Ha bisogno di una stringa o di un blocco e l'AmperSand fornisce quest'ultimo.

Per comprendere le differenze tra blocchi e proc, forse il seguente post sul blog aiuta:

Comprensione di rubini, proc e lambdas

Altri suggerimenti

La differenza è quella a.instance_eval b sta passando b Come argomento regolare a istanza_eval, mentre a.instance_eval &b lo sta passando come un blocco. Quelle sono due cose diverse.

Considera questo metodo Call:

obj.foo(bar) do |x| 
  stuff(x) 
end

Che invoca il metodo foo con una discussione regolare (bar) e un argomento di un blocco (do |x| stuff(x) end). Nella definizione del metodo, si distinguono per prefisso & al parametro di blocco:

def foo(arg, &block)

E se si desidera passare un'espressione variabile anziché un blocco letterale, che è anche realizzato dal prefisso & all'espressione (che dovrebbe produrre un proc).

Se passi una discussione con no &, va nel arg slot invece del bloccare fessura. Non importa che l'argomento sia un'istanza di Proc. La sintassi determina come viene superata e trattata con il metodo.

È perché Instance_eval accetta una stringa per valutare o un blocco. instance_eval(&block) sta passando il tuo block come blocco a istanza_eval.

La differenza cruciale è quella Un'istanza Proc è un oggetto invece Un blocco non è un oggetto. Il & è un operatore che scambia un blocco e un'istanza Proc reciprocamente.

Tutti gli argomenti a un metodo devono essere un oggetto. Oltre agli argomenti, un metodo può prendere un blocco. instance_eval è un metodo che prende un argomento stringa o un blocco. Passare un oggetto Proc non soddisferà nessun caso. Se alleghi & A un oggetto Proc, questo sarà gestito come un blocco.

Questo funzionerà:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b

Il instance_eval Il metodo può ricevere argomenti a blocchi.b è un Proc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top