Elegant `bounded` methodology in Swift - swift

I'm looking for a more elegant way to create bounded limiters for numbers, primarily to be used in setters. There are plenty of techniques for determining whether a value falls within bounds, but I don't see any native functions for forcing an incoming value to conform to those bounds.
The accepted answer here comes close but I want to cap the values rather than merely enforce them.
Here's what I have so far. I'm not sure about the Int extension. And I'd prefer to collapse the if-else into a single elegant line of code, if possible. Ideally I'd like to shorten the actual implementation in the struct, as well.
extension Int {
func bounded(_ min: Int, _ max: Int) -> Int {
if self < min {
return min
} else if self > max {
return max
} else {
return self
}
}
}
print(5.bounded(4, 6)) // 5
print(5.bounded(1, 3)) // 3
print(5.bounded(6, 9)) // 6
// Used in a sentence
struct Animal {
var _legs: Int = 4
var legs: Int {
get {
return _legs
}
set {
_legs = newValue.bounded(1, 4)
}
}
}
var dog = Animal()
print(dog.legs) // 4
dog.legs = 3
print(dog.legs) // 3
dog.legs = 5
print(dog.legs) // 4
dog.legs = 0
print(dog.legs) // 1

This is Apple's own approach, taken from this sample code:
func clamp<T: Comparable>(value: T, minimum: T, maximum: T) -> T {
return min(max(value, minimum), maximum)
}

I would generalize this extension to any Comparable, so that more types can benefit from it. Also, I would change the parameter to be a ClosedRange<Self> rather than two separate Self parameters, because that's the more common way of handling ranges in Swift. That'll come in especially handy when dealing with array indices.
extension Comparable {
func clamped(to r: ClosedRange<Self>) -> Self {
let min = r.lowerBound, max = r.upperBound
return self < min ? min : (max < self ? max : self)
}
}
// Usage examples:
10.clamped(to: 0...5) // => 5
"a".clamped(to: "x"..."z") // => "x"
-1.clamped(to: 0...1) // => 0

A very clean alternative to your if-else statements, keeping the readability would be:
extension Comparable{
func clamp(_ min: Self,_ max: Self) -> Self{
return min...max~=self ? self : (max < self ? max : min)
}
}
I think this is a good alternative to using a range as parameter, because, in my opinion, it is annoying to write 6.clamp((4...5)) each time insted of 6.clamp(4,5).
When it comes to your struct, I think you should not use this clamp extension at all, because, say, 100 does not mean 4... I cannot see the reason for doing this, but it's up to you.

Related

How to count the number of dimensions in Swift array [duplicate]

