How can I make a typed index in Zig - indexing

I have an algorithm that has two arrays with their respective indices. Only, it would be very easy to mix both indices and access one of the arrays with the wrong index. For example:
var array1 = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var index1 = 7; // the 8th element in array1, fine because array1 has a length of 10
var array2 = [_]u8{ 1, 2, 3, 4, 5 };
var index2 = 2; // the 3rd element in array2, fine because array2 has a length of 5
array2[index1] // woops, I used the wrong index with the wrong array
Is there a way to make a custom index type to associate an array with a specific type of index such that indexing an array with the wrong type of index will result in a compile error?
Such as:
var array1 = [_:Index1]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // with index type 'Index1'
var index1 : Index1 = 7; // index of type 'Index1'
var array2 = [_:Index2]u8{ 1, 2, 3, 4, 5 }; // with index type 'Index2'
var index2 : Index2 = 2; // index of type 'Index2'
array2[index1] // ERROR: array2 expects Index2 type index but Index1 type is used

const std = #import("std");
fn PickyArray(comptime T: type, n: usize, extra: anytype) type {
_ = extra;
return struct {
const Self = #This();
pub const Index = struct {
idx: usize,
};
unsafe_items: [n]T,
pub fn init(xs: [n]T) Self {
return .{.unsafe_items = xs};
}
pub fn get(self: Self, idx: Index) T {
return self.unsafe_items[idx.idx];
}
pub fn set(self: *Self, idx: Index, v: T) void {
self.unsafe_items[idx.idx] = v;
}
pub fn getPtr(self: Self, idx: Index) *T {
return &self.unsafe_items[idx.idx];
}
pub fn getSlice(self: Self, lo: Index, hi: Index) []T {
return self.unsafe_items[lo.idx..hi.idx];
}
};
}
const Array1 = PickyArray(u8, 10, "Index1");
const Index1 = Array1.Index;
const Array2 = PickyArray(u8, 5, "Index2");
const Index2 = Array2.Index;
pub fn main() void {
var array1 = Array1.init([_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
var index1 : Index1 = .{.idx=7}; // index of type 'Index1'
var array2 = Array2.init([_]u8{ 1, 2, 3, 4, 5 }); // with index type 'Index2'
var index2 : Index2 = .{.idx=2}; // index of type 'Index2'
_ = array2.get(index1); // ERROR: array2 expects Index2 type index but Index1 type is used
_ = array1;
_ = index1;
_ = array2;
_ = index2;
}
For extra credit, the type returned by getSlice should not be a normal slice and should refuse to accept integer indices.
Please do not do this.

Related

How to merge objects with Lodash, but replace arrays values?

I'm trying to replace arrays of an old object with values from a new object which has arrays... I guess it will make sense when you see an example and desire result:
https://jsfiddle.net/redlive/9coq7dmu/
const oldValues = {
a: 1,
b: [2, 21, 22, 23],
c: {
d: 3,
e: 4,
f: [5, 6, 7]
}
};
const updatedValues = {
b: [],
c: {
f: [8]
}
}
const result = _.merge( oldValues, updatedValues );
console.log(result);
/* Desire result:
{
a: 1,
b: [],
c: {
d: 3,
e: 4,
f: [8]
}
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
Use _.mergeWith(), and if the 2nd value is an array, return it. If not return undefined, and let merge handle it:
const oldValues = {"a":1,"b":[2,21,22,23],"c":{"d":3,"e":4,"f":[5,6,7]}};
const updatedValues = {"b":[],"c":{"f":[8]}};
const result = _.mergeWith(oldValues, updatedValues, (a, b) =>
_.isArray(b) ? b : undefined
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Reducing to list of object from object key and value

Given a previous Ramda groupBy to
{
'2018-Q4': 2,
'2019-Q1': 5
}
How can I map this to
[
{'quarter': '2018-Q4', 'value': 2},
{'quarter': '2019-Q1', 'value': 5},
]
Convert to pairs and then zipObj with the field names:
const { pipe, toPairs, map, zipObj } = R
const fn = pipe(
toPairs,
map(zipObj(['quarter', 'value']))
)
const data = {
'2018-Q4': 2,
'2019-Q1': 5
}
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

using vue.set in vuex is not updating the state

I'm trying to add an object into a nested array, and it is not working, but I've used this for other states and it works fine.
Has it got something to do with it begin a nested array?
this is the code I'm using
Vue.set(state.sections[getCurrentSection(state).index].rows[getCurrentRow(state).index].columns[getCurrentColumn(state).index].elements, 0, element)
this is the element object
var element = {
id: id,
style: {
backgroundColor: {
value: 'rgba(255,255,255,1)',
},
},
}
what am I doing wrong?
UPDATE
Another option to clone:
function hasProp(arg1, arg2) {
return Object.prototype.hasOwnProperty.call(arg1, arg2);
}
function extend(arg1, arg2) {
const keys = Object.keys(arg2);
const len = keys.length;
let i = 0;
while (i < len) {
arg1[keys[i]] = arg2[keys[i]];
i += 1;
}
if (hasProp(arg2, 'toString')) {
arg1.toString = arg2.toString;
}
if (hasProp(arg2, 'valueOf')) {
arg1.valueOf = arg2.valueOf;
}
return arg1;
}
const obj1 = {
a: 1,
b: 2,
c: { a: 1, b: 2}
};
const cloned = extend({}, obj1);
cloned.a = 9999;
console.log(obj1, cloned);
Make a deep copy of your state.sections;
Create a new object and make your modifications on it;
Replace state.sections with you new object - state.sections = Object.assign({}, newObject).
Your state and your view updated.

Forward and current iterators

Is there was another way of writing this?
fn main() {
let mut a = [1, 2, 3, 4, 5];
let mut iter1 = a.iter();
let mut iter2 = a.iter().skip(1).peekable();
while iter2.peek().is_some() {
println!("iter1: {:?}, iter2: {:?}", iter1.next(), iter2.next());
}
}
I am not certain of what is the exact question but the code itself could be rewritten using the windows iterator:
fn main() {
let a = [1, 2, 3, 4, 5];
for w in a.windows(2) {
println!("elem1: {:?}, elem2: {:?}", w[0], w[1]);
}
}

Sorting an nsmutable array --> order is not being saved?

kind of a noob question maybe: I'm trying to sort an nsmutablearray, but somehow the order is not being stored.
typedef struct {
float distance;
int index;
} DistanceAndIndex;
i = 0;
NSMutableArray *orderedDistances = [NSMutableArray arrayWithCapacity:(self.wayPoints.count)];
CLLocation* rwp2 = [[CLLocation alloc] initWithLatitude:52.080752 longitude:4.7527251];
latLonToEcef(rwp2.coordinate.latitude, rwp2.coordinate.longitude, 0.0, &myX, &myY, &myZ);
for (routeWayPoint *rwp in [[self wayPoints] objectEnumerator]) {
double poiX, poiY, poiZ, e, n, u;
latLonToEcef(rwp.location.coordinate.latitude, rwp.location.coordinate.longitude, 0.0, &poiX, &poiY, &poiZ);
ecefToEnu(rwp2.coordinate.latitude, rwp2.coordinate.longitude, myX, myY, myZ, poiX, poiY, poiZ, &e, &n, &u);
DistanceAndIndex distanceAndIndex;
distanceAndIndex.distance = sqrtf(n*n + e*e);
distanceAndIndex.index = i;
NSLog(#"Index = %i, %f", i, distanceAndIndex.distance);
[orderedDistances insertObject:[NSData dataWithBytes:&distanceAndIndex length:sizeof(distanceAndIndex)] atIndex:i++];
}
i=0;
[orderedDistances sortUsingComparator:(NSComparator)^(NSData *a, NSData *b) {
const DistanceAndIndex *aData = (const DistanceAndIndex *)a.bytes;
const DistanceAndIndex *bData = (const DistanceAndIndex *)b.bytes;
if (aData->distance < bData->distance) {
return NSOrderedAscending;
} else if (aData->distance > bData->distance) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
}];
for (NSData *d in [orderedDistances reverseObjectEnumerator]) {
const DistanceAndIndex *distanceAndIndex = (const DistanceAndIndex *)d.bytes;
NSLog(#"item: %i, %f", distanceAndIndex->index, distanceAndIndex->distance);
}
The output is the following:
[2021:907] Waypoints: 8
[2021:907] Index = 0, 230.078827
[2021:907] Index = 1, 171.626389
[2021:907] Index = 2, 36.015743
[2021:907] Index = 3, 103.174805
[2021:907] Index = 4, 238.837616
[2021:907] Index = 5, 278.074371
[2021:907] Index = 6, 288.319763
[2021:907] Index = 7, 321.953156
[2021:907] item: 7, 321.953156
[2021:907] item: 6, 288.319763
[2021:907] item: 5, 278.074371
[2021:907] item: 4, 238.837616
[2021:907] item: 3, 103.174805
[2021:907] item: 2, 36.015743
[2021:907] item: 1, 171.626389
[2021:907] item: 0, 230.078827
The array simply hasn't been reordered (for instance when looking at items 1,2 and 3). I feel like I'm overlooking something really basic. Any ideas?
Thanks!
You appear to be overlooking this typo:
if (aData->distance < bData->distance) {
return NSOrderedAscending;
} else if (aData->distance > bData->distance) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
The second one should be NSOrderedDescending, I think.
You seem to have two if statements that both return NSOrderedAscending