Change with_env to a function

Fixes a bug where `with_env` would return `[do: result_of_block]`. Also wraps the env changing in a `try .. after` to ensure env is correct after failures.