[PHP-DEV] Examples comparing Block Scoped RAII and Context Managers

Hi all,

The Block Scoping RFC and the Context Manager RFC cover a lot of similar use cases, and a lot of the discussion on both threads has been explicitly comparing them.

To try to picture better how they compare, I have put together a set of examples that implement the same code using both features, as well as some other variations, in this git repo: Rowan Tommins / raii-vs-cm · GitLab

A few notes:

- The syntax for the two proposals is based on the current RFC text. If they are updated, e.g. to use different keywords, I will update the examples.

- I have included examples with closures which automatically capture by value, since a lot of the same use cases come up when discussing those.

- There are many scenarios which could be included, and many ways each example could be written. I have chosen scenarios to illustrate certain strengths and weaknesses, but tried to fairly represent a "good" use of each feature. However, I welcome feedback about unintentional bias in my choices.

- Corrections and additional examples are welcome as Merge Requests to the repo, or replies here.

With that out of the way, here are my own initial thoughts from working through the examples:

- RAII + block scope is most convenient when protecting an existing object which can be edited or extended.

- When protecting a final object, or a native resource, RAII is harder to implement. In these cases, the separation of Context Manager from managed value is powerful.

- Context Managers are very concise for safely setting and resetting global state. RAII can achieve this, but feels less natural.

- An "inversion of control" approach (passing in a callback with the body of the protected block) requires capturing all variables *not* scoped to the block. Even with automatic by-value capture, those needed *after* the block would need to be listed for capture by reference.

- Building a Context Manager from a Generator can lead to very readable code in some cases, and closely mimics an "inversion of control" approach without the same variable capture problems.

I would be interested in other people's thoughts.

Regards,

--
Rowan Tommins
[IMSoP]

On 16/11/2025 15:29, Frederik Bosch wrote:

On Sat, 15 Nov 2025 23:11:44 +0000, Rowan Tommins [IMSoP] wrote:

The Block Scoping RFC and the Context Manager RFC cover a lot of similar
use cases, and a lot of the discussion on both threads has been
explicitly comparing them.

To try to picture better how they compare, I have put together a set of
examples that implement the same code using both features, as well as
some other variations, in this git repo:

Rowan Tommins / raii-vs-cm · GitLab

Another suggestion would be to follow the Java try-with-resources syntax. It does not require a new keyword to be introduced, as with the Context Manager syntax. Moreover, it aligns with current try-catch-finally usage already implemented by PHP developers.

try ($transaction = $db->newTransaction()) {
$db->execute('UPDATE tbl SET cell = :cell', ['cell'=>'value']);
}

I did have a look into that when somebody mentioned it earlier, and I believe it is almost exactly equivalent to C#'s "using" statement:

- C#: keyword "using", interface "IDisposable", method "Dispose": using statement - ensure the correct use of disposable objects - C# reference | Microsoft Learn

- Java: keyword "try", interface "AutoCloseable", method "close": The try-with-resources Statement (The Java™ Tutorials > Essential Java Classes > Exceptions)

The main difference I've spotted is how it combines with other blocks.

In Java, you can use the same block as both try-with-resources and try-catch:

try ( Something foo = new Something ) {
blah(foo);
}
catch ( SomeException e ) {
whatever();
}

In C#, you can instead use a statement version of using within any existing block:

try {
using ( Something foo = new Something );
blah(foo);
}
catch ( SomeException e ) {
whatever();
}

Both are very similar to RAII, but because both languages use non-immediate garbage collection, the method is separate from the normal destructor / finalizer, and other references to the "closed"/"disposed" object may exist.

At the moment, I haven't included examples inspired by these, because I thought they would be too similar to the existing RAII examples and clutter the repo. But if there's a difference someone thinks is worth highlighting, I can add one in.

Any object that implements TryWithContext can be used with such syntax. The function returns the exit context operation as callback.

interface TryWithContext {
public function tryWith(): \Closure;
}

I can't find any reference to this in relation to Java; did you take it from a different language, or is it your own invention?

Either way, it looks like an interesting variation on the Python-based enterContext/exitContext. Do you have any thoughts on what it's advantages or disadvantages would be?

Rather auto-capture I'd suggest explicit complete scope capture, by using the use keyword without parenthesis.

