Simple Swift function return error - macos

I am converting some algorithm pseudo code to Swift and have the following function:
func max(a: [Int], b: Int) {
var result = a[0]
var i: Int
for (i = 1; i <= b; i++) {
if (a[i] > result) {
result = a[i]
}
}
return result
}
I get an error when returning the result: 'Int' is not convertible to '()'
I've had a search online and can't find an answer to this question and am hoping someone can point me in the right direction.
Thanks

The return type is missing in the function declaration:
func max(inout a: [Int], b: Int) -> Int {
^^^^^^
Without a return type, swift defaults to an empty tuple (), and that's what the error means: int is not convertible to an empty tuple.
Also note that your return statement is misplaced: it should go right before the last closing bracket
}
return result
}
and not
return result
}
}

You must Implement the return type like this
func max(inout a: [Int], b: Int)-> Int {
var result = a[0]
var i: Int
for (i = 1; i <= b; i++) {
if (a[i] > result) {
result = a[i]
}
}
return result
}

Related

Global `comptime var` in Zig

In Zig, I can do this with no problems:
fn foo() void {
comptime var num: comptime_int = 0;
num += 1;
}
But when I try declaring the variable outside of a function, I get a compile error:
comptime var num: comptime_int = 0;
fn foo() void {
num += 1;
}
fn bar() void {
num += 2;
}
error: expected block or field, found 'var'
Zig version: 0.9.0-dev.453+7ef854682
Use the method used in zorrow. It defines the variable in a function (a block works too), then it returns a struct with functions for accessing it.
You can create a struct that defines get and set functions:
const num = block_name: {
comptime var self: comptime_int = 0;
const result = struct {
fn get() comptime_int {
return self;
}
fn increment(amount: comptime_int) void {
self += amount;
}
};
break :block_name result;
};
fn foo() void {
num.increment(1);
}
fn bar() void {
num.increment(2);
}
In the future, you will be able to use a const with a pointer to the mutable value, and the method shown above will no longer be allowed by the compiler: https://github.com/ziglang/zig/issues/7396

Sort a vector of objects by a member of map in this vector

I have a very simple question i guess but...
I have to sort a vector by it's own member, but I can not.
This is my function for filling the vector with objects from another vector.
I have to sort the vector SortDealers by specific product but I don't know how to send the name of the Stock to my overloading operator<
void CShop::sortVector(const CStock& s1)
{
vector<CDealer> SortDealers;
vector<CDealer* >::iterator it = Dealers.begin();
while (it != Dealers.end())
{
if ((*(*it)).ComapareNameProducts(s1))
{
SortDealers.push_back(*(*it));
}
it++;
}
sort(SortDealers.begin(), SortDealers.end());
copy(SortDealers.begin(), SortDealers.end(), ostream_iterator<CDealer>(cout, "\n"));
}
this is overloading operator<:
I have to sort by unsigned member of the map.
bool CDealer::operator<(const CDealer & o1)
{
unsigned res1 = 0;
unsigned res2= 0;
map<const CStock, pair<unsigned, double>>::const_iterator it = Stock.begin();
map<const CStock, pair<unsigned, double>>::const_iterator iter = o1.Stock.begin();
while (it != Stock.end())
{
res1 += it->second.first;
it++;
}
while (iter != o1.Stock.end())
{
res2 += iter->second.first;
iter++;
}
return (res1 < res2);
}
You can use functor:
class less_than
{
const string stockname;
public:
less_than(string s) : stockname(s) {}
inline bool operator() const (const CDealer& a, const CDealer& b)
{
// use stockname here
}
};
sort(SortDealers.begin(), SortDealers.end(), less_than("name"));
Also you can use lambda expression providing stock name in its capture.
Related answer.

std::find_if and lambda referencing structure field

