Cannot convert return expression of type Int to Int - swift

I wonder why this is not work:
func removingOnce (_ item: Int, from array:[Int]) -> [Int]{
var intToReturn :Int?
intToReturn = 0
for ob in array5{
if (ob == item){
intToReturn = item
}
}
return intToReturn
}
It warn me with error: Cannot convert an expression of type Int to return type Int.
It make no sense at all

The warning reads
Cannot convert an expression of type Int to return type [Int]
and not as you stated it. (I tested it in Playground)
The reason for your error is that you return an Int value intToReturn, but according to the method definition, it should return an array of Ints ->[Int]
Either change the return value to the resulting Int array or change the return type in the method definition to ->Int?
Also, you declare intToReturn as an optional Int value. (Int?) but just after that, you assign it a value and it will not ever be nil. Rather do:
var intToReturn:Int = 0 or
var intToReturn = 0

Try this
[] menas array
func removingOnce (_ item: Int, from array:[Int]) -> Int{
var intToReturn :Int?
intToReturn = 0
for ob in array5{
if (ob == item){
intToReturn = item
}
}
return intToReturn
}

This is the best solution in my opinion to do this method:
func removingOnce (_ item: Int, from array:[Int]) -> Int? {
for ob in array {
if (ob == item){
return ob
}
}
return nil
}
The problem was the returning value. You wanted to return Int and in function you return an array of Ints.

Related

Getting error non-void return value in void function | Swift

I don't understand why I am getting the following error when executing this function:
error: unexpected non-void return value in void function
return [index, dic[value]!]
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
nums.enumerated().forEach { index, value in
//the goal is to get the index of the value matching the difference
//check if current value == anything in dictionary
//MARK: Add the Index and Difference to Dictionary
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
return [index, dic[value]!]
}
dic[difference] = index
}
return []
}
print(findIndexes([0,11,15,2,7], 9))
I'm unclear what you're trying to do, but this is a version of what you are doing that compiles:
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
for (index, value) in nums.enumerated() {
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
return [index, dic[value]!]
}
dic[difference] = index
}
return []
}
Why the difference? for...in is a loop. You can return from the surrounding function from within it, break out of it, etc. forEach loops implicitly but it is not a loop; it takes a closure, and you can't return out of that unless it's a closure that yields a return value, and this one doesn't; its type, as you can see from the docs, is (Self.Element) throws -> Void — and Void means "no return value".
If you insist on using forEach, you can do what you're trying to do with a bit of extra jiggery-pokery:
func findIndexes(_ nums: [Int], _ target: Int) -> [Int] {
var dic = [Int:Int]()
var answer: [Int] = []
nums.enumerated().forEach { index, value in
let difference = (target - value)
if (dic.keys.contains(value) && !dic.values.contains(index)) {
answer = [index, dic[value]!]
return
}
dic[difference] = index
}
return answer
}
I think that does what you're trying to do, but I'm not sure; it seems unnecessarily obscure. In my personal opinion, the way to program is to Say What You Mean (SWYM).

Largest Even Number in an Array using Swift