This is a completely separate discussion I was hoping not to get into. Although I've personally advocated for "function() use (*) {}" in the past, I've used "fn() {}" in the "auto-capture" examples because it is the syntax most often proposed.

It's irrelevant for this example anyway, so I've edited it out below.

For a transaction it might look like this.

class Transaction implements TryWithContext {
public function tryWith(): \Closure
{
$this->db->beginTransaction();
return function (?\Throwable $e = null) {
if ($e) {
$this->db->rollbackTransaction();
return;
}

        $this\->db\->commitTransaction\(\);
    \};
\}

}

Looking at this example, it feels like it loses the simplicity of RAII without gaining the power of Context Managers. In particular, tryWith() as shown can't return a separate value to be used in the loop, like beginContext() can in the Python-inspired proposal.

The class would have a separate constructor and tryWith() method, with no clear distinction. Making the cleanup function anonymous prevents the user directly calling dispose()/close()/__destruct() out of sequence; but it doesn't stop the object being used after cleanup, which seems like a more likely source of errors.

Still, it's interesting to explore these variations to see what we can learn, so thanks for the suggestion.

--
Rowan Tommins
[IMSoP]

On Sat, Nov 15, 2025, at 5:11 PM, Rowan Tommins [IMSoP] wrote:

Hi all,

The Block Scoping RFC and the Context Manager RFC cover a lot of similar
use cases, and a lot of the discussion on both threads has been
explicitly comparing them.

To try to picture better how they compare, I have put together a set of
examples that implement the same code using both features, as well as
some other variations, in this git repo: Rowan Tommins / raii-vs-cm · GitLab

A few notes:

- The syntax for the two proposals is based on the current RFC text. If
they are updated, e.g. to use different keywords, I will update the
examples.

- I have included examples with closures which automatically capture by
value, since a lot of the same use cases come up when discussing those.

- There are many scenarios which could be included, and many ways each
example could be written. I have chosen scenarios to illustrate certain
strengths and weaknesses, but tried to fairly represent a "good" use of
each feature. However, I welcome feedback about unintentional bias in my
choices.

- Corrections and additional examples are welcome as Merge Requests to
the repo, or replies here.

With that out of the way, here are my own initial thoughts from working
through the examples:

- RAII + block scope is most convenient when protecting an existing
object which can be edited or extended.

- When protecting a final object, or a native resource, RAII is harder
to implement. In these cases, the separation of Context Manager from
managed value is powerful.

- Context Managers are very concise for safely setting and resetting
global state. RAII can achieve this, but feels less natural.

- An "inversion of control" approach (passing in a callback with the
body of the protected block) requires capturing all variables *not*
scoped to the block. Even with automatic by-value capture, those needed
*after* the block would need to be listed for capture by reference.

- Building a Context Manager from a Generator can lead to very readable
code in some cases, and closely mimics an "inversion of control"
approach without the same variable capture problems.

I would be interested in other people's thoughts.

Regards,

--
Rowan Tommins
[IMSoP]

Thank you to Rowan for the in depth comparison!

One thing I definitely do not like is the need for a `FileWrapper` class in the RAII file-handle example. That seems like an unnecessary level of abstraction just to squeeze the `fclose()` value onto the file handle. The fully-separated Context Manager seems a more flexible approach.

Suppose we were dealing with a considerably more involved object than a file handle, with a large interface. You'd need to either

1. Extend the class, and we all know about extends...
2. Make a wrapper that passes through the calls (which could be very verbose)
3. Do as is done here, with a simple dumb wrapper, which means in the body of the context block you have to do `$var->val` all the time, which is just clunky.

Fully separating the Context Manager from the Context Variable completely avoids that issue.

I also noted that all of the examples wrap the context block (of whichever syntax) in a try-catch of its own. I don't know if that's going to be a common pattern or not. If so, might it suggest that the `using` block have its own built-in optional `catch` and `finally` for one-off additional handling? That could point toward the Java approach of merging this functionality into `try`, but I am concerned about the implications of making both `catch` and `finally` effectively optional on `try` blocks. I am open to discussion on this front. (Anyone know what the typical use cases are in Python?)

