digitalmars.D - DbI checked integral
- Andrei Alexandrescu (32/32) Jun 24 2016 Following the recent discussion about checkedint I found it fit to
- Walter Bright (4/9) Jun 24 2016 The use of Hook with introspection is an innovative and brilliant design...
- Robert burner Schadek (13/17) Jun 25 2016 I think there is a major problem with the proposed design.
- Andrei Alexandrescu (19/32) Jun 25 2016 Thanks for the feedback. There is at least one place in which built-in
- Robert burner Schadek (12/21) Jun 26 2016 There should be away to avoid all checks, true. But I think that
- Andrei Alexandrescu (11/27) Jun 26 2016 I showed you with code examples that you cannot define a user-defined ty...
- Robert burner Schadek (7/10) Jun 27 2016 Fair enough.
- Andrei Alexandrescu (2/5) Jun 27 2016 Thanks for the suggestion. I'll add that. -- Andrei
- deadalnix (15/26) Jun 25 2016 IMO this is the same problem as for the test function with no
- Meta (4/23) Jun 25 2016 The other thread Deadalnix is referring to, for context:
- Andrei Alexandrescu (3/23) Jun 25 2016 I'm okay with eliminating the zero-parameters version following an
- Andrei Alexandrescu (6/6) Jul 18 2016 Just created https://github.com/dlang/phobos/pull/4613 to request
Following the recent discussion about checkedint I found it fit to provide more detail on the design I was thinking about. A proof of concept is at https://gist.github.com/andralex/a0c0ad32704e6ba66e458ac48add4a99. Code is alpha quality and only thinly covered by unittests, but should give a good idea on how the library works. The core type is Checked!(int, Hook), where Hook is a type that may provide state and behavior. The behavior of interest is incarnated by the following methods (all of which are optional and introspected): hookOpCast, onBadCast, hookOpEquals, onBadOpEquals, hookOpCmp, onBadOpCmp, hookOpUnary, hookOpBinary, and onOverflow. By default, if Hook has no state and implements none of these methods, e.g. is void, then Checked!(int, void) is a user-defined type that mimics the behavior of int to the maximum extent possible. Hooks may be interested in handling bad results (such as overflow, division by zero, wrong casts etc) with the onXxx methods. See e.g. Croak, which simply aborts the program with assert(0) upon any bad result. Alternatively, hooks may define hookXxx methods that customize dangerous operations in any way they want, including defining alternative typing rules (e.g. arrange that int * int yields long). With Checked, user code may use some predefined hooks (only Croak provided for now), or define others specific to the application. Hooks may store state that is publicly accessible. The next step is to implement more hooks to make sure the introspection API is expressive enough for a battery of desired behaviors (exceptions, saturated arithmetic with/without persistence or hysteresis, alternative conversions). The code stands at 1102 lines. I expect size to double in the finished library. Some of the code arguably belongs in core.checkedint. Feedback is welcome. Thanks, Andrei
Jun 24 2016
On 6/24/2016 2:31 PM, Andrei Alexandrescu wrote:The core type is Checked!(int, Hook), where Hook is a type that may provide state and behavior. The behavior of interest is incarnated by the following methods (all of which are optional and introspected): hookOpCast, onBadCast, hookOpEquals, onBadOpEquals, hookOpCmp, onBadOpCmp, hookOpUnary, hookOpBinary, and onOverflow.The use of Hook with introspection is an innovative and brilliant design pattern that enables user extensibility and customization rather than trying to lump every kitchen sink possibility into the core code.
Jun 24 2016
On Friday, 24 June 2016 at 21:31:14 UTC, Andrei Alexandrescu wrote:By default, if Hook has no state and implements none of these methods, e.g. is void, then Checked!(int, void) is a user-defined type that mimics the behavior of int to the maximum extent possible.I think there is a major problem with the proposed design. when Checked!(int, void) is to behave as an int, why do we need it in the first place. I mean we have int as a basic type. Can't we do: alias Int = int; alias Int = Checked!(int, SomeUsefulHook); On second thought, the only feature of Checked!(int, void) is to be a slower int ;-) IMO the default CheckedInt!(int, void) needs a NaN like init/failure state. After any operation that overflows the value should be NaN.
Jun 25 2016
On 6/25/16 10:38 AM, Robert burner Schadek wrote:On Friday, 24 June 2016 at 21:31:14 UTC, Andrei Alexandrescu wrote:Thanks for the feedback. There is at least one place in which built-in integrals are not entirely replaceable - literals. Consider: byte a = 0; short b = -1; ushort c = 1; All of the literals involved have type int, so in theory neither line should work. However, the compiler special-cases literals because it "knows" they are within bounds. This special casing is inaccessible to user-defined types. So it stands to reason that if you want to design a checked integral types offering a variety of checking policies, one point in the design space that needs to be attainable is "no checks at all". Then the syntactic shell works the same as with any policy, and ideally there's no overhead at all.By default, if Hook has no state and implements none of these methods, e.g. is void, then Checked!(int, void) is a user-defined type that mimics the behavior of int to the maximum extent possible.I think there is a major problem with the proposed design. when Checked!(int, void) is to behave as an int, why do we need it in the first place. I mean we have int as a basic type. Can't we do: alias Int = int; alias Int = Checked!(int, SomeUsefulHook); On second thought, the only feature of Checked!(int, void) is to be a slower int ;-)IMO the default CheckedInt!(int, void) needs a NaN like init/failure state. After any operation that overflows the value should be NaN.One good design principle is pushing policy up and implementation down. A NaN is a very specific policy, which is appropriate for a Hook definition but would look out of place in the Checked shell. Andrei
Jun 25 2016
On Saturday, 25 June 2016 at 21:32:00 UTC, Andrei Alexandrescu wrote:So it stands to reason that if you want to design a checked integral types offering a variety of checking policies, one point in the design space that needs to be attainable is "no checks at all". Then the syntactic shell works the same as with any policy, and ideally there's no overhead at all.There should be away to avoid all checks, true. But I think that problem is solved by alias Int = ***** . I think we have to take a step back and discuss what this type should actually be used for. IMO it is a debug type and as such should have sensible default debug features like. Default to NaN or throwing Exceptions.One good design principle is pushing policy up and implementation down. A NaN is a very specific policy, which is appropriate for a Hook definition but would look out of place in the Checked shell.See my above argument. If it is a debug type, and that is what I think it is, it should have sensible default hooks.
Jun 26 2016
Robert burner Schadek <rburners gmail.com> wrote:On Saturday, 25 June 2016 at 21:32:00 UTC, Andrei Alexandrescu wrote:I showed you with code examples that you cannot define a user-defined type that is interchangeable with int. So a replacement for a checked int that adds no checks is a UDT with no checks.So it stands to reason that if you want to design a checked integral types offering a variety of checking policies, one point in the design space that needs to be attainable is "no checks at all". Then the syntactic shell works the same as with any policy, and ideally there's no overhead at all.There should be away to avoid all checks, true. But I think that problem is solved by alias Int = ***** .I think we have to take a step back and discuss what this type should actually be used for. IMO it is a debug type and as such should have sensible default debug features like. Default to NaN or throwing Exceptions.That is a side discussion as trivial as deciding the defaul second argument for Checked(T, Hook = DefaultHook). This has nothing to do with the design. It is obvious to me that allowing any combination of checks allows naturally for no check. It is also trivial to enforce that at least one check is defined, so again I'd be hard pressed to frame this as a design matter. Andrei
Jun 26 2016
On Sunday, 26 June 2016 at 16:03:57 UTC, Andrei Alexandrescu wrote:Fair enough. I was looking into creating a NaN Hook. I could create it by doing some ugly stuff inside the Hook. Things would have been nicer if there is a ctor hook. p.s. a dub package would be nicelike. Default to NaN or throwing Exceptions.That is a side discussion as trivial as deciding the defaul second argument for Checked(T, Hook = DefaultHook).
Jun 27 2016
On 6/27/16 4:20 AM, Robert burner Schadek wrote:I was looking into creating a NaN Hook. I could create it by doing some ugly stuff inside the Hook. Things would have been nicer if there is a ctor hook.Thanks for the suggestion. I'll add that. -- Andrei
Jun 27 2016
On Saturday, 25 June 2016 at 14:38:43 UTC, Robert burner Schadek wrote:I think there is a major problem with the proposed design. when Checked!(int, void) is to behave as an int, why do we need it in the first place. I mean we have int as a basic type. Can't we do: alias Int = int; alias Int = Checked!(int, SomeUsefulHook); On second thought, the only feature of Checked!(int, void) is to be a slower int ;-) IMO the default CheckedInt!(int, void) needs a NaN like init/failure state. After any operation that overflows the value should be NaN.IMO this is the same problem as for the test function with no arguments. What if your policy does nothing ? This is the end case, and while probably not very useful on its own, is very important to not push a ton of complexity on user code. Just like multiplying by 0 or 1 is not very useful, yet the MUL instruction and * operator accept these as operands. Like adding 0 is not useful, yet ADD and the + operator accept these as operand. It is important for library code to handle degenerate cases gracefully. Also I'd run the code in LLVM's opt to see what comes out, but I'd be pretty sure if we are careful, it can optimize everything away and get us back to ints.
Jun 25 2016
On Saturday, 25 June 2016 at 21:46:23 UTC, deadalnix wrote:On Saturday, 25 June 2016 at 14:38:43 UTC, Robert burner Schadek wrote:The other thread Deadalnix is referring to, for context: http://forum.dlang.org/thread/skqcudmkvqtejmofxoim forum.dlang.org Shameless plug: Andrei your input is neededI think there is a major problem with the proposed design. when Checked!(int, void) is to behave as an int, why do we need it in the first place. I mean we have int as a basic type. Can't we do: alias Int = int; alias Int = Checked!(int, SomeUsefulHook); On second thought, the only feature of Checked!(int, void) is to be a slower int ;-) IMO the default CheckedInt!(int, void) needs a NaN like init/failure state. After any operation that overflows the value should be NaN.IMO this is the same problem as for the test function with no arguments.
Jun 25 2016
On 6/25/16 7:50 PM, Meta wrote:On Saturday, 25 June 2016 at 21:46:23 UTC, deadalnix wrote:I'm okay with eliminating the zero-parameters version following an appropriate deprecation cycle. It's probably useless. -- AndreiOn Saturday, 25 June 2016 at 14:38:43 UTC, Robert burner Schadek wrote:The other thread Deadalnix is referring to, for context: http://forum.dlang.org/thread/skqcudmkvqtejmofxoim forum.dlang.org Shameless plug: Andrei your input is neededI think there is a major problem with the proposed design. when Checked!(int, void) is to behave as an int, why do we need it in the first place. I mean we have int as a basic type. Can't we do: alias Int = int; alias Int = Checked!(int, SomeUsefulHook); On second thought, the only feature of Checked!(int, void) is to be a slower int ;-) IMO the default CheckedInt!(int, void) needs a NaN like init/failure state. After any operation that overflows the value should be NaN.IMO this is the same problem as for the test function with no arguments.
Jun 25 2016
Just created https://github.com/dlang/phobos/pull/4613 to request comments. One question is whether all/most useful checked integral front-ends can be implemented in terms of the hook-based DbI infrastructure in that PR. Thanks, Andrei
Jul 18 2016