nested primary expressions in swift - swift

I'm wondering how to handle this expression with swift. I implimented it in ruby like this:
def disperseValueIntoNSpaces(n,m)
accum = 0
dispersedValue = []
for k in 0...m
valCrt = ((n*(m-k))/m+0.5)-((n*(m-k-1))/m+0.5)
dispersedValue.push(valCrt.to_i)
accum += valCrt
end
return dispersedValue
end
and transferred it to swift like this:
func disperseValueIntoNSpaces(numOfRows: Int, spaces: Int) -> [Int] {
var accum: Int = 0
var n: Float = Float(numOfRows)
var m: Float = Float(spaces)
var dispersedValues: [Int] = []
for k in (0...spaces) {
let valCrt = ((n*(m-k))/m)+0.5) - ((n*(m-k-1))/m+0.5)
// error: expected expression
// error: Binary operator '-' cannot be applied to operands of type 'Float' and 'Int'
// error: Consecutive statements on a line must be separated by ';'
dispersedValues.append(Int(valCrt))
accum += valCrt
}
return dispersedValues
}
This Float minus an Int error is easy enough to fix but i'm not sure how to craft the math equation

Related

Swift 3 - Can't subtract variables: Ambiguous reference to member [subtraction] [duplicate]

I am trying to concatenate multiple strings in swift 3:
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = a! + b! + c!
When compiling I get the following error:
error: cannot convert value of type 'String' to specified type 'String?'
var d:String? = a! + b! + c!
~~~~~~~~^~~~
This used to work in swift 2. I am not sure why it doesn't work anymore.
Bug report filed by OP:
SR-1122: Failure to typecheck chain of binary operators on force-unwrapped values
Which has been resolved (fix commited to master Jan 3 2017), and should hence no longer be an issue in upcoming Swift 3.1.
This seems to be a bug (not present in Swift 2.2, only 3.0) associated with the case of:
Using the forced unwrapping operator (!) for at least 3 terms in an expression (tested using at least 2 basic operators, e.g. + or -).
For some reason, given the above, Swift messes up type inference of the expression (specifically, for the x! terms themselves, in the expression).
For all the examples below, let:
let a: String? = "a"
let b: String? = "b"
let c: String? = "c"
Bug present:
// example 1
a! + b! + c!
/* error: ambiguous reference to member '+' */
// example 2
var d: String = a! + b! + c!
/* error: ambiguous reference to member '+' */
// example 3
var d: String? = a! + b! + c!
/* error: cannot convert value of type 'String'
to specified type 'String?' */
// example 4
var d: String?
d = a! + b! + c!
/* error: cannot assign value of type 'String'
to specified type 'String?' */
// example 5 (not just for type String and '+' operator)
let a: Int? = 1
let b: Int? = 2
let c: Int? = 3
var d: Int? = a! + b! + c!
/* error: cannot convert value of type 'Int'
to specified type 'Int?' */
var e: Int? = a! - b! - c! // same error
Bug not present:
/* example 1 */
var d: String? = a! + b!
/* example 2 */
let aa = a!
let bb = b!
let cc = c!
var d: String? = aa + bb + cc
var e: String = aa + bb + cc
/* example 3 */
var d: String? = String(a!) + String(b!) + String(c!)
However as this is Swift 3.0-dev, I'm uncertain if this is really a "bug", as well as what's the policy w.r.t. reporting "bugs" in a not-yet-production version of code, but possibly you should file radar for this, just in case.
As for answering your question as how to circumvent this issue:
use e.g. intermediate variables as in Bug not present: Example 2 above,
or explicitly tell Swift all terms in the 3-term expression are strings, as in Bug not present: Example 3 above,
or, better yet, use safe unwrapping of your optional, e.g. using optional binding:
var d: String? = nil
if let a = a, b = b, c = c {
d = a + b + c
} /* if any of a, b or c are 'nil', d will remain as 'nil';
otherwise, the concenation of their unwrapped values */
Swift 3
let q: String? = "Hello"
let w: String? = "World"
let r: String? = "!"
var array = [q, w, r]
print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// HelloWorld!
let q: String? = "Hello"
let w: String? = nil
let r: String? = "!"
var array = [q, w, r]
print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// Hello!
func getSingleValue(_ value: String?..., seperator: String = " ") -> String? {
return value.reduce("") {
($0) + seperator + ($1 ?? "")
}.trimmingCharacters(in: CharacterSet(charactersIn: seperator) )
}
let val: String? = "nil"
val.flatMap({(str: String) -> String? in
return str + "value"
})
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = ""
let arr = [a,b,c]
arr.compactMap { $0 }.joined(separator: " ")
compactMap be used to filter out nil values from flattened arrays

Swift block syntax failure to infer type

Can anyone explain why this single line block with an implicit return compiles:
let r = withUnsafePointer(&msg) {
dn_expand(UnsafePointer($0), eomorig: UnsafePointer($0).advancedBy(msg.count), comp_dn: UnsafePointer($0).advancedBy(offset), exp_dn: &buf, length: buf.count)
}
but this version refactored where the only difference is to avoid the multiple calls to UnsafePointer($0) doesn't:
let s = withUnsafePointer(&msg) {
let p = UnsafePointer($0)
return dn_expand(p, eomorig: p.advancedBy(msg.count), comp_dn: p.advancedBy(offset), exp_dn: &buf, length: buf.count)
}
with error message:
Cannot convert value of type 'inout [UInt8]' (aka 'inout Array<UInt8>') to expected argument type 'inout _'
The dn_function being called is just a trivial wrapper around dn_expand from libresolv:
public static func dn_expand(msg: UnsafePointer<UInt8>, eomorig: UnsafePointer<UInt8>, comp_dn: UnsafePointer<UInt8>, exp_dn: UnsafeMutablePointer<CChar>, length: Int) -> Int {
return Int(res_9_dn_expand(msg, eomorig, comp_dn, exp_dn, Int32(length)))
}
As already said in the comments, withUnsafePointer() is not the
correct way to get a pointer to the element storage. It compiles, but
gives unexpected results, as the following example demonstrates:
var msg: [UInt8] = [1, 2, 3, 4]
func foo(x: UnsafePointer<UInt8>) {
print(x[0])
}
withUnsafePointer(&msg) {
foo(UnsafePointer($0))
}
This prints "random" numbers, but not the expected 1. The correct
way is to call the withUnsafeBufferPointer() method on the array:
msg.withUnsafeBufferPointer {
foo($0.baseAddress)
}
In your case that would be
let r = msg.withUnsafeBufferPointer {
dn_expand($0.baseAddress, eomorig: $0.baseAddress + $0.count, ...)
}
Here the return type of the closure is inferred automatically because
it is a "single-expression" closure. If the closure contains more
than one expression, you have to specify its type:
let r = msg.withUnsafeBufferPointer { bufPtr -> Int in
let p = bufPtr.baseAddress
return dn_expand(p, eomorig: p + msg.count, ...)
}
or let the compiler infer the return type from the context:
let r: Int = msg.withUnsafeBufferPointer { bufPtr in
let p = bufPtr.baseAddress
return dn_expand(p, eomorig: p + msg.count, ...)
}

Swift 2.1 Closure