In this question we have:
#include <list>
#include <algorithm>
struct S
{
int S1;
int S2;
};
int main()
{
std::list<S> l;
S s1;
s1.S1 = 0;
s1.S2 = 0;
S s2;
s2.S1 = 1;
s2.S2 = 1;
l.push_back(s2);
l.push_back(s1);
auto it = std::find_if(l.begin(), l.end(), [] (S s)
{ return s.S1 == 0; } );
}
But, if I want to find a match for s1.S1, I might try:
auto it = std::find_if(l.begin(), l.end(), [s1.S1] (S s)
{ return s.S1 == s1.S1; } );
I get a compiler error, however. This works:
auto foo = s1.S1;
auto it = std::find_if(l.begin(), l.end(), [foo] (S s)
{ return s.S1 == foo; } );
I think I understand why I need to introduce a temporary simple type as we can think of the [foo] as like a function parameter, but the use case of looking up a structure member would seem to be a frequent requirement, so what is the rationale for not supporting the usage? Or is there another way to avoid the temporary variable?
In C++11 I think you're stuck with adding in the intermediate variable. In C++14 you can use a capture with an initializer:
std::list<S>::iterator it = std::find_if(l.begin(), l.end(),
[foo = s1.S1] (S s) { return s.S1 == foo; } );
// ^^^^^^^^^^^^^

Is it possible to do a for loop while an Int is in a certain range in swift?

Is it possible to do a regular for loop while an Int is in a certain range in swift?
this is kinda what I want to achieve:
func someFunc(var plusOrMinus:Int) {
for var i:Int = 0; i == -8...8;i += plusOrMinus {
}
}
or:
func someFunc(var plusOrMinus:Int) {
for var i:Int = 0; i in -8...8;i += plusOrMinus {
}
}
or:
func someFunc(var plusOrMinus:Int) {
for var i:Int = 0; i == <-8,8>;i += plusOrMinus {
}
}
None of these work. Hope you understand the question and can help me. :)
To check if an Int is in the range -8...8 you can just check both ends of the range with a conditional and combine them with &&:
func someFunc(var plusOrMinus:Int) {
for var i = 0; i >= -8 && i <= 8; i += plusOrMinus {
println(i)
}
}
Note: Swift can infer the type Int so you don't have to assign it explicitly.
From #MartinR's comment, you could use the pattern-match operator ~= to check if i is in the range, but the method above is more straightforward and likely more efficient.
func someFunc(var plusOrMinus:Int) {
for var i = 0; -8...8 ~= i; i += plusOrMinus {
println(i)
}
}
If you want to use for…in rather than a C-style loop, you could use stride, but check which direction you’re going in to determine whether you want a target that’s less than or more than the initial value:
func someFunc(plusOrMinus: Int) {
precondition(plusOrMinus != 0)
let target = plusOrMinus > 0 ? 8 : -8
for i in stride(from: 0, through: target, by: plusOrMinus) {
println(i)
}
}
The -8...8 range you were going for is possible, but you have to explicitly create a closed interval and then check your counter is within it:
func someFunc(plusOrMinus: Int) {
let interval = -8...8 as ClosedInterval
for var i = 0; interval.contains(i); i += plusOrMinus {
println(i)
}
}

Implementing FNV hash in swift

