Thursday, May 4, 2017

Swift Initializers Delegating to Superclass Initializers

I was reading the swift 3.0 language specification and came across the situation defining how superclass initializers (constructors) must be invoked from subclass initializers:

“A designated initializer for that class confirms that all stored properties introduced by that class have a value. The memory for these stored properties is now initialized.The designated initializer hands off to a superclass initializer to perform the same task for its own stored properties.”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 3.0.1).” iBooks. https://itun.es/us/jEUH0.l
Initially, I thought it was odd that the subclass initialized itself, then the superclass was allowed to do so.  It seems that the superclass should go first since there is no connection from the super to the sub, since it was defined independently.  Consider this example though:

class sup
{
init()
{
callMe();
}
func callMe()
{
print("0");
}
}

class sub : sup
{
var n: Int;
override init()
{
n = 1;
super.init();
}
override func callMe()
{
print("\(n)");
}
}

What I forgot about is that the superclass initializer, once it has initialized all of it's properties, is allowed to call methods which could be overridden by the subclass.  If the subclass tries to call an inherited method, the compiler disallows that:

class sub : sup
{
var n: Int;
override init()
{
n = 1;
callMe();
super.init();
}
override func callMe()
{
print("\(n)");
}
}

Playground execution failed: error: SwiftInits.playground:93:3: error: use of 'self' in method call 'callMe' before super.init initializes self
callMe();

So, this is the order:

  1. Subclass initializer is called
  2. Subclass properties are all set
  3. Superclass Initializer is called.
  4. Instance methods may be called on subclass.
In the case where a class is being constructed without an explicit superclass, the same applies without step (3).  In Java step 3 is always the Object constructor so the process is the same (implicit call versus explicit call).

Java requires that the superclass constructor call must be the first line of any constructor body, and is implicitly done if not explicitly called.  Here is a similar example in Java:


class sp {
 sp()
 {
  int i = callMe(); }

 int callMe()
 {
  return 0; }
}

class sb extends sp
{
 private int n; sb()
 {
  super();  n = 1;  int i = callMe(); }

 int callMe()
 {
  return n; }

}

The way Java handles this situation is to restrict the superclass constructor from calling subclass methods.  The call to callMe in the superclass constructor actually calls the superclass version, not the subclass version.  I think the swift approach is simpler.

So, thinking about it in more detail, it makes sense.

Tuesday, November 22, 2016

When They is appropriate. ?

“If an owner participates in the first set, they can make an election, rather than being forced to either participate or relinquish their interests,” Johnny said. “It also protects the rights of small producers by giving them unprecedented safeguards.”

I suppose there is no point anymore in getting upset about how the pronouns 'them', 'they', 'their' and 'theirs' have been shoehorned into the singular neuter tense as well as plural neuter.  Historically, those pronouns have always been reserved for the plural case, but since English only contains 'it' as singular neuter, and English speakers do not like being called 'it', we are stuck with resorting to 'them', 'they' and 'their' when we don't want to say 'he' or 'she' without a definite male or female subject.  This can be done without borrowing, of course,  with the ubiquitous but disruptive he/she (she/he).  In most other cases, though, a rewrite is needed in order to convey the idea naturally.  The first sentence above, for example, can be repaired by making everything agree:

“If owners participate in the first set, they can make an election, rather than being forced to either participate or relinquish their interests.”

Now all verbs and subjects agree.  Why did the original writer not do this?  I do not know.  Maybe because of laziness, or because an editor caught the phrases "he can make an election", and "relinquish his interests" and changed them to "they can make an election", and "relinquish their interests", without considering the entire sentence. The second sentence, for whatever reason, is consistent - probably by accident since they were both written by the same author in the same paragraph.

At any rate, the handwriting seems to be on the wall.  Over the next 50 years or so, we will have changed pronoun behaviors:

  • I am
  • you are
  • he/she/it/they is
  • we are
  • you are
  • they are
