Re: [ruby, python] - code block
От: z00n  
Дата: 13.03.09 12:18
Оценка: 5 (1)
Здравствуйте, DemAS, Вы писали:

DAS>Может есть какие-то более удобные паттерны и приемы, не привязанные к

DAS>конкретному языку программирования, достигать такой же цели — гарантировать
DAS>освобождение ресурсов?

Конечно есть — для этого нужны первоклассные функции. Вот реализации на нескольких языках — общее уловить несложно:
— Если в языке нет аналога finally(unwind-protect) — написать его
— передавать то, что нужно сделать сделать с ресурсом в виде анонимной функции

http://scala.sygneca.com/patterns/loan
// Scala - есть готовый finally - все просто
def withResource[A](f : Resource => A) : A = {
    val r = getResource()  // Replace with the code to acquire the resource
    try {
        f(r)
    } finally {
        r.dispose()
    }
}

//Client code becomes very simple:
withResource{ r =>
    // do stuff with r....
}


http://groups.google.fi/group/comp.lang.functional/browse_frm/thread/5385c76d82a78171
// SML
// First of all, a function such as 
  fun finally (thunk, effect) = 
      (((fn x => fn () => x) (thunk ()) 
        handle e => fn () => raise e) o effect) () 
// can be provided to make sure that a given effect will be performed after a 
// given thunk returns - whether normally or by raising an exception. 
// It is customary to provide functions that allocate a resource, pass the 
// resource to a given body function, and take care of deallocating the 
// resource.  For example, one could provide the function 
  fun withInputString string = 
      fn body => 
         let 
            val instream = TextIO.openString string 
         in 
            finally (fn () => body instream, 
                     fn () => TextIO.closeIn instream) 
         end 
// for executing a body with an instream that reads from a string.   
// Another example of such a scoped resource management function could be 
  fun withDirStream path = 
      fn body => 
         let 
            val dirstream = OS.FileSys.openDir path 
         in 
            finally (fn () => body dirstream, 
                     fn () => OS.FileSys.closeDir dirstream) 
         end 
// for executing a body with a directory stream.  As you can see, there is 
// some duplication in structure between the above two functions that could 
// easily be factored out, but I'll ignore that aspect in this article.


Lua: http://www.lua.ru/forum/posts/list/15/89.page#704 — основан на SML варианте
--// "библиотечная" функция 
--//  pcall - это аналог try-catch
local function unwind_protect(thunk,cleanup)  
  local ok, result = pcall(thunk)  
  if cleanup then cleanup() end  
  if not ok then 
    error(res,0)  -- // rethrow exception 
  else 
    return result 
  end 
end  

--// общая функция для работы с открытыми файлами  
local function with_open_file(name,mode)  
  return function(body)  
           local f = assert(io.open(name,mode))  
           return unwind_protect(function()return body(f) end,  
                                 function()return f and f:close() end)  
         end  
end  

--// usage: os-copy --   
function os_copy2(source_path,dest_path)  
  return with_open_file(source_path,"rb") (function(source)  
    return with_open_file(dest_path,"wb") (function(dest)  
      assert(dest:write(assert(source:read("*a"))))  
      return 'copy ok'  
    end)  
  end)  
end


Если бы я знал, как в Питоне передавать анонимные функции как аргументы (lambda?) — я добавил бы пример.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.