I am trying to implement a version of FNV hash in swift. Here it is in Objective-C:
+ (uint32_t)hash:(uint8_t *)a length:(uint32_t)length
{
uint8_t *p;
uint32_t x;
p = a;
x = *p << 7;
for (int i=0; i<length; i++) {
x = (1000003 * x) ^ *p++;
x ^= length;
}
if (x == -1) {
x = -2;
}
return x;
}
Here is my attempt at porting it to swift:
func hashFNV(data: UInt8[]) -> UInt32 {
var x = data[0] << 7
for byte in data {
x *= 1000003
x ^= byte
x ^= data.count
}
if x == -1 {
x = -2
}
return x
}
It compiles but results in an error at runtime:
EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0)
Same error when I try in the playground:
Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
* thread #1: tid = 0x619fa, 0x000000010d119aad, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
* frame #0: 0x000000010d119aad
frame #1: 0x0000000100204880 libswift_stdlib_core.dylib`value witness table for Swift.Int + 160
I thought that maybe it was related to the overflow, but the following code also fails with the same error:
func hashFNV(data: UInt8[]) -> UInt32 {
var x = UInt32(data[0]) << 7
for byte in data {
x = 1000003 &* x
x ^= byte
x ^= data.count
}
if x == -1 {
x = -2
}
return x
}
EDIT:
Actually, shouldn't the fact that I am trying to assign -2 to x result in a compile error? I thought swift won't implicitly cast from what looks like Int (-2) to UInt32 (x).
Same with the x ^= byte line. byte should be UInt8 and x is UInt32.
EDIT 2:
This was a compile error (see comments below).
Fixed the compile error, still fails at runtime:
func hashFNV(data: UInt8[]) -> UInt32 {
var x = Int(data[0]) << 7
for byte in data {
x = 1000003 &* x
x ^= Int(byte)
x ^= data.count
}
if x == -1 {
x = -2
}
return UInt32(x)
}
If you are still looking for an implementation, here is mine. It is built much like the regular default Hasher from the standard lib.
struct HasherFNV1a {
private var hash: UInt = 14_695_981_039_346_656_037
private let prime: UInt = 1_099_511_628_211
mutating func combine<S: Sequence>(_ sequence: S) where S.Element == UInt8 {
for byte in sequence {
hash ^= UInt(byte)
hash = hash &* prime
}
}
func finalize() -> Int {
Int(truncatingIfNeeded: hash)
}
}
extension HasherFNV1a {
mutating func combine(_ string: String) {
combine(string.utf8)
}
mutating func combine(_ bool: Bool) {
combine(CollectionOfOne(bool ? 1 : 0))
}
}
Keep in mind that this is FNV1a, if you truly need FNV1 you can just switch the 2 lines in the loop around.
I found this GPL Swift implementation:
//
// FNVHash.swift
//
// A Swift implementation of the Fowler–Noll–Vo (FNV) hash function
// See http://www.isthe.com/chongo/tech/comp/fnv/
//
// Created by Mauricio Santos on 3/9/15.
import Foundation
// MARK:- Constants
private struct Constants {
// FNV parameters
#if arch(arm64) || arch(x86_64) // 64-bit
static let OffsetBasis: UInt = 14695981039346656037
static let FNVPrime: UInt = 1099511628211
#else // 32-bit
static let OffsetBasis: UInt = 2166136261
static let FNVPrime: UInt = 16777619
#endif
}
// MARK:- Public API
/// Calculates FNV-1 hash from a raw byte array.
public func fnv1(bytes: [UInt8]) -> UInt {
var hash = Constants.OffsetBasis
for byte in bytes {
hash = hash &* Constants.FNVPrime // &* means multiply with overflow
hash ^= UInt(byte)
}
return hash
}
/// Calculates FNV-1a hash from a raw byte array.
public func fnv1a(bytes: [UInt8]) -> UInt {
var hash = Constants.OffsetBasis
for byte in bytes {
hash ^= UInt(byte)
hash = hash &* Constants.FNVPrime
}
return hash
}
/// Calculates FNV-1 hash from a String using it's UTF8 representation.
public func fnv1(str: String) -> UInt {
return fnv1(bytesFromString(str))
}
/// Calculates FNV-1a hash from a String using it's UTF8 representation.
public func fnv1a(str: String) -> UInt {
return fnv1a(bytesFromString(str))
}
/// Calculates FNV-1 hash from an integer type.
public func fnv1<T: IntegerType>(value: T) -> UInt {
return fnv1(bytesFromNumber(value))
}
/// Calculates FNV-1a hash from an integer type.
public func fnv1a<T: IntegerType>(value: T) -> UInt {
return fnv1a(bytesFromNumber(value))
}
/// Calculates FNV-1 hash from a floating point type.
public func fnv1<T: FloatingPointType>(value: T) -> UInt {
return fnv1(bytesFromNumber(value))
}
/// Calculates FNV-1a hash from a floating point type.
public func fnv1a<T: FloatingPointType>(value: T) -> UInt {
return fnv1a(bytesFromNumber(value))
}
// MARK:- Private helper functions
private func bytesFromString(str: String) -> [UInt8] {
var byteArray = [UInt8]()
for codeUnit in str.utf8 {
byteArray.append(codeUnit)
}
return byteArray
}
private func bytesFromNumber<T>(var value: T) -> [UInt8] {
return withUnsafePointer(&value) {
Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: sizeof(T)))
}
}

Resources