<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">(Warning: rambling stream-of-conscious mode while slightly tired)</div><div class=""><br class=""></div><div class="">The names of new keywords and identifiers are subject to bike-shedding.</div><div class=""><br class=""></div><div class="">1. Set-up Protocols</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">protocol&nbsp;HardRawRepresentable:&nbsp;RawRepresentable&nbsp;{</font></div><div class=""><font face="Monaco" class="">&nbsp; &nbsp;&nbsp;init(rawValue:&nbsp;RawValue)</font></div><div class=""><font face="Monaco" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Just like RawRepresentable, but the initializer has to be non-failable (“init?” and “init!” are no longer options).</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">protocol&nbsp;RawProcessable:&nbsp;RawRepresentable&nbsp;{</font></div><div class=""><font face="Monaco" class="">&nbsp; &nbsp;&nbsp;mutating&nbsp;func&nbsp;withMutableRawValue&lt;R&gt;(_&nbsp;body: (inout&nbsp;RawValue)&nbsp;throws&nbsp;-&gt;&nbsp;R&nbsp;)&nbsp;rethrows&nbsp;-&gt;&nbsp;R</font></div><div class=""><font face="Monaco" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Maybe someone will find a use for this outside of type-copies.</div><div class=""><br class=""></div><div class="">2. Type-copy Type Syntax</div><div class=""><br class=""></div><div class="">A “typecopy” puns another value type, either nominal (structures, enumerations, or other type-copies) or structural (tuples, and fixed-size arrays if added). I guess it’d be implemented like a structure with a single instance-level stored property or an enumeration without indirect and/or associated values. Unlike a type alias, a type-copy is considered distinct from its underlying type and conversions have to be explicit casts. It has no operations by default besides copying (which every type has); adaptations of the underlying type’s interface have to be explicitly copied, and can be selective.</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">typecopy NewType: SPECIAL-ATTRIBUTES UnderlyingType, DesiredProtocols {</font></div><div class=""><font face="Monaco" class="">&nbsp; &nbsp; // Anything other nominal types have, except enumeration cases and instance-level stored properties.</font></div><div class=""><font face="Monaco" class="">&nbsp; &nbsp; // Also have new syntax to copy parts of the underlying type’s interface.</font></div><div class=""><font face="Monaco" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">All type-copies conform to RawProcessible; the particulars depend on the special attributes (which are conditional keywords).</div><div class=""><br class=""></div><div class="">The initializer that satisfies RawRepresentable is the type’s designated initializer. It cannot be defined by the user; only secretly by the system; it’s an error to introduce one anyway in the primary definition block, an extension, or a default implementation from an added protocol. Any user-declared initializer that doesn’t forward to another user-declared initializer must forward to the designated initializer.</div><div class=""><br class=""></div><div class="">2a. No Special Attributes</div><div class=""><br class=""></div><div class="">The type must define a method called</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">static func #map(rawValue: RawValue) -&gt; RawValue?</font></div></blockquote><div class=""><br class=""></div><div class="">I’m using “#map” as the name so we don’t take out any more identifiers from the user. (The existing ones, “self,” “init,” “super,” and “Self,” were already done by Objective-C.) The function must be pure relative to the input; it can call non-impurities, like “print,” but the return value must depend only on the argument and not any global state. The user cannot call this function, only the system (but it can be implemented with regular, accessible functions you do write); let’s call this accessibility “reallyprivate". The designated initializer is in the “init?” form and calls this special method for the initial state.</div><div class=""><br class=""></div><div class="">The underlying state is accessed with this stored property:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">pp reallyprivate(set) var rawValue: RawValue</font></div></blockquote><div class=""><br class=""></div><div class="">where “pp” is the type’s accessibility level.</div><div class=""><br class=""></div><div class="">The implementation of “withMutableRawValue” copies “rawValue” to a mutable copy, calls the closure passing that copy, then assigns “Self(rawValue: newCopy)!” to self, causing a runtime error if the initialization part fails.</div><div class=""><br class=""></div><div class="">2b. The “injective” Attribute</div><div class=""><br class=""></div><div class="">This means that the mapping function must be a total function, and not partial:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">static func #map(rawValue: RawValue) -&gt; RawValue</font></div></blockquote><div class=""><br class=""></div><div class="">Every legal state of RawValue is usable in the new type. (It may not be stored in the new type; the mapping function can be surjective.) These type-copies also conform to HardRawRepresentable.</div><div class=""><br class=""></div><div class="">The main external effect of this attribute is that downcasts from the underlying type to the new type use unconditional-“as”. (Downcasts and cross-casts from a type that shares the same implementation type also use unconditional-as if all the downcast phase links also use unconditional-as.)</div><div class=""><br class=""></div><div class="">2c. The “selfIdeal” Attribute</div><div class=""><br class=""></div><div class="">This means that all approved input states map to themselves in the storage state, this changes the required secret method to:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Monaco" class="">static func #approve(rawValue: RawValue) -&gt; Bool</font></div></blockquote><div class=""><br class=""></div><div class="">It effectively acts like case [2a] where “#map” calls “#approve” and returns either the input for TRUE or NIL for FALSE.</div><div class=""><br class=""></div><div class="">The main external effect of this attribute is that downcasts (and the downcast phase of cross-casts) can be trivially done with direct type punning, assuming all the “#approve” calls AND to TRUE, instead of possibly longer “#map” calls.</div><div class=""><br class=""></div><div class="">2d. Using “injective” and “selfIdeal” together</div><div class=""><br class=""></div><div class="">This combination means every input state is accepted, and map to themselves; this is exactly a “strong typedef”. Such types conform to HardRawRepresentable. There is no special method required; the value is just copied in without wasting time calling the bijective identity function. And the “rawValue” property has its “set” just as public as its “get”. (Technically, you can change “rawValue” by setting it directly or calling “withMutableRawValue”.)</div><div class=""><br class=""></div><div class="">3. Why would I want this?</div><div class=""><br class=""></div><div class="">The original inspiration was my first fixed-size array ideas have a simple structural version and a complex nominal version. Then I thought it would be better to keep arrays simple and move the nominal stuff to a generalized concept of augmentation. I also read about the C++ guys trying to add this idea in.</div><div class=""><br class=""></div><div class="">(An inspiration was reading that C++ requires std::complex to have the same layout as T[2] and allow reinterpret-casts between them, for reading in a raw array of numbers and converting them easily to complex numbers. I was thinking Swift-y of reading in a fixed-size array of ten Double (i.e. [10; Double]), reshaping it to [5; [2; Double]], then map with pun-cast to [5; Complex&lt;Double&gt;]. Here, Complex&lt;T&gt; would be a type-copy of [2; T].)</div><div class=""><br class=""></div><div class="">I got additional inspiration by reading "Quotient Types for Programmers” at &lt;<a href="http://www.hedonisticlearning.com/posts/quotient-types-for-programmers.html" class="">http://www.hedonisticlearning.com/posts/quotient-types-for-programmers.html</a>&gt;. Type-copies can be used for subset types and quotient types (and weird combo subsetted quotient types).</div><div class=""><br class=""></div><div class="">This past autumn, Apple’s latest operating systems’ APIs changed their String-ly typed values for its Views, Notification Centers, and such to use manual versions of this idea. Maybe they could change them to this.</div><div class=""><br class=""></div><div class="">4. Detection</div><div class=""><br class=""></div><div class="">How would I know if a given type is a type-copy? The protocols generally can be used for regular work, so testing them won’t help. (That was a change from an earlier idea.) I realized that maybe we can move them to “Mirror”. Add a “`typecopy`” case to “Mirror.DisplayStyle”. Add an “underlyingTypeMirror” property like the super-class one; it would be NIL if the target type isn’t actually a type-copy. Maybe add a global “implementationType(of:)” function that returns the type-copy’s implementation type (The underlying type can already be found with “RawValue”.); should calling this on a non-typecopy return NIL or itself?</div><div class=""><br class=""></div><div class="">Maybe the actual printing could be like: “MyType punning(“ + Mirror of self.rawValue + “)”.</div><div class=""><br class=""></div><div class="">I guess you could check for HardRawRepresentable to suspect a type is a injective type-copy, but there’s no way to test for self-ideal type-copies. Would that be a problem? Could it be fixed (without a lot of extra compiler magic)?</div><div class=""><br class=""></div><div class="">5. Trampolines</div><div class=""><br class=""></div><div class="">I don’t have any new ideas on how to declare a type-copy is reusing an interface from its underlying type. However, the “withMutableRawValue” method now provides a way for copied methods (manually or using “publish” for automatically) to actually work.</div><br class=""><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">—&nbsp;</div><div class="">Daryle Walker<br class="">Mac, Internet, and Video Game Junkie<br class="">darylew AT mac DOT com&nbsp;</div></div>
</div>
<br class=""></body></html>