On Friday, 12 December 2014 at 08:42:22 UTC, Manu via
Digitalmars-d wrote:
On 11 December 2014 at 23:55, via Digitalmars-d
<[email protected]> wrote:
This is a point that most people don't seem to understand yet,
and which
wasn't obvious for me either, at the beginning:
* A `ref` parameter means that it cannot escape the function,
_except_ by
return.
* A `scope ref` parameter means that it cannot escape the
function _ever_,
not even by return.
* A `scope ref` return means that it cannot leave the current
statement.
Therefore, a `scope ref` return value can be passed on to the
next function
as a `ref` argument. If that function again returns a
reference (even if not
explicitly designated as `scope`), the compiler will treat it
as if it were
`scope ref`.
Ummm. I reckon there's a good reason that people don't seem to
understand this... because it would have difficulty being any
more
unintuitive!
It's contrary to the behaviour of basically everything else in
D!
const, pure, nothrow, etc... they all work a reliable and
consistent way.
Unfortunately I have to agree.
Also, I still don't think I get it... a scope-ref return, which
has a
restriction as you say, can be subverted by being piped through
a
function that receives and returns it as ref?
What is the point?
It cannot be subverted. As soon as you pass something into a
function G() as `ref` that's been returned from a function F()
via `scope ref`, the compiler needs to treat what is returned
from G() as `scope ref`, even if it's only declared as `ref`.
As you say, it's unintuitive and non-obvious.
I'm also quite uneasy with the fact that scope would not be
transitive
as a storage class. What happens when it's applied to a value
type,
like a struct, that contains some pointers? An adaptation
wrapper for
a single pointer is super common; ie, a tiny struct passed by
value
with scope needs to have it's contained pointer receive the
scope-ness
of the argument.
I agree, this is important. In my proposal, this works without
transitivity.
The wrapper stores the pointer as a `scope` member, then by
copying the
wrapper, the pointer gets copied implicitly, to which the
normal scope
restrictions apply (`scope` on members means "will not outlive
the
aggregate"). If it stored it as normal non-scope pointer, it
couldn't get
assigned in the first place. (Additionally, some higher level
tricks are
possible if we allow scope for value types and overloading on
scope.)
How can a member be marked scope? Apparently it's a storage
class, not
a type constructor... we can only attribute storage classes to
function args/results(?).
I was talking about my proposal here, where it's a type modifier,
not a storage class.
deadalnix also brought up the problem of transitivity. This, too,
would simply go away if it's a type modifier.