I find this grotesque and unnecessary, especially since it is driven by political correctness, but that is where our language appears to be going.  Furthermore, those who safeguard the language - writers - seem to be driving the change.

:|

A Pragmatic View of Looping Constructs in Swift 3.0

As most developers who use Swift are probably aware, the traditional 'C-Style' for-loop has been deprecated - and outright disdained - in version 3.0 of the language.  A prototypical example follows:

Ex 1:
for (int i = 0; i < 100; i++)
{
// Whatever meaningful thing needs to be done 100 times

}

In Swift 2.x, this syntax is discouraged, but in Swift 3.0 it is removed altogether.  Now, in the Swift language manual, Apple explains how this can be accomplished in modern syntax:

Ex 2a - exclusive end index (does not include 100):
for i in 0 ..< 100
{
print(i);

}

Ex 2b - inclusive end index (includes 100):
for i in 0 ... 100
{
print(i);

}

That about does it for our trivial example.  Almost every real-world usage is more complex than this so I wanted to delve into those scenarios for the sake of other developers (and myself once I have forgotten).  First off, there is the incrementer expression ('i++' in Example 1).  In Java, I often write an incrementer other than i++:

Ex 3:
for (int i = 0; i < 100; i += 2)
{
// Whatever meaningful thing needs to be done 50 times

}

There is a straightforward answer for this:  The where clause:

Ex 4a - exlcusive end index:
for i in ..< 100 where i % 2 == 0
{
print(i);
}

Ex 4b - inclusive end index:
for i in ... 100 where i % 2 == 0
{
print(i);
}

The downside of the where clause is that the runtime still counts all the values that don't match the where clause.  I.E., in the loop in Ex 4 the runtime follows this process:

0:  Initialize i to 0.
1:  Evaluate where clause.  If False skip to step 3:
2:  print i (Loop body)
3:  Increment i by 1.
4:  Is i < 100?  If so go to 1:

So, if your loop skips a lot of steps, or in other words uses a large increment, then this would waste a lot of cycles.  But, take heart, there is an answer for this as well:  stride.

Ex 6a - exclusive end index:
for i in stride(from: 0, to: 100, by: 2)
{
print(i);
}

Ex 6b - inclusive end index:
for i in stride(from: 0, through: 100, by: 2)
{
print(i);
}

The stride function actually returns a struct that serves as an iterator, so there is likely no allocation of memory since this can easily be accomplished in 1 variable.  However, what about the case where you need to access not only the current value of the loop, but also the index within the loop itself?  E.G., the loop in Ex 6a might have an i value of 2, but the loop index is 1.  This is accomplished using the enumerated function:

Ex 7:
for (index, j) in stride(from: 0, to: 100, by: 2).enumerated()
{
print("\(index): \(j)");
}

The enumerated function returns an iterable set of tuples, and according to the names you provide will contain the loop index as the first variable name and the array value in the second name.  In other words, the declaration in Ex 7 might as well be (Laurel, Hardy) as (index, j).  In that case, Laurel would be my index and Hardy would contain the value.  The order matters, not the labels.

In order to use enumerated, you have to be working with an object of some sort, either a Strideable as in Ex 7, or else some other appropriate type such as an array, as in Ex 8, but it can't be a plain numeric range:

Ex 8:
let arr: [Int] = [0, 2, 4, 6, 8];

for (index, j) in arr.enumerated()
{
print("\(index): \(j)");
}

Reverse loops are something I have really not ever had much need of (reverse counting loops).  For reverse counting, I usually use an upward counting loop with a calculation for the downward counting value.  Nonetheless, these can be accomplished in many of the same ways except that it always requires a more complex interaction over the traditional loop:

Ex 9 - simple reverse iteration:
for i in (0 ..< 100).reversed()
{
print(i);
}

Ex 10 - simple reverse iteration with where:
for i in (0 ..< 100).reversed() where i % 2 == 0
{
print(i);
}

Ex 11 - simple reverse iteration with index:
for (index, i) in (0 ..< 100).reversed().enumerated()
{
print(i);
}

