You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0000-json-getters.md
+103-16
Original file line number
Diff line number
Diff line change
@@ -10,39 +10,126 @@ Introduce "getters" into the JSON package. Specifically access methods for
10
10
11
11
# Motivation
12
12
13
-
TODO Why are we doing this? What use cases does it support? What is the expected outcome?
13
+
Currently the interaction between the JSON API and the Pony reference
14
+
capability type system makes it difficult to work with JSON documents that need
15
+
to be mutated after they have been created.
16
+
17
+
By introducing getter methods it will be possible to leverage viewpoint
18
+
adaptation to enable mutations when the caller site holds a mutable reference,
19
+
but to enforce immutability when the calling alias is a `val` or `box`.
20
+
21
+
Additionally, a caller with an `iso` reference will be able to perform
22
+
mutations to the document and then recover and `iso` reference afterwards.
14
23
15
24
# Detailed design
16
25
17
-
TODO This is the bulk of the RFC. Explain the design in enough detail for somebody familiar with the language to understand, and for somebody familiar with the compiler to implement. This should get into specifics and corner-cases, and include examples of how the feature is used.
26
+
The implementation consists of using the `apply()` style access to introducing
27
+
three getters, into `JsonDoc`, `JsonObject` and `JsonArray` respectively:
18
28
19
-
# How We Teach This
29
+
- document data access: `fun apply(): this->JsonType! => ...`,
30
+
- object data access: `fun apply(): this->Array[JsonType]! => ...`,
31
+
- array data access: `fun apply(): this->Map[String, JsonType]! => ...`.
32
+
33
+
These access methods can then be used via direct calls or via syntactic sugar
34
+
calls.
20
35
21
-
TODO What names and terminology work best for these concepts and why? How is this idea best presented? As a continuation of existing Pony patterns, or as a wholly new one?
36
+
# How We Teach This
22
37
23
-
Would the acceptance of this proposal mean the Pony guides must be re-organized or altered? Does it change how Pony is taught to new users at any level?
38
+
The examples in the JSON inline documentation can be extended or changed to
39
+
demonstrate the usage of the getter methods.
24
40
25
-
How should this feature be introduced and taught to existing Pony users?
41
+
The access methods, themselves, will be documented.
26
42
27
43
# How We Test This
28
44
29
-
TODO How do we assure that the initial implementation works? How do we assure going forward that the new functionality works after people make changes? Do we need unit tests? Something more sophisticated? What's the scope of testing? Does this change impact the testing of other parts of Pony? Is our standard CI coverage sufficient to test this change? Is manual intervention required?
30
-
31
-
In general this section should be able to serve as acceptance criteria for any implementation of the RFC.
45
+
Unit tests that cover both mutable access and immutable access, as well is the
46
+
recovery of `iso` documents after mutation.
32
47
33
48
# Drawbacks
34
49
35
-
TODO Why should we *not* do this? Things you might want to note:
50
+
This is a purely additive change, so it does not incur in major risk in terms of
51
+
existing code. Additionally, the code complexity is low and should be easy to
52
+
maintain.
53
+
54
+
## Uptake and entrenchment
55
+
56
+
However, if there is uptake following these additions, the approach will likely
57
+
become entrenched, and therefore difficult to revert. Therefore, we need to be
58
+
comfortable with this approach going forward.
36
59
37
-
* Breaks existing code
38
-
* Introduces instability into the compiler and or runtime which will result in bugs we are going to spend time tracking down
39
-
* Maintenance cost of added code
60
+
## Syntactic sugar oddities
61
+
62
+
By relying on the `apply()` syntactic sugar it is possible to write expressions
63
+
that are a little contrived:
64
+
65
+
```pony
66
+
(jdoc_ref() as JsonObject)()("other_stuff") = "hello"
67
+
```
68
+
69
+
which might be more easily read if written as:
70
+
71
+
```pony
72
+
(jdoc_ref() as JsonObject).apply()("other_stuff") = "hello"
73
+
```
40
74
41
75
# Alternatives
42
76
43
-
TODO What other designs have been considered? What is the impact of not doing this?
44
-
None is not an acceptable answer. There is always to option of not implementing the RFC.
77
+
The basic approach of adding "getter" access methods seems quite reasonable.
78
+
However, the issue of method naming is really the point where alternative could
79
+
be considered.
80
+
81
+
## The current recommendation
82
+
83
+
A purely additive change using the `apply()` syntactic sugar for access. This
84
+
allows one to write:
85
+
86
+
```pony
87
+
try
88
+
let obj = (json_doc() as JsonObject)
89
+
obj()("more") = "stuff"
90
+
end
91
+
```
92
+
93
+
## Additionally include `update()`
94
+
95
+
That is, include an `update(value: JsonDoc): this->JsonType! => ...` method to
96
+
allow for setting the underlying `data` field.
97
+
98
+
## Convert the `data` field to private
99
+
100
+
The above recommendation is a non-breaking change. Therefore, the current `data`
101
+
field, which is public has be left as-is. However, it might be better
102
+
standardise on using the access methods and make the data field private. That
103
+
is, rename the field to:
104
+
105
+
-`_data`
106
+
107
+
The drawbacks of this approach are:
108
+
109
+
- it becomes a breaking change for all existing code,
110
+
- it would require the addition of a setter (such as introducing `update(...)`).
111
+
112
+
## Use `data()` as the access method
113
+
114
+
If make the data field private, we can consider using `data` as the access
115
+
method name. In this case we would not provide the syntactic sugar, but we would
116
+
still solve the core problem of data mutation.
117
+
118
+
However, the drawback of this approach is that a separate "setter" may be
119
+
needed.
120
+
121
+
## Dual access with `apply()` and `data()`
122
+
123
+
Given that the syntactic sugar approach can sometime look odd, we could consider
124
+
providing both `apply()` and `data()`. However, the drawbacks of this approach
125
+
are:
126
+
127
+
- it burdens the API user with the choice of calling `data()` or using the sugar
128
+
(or even calling `apply()`,
129
+
- it would still require providing a setter of some form.
130
+
45
131
46
132
# Unresolved questions
47
133
48
-
TODO What parts of the design are still TBD?
134
+
Should a deeper design review be carried out? Otherwise, the alternatives,
135
+
above, should cover the bulk of the potential questions.
0 commit comments