Reputation: 1
I am new to Swift and am in the process of porting the jay parser generator to output a Swift parser. In the parser skeleton file I've found constructs that use the result of an assignment expression inside a conditional. E.g. ...
if ((yyN = yySindex[yyStates[yyTop]]) != 0 &&
(yyN += yyErrorCode) >= 0 &&
yyN < yyTable.Length &&
yyCheck[yyN] == yyErrorCode) { ... }
Note in particular the (yyN += yyErrorCode) >= 0
expression
Since Swift doesn't allow assignment expressions to return a value is there an efficient way to code this type of construct in Swift?
Upvotes: 0
Views: 206
Reputation: 73176
Since Swift doesn't allow assignment expressions to return a value is there an efficient way to code this type of construct in Swift?
Yes: separate the assignments from the conditionals, and break it up into smaller components (see e.g. @tuple_cat:s answer).
(Don't do this)
For the fun of it, and for a brief look at some technical possibilities of Swift; Swift can be used to emulate heavily clustered conditional evaluations as the one above. To Swiftify your example (in a horribly non-clean way), you could use inline yyN
-capturing and Bool
-returning closures to spice up the non-readability even further:
if ({_ in yyN = yySindex[yyStates[yyTop]]; return yyN != 0}()) &&
({_ in yyN += yyErrorCode; return yyN != 0}()) &&
yyN < yyTable.Length &&
yyCheck[yyN] == yyErrorCode {
/* ... */
}
Swift also also allows defining custom operators, so we could construct assignment operators which simply calls their default versions (side effect), but returns the assigned value as a result from the assignment statement. E.g. in case yyN
is of type Int
:
// some C++ style assignment operators
infix operator ^=: AssignmentPrecedence
infix operator ^+=: AssignmentPrecedence
extension Int {
static func ^= (lhs: inout Int, rhs: Int) -> Int {
lhs = rhs
return rhs
}
static func ^+= (lhs: inout Int, rhs: Int) -> Int {
lhs += rhs
return lhs
}
}
if ((yyN ^= yySindex[yyStates[yyTop]]) != 0 &&
(yyN ^+= yyErrorCode) >= 0 &&
yyN < yyTable.Length &&
yyCheck[yyN] == yyErrorCode) {
/* ... */
}
Upvotes: 1
Reputation: 42828
Yes:
yyN = yySindex[yyStates[yyTop]]
if yyN != 0 {
yyN += yyErrorCode
if yyN >= 0 && yyN < yyTable.Length && yyCheck[yyN] == yyErrorCode {
// …
}
}
Upvotes: 0