Suppose I have some function that I want to populate my data structure using a multi-dimensional array (e.g. a Tensor class):
class Tensor {
init<A>(array:A) { /* ... */ }
}
while I could add in a shape parameter, I would prefer to automatically calculate the dimensions from the array itself. If you know apriori the dimensions, it's trivial to read it off:
let d1 = array.count
let d2 = array[0].count
However, it's less clear how to do it for an N-dimensional array. I was thinking there might be a way to do it by extending the Array class:
extension Int {
func numberOfDims() -> Int {
return 0
}
}
extension Array {
func numberOfDims() -> Int {
return 1+Element.self.numberOfDims()
}
}
Unfortunately, this won't (rightfully so) compile, as numberOfDims isn't defined for most types. However, I'm don't see any way of constraining Element, as Arrays-of-Arrays make things complicated.
I was hoping someone else might have some insight into how to solve this problem (or explain why this is impossible).
If you're looking to get the depth of a nested array (Swift's standard library doesn't technically provide you with multi-dimensional arrays, only jagged arrays) – then, as shown in this Q&A, you can use a 'dummy protocol' and typecasting.
protocol _Array {
var nestingDepth: Int { get }
}
extension Array : _Array {
var nestingDepth: Int {
return 1 + ((first as? _Array)?.nestingDepth ?? 0)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2, 3], [4]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[4], [5]]]
print(c.nestingDepth) // 3
(I believe this approach would've still worked when you had originally posted the question)
In Swift 3, this can also be achieved without a dummy protocol, but instead by casting to [Any]. However, as noted in the linked Q&A, this is inefficient as it requires traversing the entire array in order to box each element in an existential container.
Also note that this implementation assumes that you're calling it on a homogenous nested array. As Paul notes, it won't give a correct answer for [[[1], 2], 3].
If this needs to be accounted for, you could write a recursive method which will iterate through each of the nested arrays and returning the minimum depth of the nesting.
protocol _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int
}
extension Array : _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int {
// for an empty array, the minimum depth is the current depth, as we know
// that _nestingDepth is called where currentDepth <= minimumDepth.
guard !isEmpty else { return currentDepth }
var minimumDepth = minimumDepth
for element in self {
// if current depth has exceeded minimum depth, then return the minimum.
// this allows for the short-circuiting of the function.
if let minimumDepth = minimumDepth, currentDepth >= minimumDepth {
return minimumDepth
}
// if element isn't an array, then return the current depth as the new minimum,
// given that currentDepth < minimumDepth.
guard let element = element as? _Array else { return currentDepth }
// get the new minimum depth from the next nesting,
// and incrementing the current depth.
minimumDepth = element._nestingDepth(minimumDepth: minimumDepth,
currentDepth: currentDepth + 1)
}
// the force unwrap is safe, as we know array is non-empty, therefore minimumDepth
// has been assigned at least once.
return minimumDepth!
}
var nestingDepth: Int {
return _nestingDepth(minimumDepth: nil, currentDepth: 1)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2], [3]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[5], [6]]]
print(c.nestingDepth) // 3
let d: [Any] = [ [[1], [2], [[3]] ], [[4]], [5] ]
print(d.nestingDepth) // 2 (the minimum depth is at element [5])
Great question that sent me off on a goose chase!
To be clear: I’m talking below about the approach of using the outermost array’s generic type parameter to compute the number of dimensions. As Tyrelidrel shows, you can recursively examine the runtime type of the first element — although this approach gives nonsensical answers for heterogenous arrays like [[[1], 2], 3].
Type-based dispatch can’t work
As you note, your code as written doesn’t work because numberOfDims is not defined for all types. But is there a workaround? Does this direction lead somewhere?
No, it’s a dead end. The reason is that extension methods are statically dispatched for non-class types, as the following snippet demonstrates:
extension CollectionType {
func identify() {
print("I am a collection of some kind")
}
func greetAndIdentify() {
print("Hello!")
identify()
}
}
extension Array {
func identify() {
print("I am an array")
}
}
[1,2,3].identify() // prints "I am an array"
[1,2,3].greetAndIdentify() // prints "Hello!" and "I am a collection of some kind"
Even if Swift allowed you to extend Any (and it doesn’t), Element.self.numberOfDims() would always call the Any implementation of numberOfDims() even if the runtime type of Element.self were an Array.
This crushing static dispatch limitation means that even this promising-looking approach fails (it compiles, but always returns 1):
extension CollectionType {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
return 1
}
}
extension CollectionType where Generator.Element: CollectionType {
static var numberOfDims: Int {
return 1 + Generator.Element.numberOfDims
}
}
[[1],[2],[3]].numberOfDims // return 1 ... boooo!
This same constraint also applies to function overloading.
Type inspection can’t work
If there’s a way to make it work, it would be something along these lines, which uses a conditional instead of type-based method dispatch to traverse the nested array types:
extension Array {
var numberOfDims: Int {
return self.dynamicType.numberOfDims
}
static var numberOfDims: Int {
if let nestedArrayType = Generator.Element.self as? Array.Type {
return 1 + nestedArrayType.numberOfDims
} else {
return 1
}
}
}
[[1,2],[2],[3]].numberOfDims
The code above compiles — quite confusingly — because Swift takes Array.Type to be a shortcut for Array<Element>.Type. That completely defeats the attempt to unwrap.
What’s the workaround? There isn’t one. This approach can’t work because we need to say “if Element is some kind of Array,” but as far as I know, there’s no way in Swift to say “array of anything,” or “just the Array type regardless of Element.”
Everywhere you mention the Array type, its generic type parameter must be materialized to a concrete type or a protocol at compile time.
Cheating can work
What about reflection, then? There is a way. Not a nice way, but there is a way. Swift’s Mirror is currently not powerful enough to tell us what the element type is, but there is another reflection method that is powerful enough: converting the type to a string.
private let arrayPat = try! NSRegularExpression(pattern: "Array<", options: [])
extension Array {
var numberOfDims: Int {
let typeName = "\(self.dynamicType)"
return arrayPat.numberOfMatchesInString(
typeName, options: [], range: NSMakeRange(0, typeName.characters.count))
}
}
Horrid, evil, brittle, probably not legal in all countries — but it works!
Unfortunately I was not able to do this with a Swift array but you can easily convert a swift array to an NSArray.
extension NSArray {
func numberOfDims() -> Int {
var count = 0
if let x = self.firstObject as? NSArray {
count += x.numberOfDims() + 1
} else {
return 1
}
return count
}
}

How to create a generator in Swift?

Can I create a generator in Swift?
With iterator, I need store intermediate results, for example:
struct Countdown: IteratorProtocol, Sequence {
private var value = 0
init(start: Int) {
self.value = start
}
mutating func next() -> Int? {
let nextNumber = value - 1
if nextNumber < 0 {
return nil
}
value -= 1
return nextNumber
}
}
for i in Countdown(start: 3) {
print(i)
} // print 1 2 3
In this example, I need store the value.
In my situation, I want to use generator instead of iterator, because I don't want store the intermediate results of my sequence in each next.
Understanding how generators work (and why they are less important in swift) is at first difficult coming from Python.
Up to Swift v2.1 there was a protocol called GeneratorType. This was renamed to IteratorProtocol in Swift v3.0+. You can conform to this protocol to make your own objects that do just-in-time computations similar to what can be done in Python.
More information can be found in the Apple Documentation: IteratorProtocol
A simple example from IteratorProtocol page:
struct CountdownIterator: IteratorProtocol {
let countdown: Countdown
var times = 0
init(_ countdown: Countdown) {
self.countdown = countdown
}
mutating func next() -> Int? {
let nextNumber = countdown.start - times
guard nextNumber > 0
else { return nil }
times += 1
return nextNumber
}
}
let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."
However, you need to think about why you are using a generator:
Swift automatically does something "called copy on write." This means that many of the cases that use a Python generator to avoid the large copying cost of collections of objects (arrays, lists, dictionaries, etc) are unnecessary in Swift. You get this for free by using one of the types that use copy on write.
Which value types in Swift supports copy-on-write?
It is also possible to use a wrapper to force almost any object to be copy on write, even if it is not part of a collection:
How can I make a container with copy-on-write semantics?
The optimizations in swift usually mean that you do not not have to write generators. If you really do need to (usually because of data heavy, scientific calculations) it is possible as above.
Based on the code you provided and the little bit knowledge of generators that I do have, you can do something like
struct Countdown {
private var _start = 0
private var _value = 0
init(value: Int) {
_value = value
}
mutating func getNext() -> Int? {
let current = _start
_start += 1
if current <= _value {
return current
} else {
return nil
}
}
}
and then wherever you want to use it, you can do something like
var counter = Countdown(value: 5)
while let value = counter.getNext() {
print(value)
}
Walter provides a lot of good information, and generally you shouldn't be doing this in Swift, but even if you wanted an Iterator, the right way to do it is with composition, not by building your own. Swift has a lot of existing sequences that can be composed to create what you want without maintaining your own state. So in your example, you'd differ to a range's iterator:
struct Countdown: Sequence {
private var value = 0
init(start: Int) {
self.value = start
}
func makeIterator() -> AnyIterator<Int> {
return AnyIterator((0..<value).reversed().makeIterator())
}
}
for i in Countdown(start: 3) {
print(i)
} // print 1 2 3
Something has to keep the state; that's the nature of these kinds of functions (even in a world with coroutines). It's fine not to maintain it directly; just delegate to a more primitive type. Swift has a couple of dozen built-in Iterators you can use to build most things you likely need, and any iterator can be lifted to an AnyIterator to hide the implementation details. If you have something custom enough that it really requires a next(), then yes, storing the state is your problem. Something has to do it. But I've found this all to be extremely rare, and often suggests over-design when it comes up.
I have a solution similar to above, but with a slightly more "yield-y" feeling to it.
struct Countdown
{
static func generator(withStart: Int) -> () -> Int?
{
var start = withStart + 1
return {
start = start - 1
return start > 0 ? start : nil
}
}
}
let countdown = Countdown.generator(withStart: 5)
while let i = countdown()
{
print ("\(i)")
}

"sign" function in Swift

