The with-x style macros can indeed be replaced by functions that take a closure. E.g. in Scheme you have the function (call-with-input-file string proc).
The macro is slightly more concise. Contrast
(with-input-file (x "x") (print (read x))) ; Common Lisp
with (call-with-input-file "x" (lambda (x) (print (read x)))) ; Scheme