Swift closure adding more than 2 value
Compiler does not reproduce type of result correctly in this case. You should help it a little:
var calculate: (Int,Int,Int) -> Int
calculate = { Int($0+$1+$2) }
print(calculate(5,8,90)) // "103\n"
How to use trailing closure in if condition?
You have to put parentheses around the function call:
if "SMITH" == (lastNameForPerson(Person()) {$0.uppercaseString}) {
print("It's bob")
}
Or you put them around the ==
comparison (around the if
condition) in a C-style manner:
if ("SMITH" == lastNameForPerson(Person()) {$0.uppercaseString}) {
print("It's bob")
}
Alternatively, you can move the closure inside the parameter list (though this requires you to explicitly name the parameter):
if "SMITH" == lastNameForPerson(Person(), caseFolding: {$0.uppercaseString}) {
print("It's bob")
}
The reason this problem arises is that the if
statement 'claims' the {}
block, i.e. it doesn't belong to the lastNameForPerson
call any more. For the compiler, the second code block now looks like a normal block that wasn't properly separated from the previous (if
) statement.
You should probably consider avoiding a construct like this in general, since it might be hard to read (at first). Instead, you could store the result of the function call in a variable and compare that instead:
let lastName = lastNameForPerson(Person()) {$0.uppercaseString}
if "SMITH" == lastName {
print("It's bob")
}
How to use Closure to recycle code in Swift?
To expand on the already existing answers, functions allow you a high degree of reusability, and for your particular example, high-order functions might work.
Let's begin with defining the basic blocks for the data comparison operations you want to do:
/// Creates a function that acts as a comparator against the received value
func isGreater<T: Comparable>(than value: T) -> (T) -> Bool {
return { $0 > value }
}
/// Creates a function that checks if the argument in betwen the two bounds
func isWithin<T: Comparable>(_ lower: T, and upper: T) -> (T) -> Bool {
return { lower..<upper ~= $0 }
}
/// Creates a function that checks if an array contains elements that satisfy the given predicate
func contains<T>(_ predicate: @escaping (T) -> Bool) -> ([T]) -> Bool {
return { $0.contains(where: predicate) }
}
Both of the above functions create as and return a new function that can be stored and reused anywhere in your app.
Now, let's put the functions to good use:
func hasAboveThreshold(threshold: Double) -> ([Double]) -> Bool {
return contains(isGreater(than: threshold))
}
func hasBetweenThreshold(threshold1: Double, threshold2: Double) -> ([Double]) -> Bool {
return contains(isWithin(threshold1, and: threshold2))
}
Note how every piece (function) from the first code snippet was reused via function composition. Thus, you achieve the reusability goal.
Usage example:
let numbers = [1.1, 2.2, 3.3, 4.4, 5.5]
let hasBetween1AndTen = hasBetweenThreshold(threshold1: 1.0, threshold2: 10.0)
print(hasBetween1AndTen(numbers))
As you store the hasBetween1AndTen
into a variable, you can reuse it an any time, and in any place that has access to that variable.
How to receive an output for a method from a closure in Swift?
You should use a completionHandler
concept to achieve async operations like this:
struct TweetFetcher {
let tweetCount = 100
let swifter = Swifter(consumerKey: key, consumerSecret: secret)
func fetchTweets(with searchText: String, completion: @escaping ([TweetSentimentClassifierInput]?, Error?) -> Void) {
swifter.searchTweet(using: searchText, lang: "en", count: tweetCount, tweetMode: .extended) {(results, searchMetadata) in
var tweets = [TweetSentimentClassifierInput]()
let data = results.description.data(using: .utf8)
do {
let decodedData = try JSONDecoder().decode([TweetData].self, from: data!)
} catch {
print("Error with decoding, \(error)")
completion(nil, error)
}
for tweet in decodedData {
let tweetForClassification = TweetSentimentClassifierInput(text: tweet.full_text)
tweets.append(tweetForClassification)
}
completion(tweets, nil)
} failure: { (error) in
print("Error with the Twitter API request, \(error)")
completion(nil, error)
}
}
}
Usage
let fetcher = TweetFetcher()
fetcher.fetchTweets(with: "Keyword...") { tweets, error in
if let error = error {
print(error.localizedDescription)
} else {
// Use tweets array content here ...
}
}
swift maximum consecutive positive numbers
Update: Simpler solution: Split the array into slices of
positive elements, and determine the maximal slice length:
let numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
let maxConsecutive = numbers.split(whereSeparator: { $0 <= 0 }).map { $0.count }.max()!
print(maxConsecutive) // 3
Old answer:) Using the ideas from Swift running sum:
let numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
let maxConsecutive = numbers.map({
() -> (Int) -> Int in var c = 0; return { c = $0 > 0 ? c + 1 : 0; return c }
}()).max()!
Here map()
maps each array element to the count of consecutive positive
numbers up to the elements position, in this case
[1, 2, 3, 0, 0, 1, 2, 0, 0, 0, 1]
The transformation is created as an "immediately evaluated
closure" to capture a variable c
which holds the current number of
consecutive positive numbers. The transformation increments or resets c
,
and returns the updated value.
If the array is possibly large then change it to
let maxConsecutive = numbers.lazy.map( ... ).max()!
so that the maximum run length is determined without creating an
intermediate array.
Calling a swift function right after the closing bracket?
There are three types of closures in Swift:
- Global functions are closures that have a name and do not capture any values.
- Nested functions are closures that have a name and can capture values from their enclosing function.
- Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
...
Closure expressions are a way to write inline closures in a brief,
focused syntax.
(Source: Closures in the Swift book.)
In your first example:
var test = { () -> String in return "this works" }()
{ ... }
is a closure expression. This expression is evaluated
with an empty argument list ()
. The result is the string
"this works" which is then assigned to the variable.
Your second example is a global function.
Global functions are (named) closures, but not closure expressions.
There is (as far as I know) no similar way to define a function which
is immediately evaluated.
Related Topics
Does _Arraytype or _Arrayprotocol Not Available in Swift 3.1
When Two Optionals Are Assigned to an If Let Statement, Which One Gets Unwrapped? Swift Language
Swift How to Sort Dict Keys by Byte Value and Not Alphabetically
Setting Observer for Swift Objects/Properties
Swift Tuple Has Unexpected Print Result
Getting the Time Remaining in the Time Interval of a Timer in Swift
How to Change the Order of Functions Triggered
Cannot Read Property 'Keycode' 'Character' Assertion Failure When Detect Modifier Key + Numeric Key
Is There Any Particular Use of Closure in Swift? and What's the Benefit
Error: Argument Type Double/String etc. Does Not Conform to Expected Type "Anyobject"
Alamofireimage How to Clean Memory and Cache
Hiding Dividers in Nssplitview
Node.Physicsbody.Joints Downcasting Error
How to Properly Test Against Certain Values in Nseventmodifierflags via Swift
Codable Decode Property with Multiple Object Types Based on Another Value