Skip to content
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

Iterate slice by reference (not by value) #14800

Open
ysbaddaden opened this issue Jul 8, 2024 · 0 comments
Open

Iterate slice by reference (not by value) #14800

ysbaddaden opened this issue Jul 8, 2024 · 0 comments

Comments

@ysbaddaden
Copy link
Contributor

Iterating a Slice(T) with #each leads to iterating the slice by value. This is usually fine when T is a primitive (e.g. UInt8) or a Reference to a class instance, but when T is a struct it leads to getting a copy. Sometimes this is what we want, but at other times we'd like to avoid the copy and/or need to mutate the struct in-place.

This stems from the nature of Ruby where everything's supposed to be a Reference or a primitive, not a value that is passed by copy (except for primitives).

To solve this, we currently need to get the raw pointer and loop/increment it manually, but the intent ain't immediately explicit, in addition to be ugly Crystal:

slice.size.times do |i|
  ptr = slice.to_unsafe + i
  # ...
end

We could at least abstract a method, for example #each_ref(&) or #each_reference(&). We'd still have to deal with a Pointer(T), but at least the iteration part would be much more readable:

struct Slice(T)
  def each_ref(&)
    size.times { yield to_unsafe + i }
  end
end

slice.each_ref do |ptr|
  # ...
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants