I was trying to write an Int extension to clamp an Int to a specific range, like this:
extension Int {
func clamp(left: Int, right: Int) -> Int {
return min(max(self, left), right)
}
}
I was getting a compiler error and after a while I realised that min is being interpreted here as Int.min, which is a constant for the lowest Int.
I can reimplement this avoiding min/max but I'm curious: is there a way I can reference those from an Int extension?
You can prepend the module name, in this case Swift:
extension Int {
func clamp(left: Int, right: Int) -> Int {
return Swift.min(Swift.max(self, left), right)
}
}
And just for fun: You get the same result with
extension Int {
func clamp(left: Int, right: Int) -> Int {
return (left ... right).clamp(self ... self).start
}
}
using the clamp() method from ClosedInterval.
You could create a function myMin<T>(a: T, b: T) that calls min and use that in your extension.
Related
Trying to compile this code
pow(10,2)
struct Test {
var i:Int
func pow(_ p:Int) -> Int { return pow(i,p) }
}
var s = Test(i:10)
s.pow(2)
gives me a compiler error. Obviously the standard math.h function pow was blinded out by Swift's scoping rules. This rather smells like a compiler error since the math.h version of pow has a different signature. Is there any way to invoke it, though?
There are two problems: The first is how pow(i,p) is resolved.
As described in Swift 3.0: compiler error when calling global func min<T>(T,T) in Array or Dictionary extension, this
can be solved by prepending the module name to the function call.
The second problem is that there is no pow function taking
two integer arguments. There is
public func powf(_: Float, _: Float) -> Float
public func pow(_: Double, _: Double) -> Double
in the standard math library, and
public func pow(_ x: Decimal, _ y: Int) -> Decimal
in the Foundation library. So you have to choose which one to use,
for example:
struct Test {
var i:Int
func pow(_ p:Int) -> Int {
return lrint(Darwin.pow(Double(i),Double(p)))
}
}
which converts the arguments to Double and rounds the result
back to Int.
Alternatively, use iterated multiplication:
struct Test {
var i: Int
func pow(_ p:Int) -> Int {
return (0..<p).reduce(1) { $0.0 * i }
}
}
I observed at https://codereview.stackexchange.com/a/142850/35991 that
this is faster for small exponents. Your mileage may vary.
I was trying to write an Int extension to clamp an Int to a specific range, like this:
extension Int {
func clamp(left: Int, right: Int) -> Int {
return min(max(self, left), right)
}
}
I was getting a compiler error and after a while I realised that min is being interpreted here as Int.min, which is a constant for the lowest Int.
I can reimplement this avoiding min/max but I'm curious: is there a way I can reference those from an Int extension?
You can prepend the module name, in this case Swift:
extension Int {
func clamp(left: Int, right: Int) -> Int {
return Swift.min(Swift.max(self, left), right)
}
}
And just for fun: You get the same result with
extension Int {
func clamp(left: Int, right: Int) -> Int {
return (left ... right).clamp(self ... self).start
}
}
using the clamp() method from ClosedInterval.
You could create a function myMin<T>(a: T, b: T) that calls min and use that in your extension.
I'm currently working my way through the Swift Programming Manual from Apple and came across function types as parameter types.
In usual way,
func add(one : Int , _ two:Int) ->Int
{
return one+two
}
func multiply(one : Int ,_ two : Int) ->Int
{
return one*two
}
func subtract(one : Int , _ two :Int) ->Int
{
return one-two
}
add(1, 2)
subtract( 1 , 2)
multiply(1 , 2)
Using Function types as parameters,
func add(one : Int , _ two:Int) ->Int
{
return one+two
}
func multiply(one : Int ,_ two : Int) ->Int
{
return one*two
}
func subtract(one : Int , _ two :Int) ->Int
{
return one-two
}
func basic(result : (Int , Int) ->Int,_ one : Int , _ two : Int)
{
result(one,two)
}
basic(add, 1, 2)
basic(multiply, 2, 3)
So, from above code it is clear that we are writing extra function basic() and extra lines of code which are not that useful in this example and makes it complicated.It's better not to use function types as parameter types.
So,is there any example which takes advantage of the feature?
If you look at Swift's standard library you will see that many methods do that like map which is defined on Array.
map takes a function which transforms the elements of the array to a new array with a new type.
It is also a generic function but in order to keep it simple I use a function which maps Int Arrays:
func map(_ array: [Int], _ transform: Int -> Int) -> [Int] {
var result = [Int]()
for element in array {
result.append(transform(element))
}
return result
}
// map can be used with other functions
// and also closures which are functions
// without a name and can be created "on the fly"
func addByOne(i: Int) -> Int {
return i + 1
}
func square(i: Int) -> Int {
return i * i
}
map([1,2,3], addByOne) // [2,3,4]
map([1,2,3], square) // [1,4,9]
// and so on...
// with closures
map([1,2,3]) { $0 + 1 } // [2,3,4]
map([1,2,3]) { $0 * $0 } // [1,4,9]
So it is mainly used in libraries where you can offer APIs which have a much broader range of usage.
I'm trying to write an extension for the Swift Int type to save nested min()/max() functions. It looks like this:
extension Int {
func bound(minVal: Int, maxVal: Int) -> Int {
let highBounded = min(self, maxVal)
return max(minVal, highBounded)
}
}
However, I have a compilation error when assigning/computing highBounded:
IntExtensions.swift:13:25: 'Int' does not have a member named 'min'
Why aren't the functions defined by the standard library properly located?
It looks like it is trying to find a method in Int for min() and max() since you are extending Int. You can get around this and use the default min and max functions by specifying the Swift namespace.
extension Int {
func bound(minVal: Int, maxVal: Int) -> Int {
let highBounded = Swift.min(self, maxVal)
return Swift.max(minVal, highBounded)
}
}
This piece of code comes from Swift documentation https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
Apparently var is a reserved word, so why it is legal to declare: subscript(var digitIndex: Int) -> Int?
If I change the signature to subscript(#digitIndex: Int) -> Int, I will get this compiler error:
My questions are:
1) why the signature is valid?
2) why my change causes an exception?
Declaring a function argument with var means that it can be modified, is not a constant. In your case, without using var, you had a constant argument but you attempted to decrement it. Thus the error.
Your two cases are:
func foo (x: int) { /* x is a constant, like `let x: int` */ }
func foo (var x: int) { /* x is not a constant */ }