Is there a function that returns +1 for positive numbers and -1 for negatives in Swift?
I looked through the enormous file that appears if you right-click->definitions on a typical function, but if it's in there I don't know it's name.
I did this:
(num < 0 ? -1 : 1)
But I'd rather use a built-in function if there is any--for self-documenting reasons at the minimum.
Swift 4
As has already been pointed out in #Wil Shipley's Swift 4 answer, there is now a sign property in the FloatingPoint protocol:
FloatingPointSign
The sign of a floating-point value.
Enumeration Cases
case minus The sign for a negative value.
case plus The sign for a positive value.
However, the comments to the sign blueprint in the source code of FloatingPoint contains important information that is (yet?) not present in the generated docs:
/// The sign of the floating-point value.
///
/// The `sign` property is `.minus` if the value's signbit is set, and
/// `.plus` otherwise. For example:
///
/// let x = -33.375
/// // x.sign == .minus
///
/// Do not use this property to check whether a floating point value is
/// negative. For a value `x`, the comparison `x.sign == .minus` is not
/// necessarily the same as `x < 0`. In particular, `x.sign == .minus` if
/// `x` is -0, and while `x < 0` is always `false` if `x` is NaN, `x.sign`
/// could be either `.plus` or `.minus`.
emphasizing, "... .minus if the value's signbit is set" and "Do not use this property to check whether a floating point value is negative".
Summa summarum: use the new sign property of the FloatingPoint protocol to actually check whether the value's signbit is set or not, but make sure to use some care if attempting to use this property to tell whether a number is negative or not.
var f: Float = 0.0
if case .minus = (-f).sign { print("A. f is negative!") }
f = -Float.nan
if f < 0 { print("B. f is negative!") }
if case .minus = f.sign { print("C. f is negative!") }
// A. f is negative!
// C. f is negative!
Swift 3
W.r.t. built-in functions, I think the closest you'll get is the Foundation method copysign(_: Double, _: Double) -> Double
let foo = -15.2
let sign = copysign(1.0, foo) // -1.0 (Double)
Naturally needing some type conversion in case you're not operating on a number of type Double.
However, I see no reason why not to create your own extension fit to your needs, especially for such a simple function as sign as they needn't get bloated, e.g.
extension IntegerType {
func sign() -> Int {
return (self < 0 ? -1 : 1)
}
/* or, use signature: func sign() -> Self */
}
extension FloatingPointType {
func sign() -> Int {
return (self < Self(0) ? -1 : 1)
}
}
(here yielding 1 also for 0, as in the example in your question).
(Edit with regard to your comment below)
An alternative solution to the above would be to define your own protocol with a default implementation of sign(), so that all types conforming to this protocol would have access to that sign() method.
protocol Signable {
init()
func <(lhs:Self, rhs:Self) -> Bool
}
extension Signable {
func sign() -> Int {
return (self < Self() ? -1 : 1)
}
}
/* extend signed integer types to Signable */
extension Int: Signable { } // already have < and init() functions, OK
extension Int8 : Signable { } // ...
extension Int16 : Signable { }
extension Int32 : Signable { }
extension Int64 : Signable { }
/* extend floating point types to Signable */
extension Double : Signable { }
extension Float : Signable { }
extension CGFloat : Signable { }
/* example usage */
let foo = -4.2
let bar = 42
foo.sign() // -1 (Int)
bar.sign() // 1 (Int)
The simd library has a sign method:
import simd
sign(-100.0) // returns -1
sign(100.0) // returns 1
sign(0.0) // returns 0
You get simd for free if you import SpriteKit.
In Swift-4 floats have a new property:
public var sign: FloatingPointSign { get }
(However this only checks the sign bit, so it’ll fail for some cases like -0 — see that accepted answer above.)
You can use signum() if your value is an integer.
https://developer.apple.com/documentation/swift/int/2886673-signum
Here is a code snippet to make it clear;
let negative: Int = -10
let zero: Int = 0
let positive: Int = 10
print(negative.signum()) // prints "-1"
print(zero.signum()) // prints "0"
print(positive.signum()) // prints "1"
Use:
let result = signbit(number)
This will return 1 for negative numbers and 0 for positives.
let number = -1.0
print("\(signbit(number))")
1
let number = 1.0
print("\(signbit(number))")
0
FloatingPointType has a built-in computed variable but it returns a boolean. If you only need this operation on floats you can use an extension like this:
extension FloatingPointType {
var signValue: Int {
return isSignMinus ? -1 : 1
}
}
However, I believe the best approach would be to extend the SignedNumberType protocol.
extension SignedNumberType {
var signValue: Int {
return (self >= -self) ? 1 : -1
}
}
If you want 0 to return -1 then just change >= to >.
Test cases:
print(3.0.signValue)
print(0.signValue)
print(-3.0.signValue)
Since copysign cannot be used over Integer I'm using this extension:
extension Comparable where Self: SignedNumber {
var sign: Int {
guard self != -self else {
return 0
}
return self > -self ? 1 : -1
}
}

