Changeset 0d41e600
- Timestamp:
- Apr 15, 2025, 11:49:08 AM (6 days ago)
- Branches:
- master
- Children:
- 3c1e432, 471613c
- Parents:
- 768d091
- Location:
- doc/theses/mike_brooks_MMath
- Files:
-
- 2 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified doc/theses/mike_brooks_MMath/list.tex ¶
r768d091 r0d41e600 83 83 sets up a diamond inheritance with @dlink@, and declares a list head to have the more-informed type @dlist(..., DIR)@. 84 84 85 The directionality issue also has an advanced corner-case that needs treatment. 86 When working with multiple directions, while calls like @insert_first@ benefit from implicit direction disambiguation, other calls like @insert_after@ still require explicit disambiguation. 87 It happens because the call 88 \begin{cfa} 89 insert_after(r1, r2); 90 \end{cfa} 91 does not have enough information to clarify which of a request's simultaneous list directions is intended. 92 Is @r2@ supposed to be the next-priority request after @r1@, or is @r2@ supposed to join the same-requestor list of @r1@? 93 As such, the \CFA compiler gives an ambiguity error for this call. 94 To let the programmer resolve the ambiguity, the list library provides a hook for applying the \CFA language's scoping and priority rules. 95 It applies as: 96 \begin{cfa} 97 with ( DLINK_VIA(req, req.pri) ) insert_after(r1, r2); 98 \end{cfa} 99 Here, importing (using the @with@ syntax on) the @DLINK_VIA@ result causes one of the list directions to become a more attrictive candidate to \CFA's overload resolution. 100 This boost applies within the scope of the the import, which is a single line in the example just given, but could also be a custom block or an entire function body. 101 102 \noindent 103 \begin{tabular}{ll} 104 \begin{cfa} 105 void f() with ( DLINK_VIA(req, req.pri) ) { 106 ... 107 108 insert_after(r1, r2); 109 110 ... 111 } 112 \end{cfa} 113 & 114 \begin{cfa} 115 void f() { 116 ... 117 with ( DLINK_VIA(req, req.pri) ) { 118 ... 119 } 120 ... 121 } 122 \end{cfa} 123 \end{tabular} 124 125 \noindent 126 By doing in on a larger scope, a user can put code within that acts as if there is only one list direction. 127 This boost is needed only when operating on a list with several directions, using operations that do not take list heads. 128 Otherwise, the sole applicable list direction ``just works.'' 129 85 130 The \CFA library offers a type-system mediated integration with user code. 86 131 The examples presented do not use preprocessor macros. … … 92 137 The \CFA library works in headed and headless modes. TODO: elaborate. 93 138 94 \subsection{Iteration-FOUNDATIONS}95 96 TODO: This section should be moved to a Foundations chapter. The next section stays under Linked List.97 139 98 140 99 141 \subsection{Iteration} 142 143 Many languages offer an iterator interface for collections to implement, and a corresponding for-each loop syntax for consuming the items through implicit interface calls. 144 \CFA does not yet have a general-purpose form of such a feature, though it has a form that addresses some use cases. 145 This section shows why the incumbemt \CFA pattern does not work for linked lists and gives the alternative now offered by the linked-list libary. 146 Chapter 5 [TODO: deal with optimism here] presents a design that satisfies both uses and accommodates even more complex collections. 147 148 The incumbent \CFA extensible loop syntax is: 149 \begin{cfa} 150 for( elem; begin ~ end ) 151 for( elem; end ) 152 \end{cfa} 153 Many derived forms of @begin ~ end@ exist, but they of primaty interest to defining numeric ranges, so they are excluded from the linked-list discussion. 154 This ``two-place for'' syntax abbreviates, respectively: 155 \begin{cfa} 156 for( typeof(end) elem = begin; elem < end; elem += 1 ) 157 for( typeof(end) elem = 0; elem < end; elem += 1 ) 158 \end{cfa} 159 From these calls, letting @E@ be @typeof(end)@, the implied interface is: 160 \begin{itemize} 161 \item 162 case-appropriate construction: one of @void ?{}( E &, typeof(begin) )@, or @void ?{}( E &, zero_t )@, depending on the specific loop form 163 \item 164 comparison, for termination testing: @int ?<?( const E &, const E & )@ 165 \item 166 increment, for ``next item'': @E & ?+=?( E &, one_t )@ 167 \end{itemize} 168 The shortened loop works well for using a numeric range to step through an array: 169 \begin{cfa} 170 for ( i; n ) total += a[i]; 171 \end{cfa} 172 173 When used for array-stepping, the loop is acting like JavaScript's @for...in@ construct, 174 \begin{cfa} 175 for ( i in a ) total += a[i]; 176 \end{cfa} 177 albeit with different mechanisms for expressing the array's length. 178 But the similarity is that the loop binds the declared identifier (@i@) to the array's \emph{indeces}, not its contained values. 179 A linked list has only values, no keys. 180 So, to seek iteration of a linked list via the existing loop syntax is to ask whether this syntax can also do double-duty for iterating values. 181 That is, to be an analog of JavaScript's @for..of@ syntax: 182 \begin{cfa} 183 for ( e of a ) total += e; 184 \end{cfa} 185 186 The \CFA team will likely implement an extension of this functionality that moves the @~@ syntax from being part of the loop, to being a first-class operator (with associated multi-pace operators for the elided derived forms). 187 With this change, both @begin ~ end@ and @end@ (in context of the latter ``two-place for'' expression) parse as \emph{ranges}, and the loop syntax becomes, simply: 188 \begin{cfa} 189 for( elem; rangeExpr ) 190 \end{cfa} 191 The expansion and underlying API are under discussion. 192 TODO: explain pivot from ``is at done?'' to ``has more?'' 193 Advantages of this change include being able to pass ranges to functions, for example, projecting a numerically regular subsequence of array entries, and being able to use the loop syntax to cover more collection types, such as looping over the keys of a hashtable. 194 195 196 197 198 When iteratig an empty list, the question, ``Is there a further element?'' needs to be posed once, receiving the answer, ``no.'' 199 When iterating an $n$-item list, the same question gets $n$ ``yes'' answers (one for each element), plus one ``no'' answer, once there are no more elements; the question is posed $n+1$ times. 200 201 When iteratig an empty list, the question, ``What is the value of the current element?'' is never posed, nor is the command, ``Move to the next element,'' issued. When iterating an $n$-item list, each happens $n$ times. 202 203 So, asking about the existence of an element happens once more than retrieving an element's value and advancing the position. 204 205 Many iteration APIs deal with this fact by splitting these steps across different functions, and relying on the user's knowledge of iterator state to know when to call each. In Java, the function @hasNext@ should be called $n+1$ times and @next@ should be called $n$ times (doing the double duty of advancing the iteration and returning a value). In \CC, the jobs are split among the three actions, @it != end@, @it++@ and @*it@, the latter two being called one time more than the first. 206 207 TODO: deal with simultaneous axes: @DLINK_VIA@ just works 208 209 TODO: deal with spontaneous simultaneity, like a single-axis req, put into an array: which ``axis'' is @&req++@ navigating: array-adjacency vs link dereference. It should sick according to how you got it in the first place: navigating dlist(req, req.pri) vs navigating array(req, 42). (prob. future work) 210 211 \section{Implementation} 212 213 \subsection{Links} 214 215 \VRef[Figure]{fig:lst-impl-links} continues the running @req@ example, now showing the \CFA list library's internal representation. 216 217 \begin{figure} 218 \centering 219 \includegraphics{lst-impl-links.pdf} 220 \caption{ 221 \CFA list library representations for the cases under discussion. 222 } 223 \label{fig:lst-impl-links} 224 \end{figure} 225 226 The @dlink@ structure contains exactly two pointers: @next@ and @prev@. This @dlink@ content is opaque to the user. 227 228 Even though the user-facing list model is ordered (linear), the CFA library implements all listing as circular. 229 This choice helps achieve uniform end treatment and TODO finish summarizing benefit. 230 231 A link pointer targets a neighbouring @dlink@ structure, rather than a neighbouring @req@. 232 (Recall, the running example has the user putting a @dlink@ within a @req@.) 233 234 Link pointers are tagged according to whether the link is user-visible. 235 Links among user-requested neighbours are left natural, with the tag bit not set. 236 System-added links, which produce the circular implementation, have the tag bit set. 237 Iteration reports ``has more elements'' when crossing natural links, and ``no more elements'' upon reaching a tagged link. 238 239 In a headed list, the list head (@dlist(req)@) acts as an extra element in the implementation-level circularly-linked list. 240 The content of a @dlist@ is a (private) @dlink@, with the @next@ pointer purposed for the first element, and the @prev@ pointer purposed for the last element. 241 Since the head wraps a @dlink@, since a @req@ does too, and since a link-pointer targets a @dlink@, the resulting cycle is among @dlink@ strucures, situated inside of other things. 242 The tags on the links say what the wrapper is: untagged (user link) means the targeted @dlink@ is within a @req@, while tagged (system link) means the targeted @dlink@ is within a list head. 243 244 In a headless list, the cicular backing list is only among @dlink@s within @req@s. The tags are set on the links that a user cannot navigate. 245 246 No distinction is made between an unlisted item under a headed model and a singleton list under a headless model. Both are represented as an item referring to itself, with both tags set. 247 100 248 101 249
Note: See TracChangeset
for help on using the changeset viewer.