Open danielpclark opened 6 years ago
It's come to my attention upon further thinking on this subject that there is two contexts to deal with here. One is a Rust program taking advantage of Ruby and the other is a Ruby program taking advantage of Rust.
I believe there is a need for the Error
kind which is currently in Rust/ruru for the Rust program side. But I do also believe we need an Exception
/AnyException
type for dealing with Ruby centric programs. In my minds eye I see this full implemented as AnyException
being the core type used everywhere and the Error
type as a wrapper to contain behavior on Rust side for Rust applications.
I've put comments through numerous issues on this and it doesn't make sense to me to leave any of this discussion so scattered so I'm opening this issue to discuss the merits of designing the default behavior where ever
AnyObject
would return to beResult<AnyObject, AnyException>
.Pros
let val = some_result?;
.Cons
rb_protect
which will catch exceptions and allows us to build theResult
. This adds cost to the performance. When writing a Ruby program and using Rust to gain performance you don't necessarily want this added cost in performance as the major draw to use Rust in Ruby is all about performance.Exceptions to the Rule
Some scenarios won't “ever” *cough* *cough* call for an exception to be raised like when doing equality checks. Equality checks simply make sense to return the
bool
type for convenience. Although any method that can be monkey-patched and rewritten may raise exceptions in which case that should useprotect
. The choice for design and usage would then come down to how strict to adhere to The Rust Way pattern in case of risk, or provide the end user more of a choice. My thoughts on this point is to be more relaxed on enforcing the return type and trust the developers to understand the risks and choose there own implementation decisions.Alternatives
Looking at a Helix PR
with_protect
example gave me the idea to have animpl WithProtect on FnOnce()
trait. It's just a rough idea but it would be something like lazily produce aFnOnce()
closure and have that take&self
for the method definition in the WithProtect trait to route the code through something like myprotect_send
method (https://github.com/d-unseductable/ruru/pull/88). So we could domy_closure.with_protect()
to run it.Strictness
If the need for
safety
comes first and we choose a relaxed stance on enforcingResult
return types then it would come down to where we choose to draw the line. Like, for example, when instantiating a new object bothnew
andinitialize
methods are highly likely to raise an exception if the startup standards for that object are not met. However the alternative methodallocate
is nearly guaranteed to never do anything that would raise an exception so this would be one method not needing theResult
return type.Choosing a form of this as a relaxed standard will require a more case by case decision on implementing it. That would likely be the sole choice of the author of this project on his beliefs and weighting on the likeliness of any particular method to raise an exception.
My Stance
I'm not too picky about this change being implemented. With
protect_send
#88 andeval
#79 developers should have enough to take the risk out of most scenarios. But this will require programmers to be more defensive and more on guard with their code when working with ruru. Perhaps the easiest solution would be the alternative I've proposed here above.I leave this RFC here open for discussion.