Ruby a des suites ... a-t-il une construction dynamic-wind
comme Scheme?Equivalent du vent dynamique de Scheme en Ruby
Répondre
[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é.