4 ms·
Agreed. A better solution here is to have a generic accessor on the Array that can return a default value for out-of-bounds accesses. There almost is one alread
by eridius 8y ago
Agreed. A better solution here is to have a generic accessor on the Array that can return a default value for out-of-bounds accesses. There almost is one already, the two-argument version of fetch(), except that interprets negative indices as counting from the end. But if we create a variant that doesn't treat negative indices specially then the code becomes very simple
result = input.map.with_index do |_, i|
input.better_fetch(i-1, 0) + input.better_fetch(i+1, 0)
end.to_a
- chrismorgan 8y agoYeah, in Rust it’d fall very neatly out of the type system, as `input.get(i - 1).unwrap_or(0) + input.get(i + 1).unwrap_or(0)`.
- eridius 8y agoFunnily enough, that Rust code is actually buggy, because i is a usize and if i == 0 then i-1 will panic due to underflow. You'd have to write input.get(i.wrapping_sub(1)).unwrap_or(0) + input.get(i+1).unwrap_or(0) This also technically won't work right if the slice has usize::MAX elements, but that's rather unlikely. This is one area where Swift's choice of using signed Int for most things actually works quite well. The equivalent Swift code would be something like (input[safe: i-1] ?? 0) + (input[safe: i+1] ?? 0) though unfortunately Swift doesn't ship with Array.subscript(safe:) so you have to write that yourself.
- GlitchMr 8y agoA slice of a non-ZST element cannot have `usize::MAX` elements, by definition of `usize`.
- eridius 8y agoSlices of ZST elements is indeed what I was thinking of, but is there anything actually stopping me from constructing a `std::slice::from_raw_parts(0 as *const u8, usize::MAX)`? What if I'm working on an architecture where the heap and stack are separate address spaces, and every single address in the heap is reachable? In fact, doesn't WebAssembly work this way? If I can declare that my linear memory is usize::MAX bytes, then constructing a slice that covers the entire memory address seems like a potentially-valid thing to do.
- masklinn 8y ago> i is a usize and if i == 0 then i-1 will panic due to underflow. Not in release mode.
- eridius 8y agoWhile it's true that it doesn't panic in release mode, that's supposed to be an optimization and the correct semantics are what's implemented in debug mode. Besides, you don't want to write a program that only functions in release mode.
- p4lindromica 8y agoIn ruby, this is most easily achieved with: result = input.each_cons(3).map do |left, _, right| left + right end This maps over consecutive three-tuples in `input` and returns empty array for `len(input) < 3`. Edit: nevermind, boundary conditions are still special cases.