digitalmars.D - The design of the hooks in std.experimental.checkedint
- Jacob Carlborg (42/42) Jun 03 2017 I've been looking a bit at the design of the hooks in
- Andrei Alexandrescu (13/66) Jun 03 2017 That would be an interesting experiment. If there is a net reduction of
- Jacob Carlborg (14/23) Jun 04 2017 I'm not sure I fully understand without a code example but I would say
- Andrei Alexandrescu (8/21) Jun 04 2017 Hook function is defined: "I want to hook this entire operation."
- Jacob Carlborg (6/12) Jun 05 2017 The whole idea was to reduce the number of "static if" in the
- Petar Kirov [ZombineDev] (8/19) Jun 05 2017 (As I'm sure you know) this can be solved by using UDAs. I.e. the
- Petar Kirov [ZombineDev] (4/24) Jun 05 2017 ...indicating to the shell that the there was *no* interest in
I've been looking a bit at the design of the hooks in std.experimental.checkedint. Due to all hooks being optional there's quite a few "static if" in the implementation of checkedint to check if a hook is implemented. Wouldn't it be simpler if all hooks were required and a default implementation was provided instead? Currently the Abort hook is the default hook that defines a couple of hooks but not all of them. If a default hook is instead implements all hooks but is implemented as a template it can be mixed in into custom hooks that want to change the behavior. For example, I want a hook that only defines the default value. Today that would look like this: struct DefaultValueHook { static T defaultValue!(T)() { return 1; } } If all hooks were required to be implemented but a default implementations would be provided it would look like this instead: mixin template DefaultHook() { T defaultValue!(T)() { return T.init; } ... // the rest of the hooks } struct DefaultValueHook { static: mixin DefaultHook; // provides default implementation for all hooks T defaultValue!(T)() { return 1; } // "overrides" defaultValue defined in DefaultHook } One extra line of could is required, the mixin. It should also be simpler if you want to customize an existing hook but just override one of the hooks. Example: struct DefaultValueHook { mixin Warn; Dst onBadCast(Dst, Src)(Src src) { assert(0); } } In the implementation of Checked it would know that a hook is always provided and quite a few of the existing "static if" could be removed. Thoughts? -- /Jacob Carlborg
Jun 03 2017
On 06/03/2017 11:59 AM, Jacob Carlborg wrote:I've been looking a bit at the design of the hooks in std.experimental.checkedint. Due to all hooks being optional there's quite a few "static if" in the implementation of checkedint to check if a hook is implemented. Wouldn't it be simpler if all hooks were required and a default implementation was provided instead?That would be an interesting experiment. If there is a net reduction of lines of code, that would be quite nice. One question - current logic decides whether to call e.g. hookOpBinary vs. perform the default operation followed by onOverflow. How would that work if both hookOpBinary and onOverflow are defined?Currently the Abort hook is the default hook that defines a couple of hooks but not all of them. If a default hook is instead implements all hooks but is implemented as a template it can be mixed in into custom hooks that want to change the behavior. For example, I want a hook that only defines the default value. Today that would look like this: struct DefaultValueHook { static T defaultValue!(T)() { return 1; } } If all hooks were required to be implemented but a default implementations would be provided it would look like this instead: mixin template DefaultHook() { T defaultValue!(T)() { return T.init; } ... // the rest of the hooks } struct DefaultValueHook { static: mixin DefaultHook; // provides default implementation for all hooks T defaultValue!(T)() { return 1; } // "overrides" defaultValue defined in DefaultHook } One extra line of could is required, the mixin.I'm unclear whether this is a step in the right direction. Why have user code work more to provide less information to the framework? Let user code define what it can, and the framework takes care of the rest. A look at how std.experimental.allocator would work if all primitives were required would also be useful.It should also be simpler if you want to customize an existing hook but just override one of the hooks. Example: struct DefaultValueHook { mixin Warn; Dst onBadCast(Dst, Src)(Src src) { assert(0); } } In the implementation of Checked it would know that a hook is always provided and quite a few of the existing "static if" could be removed. Thoughts?A look at an alternative design would definitely be interesting. Andrei
Jun 03 2017
On 2017-06-03 23:45, Andrei Alexandrescu wrote:One question - current logic decides whether to call e.g. hookOpBinary vs. perform the default operation followed by onOverflow. How would that work if both hookOpBinary and onOverflow are defined?I'm not sure I fully understand without a code example but I would say that the default hook would implement hookOpBinary to perform the default operation and then call onOverflow.I'm unclear whether this is a step in the right direction. Why have user code work more to provide less information to the framework?I don't see how it would provide less information to the framework.Let user code define what it can, and the framework takes care of the rest.Well, the default hook is part of the framework.A look at how std.experimental.allocator would work if all primitives were required would also be useful.Yes. I haven't looked that carefully on how DbI is used in the allocators yet.A look at an alternative design would definitely be interesting.Note that it doesn't need to be an either or case. Some of hooks can be required while other are optional. This suggestion is perfect when the logic is: if there's a hook, call that, otherwise perform a default operation. It's less ideal when there are multiple conditional branches. -- /Jacob Carlborg
Jun 04 2017
On 06/04/2017 03:25 PM, Jacob Carlborg wrote:On 2017-06-03 23:45, Andrei Alexandrescu wrote:What would be the advantage of moving the default into a hook?One question - current logic decides whether to call e.g. hookOpBinary vs. perform the default operation followed by onOverflow. How would that work if both hookOpBinary and onOverflow are defined?I'm not sure I fully understand without a code example but I would say that the default hook would implement hookOpBinary to perform the default operation and then call onOverflow.Hook function is defined: "I want to hook this entire operation." Hook function is not defined: "I am not interested in hooking this operation." If hook is always defined, the shell cannot identify what a particular hook has an interest in. AndreiI'm unclear whether this is a step in the right direction. Why have user code work more to provide less information to the framework?I don't see how it would provide less information to the framework.
Jun 04 2017
On 2017-06-04 21:52, Andrei Alexandrescu wrote:What would be the advantage of moving the default into a hook?The whole idea was to reduce the number of "static if" in the implementation.Hook function is defined: "I want to hook this entire operation." Hook function is not defined: "I am not interested in hooking this operation." If hook is always defined, the shell cannot identify what a particular hook has an interest in.Right. -- /Jacob Carlborg
Jun 05 2017
On Monday, 5 June 2017 at 10:29:26 UTC, Jacob Carlborg wrote:(As I'm sure you know) this can be solved by using UDAs. I.e. the members of the mixin template can be tagged with e.g. default indicating to the shell that the there was interest in overriding them. Of course static ifs will be needed again, but if we assume that in the common case the shell doesn't need to differentiate between user defined and default hooks, then this can be a net win in terms of LoC needed for the shell.Hook function is defined: "I want to hook this entire operation." Hook function is not defined: "I am not interested in hooking this operation." If hook is always defined, the shell cannot identify what a particular hook has an interest in.Right.
Jun 05 2017
On Monday, 5 June 2017 at 16:04:18 UTC, Petar Kirov [ZombineDev] wrote:On Monday, 5 June 2017 at 10:29:26 UTC, Jacob Carlborg wrote:...indicating to the shell that the there was *no* interest in overriding them.(As I'm sure you know) this can be solved by using UDAs. I.e. the members of the mixin template can be tagged with e.g. default indicating to the shell that the there was interest in overriding them. Of course static ifs will be needed again, but if we assume that in the common case the shell doesn't need to differentiate between user defined and default hooks, then this can be a net win in terms of LoC needed for the shell.Hook function is defined: "I want to hook this entire operation." Hook function is not defined: "I am not interested in hooking this operation." If hook is always defined, the shell cannot identify what a particular hook has an interest in.Right.
Jun 05 2017