Currently recursive type definitions for functions are not allowed.
If they were allowed, writing type-safe code for state machines would become much easier and simpler. The basic technique is to represent each state with a unique function which returns either itself or other function as the next state. This would eliminate the need to rely on enums or to subclass a root class.
Some examples follow to demonstrate the technique.
State Machines with Free Functions
Implementing a state machine with free functions requires defining a type for a free function returning itself or other free function with the same signature:
typealias Function = (OptionalArgTypeList) -> Function
Example F.1: Ideal but not possible
// Ideal but not possible
//
typealias State = () -> State // error: Type alias State references itself
func state1 () -> State {
print ("-->", #function)
return state1
}
func state2 () -> State {
print ("-->", #function)
return state2
}
// Helper function
func run (_ f:State) -> State {
return f ()
}
// test drive
let s1 = state1 ();
let s2 = run (s1) // s2 = s1 ()
let s3 = run (s2) // s3 = s2 ()
Example F.2: Possible but not type safe
// Possible but not type safe
//
typealias State = Any
func state1 () -> State {
print ("-->", #function)
return state2
}
func state2 () -> State {
print ("-->", #function)
return state1
}
// Helper function
func run (_ f:State) -> State {
let ff = f as! (() -> Any)
return ff ()
}
State Machines with Member Functions
Implementing a state machine with member functions requires defining a type for a member function returning itself or other member function with the same signature:
typealias Function = (ClassOrStructType)(OptionalArgTypeList) -> Function
Example M.1: Ideal but not possible
// Ideal but not possible
//
struct SM {
typealias State = (Self) -> (() -> State) // error: Type alias State references itself
func state1 () -> State {
print ("--> \(type (of:self)) \(#function)")
return Self.state2
}
func state2 () -> State {
print ("--> \(type (of:self)) \(#function)")
return Self.state1
}
// helper function
func run (_ f:State) -> State {
return f (self)()
}
}
// Test drive
let sm = SM ()
let s1 = sm.state1 ()
let s2 = sm.run (s1) // s2 = s1 (sm)()
let s3 = sm.run (s2) // s3 = s2 (sm)()
Example M.2: Possible but not type safe
// Possible but not type safe
//
struct SM {
typealias State = Any
func state1 () -> State {
print ("--> \(type (of:self)) \(#function)")
return Self.state2
}
func state2 () -> State {
print ("--> \(type (of:self)) \(#function)")
return Self.state1
}
// helper function
func run (_ f:State) -> State {
let ff = f as! ((Self)->()->State)
return ff (self)()
}
}
Why can't the compiler accept this recursive type definition?
typealias State = () -> State // error: Type alias State references itself
Are there any technical barriers?