Would this be any different than defining them regardless and just let monkeypatching handle merging in the implementation when the component is required?
Oo I never considered making the type an alias to another type
. I tried this out with:
alias Athena::Validator::Validator::ValidatorInterface = Nil
# ...
def initialize(
@serializer : ASR::SerializerInterface,
@annotation_resolver : ATH::AnnotationResolver,
@validator : Athena::Validator::Validator::ValidatorInterface? = nil,
); end
Unfortunately, compiler doesn’t like this:
213 | @validator : Athena::Validator::Validator::ValidatorInterface? = nil,
^
Error: instance variable @validator of SomeType was inferred to be Nil, but Nil alone provides no information
Reminds me a bit of some of the implicit interface stuff talked about in [RFC] Standardized Abstractions.
This would work quite well for this use case yea! Tho as I brought up earlier maybe there would be a world in which it’s more opt-in via new syntax/annotation/type or something as to @bcardiff’s point to silently ignoring errors when you might actually want them.
- Annotation:
@[Optional] @validator : ValidatorInterface? = nil - Syntax:
@validator : ?ValidatorInterface? = nil(prefix with?or something along those lines) - New Type:
@validator : Optional(ValidatorInterface) = nil(Tho might run into the same problem as aliasing it toNil)
Yea, looking at the code for my use case again, this wouldn’t be a 100% solution as there is still code later on doing like:
if object.is_a?(Array) && constraints && !constraints.is_a?(Athena::Validator::Constraints::All)
constraints = Athena::Validator::Constraints::All.new constraints
end
Which I would expect to error when not used as well. Granted guarding some block of code with macro if logic would be a lot more straightforward than the constructor. So may still be useful to have.
Another idea would be to do some refactoring to extract the logic into another type that could be provided/called but that just would no-op when the validator component isn’t installed. Tho I suppose this is really just moving the macro if logic to somewhere else and not really eliminating the problem.
Either way it’s def seeming like macro if logic is going to be the best option, as even if i were to stub out the types, will also have to handle constructors of those types and such as well and that’s just not worth the effort.