root/trunk/docsrc/const-faq.dd

Revision 1386, 10.0 kB (checked in by walter, 2 years ago)

bugzilla 3580 Update docs s/invariant/immutable/

Line 
1 Ddoc
2
3 $(D_S const(FAQ),
4
5     $(P D's const system is unique, and so there are a lot of
6     questions about it.
7     )
8
9     $(UL
10
11     $(ITEMR const, Why does D have const?)
12     $(ITEMR principles, What principles drove the D const design?)
13     $(ITEMR transitive-const, What is $(I transitive const)?)
14     $(ITEMR head-const, What is $(I head const)?)
15     $(ITEMR tail-const, What is $(I tail const)?)
16     $(ITEMR logical-const, What is $(I logical const)?)
17     $(ITEMR readonly, Why not use $(I readonly) to mean read only view?)
18     $(ITEMR java-const, Why did Java reject const?)
19     $(ITEMR cpp-const, How does const differ in C++?)
20     $(ITEMR invariant-strings, Why are strings immutable?)
21     $(ITEMR const-parameters, Why aren't function parameters const by default?)
22     $(ITEMR static-members, Are static class members covered by transitive const?)
23     $(ITEMR invariant, What is $(I immutable) good for?)
24     )
25
26 $(ITEM const, Why does D have const?)
27
28     $(P People often express frustration with const and immutable
29     in D 2.0 and wonder if it is worth it.
30     )
31
32     $(OL
33
34     $(LI It makes function interfaces more self-documenting. Without
35     transitive const, for all pointer/reference parameters one must rely on
36     the documentation (which is always missing, out of date, or wrong). Note
37     that without transitivity, C++ const is nearly useless for such
38     self-documentation, which is why C++ programmers tend to rely on
39     convention instead.
40     )
41
42     $(LI It makes for interfaces that can be relied upon, which becomes
43     increasingly important the more people that are involved with the code.
44     In other words, it scales very well. People who are involved with
45     projects with large teams of programmers say that lack of const
46     makes their lives difficult because they cannot rely on the compiler to
47     enforce convention. The larger the team, the worse it gets. Managing
48     APIs is critical to a large project - it's why BASIC doesn't scale (for
49     an extreme example).
50     )
51
52     $(LI Const transitivity makes for some interesting optimization
53     opportunities. The value of this has not been explored or exploited.
54     )
55
56     $(LI Here's the biggie. Points 1..3 are insignificant in comparison. The
57     future of programming will be multicore, multithreaded. Languages that
58     make it easy to program them will supplant languages that don't.
59     Transitive const is key to bringing D into this paradigm. The surge in
60     use of Haskell and Erlang is evidence of this coming trend (the killer
61     feature of those languages is they make it easy to do multiprogramming).
62     C++ cannot be retrofitted to supporting multiprogramming in a manner
63     that makes it accessible. D isn't there yet, but it will be, and
64     transitive const will be absolutely fundamental to making it work.
65     )
66     )
67
68     $(P Of course, for writing single-threaded one man programs of
69     fairly modest size, const is not particularly useful.
70     And in D const can be effectively ignored by just not using it, or
71     by using D 1.0. The only place const is imposed is with the immutable
72     string type.
73     )
74
75 $(ITEM principles, What principles drove the D const design?)
76
77     $(OL
78     $(LI It will be mathematically sound. That means there
79     are no legal escapes from it.)
80     $(LI Any type can be wrapped in a struct and the resulting
81     struct can still exhibit the same const behavior - in other
82     words, no magic behavior for certain types.)
83     $(LI Const behavior will be transitive.)
84     $(LI Const behavior for type T will be equivalent for all types T.)
85     )
86
87 $(ITEM transitive-const, What is $(I transitive const)?)
88
89     $(P Transitive const means that once const is applied to a type,
90     it applies recursively to every sub-component of that type. Hence:
91     )
92
93 ---
94 const(int*)** p;
95 p += 1;   // ok, p is mutable
96 *p += 1;  // ok, *p is mutable
97 **p += 1; // error, **p is const
98 ***p += 1; // error, ***p is const
99 ---
100
101     $(P With transitivity, there is no way to have a
102     $(I const pointer to mutable int).
103     )
104
105     $(P C++ const is not transitive.)
106
107 $(ITEM head-const, What is $(I head const)?)
108
109     $(P Head const is where the const applies only to the component
110     of the type adjacent to the const. For example:
111     )
112
113 ---
114 headconst(int**) p;
115 ---
116     $(P would be read as p being a: $(I const pointer to mutable pointer
117     to mutable int.) D does not have head const (the $(CODE headconst) is
118     there just for illustrative purposes), but C++ const is
119     a head const system.
120     )
121
122 $(ITEM tail-const, What is $(I tail const)?)
123
124     $(P Tail const is the complement of head const - everything reachable
125     from the const type is also const except for the top level. For
126     example:
127     )
128
129 ---
130 tailconst(int**) p;
131 ---
132     $(P would be read as p being a: $(I mutable pointer to const pointer
133     to const int.) Head const combined with tail const yields transitive
134     const.
135     D doesn't have $(CODE tailconst) (the keyword is there just for
136     illustrative purposes) as a distinct type constructor.
137     )
138
139 $(ITEM logical-const, What is $(I logical const)?)
140
141     $(P $(I Logical const) refers to data that appears to be constant
142     to an observer, but is not actually const. An example would be
143     an object that does lazy evaluation:)
144
145 ---
146 struct Foo {
147     mutable int len;
148     mutable bool len_done;
149     const char* str;
150     int length()
151     {   if (!len_done)
152         {   len = strlen(str);
153         len_done = true;
154         }
155     return len;
156     }
157     this(char* str) { this.str = str; }
158 }
159 const Foo f = Foo("hello");
160 bar(f.length);
161 ---
162
163     $(P The example evaluates $(CODE f.len) only if it is needed.
164     $(CODE Foo) is logically const, because to the observer of the object
165     its return values never change after construction.
166     The $(CODE mutable) qualifier says that even if an instance
167     of $(CODE Foo) is const, those fields can still change.
168     While C++ supports the notion of logical const, D does not,
169     and D does not have a $(CODE mutable) qualifier.
170     )
171
172     $(P The problem with logical const is that const is no longer
173     transitive. Not being transitive means there is the potential
174     for threading race conditions, and there is no way to determine
175     if an opaque const type has mutable members or not.
176     )
177
178     $(P Reference:
179     $(LINK2 http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_025.html, mutable: bitwise vs. logical const)
180     )
181
182 $(ITEM readonly, Why not use $(I readonly) to mean read only view?)
183
184     $(P $(I Readonly) has a well established meaning in software to
185     mean ROM, or Read Only Memory that can never be changed.
186     For computers with hardware protection for memory pages, readonly
187     also means that the memory contents cannot be altered.
188     Using readonly in D to mean a read only view of memory that could
189     be altered by another alias or thread runs counter to this.
190     )
191
192 $(ITEM java-const, Why did Java reject const?)
193
194     $(P $(LINK http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070)
195     )
196
197 $(ITEM cpp-const, How does const differ in C++?)
198
199     $(P C++ has a const system that is closer to D's than any other
200     language, but it still has huge differences:)
201
202     $(OL
203     $(LI const is not transitive)
204     $(LI no immutables)
205     $(LI const objects can have mutable members)
206     $(LI const can be legally cast away and the data modified)
207     $(LI $(CODE const T) and $(CODE T) are not always distinct types)
208     )
209
210 $(ITEM invariant-strings, Why are strings immutable?)
211
212     $(P $(LINK2 http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29, Immutable Strings)
213     )
214
215 $(ITEM const-parameters, Why aren't function parameters const by default?)
216
217     $(P Since most (nearly all?) function parameters will not be modified,
218     it would seem to make sense to make them all const by default,
219     and one would have to specifically mark as mutable those that would
220     be changed. The problems with this are:
221     )
222
223     $(OL
224
225     $(LI It would be a huge break from past D practice, and practice
226     in C, C++, Java, C#, etc.)
227     $(LI It would require a new keyword, say $(CODE mutable).)
228     $(LI And worst, it would make declarations inconsistent:
229 ---
230 void foo(int* p) {
231    int* q;
232    ...
233 }
234 ---
235     $(CODE p) points to const, and $(CODE q) points to mutable.
236     This kind of inconsistency leads to all sorts of mistakes.
237     It also makes it very hard to write generic code that deals with
238     types.
239     )
240     )
241
242     $(P Using $(CODE in) can mitigate the ugliness of having to annotate
243     with $(CODE const):)
244 ---
245 void str_replace(in char[] haystack, in char[] needle);
246 ---
247
248 $(ITEM static-members, Are static class members covered by transitive const?)
249
250     $(P A static class member is part of the global state of a program,
251     not part of the state of an object. Thus, a class having a mutable
252     static member does not violate the transitive constness of an object
253     of that class.
254     )
255
256 $(ITEM invariant, What is $(I immutable) good for?)
257
258     $(P Immutable data, once initialized, is never changed.
259     This has many uses:
260     )
261
262     $(UL
263     $(LI Access to immutable data need not be synchronized
264     when multiple threads read it.)
265     $(LI Data races, tearing, sequential consistency, and
266     cache consistency are all non-issues when working with
267     immutable data.)
268     $(LI Pure functions can only accept immutable parameters.)
269     $(LI When doing a $(I deep copy) of a data structure,
270     the immutable portions need not be copied.)
271     $(LI Invariance allows a large chunk of data to be treated
272     as a value type even if it is passed around by reference
273     (strings are the most common case of this).)
274     $(LI Immutable type provides more self-documenting information
275     to the programmer.)
276     $(LI Immutable data can be placed in hardware protected read-only
277     memory, or even in ROMs.)
278     $(LI If immutable data does change, it is a sure sign of a memory
279     corruption bug, and it is possible to automatically check for
280     such data integrity.)
281     $(LI Immutable types provide for many program optimization
282     opportunities.)
283     )
284
285     $(P $(I const) acts as a bridge between the mutable and immutable
286     worlds, so a single function can be used to accept both types
287     of arguments.)
288 )
289
290 Macros:
291     TITLE=const(FAQ)
292     WIKI=constFAQ
293     ITEMR=$(LI $(LINK2 #$1, $+))
294     ITEM=<hr><h3><a name="$1">$+</a></h3>
Note: See TracBrowser for help on using the browser.