<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">2016-07-26 21:59 GMT+02:00 Sven Barth <span dir="ltr"><<a href="mailto:pascaldragon@googlemail.com" target="_blank">pascaldragon@googlemail.com</a>></span>:<br><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">First of let me tell you that in essence and in general I'm in support<br>
of your "default" idea (and the resulting idea to use this for smart<br>
pointers), though I have a few points, but I hope that we'll be able to<br>
solve these. :)<br></blockquote><div><br></div><div>Note: Generally I am working on boost-spirit like solution for Pascal so one single bad move will destroy my further plans...</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">First of it might be better not to name the tests "tdefaultX.pp" as that<br>
is already used for the Default() intrinsic... :/<br></blockquote><div><br></div><div>No problem with that - we can change this ;)<br></div><div> <br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
Second I don't know whether it's a good idea to use this with fields<br>
(though kudos for omitting the ";" between type and "default" ;) ).<br>
Maybe it would be better - to stay with the source of your idea - to<br>
only allow this for properties. This would allow to keep the field<br>
itself private for example and control its access through the setter<br>
(and ordinary as well as management operators), something that one<br>
couldn't do if one would need to use operators as the field would need<br>
to be public to be really useful outside of the record instance.<br></blockquote><div><br></div><div>Property was considered for "default" as main option but has many weakness. Sure, default "non indexed" property can be added as addition but <span lang="en"><span>definitely </span></span>not as main idea, because:<br><br></div><div>1. It breaks tdefault17 :<br><a href="https://github.com/maciej-izak/PascalSmartPointers/blob/master/tests/tdefault17.pp" target="_blank">https://github.com/maciej-izak/PascalSmartPointers/blob/master/tests/tdefault17.pp</a><br><a href="http://forum.lazarus.freepascal.org/index.php/topic,32482.msg209584.html#msg209584" target="_blank">http://forum.lazarus.freepascal.org/index.php/topic,32482.msg209584.html#msg209584</a></div><div><br></div><div>(yes I know we can use property for this but you need to declare additional getter/setter which is not much elegant in that case)<br><br></div><div>2. "default" for field is unique for [Nil|Null]able types (fastest possible implementation, and very correct for Pascal language. Nilable type works exactly like pointers with nice additions):<br><br></div><div>=== code begin ===<br>type<br> // record constraint is designed for nullable types :P see #24073<br> // #24073 Is already fixed in my implementation. record constraint accepts<br></div><div> // all not nilable types (including sets and strings - empty string as logical entity is not nil at all) <br></div><div> TNullable<T: record> = record <br> public type<br> PT = ^T;<br> strict private<br> Instance: ^T default;<br> function GetValue: T;<br> public<br> property Value: T read GetValue;<br><br> function HasValue: Boolean; inline;<br> function GetValueOrDefault: T;<br><br> class operator Implicit(A: T): TNullable<T>;<br> class operator Implicit(A: TNullable<T>): T;<br> class operator Implicit(A: PT): TNullable<T>;<br><br> class operator Equal(A: TNullable<T>; B: PT): Boolean;<br><br> class operator Initialize(var A: TNullable<T>);<br> class operator Finalize(var A: TNullable<T>);<br> class operator Clone(constref Src: TNullable<T>; var Dest: TNullable<T>);<br> class operator Copy(var Rec: TNullable<T>);<br> end;<br></div><div>=== code end ===<br></div><div> </div><div>3. "default" need to be transparent and usable with existing code base, some compiler magic is part of my further compiler development (I mean here "Storage Modifiers" and ARC objects in DelphiNextgen mode). With current approach is possible to pass record with default field as var/out/constref parameter. With property that is impossible.</div><div><br></div><div>4. for property for records there exist well know problems for "with"</div><div><br></div><div>5. "default" is designed as specialized helpers for TArray<T> and for Interfaces, property will block passing "default field" as var/out/constref parameter (similar to point 3).</div><div><br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<br>
Third I don't really agree with the notion that the record methods,<br>
fields, etc. take precedence to the default field. See further down for<br>
my suggestion to solve this (though that idea isn't without its flaws<br>
either).<br>
<br>
Question: can "default" only be used in "record" or also in "object" and<br>
"class"?<br></blockquote><div><br></div><div>Current implementation allows "default" only for "records".<br></div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<span><br>
><br>
> Tests (very good way to see how it works. NOTE: I need to add few other<br>
> tests for functions with var/const/out, "for in do" loop and for arrays<br>
> and indexed properties - help with additional tests is welcome):<br>
><br>
> <a rel="noreferrer" href="https://github.com/maciej-izak/PascalSmartPointers/tree/master/tests" target="_blank">https://github.com/maciej-izak/PascalSmartPointers/tree/master/tests</a><br>
<br>
</span>Note: tests for visibility.<br></blockquote><div><br></div><div>Right, but note that "default" is implicitly used even when is declared as strict private (which is correct and by design - for example see TNullable above). For "default" non indexed properties that rule might be incorrect.</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote"><span>
> The way how to obtain pointer can be a little confusing for most of<br>
> Pascal programmers. Anyway nothing new for Pascal language. In Pascal we<br>
> have little known @@ operator to get pointer to variable which handle<br>
> pointer to procedure/function. For records with "default field" @ means<br>
> "get pointer to default field" and @@ means "get pointer to record".<br>
<br>
</span>While I have to admit that I haven't known the @@-operator I don't<br>
necessarily agree with its use. Take tdefault7 and tdefault8 for example<br>
where you let the left hand side of the assignment determine which<br>
pointer is used. In tdefault7 it's the pointer to "a" while in tdefault8<br>
it's the pointer to "a.DefaultValue". </blockquote><div><br></div><div>@@ operator is very simple way to determine where you point. In any other case we have casting hell. See below (and more below). @@ exist rather as fulfillment to pa := @a; form tdefault7.pp (anyway is necessary for untyped pointers). You might not like @@ operator but @@ is part of long tradition. In practice works like a charm and is very clear.</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">Since normally in Pascal the<br>
result type of an expression is *not* determined by the left hand side<br>
of an assignment that's rather confusing (yes, there are exceptions, but<br>
that doesn't mean that one needs to add a new one).<br></blockquote><div><br></div><div>That is also by design. That is because you can't declare as "default field" nor "normal field" the field of owner type, so as logical consequence the syntax needs to be allowed (I mean here pa := @a; form tdefault7.pp). In daily usage it works very well and any other compiler behavior is irrational. Thank this feature most of programmers don't need to use @@ syntax (btw. the idea of introducing this was not forcing others to use @@). Additionally is necessary to get ride of untyped/typed pointers so we have rules presented in example tdefault8. Anyway for complex solution @@ is needed.</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
<br>
My idea to solve this coincides with my idea to solve the problem to<br>
access the record instead of the default field: typecasts.<br>...<br>
Essentially a typecast would disable the default field for the type it<br>
had been casted to.<br></blockquote><div><br></div><div>That was my first implementation (!!!). Which is definitely bad. :\ It breaks a lot of other important rules. For example is impossible to get ride of Implicit/Explicit operators when as "default field" is declared record which has Implicit/Explicit operators. Really, really bad idea, end-user code looks terrible and is unclear.</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
Of course this idea with the default field taking precedence becomes<br>
tainted a bit if one considers the management operators or the<br>
assignment operators as these would be part of the record and not the<br>
default field, but would still need to work...<br></blockquote><div><br></div><div>Remember that "default" is designed not "only" for SmartPtr/Obj and for Nilable types but also for "specialized" helpers for any type (for example for TArray<T>, for Interfaces etc). We can't do exception only for management operators and for assignment operators - unclear rule.</div><div> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex" class="gmail_quote">
Note: don't forget to test with global operator overloads ;)<br></blockquote><div><br></div><div>I will try to remember ;) </div></div><br>-- <br><div><div dir="ltr"><div>Best regards,<br>Maciej Izak</div></div></div>
</div></div>