[OT] What are D's values?
Steven Schveighoffer
schveiguy at gmail.com
Fri Oct 8 15:35:26 UTC 2021
On 10/7/21 1:35 PM, H. S. Teoh wrote:
> On Wed, Oct 06, 2021 at 11:59:46AM -0400, Steven Schveighoffer via Digitalmars-d wrote:
> [...]
>> There is one place where I have struggled though, and D might be able to do
>> better. And that is with optional parentheses and taking the address. When a
>> property can be either an accessor or a field, then `obj.prop` can work the
>> same. However, `&obj.prop` is not the same.
>>
>> I have solved it by using this stupid function:
>>
>> ```d
>> auto ref eval(T)(auto ref T t) { return t; }
>>
>> // instead of &obj.prop
>> auto ptr = &eval(obj.prop);
>> ```
>
> IMO, taking the address of something is a low-level operation that
> doesn't really belong in higher-level logic. Unsurprisingly, therefore,
> it doesn't lend itself well to the malleability that generally applies
> in D code.
>
> The fact of taking the address of something imposes the implicit
> assumption that that object has an address to be taken in the first
> place. Meaning that once you use such an operation, the target object
> is no longer Liskov-substitutable with anything else that may not have
> an address (e.g. an accessor function). So this imposes limitations on
> what kinds of refactoring the code will be amenable to.
To give more context, it is solely for this little function:
```d
auto firstElem(R)(R r) if (hasLvalueElements!R)
{
if(r.empty)
return null;
return &(eval(r.front));
}
```
Why do I need this function? Because Phobos doesn't give me nice access
to things from `find`. Instead, it gives me a range. Which is useful for
some cases, but for others, I just want to get reference access of the
element I was looking for.
So compare the two possibilities:
```d
auto result = someRange.find(elem);
if(!result.empty) {
if(result.front.x > 5)
result.front.x -= 5;
}
// vs.
if(auto v = someRange.find(elem).firstElem) {
if(v.x > 5)
v.x -= 5;
}
```
For some things, pointers are the best interface.
Sure, I could wrap this up in a type, but it still would need to store a
pointer internally (or the range itself), plus a pointer is already
doing exactly what I need it to do.
The main issue is that `obj.method` means different things depending on
context.
As kind of another similar story, A long time ago, an eponymous template
allowed some access to things inside the template, and did not always
map directly to the eponymous member *in some situations*. While this
allowed greater flexibility, it produced odd behavior. Eventually, all
access of the internals of an eponymous template were removed, and it
always *always* just means the eponymous member. This removed some
expressiveness, but the result is much much cleaner.
I would like to see something similar for property methods.
> [...]
>> While it's nice D has a mechanism to work around this difference, I
>> find having to use such shims a bit awkward. And it's a direct
>> consequence of hiding the implementation of a field/property behind
>> the same syntax. You can find other cases where D can be awkward (such
>> as `typeof(obj.prop)` or checking types regardless of mutability).
>>
>> What is the "better" answer though? I don't know.
> [...]
>
> Not necessarily a better answer: static if to discover whether something
> is a field or an accessor, and extract the address appropriately,
> possibly encapsulated in a utility function? Not much different from
> your .eval hack, though.
This would be horrid. Basically, your code starts looking like:
```d
static if(isAccessor!(obj.foo)) // have fun writing this, there's lots
of traps.
return &obj.foo();
else
return &obj.foo;
```
The eval hack is much much cleaner. It means "this is an expression, not
a symbol". Maybe the answer is to do this with some syntax feature, so I
can avoid calling silly hack functions.
> The C++ answer is to allow overloading of unary &. However, that opens
> up a whole 'nother can o' worms that I would not recommend.
Nope, I would never want that. I want a pointer when I ask for a pointer.
-Steve
More information about the Digitalmars-d
mailing list