Come funziona whileTrue: funziona in Smalltalk?

4

Voglio sapere come funziona whileTrue: . Ho cercato l'implementazione in BlockClosure :

whileTrue: aBlock 
    ^ [self value] whileTrue: [aBlock value]

E un'altra implementazione senza parametro:

whileTrue
    ^ [self value] whileTrue: []

Ma non so come funzioni, questo è un metodo ricorsivo, ma questo mi ha portato a porre diverse domande:

  1. Come si conclude questa chiamata ricorsiva?
  2. Se [self value] restituisce un oggetto Boolean , perché whileTrue: non è implementato nel tipo Boolean ?
  3. Perché esiste un'altra implementazione denominata whileTrue che non riceve alcun blocco e valuta self ?
posta Lucas Gabriel Sánchez 15.10.2014 - 14:42
fonte

2 risposte

4

whileTrue: è in linea dal compilatore, ecco perché non vedi l'effettiva implementazione. Ecco il commento di Pharo:

"Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true."

Se guardi il codice byte di #whileTrue: vedrai che il compilatore usa semplicemente un salto per creare il ciclo:

17 <70> self
18 <C9> send: value
19 <9C> jumpFalse: 25
20 <10> pushTemp: 0
21 <C9> send: value
22 <87> pop
23 <A3 F8> jumpTo: 17 <---- here's the jump
25 <7B> return: nil

#whileTrue è anche direttamente in linea (codice byte leggermente ottimizzato). L'inlining è anche il motivo per cui non c'è implementazione di questo in Boolean (a parte il fatto che non ha senso rivalutare un booleano ...).

#whileTrue è lì in modo che tu possa facilmente creare cicli infiniti l'unico terminato, ad es. quando il processo termina, viene segnalato un semaforo, si verifica un'eccezione ecc.

    
risposta data 15.10.2014 - 16:51
fonte
3

My Smalltalk è un po 'arrugginito, e non ho Smalltalk installato al momento, quindi potrebbero esserci alcuni errori di sintassi, ma ti viene l'idea:

whileTrue: aBlock
    ↑ self value ifTrue: [aBlock value. self whileTrue: aBlock]

Ecco una versione in Ruby che ho effettivamente testato, di cui sopra (spero) sia una traduzione:

class Proc
  def vhile(block)
    self.().iff(thn: -> {block.(); vhile(block)})
  end
end

Hai bisogno dei seguenti monkeypatch per far funzionare i condizionali in stile Smalltalk:

class TrueClass
  def iff(thn:, els: ->{})
    thn.()
  end
end

class FalseClass
  def iff(thn:, els: ->{})
    els.()
  end
end
    
risposta data 15.10.2014 - 17:19
fonte

Leggi altre domande sui tag