This is a feature suggestion.
Suppose the following code:
obj.foo? = bar
This should actually call obj.foo=(bar) and not obj.foo?= (bar). Why? Because then you can write the following:
class A
property! foo
end
a = A.new
a.foo? ||= bar
Whether this is accepted or not, I think we should disallow methods ending in ?=.
This is interesting. Right now when you do:
hash[key] ||= value
it gets rewritten to:
hash[key]? || (hash[key] = value)
While when you do:
obj.property ||= value
it gets rewritten to:
obj.property || (obj.property = value)
There is a small inconsistency here, but the object implementing [] is most probably a Hash or a Hash-like object where you could get a nilable value (and Hash already has the []? method implemented), while for any object it's hard to know whether it's going to have property be nilable, raise, or there would be an alternative property? method.
So, we can leave things as they are and make:
obj.property? ||= value
be rewritten to:
obj.property? || (obj.property = value)
That way we cover all cases.
I'm not sure this is what you are suggesting. I would forbid writing obj.property? = value just by itself, but allow it when there's the ||= (or &&=).
To make it even more consistent, one would have to write hash[key]? ||= value, but I'm not really sure about this last thing.
It's sort of what I'm suggesting yes, I think it could be more intuitive by letting the compiler check whether there's obj.property? defined. When it is, rewrite to obj.property? || (object.property = value), if it's not defined rewrite to obj.property || (object.property = value). Then the same behavior could be used for Hash like calls too and they're no longer special cased.
@jhass I think we can do that. But right now the syntax sugar is expanded by the parser, so we'd have to change that to expand it in the semantic phase. I don't see why we shouldn't do that: the smarter the compiler and the less the user has to choose what's the obvious correct way to do things, the better. Then we wouldn't even need that obj.property? ||= value syntax.
The only "issue" is if obj is a union type and there's a mixed behaviour. We'll have to think about that as well.
I don't think this should be driven by semantics. That would change the behaviour when a matching method is added in otherwise unrelated code.
I experienced this issue in combination with property! and I think the best solution would simply to expand obj.property? ||= value to obj.property? || (obj.property = value). There can't be a foo?= method anyway, so this would make perfectly sense.
Most helpful comment
This is interesting. Right now when you do:
it gets rewritten to:
While when you do:
it gets rewritten to:
There is a small inconsistency here, but the object implementing
[]is most probably a Hash or a Hash-like object where you could get a nilable value (and Hash already has the[]?method implemented), while for any object it's hard to know whether it's going to havepropertybe nilable, raise, or there would be an alternativeproperty?method.So, we can leave things as they are and make:
be rewritten to:
That way we cover all cases.
I'm not sure this is what you are suggesting. I would forbid writing
obj.property? = valuejust by itself, but allow it when there's the||=(or&&=).To make it even more consistent, one would have to write
hash[key]? ||= value, but I'm not really sure about this last thing.