Hi Thomas -
This is an interesting problem. If I understand correctly, you need to have the property set because you have some validation that is going to depend on the 'new' value being stored in the property (i.e. the post-set calculations that might throw an error).
I can think a few strategies, but none are perfect. In terms of 'is there a better approach' I suppose it would be ideal if you could validate the new values without needing to 'commit' the set, but I can easily see why that might be challenging for a really complex object/calculation.
I can't think of a way to prevent the setter from recursing when using a separate method - I tried some tricks like anonymous functions and evalin to no avail. Maybe you could use a logical 'lock' property to achieve the same effect? It's not a great solution but it would clean up the code a little bit (example below).
Some alternate strategies include making a public and a private version of each property to add another 'layer' (this probably adds just as much complexity) or to make use of PreSet and PostSet listeners (however this means storing the old value somewhere, so I think not great).
The following code keeps the line that does the actual setting in the setter. It prevents recursion by using the customSetter when called directly (obj.setlock is false) but a direct set when called from customSetter (obj.setlock is true). I think you can use one customSetter for multiple properties (you'd need to pass the property name as an argument), but whether or not you can achieve one 'lock' property depends on whether setting a property can have a side effect on another property.
Note that I used try/catch to trap the errors, but your me = ... line would work just as well here if that's how you track your exceptions. However it is critical is that the setlock property is set to false by the end of customSetter no matter what happens. Also note - I didn't handle the potential conflict around saving and loading objects in the class - I think that's okay because the object can't be saved with prop in an invalid state, so it doesn't matter which branch the setter goes down (I think it will always do the customSetter branch).
classdef foo_set < handle
properties (Transient, Access=private)
oldval = obj.prop;