May 20, 2014 Re: Memory allocation purity | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Mon, 19 May 2014 15:20:46 -0400
Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com>
wrote:
> On Mon, 19 May 2014 15:03:55 -0400, Dicebot <public@dicebot.lv> wrote:
>
> > On Monday, 19 May 2014 at 17:35:34 UTC, Steven Schveighoffer wrote:
> >> On Mon, 19 May 2014 13:31:08 -0400, Ola Fosheim Grøstad <ola.fosheim.grostad+dlang@gmail.com> wrote:
> >>
> >>> On Monday, 19 May 2014 at 17:11:43 UTC, Steven Schveighoffer wrote:
> >>>> It shouldn't matter. Something that returns immutable references, can return that same thing again if asked the same way. Nobody should be looking at the address in any meaningful way.
> >>>
> >>> I think this is at odds with generic programming. What you are saying is that if you plug a pure function into an algorithm then you have to test for "pure" in the algorithm if it is affected by object identity. Otherwise, goodbye plug-n-play.
> >>
> >> I think I misstated this, of course, looking at the address for certain reasons is OK, Object identity being one of them.
> >
> > immutable(Object*) alloc() pure
> > {
> > return new Object();
> > }
> >
> > bool oops() pure
> > {
> > auto a = alloc();
> > auto b = alloc();
> > return a is b;
> > }
> >
> > This is a snippet that will always return `true` if memoization is at work and `false` if strongly pure function will get actually called twice. If changing result of your program because of silently enabled compiler optimization does not indicate a broken compiler I don't know what does.
>
> The code is incorrectly implemented, let me fix it:
>
> bool oops() pure
> {
> return false;
> }
Sure, that particular example may be contrived, but there's plenty of code out there that checks for whether two objects are the same object. A classic example would be for skipping equality checks if the two objects are the same object, but it could be used in far more complex situations that don't involve doing equality checks when two objects aren't the same.
The reality of the matter is that regardless of whether you think that checking two objects to see whether they're the same object is a valid operation or not, it's perfectly legal to do so and _will_ happen in code, so if the compiler makes optimizations which will change whether two objects are the same object (e.g. optimizing out a second call to a pure function within an expression so that the result is reused in spite of the fact that the function returns a new object each time it's called), then the result is that the semantics of the program have changed due to an optimization. And that is most definitely a bad thing.
IMHO, if the compiler cannot guarantee that a pure function returns the same object every time if it returns a reference type, then the compiler should never optimize out multiple calls to that function. To do otherwise would make it so that the semantics of the program change due to an optimization.
- Jonathan M Davis
|
May 20, 2014 Re: Memory allocation purity | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | On Mon, 19 May 2014 18:46:22 -0400, Dicebot <public@dicebot.lv> wrote: > On Monday, 19 May 2014 at 20:51:22 UTC, Steven Schveighoffer wrote: >> On Mon, 19 May 2014 16:23:34 -0400, Dicebot <public@dicebot.lv> wrote: >>> Oh, and are probably eager to show me links to specs which indicate what part of my snippet breaks the type system? Is it allocation that is forbidden in reasonable code? Or object identity? >> >> None is forbidden, and the combination above is a BUG. Bugs happen, compilers actually compile them. pure != bug-free. > > No it is not. It is semantically valid code which does exactly what it was expected to do. Unless compiler optimization happens which will actually introduce a bug silently. It is optimization that is broken, not code itself. Again, the bug is to break if a function that allocates an immutable object for some reason re-uses the immutable object (perfectly legitimate optimization, whether done by the compiler or intentionally). I still have not seen the code that somehow can't handle this. > And this is not some sort of imaginary code. `alloc` implementation may be located in some other static library and not available to compiler. It is likely to be not a plain `alloc` in real code but some utility function that creates and returns object internally. alloc isn't the problem. oops is incorrectly implemented to depend on implementation details of the allocator. >>> Please stop this "write proper code" absurdism. This code is safe, doesn't use casts or pointer forging or any other dirty low level tricks. If compiler can't reject it as invalid and goes into funny mode instead, compiler is fucked. There can be no excuse for it. >> >> The code above relies on implementation details of the allocator to do it's work. It's invalid to do so. > > Wrong again. It does not rely upon anything. It simply checks if two objects returned by two functions calls are identical. With zero assumptions about it. Then why is oops returning true a failure case? >> Please show me the code that goes into "funny land" because of an incorrect result of oops. > > What the hell are you speaking about? Getting two different results for a function depending on -O flag is not weird enough for you? It's not unheard of. When you violate language assumptions, it happens. I've seen code that breaks when -O is passed, vs. when it's not. > - Hey, this program produces a wrong output! > - But it doesn't wipe your system. You will be fine. This is a superficial reading of my statement ;) > > At this point it is hard to believe you are serious and not trolling. Yeah, it was kind of trolling, but I keep asking questions and have been given the same irrelevant answers. Sorry. -Steve |
May 20, 2014 Re: Memory allocation purity | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Mon, 19 May 2014 23:33:30 -0400, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > On Mon, 19 May 2014 15:20:46 -0400 > Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> > wrote: > >> On Mon, 19 May 2014 15:03:55 -0400, Dicebot <public@dicebot.lv> wrote: >> >> > On Monday, 19 May 2014 at 17:35:34 UTC, Steven Schveighoffer wrote: >> >> On Mon, 19 May 2014 13:31:08 -0400, Ola Fosheim Grøstad >> >> <ola.fosheim.grostad+dlang@gmail.com> wrote: >> >> >> >>> On Monday, 19 May 2014 at 17:11:43 UTC, Steven Schveighoffer >> >>> wrote: >> >>>> It shouldn't matter. Something that returns immutable >> >>>> references, can return that same thing again if asked the same >> >>>> way. Nobody should be looking at the address in any meaningful >> >>>> way. >> >>> >> >>> I think this is at odds with generic programming. What you are >> >>> saying is that if you plug a pure function into an algorithm then >> >>> you have to test for "pure" in the algorithm if it is affected by >> >>> object identity. Otherwise, goodbye plug-n-play. >> >> >> >> I think I misstated this, of course, looking at the address for >> >> certain reasons is OK, Object identity being one of them. >> > >> > immutable(Object*) alloc() pure >> > { >> > return new Object(); >> > } >> > >> > bool oops() pure >> > { >> > auto a = alloc(); >> > auto b = alloc(); >> > return a is b; >> > } >> > >> > This is a snippet that will always return `true` if memoization is >> > at work and `false` if strongly pure function will get actually >> > called twice. If changing result of your program because of >> > silently enabled compiler optimization does not indicate a broken >> > compiler I don't know what does. >> >> The code is incorrectly implemented, let me fix it: >> >> bool oops() pure >> { >> return false; >> } > > Sure, that particular example may be contrived, but there's plenty of code out > there that checks for whether two objects are the same object. A classic > example would be for skipping equality checks if the two objects are the same > object If anything, the optimization will make this more efficient. > , but it could be used in far more complex situations that don't involve > doing equality checks when two objects aren't the same. This is hand-waving. I need a real example to understand. > The reality of the matter is that regardless of whether you think that > checking two objects to see whether they're the same object is a valid > operation or not, it's perfectly legal to do so and _will_ happen in code, so > if the compiler makes optimizations which will change whether two objects are > the same object (e.g. optimizing out a second call to a pure function within > an expression so that the result is reused in spite of the fact that the > function returns a new object each time it's called), then the result is that > the semantics of the program have changed due to an optimization. And that is > most definitely a bad thing. How so? What exactly happens when two identical, but immutable objects, are optimized into being the same object? > IMHO, if the compiler cannot guarantee that a pure function returns the same > object every time if it returns a reference type, then the compiler should > never optimize out multiple calls to that function. To do otherwise would > make it so that the semantics of the program change due to an optimization. General reference type, yes. Immutable reference type, no. -Steve |
May 20, 2014 Re: Memory allocation purity | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Mon, 19 May 2014 23:14:03 -0400, Jonathan M Davis via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > On Mon, 19 May 2014 13:11:43 -0400 > Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> > wrote: > >> On Mon, 19 May 2014 12:35:26 -0400, Jonathan M Davis via >> Digitalmars-d <digitalmars-d@puremagic.com> wrote: >> >> > On Mon, 19 May 2014 09:42:31 -0400 >> > Steven Schveighoffer via Digitalmars-d <digitalmars-d@puremagic.com> >> > wrote: >> > >> >> On Sun, 18 May 2014 09:58:25 -0400, H. S. Teoh via Digitalmars-d >> >> <digitalmars-d@puremagic.com> wrote: >> >> >> >> > On Sat, May 17, 2014 at 11:51:44AM -0700, Jonathan M Davis via >> >> > Digitalmars-d wrote: >> >> >> On Thu, 15 May 2014 08:43:11 -0700 >> >> >> Andrei Alexandrescu via Digitalmars-d >> >> >> <digitalmars-d@puremagic.com> wrote: >> >> >> >> >> >> > On 5/15/14, 6:28 AM, Dicebot wrote: >> >> >> > > This is not true. Because of such code you can't ever >> >> >> > > automatically memoize strongly pure function results by >> >> >> > > compiler. A very practical concern. >> >> >> > >> >> >> > I think code that doesn't return pointers should be >> >> >> > memoizable. Playing tricks with pointer comparisons would be >> >> >> > appropriately penalized. -- Andrei >> >> >> >> >> >> Agreed. The fact that a pure function can return newly allocated >> >> >> memory pretty much kills the idea of being able to memoize pure >> >> >> functions that return pointers or references, because the >> >> >> program's behavior would change if it were to memoize the >> >> >> result and reuse it. >> >> >> >> Memoizing reference returns that are immutable should be fine. >> > >> > Only if you consider it okay for the behavior of the function to >> > change upon >> > memoization - or at least don't consider that the behaviors changed >> > due to the >> > fact that the objects are equal but not the same object (which can >> > matter for >> > reference types) >> >> It shouldn't matter. Something that returns immutable references, >> can return that same thing again if asked the same way. > > Except that a pure function _can't_ return the same object by definition - not > unless it was passed in via an argument. Compiles today (2.065): immutable(Object) alloc() pure { static immutable o = new immutable(Object); return o; } >> >> Such a program is incorrectly written. > > Well, then Object.toHash is incorrectly written. > It might actually be, yes. toHash really should examine the object contents, not the address. -Steve |
Copyright © 1999-2021 by the D Language Foundation