Extending Generic Integer Types in Swift

So I'm trying to extend Swift's integer types with a few convenient functions that I use a lot, however I'm not clear on which protocols I should be extending.
As an example, let's say I want to implement a function for clamping a value (if it's less than a minimum set it to that, otherwise if it's greater than a maximum then set it to that instead). My first thought was to do something like this:
extension Int {
func clamp(minimum:Int, maximum:Int) {
if self < minimum { return minimum }
if self > maximum { return maximum }
return self
}
}
Bit of a simplistic example, but it illustrates the problem; if I want to now call this for a UInt then naturally I can't, so I have to add an equivalent to UInt, but that won't work for a UInt16 and so-on.
I thought that I could perhaps extend something higher up the chain, and use generics instead, however protocols such as IntegerType can't seem to be extended.
So, is there somewhere more appropriate that I could put my extension(s)?
For Swift 2, see Andriy Gordiychuk's answer, which will be correct then. If you require Swift 1, then this cannot be done with extensions, and must be done with free functions. This is why there are so many free functions in stdlib that became extensions in Swift 2.
For Swift 1, what you have to do is:
func clamp<T:Comparable>(value: T, #minimum:T, #maximum:T) -> T {
if value < minimum { return minimum }
if value > maximum { return maximum }
return value
}
If you prefer modifying the value (as Andriy's example does), you can do it this way:
func clamp<T:Comparable>(inout value: T, #minimum:T, #maximum:T) {
if value < minimum { value = minimum }
else if value > maximum { value = maximum }
}
Otherwise you have to write an extension on every type. It's the only other answer in Swift 1. Swift 2 is much better.
While Swift 2.0 is still in beta I suggest you to add extensions like you illustrated. You will have to copy-paste the same code for Int, Int64 etc, but there is no other way to do what you want at the moment.
Once Swift 2.0 is out you will be able to do this
extension IntegerType {
mutating func clamp(minimum:Self, maximum:Self) {
if self < minimum { self = minimum }
if self > maximum { self = maximum }
}
}
If you can wait with the release of your app until some time in September then I encourage you to start using Swift 2.0 right now.
Update
With Swift 2.0 you can also add extension to Comparable protocol which will ensure that clamp() is available for other types such as Double, Float, etc
extension Comparable {
mutating func clamp(minimum:Self, maximum:Self) {
if self < minimum { self = minimum }
if self > maximum { self = maximum }
}
}
By way of example, here is an integer implementation of clamped that also applies generically to anything that can use it:
extension Comparable
{
func clamped(from lowerBound: Self, to upperBound: Self) -> Self {
return min(max(self, lowerBound), upperBound)
}
func clamped(to range: ClosedRange<Self>) -> Self {
return min(max(self, range.lowerBound), range.upperBound)
}
}
extension Strideable where Self.Stride: SignedInteger
{
func clamped(to range: CountableClosedRange<Self>) -> Self {
return min(max(self, range.lowerBound), range.upperBound)
}
}
And the test cases:
7.clamped(from: 3, to: 6) // 6
7.clamped(to: 3 ... 6) // 6
7.clamped(to: 3 ... 7) // 7
7.clamped(to: 3 ... 8) // 7
7.0.clamped(to: 3.0 ... 6.0) // 6
7.0.clamped(to: 3.0 ... 7.0) // 7
7.0.clamped(to: 3.0 ... 8.0) // 7
extension Comparable {
func clamp(var minimum: Self, var _ maximum: Self) -> Self {
if maximum < minimum { swap(&maximum, &minimum) }
if self < minimum { return minimum }
if self > maximum { return maximum }
return self
}
}
You are on the right track. In fact you are talking about Protocol Oriented Programming.
Protocol extensions: Swift is very focused on protocol-oriented
development — there’s even a session on the topic at WWDC 2015. Swift
2.0 adds protocol extensions, and the standard library itself uses them extensively. Where you used to use global functions, Swift 2.0
now adds methods to common types so functions chain naturally, and
your code is much more readable.
https://developer.apple.com/swift/blog/?id=29
In fact a big feature of Swift 2.0 is that it allows you to add methods to protocols so you can add clamp to IntegerType.
The video explains very well the topic of Protocol Oriented Programming: https://developer.apple.com/videos/wwdc/2015/?id=408
You just need to upgrade to Swift 2.0.

What is the shortest way to run same code n times in Swift?

I have a code that I need to run exactly n times in Swift. What is the shortest possible syntax for that?
I am currently using the for loop but it is a lot of typing.
for i in 0..<n { /* do something */ }
Is there a shorter/nicer way for running same code n times in Swift?
Speaking of syntax, you might define your own shortest syntax:
extension Int {
func times(_ f: () -> ()) {
if self > 0 {
for _ in 0..<self {
f()
}
}
}
func times(_ f: #autoclosure () -> ()) {
if self > 0 {
for _ in 0..<self {
f()
}
}
}
}
var s = "a"
3.times {
s.append(Character("b"))
}
s // "abbb"
var d = 3.0
5.times(d += 1.0)
d // 8.0
Sticking with a for loop - you could extend Int to conform to SequenceType to be able to write:
for i in 5 { /* Repeated five times */ }
To make Int conform to SequenceType you'll could do the following:
extension Int : SequenceType {
public func generate() -> RangeGenerator<Int> {
return (0..<self).generate()
}
}
You have several ways of doing that:
Using for loops:
for i in 1...n { `/*code*/` }
for i = 0 ; i < n ; i++ { `/*code*/` }
for i in n { `/*code*/` }
using while loops:
var i = 0
while (i < n) {
`/*code*/`
` i++`
}
var i = 0
repeat {
` /*code*/`
`i++`
} while(i <= n)
for _ in 1...5 {
//action will be taken 5 times.
}
you could use functional programming on a range instead of a loop, for shorter and "nicer" syntax for example
(0..<n).forEach{print("Index: \($0)")}
Other answers mention defining your own syntax for that. So - that can be fine for a tiny personal project, or as a learning experience. But defining your own syntax for something so trivial and basic in a large project would be maintenance and readability hell.
You could do something like this:
10⨉{ print("loop") }
Using a custom operator and an extension on Int:
infix operator ⨉ // multiplication sign, not lowercase 'x'
extension Int {
static func ⨉( count:Int, block: () ->Void ) {
(0..<count).forEach { _ in block() }
}
}
ABakerSmith's answer updated for Swift 4:
extension Int: Sequence {
public func makeIterator() -> CountableRange<Int>.Iterator {
return (0..<self).makeIterator()
}
}
Use:
for i in 5 {
//Performed 5 times
}
Shorter and (I think) clearer:
for i in 1...n { } // note: this will fail if n < 1
or
for i in n { }
In Swift, what you have is the shortest syntax for performing a loop operation.
Swift provides two kinds of loop that perform a set of statements a
certain number of times:
The for-in loop performs a set of statements for each item in a
sequence.
The for loop performs a set of statements until a specific
condition is met.
If you want to run it infinite times, well try using a while.
There are a lot of answers here, highlighting just how creative you can be, with Swift.
I needed an array so I did this
extension Int {
func of<T>(iteration: (Int) -> T) -> [T] {
var collection = [T]()
for i in 0..<self {
collection.append(iteration(i))
}
return collection
}
}
fun strings() -> [String] {
return 4.of { "\($0) teletubby" }
}
for-loops are a common way to repeat code. Here is an example of using a for-loop to hide six outlets, versus writing the same code for six outlets. Plus if you make another outlet all you have to do is add it to the array.
let array = [outLet0, outlet1, outlet2, outLet3, outLet4, outLet5]
for outlet in array {
outlet.hidden = true
}
Versus writing it like this:
outlet0.hidden = true
outlet1.hidden = true
outlet2.hidden = true
outlet3.hidden = true
outlet4.hidden = true
outlet5.hidden = true
ONLY 5 CHARACTERS (not including n or code)
r(){}
If you're just testing things and need a REALLY short line, try this. Emphasis on using this for testing, not in production, because no one will know what is going on without documentation.
define this somewhere globally
func r(_ n : UInt, _ c: #escaping () -> Void) { for _ in 0..<n { c() } }
call this when you want to run it
r(5) { /*code*/ }
Swift is so awesome, just write your own function or extension and you got it ;) 100 of options there, everyone can do it its own way just look at those answers here.
Or better, write it as you already do, as is common when apps are build in team, as everyone would do it differently anyway and all projects need those extension to be written again or own libs to have and maintain just for stupid thing, that you can write just by some standard way, as you already did with your for loop.
The only loop shorter than that is an infinite while loop:
while (true) {
}
But you would still have to increase a counter and check it in the loop to break the loop, and in the end it wouldn't be shorter.