Re: The design of the hooks in std.experimental.checkedint

2017-06-05 Thread via Digitalmars-d
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:
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.


(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.


...indicating to the shell that the there was *no* interest in 
overriding them.


Re: The design of the hooks in std.experimental.checkedint

2017-06-05 Thread via Digitalmars-d

On Monday, 5 June 2017 at 10:29:26 UTC, Jacob Carlborg wrote:
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.


(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.


Re: The design of the hooks in std.experimental.checkedint

2017-06-05 Thread Jacob Carlborg via Digitalmars-d

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


Re: The design of the hooks in std.experimental.checkedint

2017-06-04 Thread Andrei Alexandrescu via Digitalmars-d

On 06/04/2017 03:25 PM, Jacob Carlborg wrote:

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.


What would be the advantage of moving the default into a hook?


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.


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.



Andrei



Re: The design of the hooks in std.experimental.checkedint

2017-06-04 Thread Jacob Carlborg via Digitalmars-d

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


Re: The design of the hooks in std.experimental.checkedint

2017-06-03 Thread Andrei Alexandrescu via Digitalmars-d

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


The design of the hooks in std.experimental.checkedint

2017-06-03 Thread Jacob Carlborg via Digitalmars-d
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