AdaCore / ada-spark-rfcs

Platform to submit RFCs for the Ada & SPARK languages
63 stars 28 forks source link

[RFC] Simple return by reference syntax #27

Open jere-software opened 5 years ago

jere-software commented 5 years ago

Direct link to text: https://github.com/jeremiahbreeden/ada-spark-rfcs/blob/topic/simple_return_by_ref/considered/rfc-simplified-return-by-reference.rst

jere-software commented 5 years ago

I'm not a great writer, so I am sure I could be better at laying this out. Let me know what I need to clarify. I may ask some questions about how to present it in the RFC though

raph-amiard commented 5 years ago

Hi @jeremiahbreeden ! First, thank you very much for your contribution. I agree that making reference types easier to use is a worthy goal.

However:

  1. In your RFC you demonstrate how to create a function that returns a reference, but not how to use this result. How would the call site look like ? It seems to me that this is a big hole in your proposal: If you want some kind of short-hand syntax to refer to reference types, it needs to work everywhere.

  2. In that light, the use of the "aliased" keyword seems inoportune, since it already has a meaning on a variable declaration, that will be different.

What do you think about this ?

Also I cannot help but think that some version of implicitly instantiated generics might work just fine here, if you had a package Ada.Containers.Simple_Reference you could then do

package R renames Ada.Containers.Simple_Reference;

function Reference(Source : in out Thing) return R (Some_Type).Ref is
   ...
end Reference;

This gets rid of the tedious part about reference types - declaring them.

jere-software commented 5 years ago

First of all, thank you for the comments!

Hi @jeremiahbreeden ! First, thank you very much for your contribution. I agree that making reference types easier to use is a worthy goal.

However:

1. In your RFC you demonstrate how to create a function that returns a reference, but not how to use this result. How would the call site look like ? It seems to me that this is a big hole in your proposal: If you want some kind of short-hand syntax to refer to reference types, it needs to work everywhere.

UPDATE: I took a stab at adding some usage examples to the proposal. I don't know if that is what you originally meant though. If my updates didn't cover it, can you please provide some sort of code like example where you expect there to be a hole? That way I can address the concern directly.

Can you please elaborate? In my proposal, I mentioned it would work exactly as it does for the types that use implicit_dereference (like how it is currently used in Ada containers as one example). For example, if you had a type that provided the reference function, you could do something like:

Some_Container_Object.Reference(Cursor) := 23; -- assuming it was an aliased integer being returned

or

Some_Procedure(Some_Container_Object.Reference(Cursor)); -- assuming an Integer parameter

or if the return type is a tagged record with primitive operations:

Some_Container_Object.Reference(Cursor).Some_Primitive_Op;

And of course, if the Variable_Indexing aspect was defined, then they would just be Some_Container_Object(Cursor) := 23; Some_Procedure(Some_Container_Object(Cursor)); Some_Container_Object(Cursor).Some_Primitive_Op;

I'm not sure I understand what the hole would be, can you expound? I don't mind updating the proposal, I just need to understand your question better to address it.

NOTE: This does not have to be tied to containers or cursors...just handy examples

2. In that light, the use of the "aliased" keyword seems inoportune, since it already has a meaning on a variable declaration, that will be different.

I agree, though it isn't the first time we have reused a keyword for something than it is original meaning (see "limited" or "all" for example). I'm not tied to it, I just didn't want to bog the proposal down with a new keyword, cause that tends to degrade discussions off on tangents. I'm definitely open to using some other keyword or syntax.

What do you think about this ?

Also I cannot help but think that some version of implicitly instantiated generics might work just fine here, if you had a package Ada.Containers.Simple_Reference you could then do

package R renames Ada.Containers.Simple_Reference;

function Reference(Source : in out Thing) return R (Some_Type).Ref is
   ...
end Reference;

This gets rid of the tedious part about reference types - declaring them.

I don't disagree here. That sounds like a possible alternative. I don't know how I would make a package that is used in that way (unless you are also proposing a different syntax here with the R(Some_Type).Ref and are proposing the compiler would provide the package as well). However, if this method is used, it is important to this proposal that the underlying access type is not visible or available to the user of the package or the return type.

EDIT: could not get the pretty syntax highlighting to work in the comments, sorry :(

jere-software commented 5 years ago

Side note, I am also not opposed to using an aspect instead of "aliased":

function Reference(Container : in out Container_Type; Index : Index_Type) return Some_Type with Return_By_Reference => True;

I just wasn't sure this would be as maintainable or readable. Thoughts?

My original "aliased" form would show up in both the spec and body files, so no matter how someone looked up a function it would see the return type. With an aspect, just the spec shows it...so not as good in that regard.

mosteo commented 5 years ago

Another possibility for the return syntax:

function By_Ref (...) return renames Some_Type;

In the vein of reusing the existing keywords in the spirit of the proposal.

jere-software commented 4 years ago

My first reaction feels weird on this, but I am not opposed. My main goal is to get access types as far from the client of packages as possible, so hopefully the community can come up with a good verbage

Another possibility for the return syntax:

function By_Ref (...) return renames Some_Type;

In the vein of reusing the existing keywords in the spirit of the proposal.

sttaft commented 4 years ago

For what it is worth, using "return aliased T" feels about right to me, as we currently use "aliased" to force pass by reference on formal parameters. Presumably the rules would mimic closely the current rules on returning objects of an anonymous access type, or objects with an access discriminant, to ensure no dangling references. One issue is whether the return object is a variable or a constant. Conceivably you could say it is a variable by default, and you would have to say "return aliased constant T" if you wanted it to be treated as a constant. Not sure that is the right default, but this could provide a more elegant way to get user-defined container indexing than the current rather round-about way using access discriminants.

-Tuck

On Wed, Jan 8, 2020 at 11:43 AM Jere notifications@github.com wrote:

My first reaction feels weird on this, but I am not opposed. My main goal is to get access types as far from the client of packages as possible, so hopefully the community can come up with a good verbage

Another possibility for the return syntax:

function By_Ref (...) return renames Some_Type;

In the vein of reusing the existing keywords in the spirit of the proposal.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/AdaCore/ada-spark-rfcs/pull/27?email_source=notifications&email_token=AANZ4FOPY4E662MBB3K22E3Q4X7DDA5CNFSM4IK2W3F2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEINGHEI#issuecomment-572154769, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANZ4FI7DG3EST22YBPRCKTQ4X7DDANCNFSM4IK2W3FQ .