Regarding `let`, I think there's promise in such a keyword to opt-in to "unset this at the end of this lexical block." However, it's also off topic from everything else here, as I think it's very obvious now that the need to do more than just `unset()` is common. Sneaking hidden "but if it also implements this magic interface then it gets a bonus almost-destructor" into it is non-obvious magic that I'd oppose. I'd be open to a `let` RFC on its own later (which would likely also make sense in `foreach` and various other places), but it's not a solution to the "packaged setup/teardown" problem.

---

Another thing that occurs to me, from both this writeup and the discussion in both threads, is that "escaped variables" are an unsolvable problem. If a context variable is "open" (for some generic definition of open; that could be a file handle or an unflushed buffer or DB transaction or just a large memory sink), and then a reference to it is saved elsewhere, then when the context block ends, there's two problems that could happen:

* If the context block force-closes the variable, then the escaped reference is no longer valid. This may or may not cause problems.
* If the context block does not force-close the variable, then we can't know that the end of the context block has flushed/completed the process. This may or may not cause problems.

Which one is less of a problem is going to vary with the particular situation. I don't think we can make a language-wide statement about which is always less problematic. That means we need to allow individual cases to decide for themselves which "leak problem" they want to have.

Which is exactly the benefit of the separation of the Context Manager from the Context Variable. The CM can be written to rely on `unset()` closing the object (risk 2), or to handle closing it itself (risk 1), as the developer determines.

Moreover, it's possible to have two different strategies for the same context variable, as either 2 separate Context Managers or one manager with a constructor parameter.

Suppose the context variable is a `Buffer` instance of some kind, which has a `flush()` method and a destructor that calls `flush()`. Both `ForcedBufferContext` and `LazyBufferContext` could return the same Buffer class, but have different approaches to when the flush happens. That's a level of flexibility that's impossible to achieve if the "exit" logic is on the context variable itself, whether in the destructor or a separate interface method.

Alternatively, `new BufferContext(force: true)` (or whatever) would avoid the need for 2 classes, depending on the specifics of the use case.

To, me, that's a strong argument in favor of the Context Manager approach.

On 18/11/2025 17:23, Larry Garfield wrote:

One thing I definitely do not like is the need for a `FileWrapper` class in the RAII file-handle example. That seems like an unnecessary level of abstraction just to squeeze the `fclose()` value onto the file handle. The fully-separated Context Manager seems a more flexible approach.

Yes, exploring how exactly that flexibility could be used was part of my motivation for the examples I picked.

The downside is that it is slightly harder to understand at first glance: someone reading "using (file_for_write('file.txt') as $fh)" might well assume that $fh is the value returned from "file_for_write('file.txt')", rather than the value returned from "file_for_write('file.txt')->enterContext()".

What made sense to me was comparing to an Iterator that only goes around once - in "foreach (files_to_write_to() as $fh)", the "files_to_write_to()" call doesn't return $fh either, "files_to_write_to()->current()" does.

I also noted that all of the examples wrap the context block (of whichever syntax) in a try-catch of its own. I don't know if that's going to be a common pattern or not. If so, might it suggest that the `using` block have its own built-in optional `catch` and `finally` for one-off additional handling? That could point toward the Java approach of merging this functionality into `try`, but I am concerned about the implications of making both `catch` and `finally` effectively optional on `try` blocks. I am open to discussion on this front. (Anyone know what the typical use cases are in Python?)

Looking at the parser, I realised that a "try" block with neither "catch" nor "finally" actually matches the grammar; it is only rejected by a specific check when compiling the AST to opcodes. Without that check, it would just compile to some unnecessary jump table entries.

I guess an alternative would be allowing any statement after the using() rather than always a block, as in Seifeddine and Tim's proposal, which allows you to stack like this:

using ($db->transactionScope()) try {
// ...
}
catch ( SomeSpecificException $e ) {
// ...
}

Or, the specific combination "try using( ... )" could be added to the parser. (At the moment, "try" must always be followed by "{".)

As I noted in one of the examples (file-handle/application/1b-raii-with-scope-block.php), there is a subtle difference in semantics between different nesting orders - with "try using()", you can catch exceptions thrown by enterContext() and exitContext(); with "using() try", you can catch exceptions before exitContext() sees them and cleans up.

It seems Java's try-with-resources is equivalent to "try using()":

> In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.

