Re: tupleof seems to break encapsulation

2020-09-06 Thread Jacob Carlborg via Digitalmars-d-learn

On 2020-09-05 07:14, 60rntogo wrote:

I wouldn't dispute that it is useful, but that's besides the point. If I 
declare something private, it's usually because I want to preserve 
certain invariants and I want the compiler to provide a guarantee that I 
don't accidentally violate them. As it stands, the compiler cannot 
guarantee that if I use tupleof.


I don't really have an issue with read-only access to private fields 
(but arguments could be made against it) and then serialization would 
still be possible. However, if my struct is supposed to maintain 
invariants, then any attempt at deserialization that naively reads from 
a tuple without establishing these invariants should fail to compile.


I wouldn't mind if `tupleof` was not allowed in @safe code, which Walter 
mentions in one of the linked issues. Although it would be a breaking 
change.


Secondly, my serialization library, Orange [1], uses `tupleof` to read 
and write fields. It also supports before and after hooks for both 
serialization and deserialization. This allows to implement any 
invariants that are not covered by just restoring the fields. It also 
supports implementing a method that allows to take full control of the 
(de)serialization of a specific type.


Thirdly, you can do the same thing with pointer arithmetic. Although 
this is not allowed if @safe code.


[1] https://github.com/jacob-carlborg/orange

--
/Jacob Carlborg


Re: tupleof seems to break encapsulation

2020-09-04 Thread 60rntogo via Digitalmars-d-learn

On Friday, 4 September 2020 at 17:36:00 UTC, Jacob Carlborg wrote:
It's useful for serialization and, as you can see in your 
example, for debugging as well. `writeln` will print the values 
of the fields in a struct, even for private fields.


I wouldn't dispute that it is useful, but that's besides the 
point. If I declare something private, it's usually because I 
want to preserve certain invariants and I want the compiler to 
provide a guarantee that I don't accidentally violate them. As it 
stands, the compiler cannot guarantee that if I use tupleof.


I don't really have an issue with read-only access to private 
fields (but arguments could be made against it) and then 
serialization would still be possible. However, if my struct is 
supposed to maintain invariants, then any attempt at 
deserialization that naively reads from a tuple without 
establishing these invariants should fail to compile.


Re: tupleof seems to break encapsulation

2020-09-04 Thread Paul Backus via Digitalmars-d-learn

On Friday, 4 September 2020 at 18:23:09 UTC, H. S. Teoh wrote:
On Fri, Sep 04, 2020 at 07:36:00PM +0200, Jacob Carlborg via 
Digitalmars-d-learn wrote: [...]
It's useful for serialization and, as you can see in your 
example, for debugging as well. `writeln` will print the 
values of the fields in a struct, even for private fields.


It's certainly useful, but violates private.  I'd propose 
restricting it to -debug or at the very least @system, so that 
normal @safe code will behave as expected.



T


Previously:

https://issues.dlang.org/show_bug.cgi?id=19326
https://issues.dlang.org/show_bug.cgi?id=20941


Re: tupleof seems to break encapsulation

2020-09-04 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Sep 04, 2020 at 07:36:00PM +0200, Jacob Carlborg via 
Digitalmars-d-learn wrote:
[...]
> It's useful for serialization and, as you can see in your example, for
> debugging as well. `writeln` will print the values of the fields in a
> struct, even for private fields.

It's certainly useful, but violates private.  I'd propose restricting it
to -debug or at the very least @system, so that normal @safe code will
behave as expected.


T

-- 
It's amazing how careful choice of punctuation can leave you hanging:


Re: tupleof seems to break encapsulation

2020-09-04 Thread Jacob Carlborg via Digitalmars-d-learn

On 2020-09-04 12:16, 60rntogo wrote:

Consider the following code.

foo.d
---
module foo;

struct Foo
{
   private int i;
}
---

main.d
---
void main()
{
   import std.stdio;
   import foo;

   auto x = Foo();
   writeln(x);
   // ++x.i;
   ++x.tupleof[0];
   writeln(x);
}
---

As expected, the commented line does not compile. If I uncomment it, I 
get the error "no property i for type foo.Foo". However, the rest of the 
code compiles just fine and outputs:

---
Foo(0)
Foo(1)
---

This appears to defeat the purpose of declaring i private. What am I 
missing?


It's useful for serialization and, as you can see in your example, for 
debugging as well. `writeln` will print the values of the fields in a 
struct, even for private fields.


--
/Jacob Carlborg


Re: tupleof seems to break encapsulation

2020-09-04 Thread Simen Kjærås via Digitalmars-d-learn

On Friday, 4 September 2020 at 10:16:47 UTC, 60rntogo wrote:

Consider the following code.

foo.d
---
module foo;

struct Foo
{
  private int i;
}
---

main.d
---
void main()
{
  import std.stdio;
  import foo;

  auto x = Foo();
  writeln(x);
  // ++x.i;
  ++x.tupleof[0];
  writeln(x);
}
---

As expected, the commented line does not compile. If I 
uncomment it, I get the error "no property i for type foo.Foo". 
However, the rest of the code compiles just fine and outputs:

---
Foo(0)
Foo(1)
---

This appears to defeat the purpose of declaring i private. What 
am I missing?


It's a known issue: https://issues.dlang.org/show_bug.cgi?id=19326

There are some very good reasons to allow some access to private 
fields, though it should be more limited than is currently the 
case.


--
  Simen


tupleof seems to break encapsulation

2020-09-04 Thread 60rntogo via Digitalmars-d-learn

Consider the following code.

foo.d
---
module foo;

struct Foo
{
  private int i;
}
---

main.d
---
void main()
{
  import std.stdio;
  import foo;

  auto x = Foo();
  writeln(x);
  // ++x.i;
  ++x.tupleof[0];
  writeln(x);
}
---

As expected, the commented line does not compile. If I uncomment 
it, I get the error "no property i for type foo.Foo". However, 
the rest of the code compiles just fine and outputs:

---
Foo(0)
Foo(1)
---

This appears to defeat the purpose of declaring i private. What 
am I missing?