Yes, you're right - they're equivalent.
Except for one thing: you can redefine the former, you cannot redefine the latter without a messy HIDE directive and a complete redefinition. And - very important - all previous calls would be invalidated.
Your solution works fine for a template like CONVERT.4TH - but not for a library. And yes, this "redefinition thingy" is actually used in the repository:
dc.4th: :noname #UndefName throw ; is NotFound \ standard 'abort' word
editor.4th: :noname #UndefName throw ; is NotFound \ for interpret library
euro.4th: :noname ." Unknown command '" type ." '" cr ; is NotFound
ipsubnet.4th: :noname ." Unknown command '" type ." '" cr ; is NotFound
sudoku.4th: :noname ." Unknown command '" type ." '" cr ; is NotFound
filer.4th: :noname oops throw ; is NotFound ( --)
spiles.4th: :noname oops throw ; is NotFound ( --)
There are a few programs that repeat the original definition - but it's not required, as skyquery.4th and topitsm.4th prove. These programs use the default definition.
And yes, you can redefine any word in 4tH - but not as liberally as in vanilla Forth. It requires the "HIDE" word. And previous calls are not converted - so these will always defer to the original definition.
You can compare a "DEFER"red word best as a VALUE containing an execution token (function pointer), followed by an EXECUTE. And since a VALUE is a variable, the address it jumps to is dependent on what the variable contains. In short - change the variable, change the location it jumps to. It's as easy as that.
Hans Bezemer