Regarding `let`, I think there's promise in such a keyword to opt-in to "unset this at the end of this lexical block." However, it's also off topic from everything else here, as I think it's very obvious now that the need to do more than just `unset()` is common. Sneaking hidden "but if it also implements this magic interface then it gets a bonus almost-destructor" into it is non-obvious magic that I'd oppose. I'd be open to a `let` RFC on its own later (which would likely also make sense in `foreach` and various other places), but it's not a solution to the "packaged setup/teardown" problem.

I completely agree. I think an opt-in for block scope would be useful in a number of places, and resource management is probably the wrong focus for designing it. For instance, it would give a clear opt-out for capture-by-default closures:

function foo() {
// ... code setting lots of variables ...
$callback = function() use (*) {
let $definitelyNotCaptured=null;
// ... code mixing captured and local variables ...
}
}

Which is exactly the benefit of the separation of the Context Manager from the Context Variable. The CM can be written to rely on `unset()` closing the object (risk 2), or to handle closing it itself (risk 1), as the developer determines.

Something the examples I picked don't really showcase is that a Context Manager doesn't need to be specialised to a particular task at all, it can generically implement one of these strategies.

The general pattern is this:

class GeneralPurposeCM implements ContextManager {
public function __construct(private object $contextVar) {}
public function enterContext(): object { return $this->contextVar; }
public functoin exitContext(): void {}
}

- On its own, that makes "using(new GeneralPurposeCM(new Something) as $foo) { ... }" a very over-engineered version of "{ let $foo = new Something; ... }"

- To emulate C#, constrain to "IDisposable $contextVar", and call "$this->contextVar->Dispose()" in exitContext()

- To emulate Java, constrain to "AutoCloseable $contextVar" and call "$this->contextVar->close()" in exitContext()

- To throw a runtime error if the context variable still has references after the block, swap "$this->contextVar" for a WeakReference in beginContext(); then check for "$this->contextVarWeakRef->get() !== null" in exitContext()

- To have objects that "lock and unlock themselves", constrain to "Lockable $contextVar", then call "$this->contextVar->lock()" in beginContext() and "$this->contextVar->unlock()" in exitContext()

The only things you can't emulate are:

1) The extra syntax options provided by other languages, like C#'s "using Something foo = whatever();" or Go's "defer some_function(something);"

2) Compile-time guarantees that the Context Variable will not still have references after the block, like in Hack. I don't think that's a realistic goal for PHP.

Incidentally, while checking I had the right method name in the above, I noticed the Context Manager RFC has an example using "leaveContext" instead, presumably an editing error. :slight_smile:

Regards,

--
Rowan Tommins
[IMSoP]

On Wed, Nov 19, 2025, at 4:19 PM, Rowan Tommins [IMSoP] wrote:

On 18/11/2025 17:23, Larry Garfield wrote:

One thing I definitely do not like is the need for a `FileWrapper` class in the RAII file-handle example. That seems like an unnecessary level of abstraction just to squeeze the `fclose()` value onto the file handle. The fully-separated Context Manager seems a more flexible approach.

Yes, exploring how exactly that flexibility could be used was part of
my motivation for the examples I picked.

The downside is that it is slightly harder to understand at first
glance: someone reading "using (file_for_write('file.txt') as $fh)"
might well assume that $fh is the value returned from
"file_for_write('file.txt')", rather than the value returned from
"file_for_write('file.txt')->enterContext()".

What made sense to me was comparing to an Iterator that only goes
around once - in "foreach (files_to_write_to() as $fh)", the
"files_to_write_to()" call doesn't return $fh either,
"files_to_write_to()->current()" does.

That's a good analogy, I like it.

I also noted that all of the examples wrap the context block (of whichever syntax) in a try-catch of its own. I don't know if that's going to be a common pattern or not. If so, might it suggest that the `using` block have its own built-in optional `catch` and `finally` for one-off additional handling? That could point toward the Java approach of merging this functionality into `try`, but I am concerned about the implications of making both `catch` and `finally` effectively optional on `try` blocks. I am open to discussion on this front. (Anyone know what the typical use cases are in Python?)

Looking at the parser, I realised that a "try" block with neither
"catch" nor "finally" actually matches the grammar; it is only rejected
by a specific check when compiling the AST to opcodes. Without that
check, it would just compile to some unnecessary jump table entries.

I guess an alternative would be allowing any statement after the
using() rather than always a block, as in Seifeddine and Tim's
proposal, which allows you to stack like this:

