Skip to content

Array/Slice custom index type #1830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Hejsil opened this issue Dec 14, 2018 · 7 comments
Open

Array/Slice custom index type #1830

Hejsil opened this issue Dec 14, 2018 · 7 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@Hejsil
Copy link
Contributor

Hejsil commented Dec 14, 2018

One thing I end of doing sometimes is constructing a table that maps all u4 values to something else. I tend to do this with arrays:

const channel_message_table = blk: {
    var res = []?midi.ChannelMessage.Kind{null} ** (math.maxInt(u4) + 1);
    res[0x8] = midi.ChannelMessage.Kind.NoteOff;
    res[0x9] = midi.ChannelMessage.Kind.NoteOn;
    res[0xA] = midi.ChannelMessage.Kind.PolyphonicKeyPressure;
    res[0xB] = midi.ChannelMessage.Kind.ControlChange;
    res[0xC] = midi.ChannelMessage.Kind.ProgramChange;
    res[0xD] = midi.ChannelMessage.Kind.ChannelPressure;
    res[0xE] = midi.ChannelMessage.Kind.PitchBendChange;
    break :blk res;
};

And then, when I wanna access items in my array, I ensure that I have a u4 type before I index:

const upper = @truncate(u4, b >> 4);
const lower = @truncate(u4, b);
if (channel_message_table[upper]) |kind| {

As long as I ensure that I index with a u4 this is 100% safe. Sadly the compiler doesn't enforce this.

Here are a few benitfits that this kind of feature could provide:

  • Smaller slices. A slice of type [u4]u8 (this is made up syntax) would be the same as this struct: struct { ptr: [*]u8, len: u4 }. This should also work for enum arrays: [SomeEnum]u8 == struct { ptr: [*]u8, len: @TagType(SomeEnum) }. This would work well with the replace @setRuntimeSafety with @optimizeFor #978, as a struct marked @optimizeFor(.Small) would allow data to be packed with the length of the slice:
struct(@optimizeFor(.Small)) {
    slice: [u4]u8,
    meta: u4,
}
// data layout:
//            len
// | ptr     | |
// pp pp pp pp lm
//              |
//             meta
  • Static garenties about the access into these arrays/slices.

Ofc, this might not require a feature. I can imagine a userland implementation that could give me all these benifits (except for the fact that I'd have to call .at(index) instead of [index])

@Hejsil Hejsil added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Dec 14, 2018
@Hejsil
Copy link
Contributor Author

Hejsil commented Dec 14, 2018

Actually, my proposal starts with a use case this doesn't solve. channel_message_table is safe to index with all values of u4, but if I slice channel_message_table, the length is math.maxInt(u4) + 1 which requires at least a u5 as a length.

And now that I think about it. This is two proposals

  • Custom index type
  • Custom length type

@andrewrk andrewrk added this to the 0.5.0 milestone Dec 16, 2018
@shawnl
Copy link
Contributor

shawnl commented Apr 1, 2019

This is a bad idea because each function that accepts slices would now have to have multiple compiled versions for the multiple types of slices. If you want this do it manually, with arrays.

@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Aug 27, 2019
@andrewrk andrewrk modified the milestones: 0.6.0, 0.7.0 Dec 31, 2019
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Oct 10, 2020
@xmarto
Copy link

xmarto commented Dec 1, 2020

This is a bad idea because each function that accepts slices would now have to have multiple compiled versions for the multiple types of slices. If you want this do it manually, with arrays.

It doesn't have to be that way. You can always have small slices coerce into bigger ones. That way you can have general-purpose functions accept usize slices that work with everything else.

I think this would play well with #3806. You could have special slices for arrays with a maximum size given by a range type, and it would give the compiler room to use spare values for metadata. In fact, that would help with the problem of requiring an extra bit for the size type, which would only be the case if you need to use the whole power-of-two range for indices (and if so, you could still store other things in the extra space you get with one more bit).

@andrewrk
Copy link
Member

I want to tackle the proposal #3806 and figure out a decision on that one before this one.

@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 May 19, 2021
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 Nov 23, 2021
@andrewrk andrewrk modified the milestones: 0.10.0, 0.11.0 Apr 16, 2022
@aganm
Copy link

aganm commented Jun 20, 2022

I was searching about typed indices and I think this issue is exactly what I'm trying to do. To give some context, I have an algorithm that has two arrays, each 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

I would love it if there was 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

Any plans to have such a feature eventually?

@wooster0
Copy link
Contributor

wooster0 commented Mar 15, 2023

See also #14926 which is more or less a duplicate of this but is a bit more detailed on the syntax and has some discussion too.

@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Apr 9, 2023
@andrewrk andrewrk modified the milestones: 0.13.0, 0.12.0 Jul 9, 2023
@nektro
Copy link
Contributor

nektro commented Feb 6, 2025

search keyword: indexedby

@andrewrk andrewrk modified the milestones: 0.14.0, 0.15.0 Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

7 participants