2010-10-06 28 views

Répondre

5

[Cette réponse est écrite en pensant aux programmeurs Scheme (l'OP a déjà posé d'autres questions sur le Scheme ici, donc c'est une valeur sûre). Si vous êtes ici parce que vous êtes un programmeur Ruby sans arrière-plan Scheme, lisez la note pour un contexte. :-)]

L'IRM ne fonctionne pas (voir ci-dessous); et si l'IRM ne le fait pas, cela signifie qu'il n'y a pas de moyen portable d'utiliser une telle fonctionnalité même si une autre implémentation le fournit.

J'ai effectivement inspecté le code source de l'IRM 1.9.1, juste pour être sûr. Dans tous les cas, voici un code pour démontrer que même la protection de déroulement normale (ensure) ne fonctionne pas correctement avec les suites sur l'IRM (testé avec 1.8.7 et 1.9.1). (Il ne fonctionne pas correctement avec JRuby (je l'ai testé avec 1,5), donc il va montrer qu'il est une chose spécifique à l'implémentation. Mais notez que JRuby ne fournit échapper continuations, pas les fins générales.)

callcc do |cc| 
    begin 
    puts 'Body' 
    cc.call 
    ensure 
    puts 'Ensure' 
    end 
end 

(pour tester l'IRM 1.9+, vous devez soit exécuter avec l'option -rcontinuation, ou mettre require 'continuation' en haut du fichier.)


pour les lecteurs qui ne savent pas ce qu'est un dynamic-wind est, il est un moyen pour spécifier le code à exécuter lorsque le code couvert est quitté (un peu comme ensure), ainsi que code à exécuter lorsque le code couvert est ré-entré. (Cela peut se produire lorsque vous utilisez call/cc dans le code couvert, et invoquer l'objet de poursuite après le code couvert a été sorti.)

exemple totalement artificiel:

def dynamic_wind pre, post, &block 
    raise 'Replace this with a real implementation, kthx' 
end 

def redirect_stdout port, &block 
    saved = $stdout 
    set_port = lambda {$stdout = port} 
    reset_port = lambda {$stdout = saved} 
    dynamic_wind set_port, reset_port, &block 
end 

cc = nil 
# cheap way to nuke all the output ;-) 
File.open '/dev/null' do |null| 
    redirect_stdout null do 
    callcc {|cc|} 
    puts 'This should not be shown' 
    end 
    puts 'This should be shown' 
    cc.call 
end 

Ainsi, un bon fonctionnement dynamic_wind mise en œuvre ferait en sorte que $stdout soit redéfinie sur le flux /dev/null lorsque la continuation est invoquée, de sorte que dans toutes les instances où puts 'This should not be shown' est exécuté, ce texte n'est en effet pas affiché.