Здравствуйте, 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?) — я добавил бы пример.