My original ideas for supporting optional values were based around the concept of what I call a "null-checked block" - an 'if' statement or similar structure that would naturally guarantee that a null pointer access would never happen because 1) only optional values could be 'null', and 2) you would have to check an optional value before you could use it. For example, one possible syntax would be:
local i = st.locate( '.' ) : Integer? if (i) println "Dot found at $." (i) else println "No dot found." endIf
I proceeded along this path for a while - adding null-checked block support into the compiler and converting some string methods to use it - before realizing that null-checked blocks could be significantly more cumbersome than using conventional syntax. Here are two examples.
# Example 1A - original syntax local i = st.locate( '\n' ) while (i != -1) println st.substring( 0, i-1 ) st = st.substring( i+1 ) i = st.locate( '\n' ) endWhile # Example 1B - null-checked block syntax # Not too bad, just a little awkward local i = st.locate( '\n' ) while (i) if (i) println st.substring( 0, i-1 ) st = st.substring( i+1 ) endIf i = st.locate( '\n' ) endWhile # Example 2A - original syntax local i1 = st.locate( '/' ) local i2 = st.locate( '\\' ) if (i1 == -1 or (i2 != -1 and i2 < i1)) i1 = i2 if (i1) println "First slash is at $." (i1) # Example 2B - null-checked block syntax, attempt 1 # Already getting out of control local i1 = st.locate( '/' ) local i2 = st.locate( '\\' ) if (not i1) i1 = i2 else if (i2) if (i2 < i1) i1 = i2 # DOH! # 'i1' is already the checked value so I'm prevented # from assigning to the optional value. Also note that # an if-check ("if (i2)") can't have any other # logic in it (like "i2 < i1") since it's converted # to use a separate mechanism internally. # Example 2C - null-checked block syntax, attempt 2 # Works but pretty heinous! local i1 = st.locate( '/' ) local i2 = st.locate( '\\' ) local first_i : Integer? if (i1) if (i2) if (i2 < i1) first_i = i2 else first_i = i1 else first_i = i1 endIf else first_i = i2 endIf if (first_i) println "First slash is at $." (first_i)
That last bit of convoluted logic was the deal-breaker. I decided I wanted the standard approach to be something much simpler, even if it didn't protect the programmer 100% against the Null Pointer Errors. I removed the null-checked blocks for now (maybe forever) and am now using the mechanism of
x.value to null-check and use optional value
x. I can still generate Swift code from that down the road (which was kind of the whole point) using Swift's forced unwrapping. My example 2A from above becomes:
# Example 2D - Rogue optional value syntax # Note: writing "if (i1)" is equivalent to "if (i1.exists)". local i1 = st.locate( '/' ) local i2 = st.locate( '\\' ) if (not i1 or (i2 and i2.value < i1.value)) i1 = i2 if (i1) println "First slash is at $." (i1.value)