using ($db->transactionScope()) try {
    // ...
}
catch ( SomeSpecificException $e ) {
    // ...
}

Or, the specific combination "try using( ... )" could be added to the
parser. (At the moment, "try" must always be followed by "{".)

As I noted in one of the examples
(file-handle/application/1b-raii-with-scope-block.php), there is a
subtle difference in semantics between different nesting orders - with
"try using()", you can catch exceptions thrown by enterContext() and
exitContext(); with "using() try", you can catch exceptions before
exitContext() sees them and cleans up.

It seems Java's try-with-resources is equivalent to "try using()":

In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.

Thanks. I'll discuss these options with Arnaud. Anyone else want to weigh in here?

Which is exactly the benefit of the separation of the Context Manager from the Context Variable. The CM can be written to rely on `unset()` closing the object (risk 2), or to handle closing it itself (risk 1), as the developer determines.

Something the examples I picked don't really showcase is that a Context
Manager doesn't need to be specialised to a particular task at all, it
can generically implement one of these strategies.

The general pattern is this:

class GeneralPurposeCM implements ContextManager {
    public function __construct(private object $contextVar) {}
    public function enterContext(): object { return $this->contextVar; }
    public functoin exitContext(): void {}
}

- On its own, that makes "using(new GeneralPurposeCM(new Something) as
$foo) { ... }" a very over-engineered version of "{ let $foo = new
Something; ... }"

True! It may make sense eventually to provide a "UnsetThis(mixed $var)" CM in the stdlib. Not something to include now, but I've no issue with it existing eventually.

Incidentally, while checking I had the right method name in the above,
I noticed the Context Manager RFC has an example using "leaveContext"
instead, presumably an editing error. :slight_smile:

Indeed. Fixed now, thanks.

--Larry Garfield

Hi

I've had the opportunity to take a look now.

Am 2025-11-16 00:11, schrieb Rowan Tommins [IMSoP]:

- The syntax for the two proposals is based on the current RFC text. If they are updated, e.g. to use different keywords, I will update the examples.

The block scoping RFC has been updated to `let()`.

- There are many scenarios which could be included, and many ways each example could be written. I have chosen scenarios to illustrate certain strengths and weaknesses, but tried to fairly represent a "good" use of each feature. However, I welcome feedback about unintentional bias in my choices.

1.

For db-transaction/implementation/1-raii-object.php I'd like to note that it is not necessary to proxy execute() through the transaction object. It could also be used as a simple guard object which only purpose is to be constructed and destructed.

     let ($txn = $db->begin()) {
         $db->execute('…');
     }

or possibly:

     let (
         $db = connect(),
         $txn = $db->begin(),
     ) { … }

In that way it is similar to the 2x-context-manager-anon-class.php example. The same “guard object” possibility also exists for the other examples as far as I can tell.

2.

The RAII object in 'file-handle' serves no purpose. PHP will already call `fclose()` when the resource itself goes out of scope, so this is existing behavior with extra steps. The same is true for the 0-linear-code example in file-object. You don't need the `fclose()` there.

3.

The docblock in locked-pdf/application/2-context-manager.php is incorrectly copy and pasted.

With that out of the way, here are my own initial thoughts from working through the examples:

- RAII + block scope is most convenient when protecting an existing object which can be edited or extended.

- When protecting a final object, or a native resource, RAII is harder to implement. In these cases, the separation of Context Manager from managed value is powerful.

- Context Managers are very concise for safely setting and resetting global state. RAII can achieve this, but feels less natural.

- An "inversion of control" approach (passing in a callback with the body of the protected block) requires capturing all variables *not* scoped to the block. Even with automatic by-value capture, those needed *after* the block would need to be listed for capture by reference.

- Building a Context Manager from a Generator can lead to very readable code in some cases, and closely mimics an "inversion of control" approach without the same variable capture problems.

I would be interested in other people's thoughts.