I'm a beginner in Swift, I'm trying to make a function that determines the largest even number in an array, here's my code that's not working:
func largestEven(array: [Int]) -> Int {
let array = [5,12,6,8]
var evenArray = array.filter({$0 % 2 == 0})
let highestEven = evenArray.max()
return highestEven
}
print(largestEven(array: [5,12,6,8]))
Change
func largestEven(array: [Int]) -> Int {
to
func largestEven(array: [Int]) -> Int? {
The reason is that max() yields an Optional Int, because the array might be empty. So you cannot return a simple Int; you must return that Optional.
Not sure why you define a local array in your function.
A simple implementation could be something like (note the optional Int as return type):
func largestEven(array: [Int]) -> Int? {
array.filter { $0.isMultiple(of: 2) }.max()
}

swift affect value to inout generic variable

I want to simplify this piece of code with a T variable but could not succeed in compiling it. Hope could you give me the way.
here is the "duplicate" code I want to rewrite :
func getIntegerValue (listValues: [Any], numValueToRead: Int, readValue: inout Int) -> Bool {
if numValueToRead < 0 || numValueToRead >= listValues.count {
return false
}
let value = listValues [numValueToRead]
if type (of: value) == type(of: readValue) {
readValue = value as! Int
return true
} else {
return false
}
}
func getStringValue (listValues: [Any], numValueToRead: Int, readValue: inout String) -> Bool {
if numValueToRead < 0 || numValueToRead >= listValues.count {
return false
}
let value = listValues [numValueToRead]
if type (of: value) == type(of: readValue) {
readValue = value as! String
return true
} else {
return false
}
}
Here is the code I wrote but do not compile :
func getValue <T> (listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
if numValueToRead < 0 || numValueToRead >= listValues.count {
return false
}
let value = listValues [numValueToRead]
if type (of: value) == type(of: readValue) {
switch value {
case let integerValue as Int:
readValue = integerValue
case let stringValue as String:
readValue = stringValue
default:
return false
}
return true
} else {
return false
}
}
for those affectations I got those compilation errors :
readValue = integerValue -> 'Int' is not convertible to 'T'
readValue = stringValue -> 'String' is not convertible to 'T'
Is there a way to synthetise my two functions with a unique one using generics ?
You theoretically could make it compile by adding forced casts, since you already know that value has the type T:
case let integerValue as Int:
readValue = integerValue as! T
case let stringValue as String:
readValue = stringValue as! T
But the far better solution is to use a conditional cast (as? T) and
conditional binding (if let):
func getValue<T>(listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
if numValueToRead < 0 || numValueToRead >= listValues.count {
return false
}
let value = listValues[numValueToRead]
if let tvalue = value as? T {
readValue = tvalue
return true
} else {
return false
}
}
which then works for arbitrary types, not only Int and String.
A “swiftier” way would be return an optional value (with nil
indicating "no value"). The code can then be simplified to
func getValue<T>(listValues: [Any], numValueToRead: Int) -> T? {
guard listValues.indices.contains(numValueToRead) else {
return nil
}
return listValues[numValueToRead] as? T
}
This should work:
func getValue <T> (listValues: [Any], numValueToRead: Int, readValue: inout T) -> Bool {
if numValueToRead < 0 || numValueToRead >= listValues.count {
return false
}
let value = listValues [numValueToRead]
if type (of: value) == type(of: readValue) {
if let genericValue = value as? T {
readValue = genericValue
return true
}
return false
} else {
return false
}
}
At first sight, the function is wrongly named. You cannot call function getValue when it returns bool... I would call it transform or modify or something other than get value, because you are NOT getting value.
I think this method suits better your needs, not tested tought it should work.
func transformValue<T>(from listValues: [Any], numValueToRead: Int, readValue: inout T?) throws -> Bool {
// Guard suits better this case...
guard numValueToRead > 0 || numValueToRead < listValues.count else { return false }
let value = listValues[numValueToRead]
if type (of: value) == type(of: readValue) {
guard let value = value as? T else {
throw NSError(
domain: "Smth",
code: 1,
userInfo: ["Description": "Failed to cast to generic type T"]
)
}
readValue = value as? T
return true
}
return false // No need to call else...
}
Explenation: Returning optional generic type T is much safer. You try to cast it, you fail and you throw error that something went wrong. In my opinion saving force casts with throwing errors is much more safer approach, you know what went wrong and so.
As #MartinR pointed out, returning a nil value instead of an inout+Bool combination gives the same results, but with less, and more readable code. This is the path Swift also took when importing most of the NSError ** methods from Objective-C (i.e. dropped the last parameter, imported them as throwable functions).
These being said, another approach would be to add an extension over Array for extracting the value:
extension Array {
subscript<T>(_ index: Int, as type: T.Type) -> T? {
guard 0..<count ~= index else { return nil }
return self[index] as? T
}
}
let arr: [Any] = [1, "two", 3, "four"]
arr[1, as: String.self] // two
arr[2, as: String.self] // nil

Cannot convert type of Int to expected value [MyCustomType]

Xcode 8.3.3 is giving me this Swift 3 error on this line
values2[index] = nextValue(currentValue)
Cannot convert value of type 'Int' to expected argument type 'Card'
Here's my code:
//
// Card.swift
// match
//
// Created by quantum on 05/09/2017.
// Copyright © 2017 Quantum Productions. All rights reserved.
//
import UIKit
class Card: NSObject {
var quantity = 0
var fill = 0
var shape = 0
var color = 0
override var description : String {
return "Q" + String(quantity) + "/F" + String(fill) + "/S" + String(shape) + "/C" + String(color)
}
override init() {
super.init()
}
static func properties() -> [String] {
return ["quantity", "fill", "shape", "color"]
}
static func isMatch(cards: [Card]) -> Bool {
for property in self.properties() {
var sum = 0
for card in cards {
sum = sum + (card.value(forKey: property) as! Int)
}
if !([3, 6, 9, 7].contains(sum)) {
return false
}
}
return true
}
static func deck(_ values: [Int], _ index: Int, _ max: Int, _ acc: [Card]) -> [Card]{
let currentValue = values[index]
var values2 = values
if currentValue >= max {
if index == 0 {
return acc
}
values2[index] = 0
values2[index-1] = values2[index-1] + 1
return deck(values, index - 1, max, acc)
} else {
var acc2 = acc
let card = Card()
for (index, element) in self.properties().enumerated() {
card.setValue(values[index], forKey: element)
}
acc2.append(Card())
values2[index] = nextValue(Card())
return deck(values2, index, max, acc2)
}
}
func nextValue(_ v: Int) -> Int {
if (v == 0) {
return 1
} else if (v == 1) {
return 2
}
return 4
}
static func deck() -> [Card] {
return deck([1,1,1,1], 4, 3, [Card]())
}
}
this is inside of my Card class.
Strangely, if I try (this is wrong, I'm testing the compiler error)
values2[index] = nextValue(Card())
I get the error Cannot assign the value of type (Int) -> Int to type 'Int'.
Swift thinks my Card is an Int? I'm confused as to what's happening.
I expected to get the call nextvalue with the variable currentvalue, which should be an Int.
It's a bad error message from the compiler.
Your problem is that deck is declared static, but you're trying to call nextValue which is not declared static. This means that nextValue implicitly takes a hidden argument, self, but deck isn't providing it.
If you add static to the func nextValue declaration, it will work like you expect. (You'll get an error on the line referring to self.properties instead, but you'll be closer.)
To make this work properly, you probably want all these functions to be non-static instead. Just think about how this code gets called initially (i.e. how you get your first instance of Card).
A static method cannot call an instance method: the idea makes no sense, as there is no instance. Thus your reference to nextValue is impossible. That is why the line is problematic. How can a static method deck call an instance method nextValue?

Swift: Function returning an Array of IntegerType

I would like to create a function that takes an NSData parameter, and, depending on what it reads from the NSData it returns an Array<Int8>, Array<Int16>, Array<Int32>, or Array<Int64>.
Basically, I need to return an array of IntegerType, with the specific subtype being determined at runtime.
I am stuck at the signature declaration of the function. (The inside would just be a simple switch, that would create the specific array type and return it).
The following very basic test does not compile
class Test {
func test(data:NSData) -> Array<IntegerType> {
return [1, 2, 3]
}
}
EDIT
It seems to be currently not possible, not because of having to return an array of a protocol type, but because the IntegerType protocol uses Self. Here is an interesting related question
IntegerType is a protocol, so the following should work:
class Test {
func test(data:NSData) -> Array<T: IntegerType> {
[1, 2, 3]
}
}
You can use enum with associated values for that:
enum IntArray {
case Int8([Swift.Int8])
case Int16([Swift.Int16])
case Int32([Swift.Int32])
case Int64([Swift.Int64])
}
class Test {
func test(data:NSData) -> IntArray {
return IntArray.Int8([1, 2, 3]);
}
}
on user side:
let obj = Test()
let array = obj.test(dat)
switch array {
case .Int8(let ary):
// here, ary is [Int8]
...
case .Int16(let ary):
// here, ary is [Int16]
...
case .Int32(let ary):
// here, ary is [Int32]
...
case .Int64(let ary):
// here, ary is [Int64]
...
}
As others have said in the comments, this won't work if you are trying to determine the function's return type at runtime. Swift generics only work at compile time, so changing the return type based off of what's in an NSData won't work.
If you can determine the return type at compile time, then you can use a generic function declaration like so:
func test<T: IntegerType>(data: NSData) -> Array<T> {
return [1, 2, 3]
}
Note: If you don't specify the type explicitly in your function somehow, then you'll need to define the variable the value returned from the function is assigned to. Like so:
var int8Array: Array<Int8> = test(NSData())
Since none of the generic based solutions are working, why don't you try returning [Any] and just check the return type as follows:-
func test(data:NSData) -> [Any]
{
var value1:Int8 = 1
var value2:Int8 = 2
return [value1,value2]
}
var x = test(NSData())
for xin in x
{
var intxin = xin as? Int8
if intxin != nil
{
println(intxin!)
}
}
The way I solved my problem was by defining the following protocol:
protocol IntegerArrayProtocol {
init(rawData: NSData!, length: Int)
func count() -> Int
subscript(index:Int) -> Int { get }
}
This deals with all the operations I need to perform on the array:
Read it from raw memory
Count how many elements it has
Access its elements by index, always returning Ints, regardless of the underlying integer
type
Then, I created a parameterized class that implements the protocol:
final class IntegerArray<T: ConvertibleToInteger>: IntegerArrayProtocol {
let arr: [T]
init(rawData: NSData!, length: Int){
//create array and allocate memory for all elements
arr = Array<T>(count: length, repeatedValue: T.zero())
// read it from the NSData source
// ....
}
func count() -> Int{
return arr.count
}
subscript(index:Int) -> Int {
get {
return arr[index].asInt()
}
}
}
The parameter types T should be able to convert themselves to Int, and should have a zero value (used when I initialize the array). For that, I created the ConvertibleToInteger protocol, which is used above to restrict the possible Ts:
protocol ConvertibleToInteger {
class func zero() -> Self
func asInt() -> Int
}
Then, I extended every type that I would like to create arrays of:
extension Int8: ConvertibleToInteger{
static func zero() -> Int8{
return 0
}
func asInt() -> Int{
return Int(self)
}
}
extension Int16: ConvertibleToInteger{
static func zero() -> Int16{
return 0
}
func asInt() -> Int{
return Int(self)
}
}
extension Int32: ConvertibleToInteger{
static func zero() -> Int32{
return 0
}
func asInt() -> Int{
return Int(self)
}
}
extension Int64: ConvertibleToInteger{
static func zero() -> Int64{
return 0
}
func asInt() -> Int{
return Int(self)
}
}
Finally, to read an array from NSData, I created the following function:
func readArray(rawData: NSData, length: Int): IntegerArrayProtocol? {
qBytes = // read from NSData how many bytes each element is
switch(qBytes){
case 1:
return IntegerArray<Int8>(rawData: rawData, length: length)
case 2:
return IntegerArray<Int16>(rawData: rawData, length: length)
case 3 ... 4:
return IntegerArray<Int32>(rawData: rawData, length: length)
case 5 ... 8:
return IntegerArray<Int64>(rawData: rawData, length: length)
default:
return nil
}
}