Attribute transference from callbacks?
Manu
turkeyman at gmail.com
Wed Dec 11 22:26:57 UTC 2024
On Wed, 11 Dec 2024 at 08:25, Timon Gehr via Digitalmars-d <
digitalmars-d at puremagic.com> wrote:
> On 12/9/24 07:47, Manu wrote:
> > On Mon, 9 Dec 2024 at 01:51, Timon Gehr via Digitalmars-d <digitalmars-
> > d at puremagic.com <mailto:digitalmars-d at puremagic.com>> wrote:
> >
> > On 12/8/24 06:54, Manu wrote:
> > > Here's the stupidest idea ever: expand inout to take an
> argument...
> > >
> > > void parseThings(string s, void delegate(Thing) inout(nothrow)
> > > inout(@nogc) sink) inout(nothrow) inout(@nogc)
> > > {
> > > //...
> > > sink(Thing());
> > > //...
> > > }
> > > ...
> >
> > Issue with this is you will still not know which `inout`s match up.
> > This
> > is already an issue with the existing `inout`, which just arbitrarily
> > selects a convention. In particular, it does not really work with
> > higher-order functions the way you'd need it to here.
> >
> >
> > Yes, this is obviously an issue, and we have it in D comprehensively;
> > it's the main issue with our 'safe' stuff too; where rust has explicit
> > lifetime attribution... it's essentially the same problem all round; it
> > needs tags that specify things which are associated.
> > In lieu of that though, I would say, if there are multiple things marked
> > inout(...) in the way I proposed, you would assume the most pessimistic
> > from the set of possibilities is supplied.
> >
> > void inheritAttribs(string s, void delegate() inout(nothrow)
> > inout(@nogc) fun_1, void delegate() inout(nothrow) inout(@nogc) fun_2)
> > inout(nothrow) inout(@nogc)
> > {
> > //...
> > fun_1();
> > fun_2();
> > //...
> > }
> >
> > In this case, `inheritAttribs` would only be nothrow in the event BOTH
> > fun_1 and fun_2 are nothrow, likewise for nogc...
> > ...
>
> Well, this is one limitation, but the `inout` on the delegate does not
> even match up with the `inout` on `inheritAttribs` those are already
> different.
>
> This does not compile;
>
> ```d
> inout(int)* foo(inout(int)* delegate()inout dg,inout(int)* x){
> return x;
> }
>
> void main(){
> const(int)* delegate()const dg;
> const(int)* x;
> foo(dg,x); // error
> }
> ```
>
> It seems at least this would need to work.
>
> `inout` is very confusing because different `inout` annotations can get
> conflated or not conflated. It's also the main reason why the
> implementation is unsound, it's not done consistently during type checking.
>
I agree that's a problem. It's classic D though where things are
non-uniform that way.
The resolution would probably be to always conflate all inouts; since we
can't tag them individually, we have to assume they're all uniformly
tagged; and they all take on the most restrictive state from the call.
>
> > > Surely people have had better ideas? But you get the point, and
> > this is
> > > basically essential to make the 'sink' pattern work at all in D.
> > >
> > > No, no templates; it's not right to generate multiple copies of
> > identical functions just because something it CALLS would transfer
> > an attribute. The function itself is identical no matter the state
> > of any attribute transference, and so this isn't a template problem;
> > it's a pattern matching problem.
> >
> > Well, it can be seen as a homogeneous vs heterogeneous compilation
> > problem. The attributes can still act a bit like template parameters,
> > but only one instance must be created that works for all of them.
> It's
> > sometimes called parametric polymorphism.
> >
> >
> > Right. Do you have examples of this from other languages and how it's
> > expressed? Lifetime's in Rust are the obvious benchmark, but I don't see
> > any evidence that D has a taste for this sort of thing.
> > ...
>
> Well, Java, C#, Scala support homogeneous compilation in their generics.
>
> In Haskell everything is polymorphic by default with implicit universal
> quantification over lower-case type parameters.
>
> > I do think that inout could work for all attributes the same as inout
> > does for const (with the same limitations).
>
> Well, as I showed above, those limitations are kind of fatal for your
> use case.
>
Sorry, I didn't follow what makes them fatal?
> You could see `inout` as
> > shorthand for `inout(const)` under my suggestion.
> > Obviously it must enforce the most restrictive implementation inside the
> > code; my function `inheritAttribs` above must be nothrow and nogc
> > internally, but externally it would allow a mapping from one of the
> > 'input' attributes to the 'output' attribute in a non-templated way.
>
> `inout` also interacts with `immutable`, not only `const`.
>
The way I saw it was that at compile time, `inout` is presumed to be
equivalent to const. You can't pass an inout(int)* to an immutable(int)*,
but you can pass to a const(int)*... but yeah, in terms of conceptual
precision, I see your point.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20241212/5a6aca5a/attachment.htm>
More information about the Digitalmars-d
mailing list