At first, I apologize for my English!
Please help me detect when I was wrong.
let arrayInt = [0, 1, 2, 3, 4, 5, 7, 8, 9]
func myF(array: [Int], cl:(n1: Int, n2: Int) -> Bool) -> Int {
var number : Int
for value in array {
if cl(n1: number, n2: value) {
number = value
}
}
return number
}
myF(arrayInt, { cl: (n1: Int, n2: Int) -> Bool in
return n1 < n2
})
The function takes an array of Int and closure returns Int. Closure should take two Int numbers and return Bool yes or no. It is necessary to walk in a loop through the array and compare elements of array with variable using closure . If closure returns yes, you write the value of the array into variable. At the end of the function returns the variable. We need find max and min value in array.
I have 3 issue:
consecutive statements on a line must be separated by ';'
expected expression
contextual type for closure argument list expects 2 arguments, which cannot be implicitly ignored
Please don't proposed me use method "sort()". I am learning of "closure".
First of all you need to initialize your number variable: var number : Int -> var number = 0
Second, the function call with closure is not correct. There are several ways to call a closure:
let y = myF(arrayInt, cl: { (n1: Int, n2: Int) -> Bool in
return n1 < n2
})
or
let x = myF(arrayInt) { (n1, n2) -> Bool in
return n1 < n2
}
or even
let z = myF(arrayInt) { n1, n2 in
return n1 < n2
}
and
let w = myF(arrayInt) { $0 < $1 }
This link and this one should help you
Full code sample:
let arrayInt = [1, 2, 3, 0, 4]
func myF(array: [Int], cl: (n1: Int, n2: Int) -> Bool) -> Int {
var number = 0
for i in array {
if cl(n1: number, n2: i) {
number = i
}
}
return number
}
let x = myF(arrayInt) { (n1, n2) -> Bool in
return n1 < n2
}
First replace:
myF(arrayInt, { cl: (n1: Int, n2: Int) -> Bool in
by:
myF(arrayInt, cl: { (n1: Int, n2: Int) -> Bool in
because cl is the parameter name and all included in { } is the closure.
Second initialize number in myF function replacing:
var number : Int
by:
var number = array[0]
if the goal of the closure is to find max or min value.

Swift's pow() function won't accept Doubles as arguments

I created this infix operator ^^ as a substitute to using the pow function:
infix operator ^^ { associativity left precedence 155 }
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T {
return pow(left as Double, right as Double)
}
I used the IntegerLiteralConvertible protocol as a type constraint for the generics left and right, because from my understanding this diagramm shows, that it basically includes all number types.
In order to use the pow function I have to downcast left and right to Double though, which I did using the as operator. It's not the safest approach, but that's besides the point.
When implementing the function this way swift tells me:
<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)'
return pow(left as Double, right as Double)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now as far as I know pow takes two Doubles as parameters, so why is it complaining about this?
why is it complaining about this?
Because pow returns Double. And Double is not identical to T. The error message is misleading, but it means "Cannot find pow that accepts (Double, Double) and returns T type"
I think you are misunderstanding "cast" in Swift. In Swift as does not convert numeric types.
let intVal:Int = 12
let doubleVal:Double = intVal as Double
// ^ [!] error: 'Int' is not convertible to 'Double'
And If the type of operand is not predictable at compile time, invalid casting causes runtime error:
func foo<T: IntegerLiteralConvertible>(x: T) {
x as Double // <-- Execution was interrupted
}
foo(12 as Int)
Instead, we must explicitly "convert" them. see the document: Numeric Type Conversion
let intVal:Int = 12
let doubleVal:Double = Double(intVal)
This works only because Double has init(_ v: Int) initializer. The following code does not compile:
func foo<T: IntegerLiteralConvertible>(x: T) {
Double(x)
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T'
}
Because Double does not have init<T:IntegerLiteralConvertible>(_ val:T) initializer.
So, if you want to use pow(), you must convert T to Double for arguments, and convert Double to T for returning value. And there is no simple solution for that.
Thanks #Martin R. This comes from the only question I have posted so far at S.O.
import Cocoa
Protocols
protocol Fraction { init(_ value:Double) ; var asDouble : Double { get } }
protocol Text { init(_ value:String) ; var asString : String { get } }
Extensions
extension String : Text { var asString : String { return self } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
infix operator ^^
infix operator ^^ { associativity left precedence 170 }
func ^^<T:IntegerType, U:IntegerType> (var base:T, var power:U) -> T {
if power < 0 { return 0 }
var result: T = 1
if power > 0 {
if power % 2 == 1 { result *= base }
power /= 2
}
while power > 0 {
base *= base
if power % 2 == 1 { result *= base }
power /= 2
}
return result
}
func ^^<T:Fraction, U:Fraction> (base: T, power: U) -> T {
return T(pow(base.asDouble, power.asDouble))
}
func ^^<T:Text, U:IntegerType> (base:T, var power:U) -> T {
if power <= 0 { return "" as T }
if power == 1 { return base as T }
return power > 1 ? {var result = ""; for x in 1...power { result+=base.asString };return result as T}() : "" as T
}
func ^^<T:Text, U:Text> (base:T, var power:U) -> T {
return "" as T
}
testing
println(1 ^^ -1) // "0" Int
println(1 ^^ 0) // "1" Int
println(1 ^^ 1) // "1" Int
println(1 ^^ 2) // "1" Int
println(2 ^^ -1) // "0" Int
println(2 ^^ 0) // "1" Int
println(2 ^^ 1) // "2" Int
println(2 ^^ 2) // "4" Int
println(2 ^^ 8) // "256" Int
println(2 ^^ 16) // "65536" Int
println(2 ^^ 32) // "4294967296" Int
println(2 ^^ 62) // "4611686018427387904"
println(UInt(2) ^^ 8) // "256" UInt
println(UInt64(2) ^^ 8) // "256" UInt64

How do you overload an operator in swift?

Say you have a class C. It has two instance variables, number and vector. vector is just an array of either ints or doubles.
I would like to do the following:
c1 = C()
c1.number = 2
c1.vector = [1,2,3]
c2 = C()
c2.number = 3
c2.vector = [4,6,7]
println(c1.number + c2.number) \\print to screen 5
println(c1.vector + c2.vector) \\ print [5,8,10]
Basically, I'm looking to overload the "+" operator so that it knows which "version" of the "+" to use depending of the type.
The + operator is already defined for the type Array. It does an array merge and tacks the values of the rvalue onto the lvalue. To do a sum of values by index you can do something like this:
protocol Numeric { }
extension Double: Numeric {}
extension Int: Numeric {}
func +<T: Numeric>(left: [T], right: [T]) -> [T]? {
var numElements: Int = 0
if count(left) != count(right) {
return nil
} else {
numElements = count(left)
}
var result = [T]()
for var i = 0; i < numElements; ++i {
if let lvalue = left[i] as? Int, rvalue = right[i] as? Int {
result.append(lvalue + rvalue as! T)
} else if let lvalue = left[i] as? Double, rvalue = right[i] as? Double {
result.append(lvalue + rvalue as! T)
}
}
return result
}
But generally, I wouldn't advise overriding a predefined operator because of the high potential to cause confusion and chaos later on down the road.