Closed omusil24 closed 7 years ago
@omusil24 hashdecls require explicit declarations and conversions for assignments; they are not subject to automatic type folding (whereas complex hashes are, as seen in the error messages quoted above).
To make the assignment to a hashdecl, you must use the cast<>
operator. The new
operator also can create a hashdecl value explicitly.
This is by design - that hashdecl values can be assigned to hash
lvalues, but not vice-versa without an explicit conversion (cast<>
) or declaration (new
).
It would be theoretically possible to implement automatic type folding to a hashdecl at parse time if all key names and value types are known at parse time, but this also would involve a "constructor"-like call in that any keys in the hashdecl that are not included in the assignment that have initializer expressions would be implicitly initialized with the assignment - to avoid that, we require explicit conversions etc as described above.
IMO there should be a runtime conversion there instead of parse errors/exceptions.
@omusil24 IMO there should not because it requires an implicit constructor call
This makes it very user-unfriendly... Is it only because of performance reasons?
This makes it very user-unfriendly... Is it only because of performance reasons?
no, it's just to make it clear to the programmer that it's more than a simple assignment - just like you cannot assign a hash to an object without first instantiating the object.
So when the user writes
list<hash<HD>> params = (new hash<HD>(("name": 5)),);
it takes more effort for the programmer to write out the hashdecl initialization values, but like this it's clear that there is more code being executed than just a hash assignment. In this case the hashdecl doesn't have any other keys or any member initialization expressions, but it could.
If we had support for something closer to C/C++ in Qore, it would look like this:
list<hash<HD>> params = (hash<HD>(("name": 5)),);
but this is in fact not legal; in Qore you currently need the new
operator.
Why does it need to be clear to the programmer? He doesn't care about that. (S)he just wants to assign a hashdecl-formatted hash list to a variable of that type, which intuitively should not be a problem...
If there's more than one hash and it has more keys, this (the new-operator initialization style) would get quickly unnecessarily long and verbose.
supporting automatic conversion to hashdecl values at runtime would leave Qore open to implicit runtime type errors, which is something that I would like to eliminate in the future (ex: the upcoming %strong-types
directive). That's another strong reason for not doing it.
What do you mean by "implicit runtime type errors"?
What do you mean by "implicit runtime type errors"?
I mean runtime type errors due to implicit type conversions that fail - for example - if runtime type conversion to hashdecls would be supported transparently, then:
# this would succeed
hash<HD> h0 = ("name": 5);
# but the following would fail with a runtime type error:
any val = "5";
hash<HD> h1 = ("name": val);
# as will the following:
hash h = ("name": "five");
hash<HD> h2 = h;
If we would allow the first one to succeed with an implicit runtime type conversion to a hashdecl, then the last two need to fail at parse time to eliminate the possibility of runtime type errors.
So to support the first example above, implicit runtime type conversions from a hash -> hashdecl must be supported, and to exclude the last two examples, the parse-time type checking must be deterministic (or a parse exception must be raised).
The problem is that if we allow for implicit runtime type conversions from a hash -> hashdecl, then we have more complicated runtime type matching, which for large hashdecls will have a performance impact in things like runtime variant matching (for example with call signatures with large hashdecls as parameters), which is currently very fast. I believe there are other possible runtime performance impacts.
Currently htis logic is very fast - if you didn't declare it as a hashdecl, then no attempt at implcit runtime matching is performed.
The problem is that if we allow for implicit runtime type conversions from a hash -> hashdecl, then we have more complicated runtime type matching, which for large hashdecls will have a performance impact in things like runtime variant matching (for example with call signatures with large hashdecls as parameters), which is currently very fast.
That's a reasonable argument. Then what about not allowing this automatic conversion for everything but just for assignments?
because a change like that would make the language internally much more complicated and less consistent
As a Qore user, I would expect better automatic type conversion...