Restricting field access in records?

31 views
Skip to first unread message

Johannes Qvarford

unread,
Sep 15, 2012, 12:11:06 PM9/15/12
to clay-l...@googlegroups.com
Hi, I'm new to Clay and I'm currently experimenting with variants.

I have this code:

//main.clay
import Rectangle.*;

main()
{
    var r1 = Rectangle(5,4);
    var r2 = Rectangle(20,12);
    println("width: ", r1.width);
    getInfo(Shape(r1));
    getInfo(Shape(r2));
}
//

//Shape.clay
variant Shape();

define area;
define length;
define width;
define name;

getInfo(s:Shape)
{
    println("Shape ", name(*s),
    " with length ", length(*s),
    " and width ", width(*s));
}
//

//Rectangle.clay
public import Shape.*;

record Rectangle(length:Int, width:Int);

overload area(r:Rectangle) = r.width * r.length;
overload length(r:Rectangle) = r.length;
overload width(r:Rectangle) = r.width;
overload name(r:Rectangle) = #"Rectangle";

instance Shape(Rectangle);
//

Now, i want this line:
/*main.clay*/ println("width: ", r1.width);
...to result in a compilation error.

Basically, I want to be able store a Rectangle on the stack, while still preventing field access, like in c++.
How can I do that in clay?

I tried to make Rectangles members private by making it's declaration private, but that just prevented the constructor
from being called explicitly outside of Rectangle.clay.

Joe Groff

unread,
Sep 15, 2012, 12:46:15 PM9/15/12
to clay-l...@googlegroups.com
On Sat, Sep 15, 2012 at 9:11 AM, Johannes Qvarford
<johannes...@gmail.com> wrote:
> Basically, I want to be able store a Rectangle on the stack, while still
> preventing field access, like in c++.
> How can I do that in clay?
>
> I tried to make Rectangles members private by making it's declaration
> private, but that just prevented the constructor
> from being called explicitly outside of Rectangle.clay.

This is currently not possible. Field accesses such as `a.b` work by
desugaring into calls to the prelude function `fieldRef(a, #"b")`. The
field name is just a static string, and individual overloads cannot
currently be made public or private, only the symbol `fieldRef` as a
whole. The easiest thing to do is to mark private fields by naming
convention, such as `_length`.

-Joe

Joe Groff

unread,
Sep 15, 2012, 1:25:20 PM9/15/12
to Johannes Qvarford, Clay Programming Language
On Sat, Sep 15, 2012 at 10:18 AM, Johannes Qvarford
<johannes...@gmail.com> wrote:
> Bummer.
> Thanks for the help, though!

If you don't like the naming convention approach, here's something you
can do. Make a variant for the public type, with the private type as
its only member:

```
variant Rectangle (RectangleImpl);
private record RectangleImpl (...);
```

External code will not be able to reference the RectangleImpl type and
thus won't be able to see its fields. Within the module,
`variantAs(RectangleImpl, rect)` will give you a reference to the
RectangleImpl. This has the disadvantages of an extra word of space
overhead for the variant tag, and some boilerplate to access the
private members in the implementation. Eventually we hope to have a
strong typedef feature, like Haskell's newtypes, which will allow this
technique without the overhead of a variant.

-Joe
Reply all
Reply to author
Forward
0 new messages