#-- # merlin/let.rb : merlin-let 0.0.1 # # Copyright (C) 2004 Merlin Hughes # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #++ # Lisp/Scheme-like let mixin for IO, Hash and ENV. # # Disclaimer: I know neither Lisp, Scheme nor Ruby. # # io.let(io) { |io| block } # - Reopens the IO object with the parameter, # executes the block and then restores the # IO object. A dup of the original IO is # passed as a parameter to the block. # # STDERR.let(STDOUT) { |stderr| # STDERR.puts("I'm going to STDOUT") # stderr.puts("I'm going to STDERR") # } # STDERR.puts("I'm going to STDERR") # # hash.let(array) { |array| block } # - array is a [key, value] pair or an array of [key, value] pairs # - Reassigns the specified entries in the hash # to the specified values, or removes the entry # if the pair has no second element, executes # the block, and then restores the hash # entries. The original values are passed # to the block in the same format as they # are passed to the let method. # # ENV.let(array) { |array| block } # array is a pair or an array of pairs # - array is a [key, value] pair or an array of [key, value] pairs # - Ditto. # # ENV.let([ [ 'PATH' ], [ 'HOME', '/tmp' ] ]) { |originals| # # PATH is removed, and HOME is /tmp # } # # PATH and HOME are restored module IOLet # TODO: I could redefine reopen similarly. def let(io) original = dup begin reopen(io) yield(original) ensure reopen(original) end end end module HashLet def let(values) originals = [] begin simple = values.first.is_a?(Array) (simple ? values : [ values ]).each { | pair | key, value = pair originals << (has_key?(key) ? [ key, self[key] ] : [ key ]) (pair.length > 1) ? (self[key] = value) : delete(key) } yield(simple ? originals : originals.first) ensure originals.reverse_each { | pair | key, value = pair (pair.length > 1) ? (self[key] = value) : delete(key) } end end end class IO include IOLet end class Hash include HashLet end ENV.extend HashLet