I was about to comment that the 'file' examples were not equivalent, because the context manager and IOC ones didn't include the error logging, until I noticed it was hidden away in the implementation. This probably suggests that I implicitly expected to see all relevant control flow. Exception handling and logging in particular probably greatly depend on the surrounding context to be useful (e.g. to adapt the log message or to enhance it with additional context data). So while it might superficially look cleaner / simpler, I feel that this kind of generic handling will bite you sooner or later. So with the context manager example, I would expect the “exception introspection” capability to be used to properly tear down the context, but not for cross-cutting concerns such as logging. I'm not sure if this would qualify as “unintentional bias”, but it's certainly something that affected by perception of the code.

Best regards
Tim Düsterhus

Hi

Am 2025-11-19 23:19, schrieb Rowan Tommins [IMSoP]:

On 18/11/2025 17:23, Larry Garfield wrote:

One thing I definitely do not like is the need for a `FileWrapper` class in the RAII file-handle example. That seems like an unnecessary level of abstraction just to squeeze the `fclose()` value onto the file handle. The fully-separated Context Manager seems a more flexible approach.

Yes, exploring how exactly that flexibility could be used was part of my motivation for the examples I picked.

The downside is that it is slightly harder to understand at first glance: someone reading "using (file_for_write('file.txt') as $fh)" might well assume that $fh is the value returned from "file_for_write('file.txt')", rather than the value returned from "file_for_write('file.txt')->enterContext()".

What made sense to me was comparing to an Iterator that only goes around once - in "foreach (files_to_write_to() as $fh)", the "files_to_write_to()" call doesn't return $fh either, "files_to_write_to()->current()" does.

For me the relevant keyword that indicates that the value is not used directly is not the 'as', but the 'each' part of the 'foreach'. Just by reading it as a English sentence, it becomes clear to me what is happening.

The same is not true for me for `using (file_for_write('file.txt') as $fh)` or even worse `using (new Manager() as $notActuallyTheManager)` (which is part of the RFC). AFAICT the latter is not so much a problem in Python, because there is no difference between constructors and factory functions and also because there is no actual type declaration. This means `open()` could be a function returning a file handle or it could be the “constructor“ for a context manager (that then returns the file handle as part of entering the context) and the difference is effectively indistinguishable from the outside, which is not the case in PHP.

Best regards
Tim Düsterhus

On 27 November 2025 09:08:14 GMT, "Tim Düsterhus" <tim@bastelstu.be> wrote:

For me the relevant keyword that indicates that the value is not used directly is not the 'as', but the 'each' part of the 'foreach'. Just by reading it as a English sentence, it becomes clear to me what is happening.

The same is not true for me for `using (file_for_write('file.txt') as $fh)` or even worse `using (new Manager() as $notActuallyTheManager)` (which is part of the RFC).

Hi Tim,

Thanks for your thoughts. I will definitely go over your other email in detail when I have some more time and energy, and update some of my examples.

Regarding this point, I think it's a really interesting observation, and I wonder if we should be looking for different keywords that read more clearly. For instance:

using(new SomeManager() for $someResource)

using($someResource from new SomeManager())

context(new SomeManager() giving $someResource)

Regards,

Rowan Tommins
[IMSoP]

On Thu, Nov 27, 2025, at 8:43 AM, Rowan Tommins [IMSoP] wrote:

On 27 November 2025 09:08:14 GMT, "Tim Düsterhus" <tim@bastelstu.be> wrote:

For me the relevant keyword that indicates that the value is not used directly is not the 'as', but the 'each' part of the 'foreach'. Just by reading it as a English sentence, it becomes clear to me what is happening.

The same is not true for me for `using (file_for_write('file.txt') as $fh)` or even worse `using (new Manager() as $notActuallyTheManager)` (which is part of the RFC).

Hi Tim,

Thanks for your thoughts. I will definitely go over your other email in
detail when I have some more time and energy, and update some of my
examples.

Regarding this point, I think it's a really interesting observation,
and I wonder if we should be looking for different keywords that read
more clearly. For instance:

using(new SomeManager() for $someResource)

using($someResource from new SomeManager())

context(new SomeManager() giving $someResource)

Regards,

Rowan Tommins
[IMSoP]

We're very open to tweaking the keywords. I can see the argument for "as" being a little misleading in PHP's case. Though I'd prefer to have the EXPR first and VAR second, whatever the keyword is.

Another potential we thought of: Just plain =>. It already doesn't imply equals, would have no keyword breaks, and is still only 2 characters.

using (new SomeManager() => $someResource) {
  // ...
}

Thoughts?

--Larry Garfield