Ex 12 - reverse iteration with stride:
for i in stride(from: 0, to: 100, by: 1).reversed()
{
print(i);
}

Ex 13 - reverse iteration with stride and index:
for (index, i) in stride(from: 0, to: 100, by: 1).reversed().enumerated()
{
print(i);
}

Ex 14 - reverse iteration with stride and a negative increment.  May not be 'proper', but it works:
for i in stride(from: 100, to: 0, by: -1)
{
print(i);
}

"Wait", you say, "What about the case where I have to loop with . . . <blah> <blah> <blah> <some special circumstance>???!?"  There is always some special circumstance which can't be accounted for in the language itself without making everything too complicated.  The fallback answer is the trusty while loop:

Ex 15 - loop starting with my Aunts' age, skip 17039 days until you reach my julian birth date
let julianBirthday = 2440131;
let myAuntsAge = 31;
let unusualInterval = 17039;

var loopIndex = 0;
var counter = myAuntsAge;

while(counter < julianBirthday)
{
print("\(loopIndex): \(counter)");
counter += unusualInterval;
loopIndex += 1;
}

Ex 15, besides being completely useless, demonstrates that the basic while loop is much more tedious to build but contains enough to handle just about any situation.  It is also not a very good example, because it can be written using the simplified versions:

Ex 16 - our loop was really not that special:
for (loopIndex, counter) in stride(from: myAuntsAge, to: julianBirthday, by: unusualInterval).enumerated()
{
print("\(loopIndex): \(counter)");
}

Wednesday, February 24, 2016

Swift asserttions

I just ran across this today.  It's pretty cool - assertions in swift can be implemented using a closure shorthand which runs efficiently.

Saturday, November 28, 2015

(Im)Proper way to end an iOS app . . .

I am very new to Swift and iOS programming in general, and I had a situation where I wanted to throw an exception to fail an app in an unacceptable situation, and all I knew to do was to call exit(1) in plain old C-fashion.  I put that in my code like on the first day, and I forgot about it.  Since then I have had a lot of bizarre problems with XCode like not running my tests and just logging weird errors like "Failed to bootstrap" and other things.  I finally figured out that was what was causing the errors, and instead I could use:


    fatalError(@autoclosure message: () -> String = default, file: StaticString = default, line: UInt = default)

E.G.

   fatalError("You did something dumb.");

and it accomplishes the same thing (tells me I have done something stupid), but now the debugger stops on that line of code so I remember exactly what I have done.

exit(int), don't use it.

By the way, this is something that only a developer could do, clearly this would not be the way to handle an unexpected user condition.

Tuesday, November 24, 2015

Preach it, brother.

I came across this post today.


I especially like this:  “There is a fundamental difference between the few developers that will become highly skilled and all the other copy and paste developers. The former know they lack knowledge and take the time to grow it. The latter never bother, they go on with what little they know, trying to hack together something and calling it a day.”

Life can be frustrating as a dig-in-and-find-out-how-it-works developer, but I have always admired someone who will dig into something, endure the frustration and "What were they thinking???!?" moments, and come out on the other side with an actual understanding of how something works.

Wednesday, November 4, 2015

Swift Protocol-Oriented programming

Apple makes a big deal about Protocols in swift and how they are better than anything else ever.  I found it quite irritating that nowhere in their explanation of what makes them so great did they mention that a protocol is eerily similar to an interface in Java.  Moving from a C++ background to Java, I was completely baffled why you would use an interface rather than an abstract class.  That question was answered back in 1997 when I started designing applications and APIs using interfaces first.  Nowadays, moving into swift, protocols certainly have features that interfaces do not - such as extensions and conditional conformance - but really - this is not something they just pulled out of nowhere.  I wish they didn't have to act like every thing they do is new and unprecedented.

It would be so much more honest for them to come out and say, "In designing a new language, we looked at what works in Java, Lisp, Python, (gasp) Perl, Haskell, Go, JavaScript - the needs of iOS and the environment apps find themselves in - and created a best-of-breed language."