Borrow error when I try to modify last element of a vector [closed] - vector

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 months ago.
Improve this question
I am trying to modify a Vec<i32> by doing thing[thing.len() - 1] = other_thing;. I get an error telling me that I borrowed first a mutable reference, then an immutable one. I could not find a workaround. How to modify last element of a vector in rust.
Working example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a092f6778df0290de7cee1f2321bf175

You can't borrow the same variable as mutable and immutable at the same time.
When you are trying to get length of vector, this is where immutable borrowing happens and panics (because at the same time you are trying to change it's content, eg. mutable borrowing)
You can do it in multiple ways.
Let's assume you have a vector with 2 slices
let mut thing = vec![[1, 2], [3, 4]];
First, with calculating and getting last item from vector manually (as you did in your version)
let len = thing.len(); // immutable borrow use
thing[len - 1][1] = 20; // mutable borrow use
But more idiomatic way of doing this is to use methods provided by slice/vec and map over returned Option
To get the last item we can use last_mut (which will return Option) and map on that Option to get last item of nested slice, and change it's value to 20
// Set vector's last slice's value at index 1 to 20
thing.last_mut().map(|s| s[1] = 20);
// Set vector's last slice's last value to 20
// In our case this is the same as previous one
thing.last_mut().map(|s| s.last_mut().map(|i| *i = 20));
assert_eq!(vec![[1, 2], [3, 20]], thing);

Related

How does subtracting .as_ptr() values work?

Looking at a code snippet for parsing HTTP requests provided as part of the Tokio examples, I see the following code:
let toslice = |a: &[u8]| {
let start = a.as_ptr() as usize - src.as_ptr() as usize;
assert!(start < src.len());
(start, start + a.len())
};
As I understand, the above code snippet it is getting the pointer location for the input vector a and the pointer location for a variable outside the scope of the closure and subtracting them. Then it returns a tuple containing this calculated value and the calculated value plus the length of the input vector.
What is this trying to accomplish? One could end up with a negative number and then panic because it wouldn't cast to usize. In fact, when I compile the example, this is exactly what happens when the input is the bytes for the string GET or POST, but not for other values. Is this a performance optimization for doing some sort of substring from a vector?
Yes this is just subtracting pointers. The missing context is the closure clearly intends that a must be a subslice (substring) of the closed-over src slice. Thus toslice(a) ends up returning the start and end indices of a inside src. More explicitly, let (start, end) = toslice(a); means src[start] is a[0] (not just equal value, they are the same address), and src[end - 1] is the last byte of a.
Violating this context assumption will likely produce panics. That's fine because this closure is a local variable that is only used locally and not exposed to any unknown users, so the only calls to the closure are in the example you linked and they evidently all satisfy the constraint.

bulk adding to a map, in F#

I've a simple type:
type Token =
{
Symbol: string
Address: string
Decimals: int
}
and a memory cache (they're in a db):
let mutable private tokenCache : Map<string, Token> = Map.empty
part of the Tokens module.
Sometimes I get a few new entries to add, in the form of a Token array, and I want to update the cache.
It happens very rarely (less than once per million reads).
When I update the database with the new batch, I want to update the cache map as well and I just wrote this:
tokenCache <- tokens |> Seq.fold (fun m i -> m.Add(i.Symbol, i)) tokenCache
Since this is happening rarely, I don't really care about the performance so this question is out of curiosity:
When I do this, the map will be recreated once per entry in the tokens array: 10 new tokens, 10 map re-creation. I assumed this was the most 'F#' way to deal with this. It got me thinking: wouldn't converting the map to a list of KVP, getting the output of distinct and re-creating a map be more efficient? or is there another method I haven't thought about?
This is not an answer to the question as stated, but a clarification to something you asked in the comments.
This premise that you have expressed is incorrect:
the map will be recreated once per entry in the tokens array
The map doesn't actually get completely recreated for every insertion. But at the same time, another hypothesis that you have expressed in the comments is also incorrect:
so the immutability is from the language's perspective, the compiler doesn't recreate the object behind the scenes?
Immutability is real. But the map also doesn't get recreated every time. Sometimes it does, but not every time.
I'm not going to describe exactly how Map works, because that's too involved. Instead, I'll illustrate the principle on a list.
F# lists are "singly linked lists", which means each list consists of two things: (1) first element (called "head") and (2) a reference (pointer) to the rest of elements (called "tail"). The crucial thing to note here is that the "rest of elements" part is also itself a list.
So if you declare a list like this:
let x = [1; 2; 3]
It would be represented in memory something like this:
x -> 1 -> 2 -> 3 -> []
The name x is a reference to the first element, and then each element has a reference to the next one, and the last one - to empty list. So far so good.
Now let's see what happens if you add a new element to this list:
let y = 42 :: x
Now the list y will be represented like this:
y -> 42 -> 1 -> 2 -> 3 -> []
But this picture is missing half the picture. If we look at the memory in a wider scope than just y, we'll see this:
x -> 1 -> 2 -> 3 -> []
^
|
/
y -> 42
So you see that the y list consists of two things (as all lists do): first element 42 and a reference to the rest of the elements 1->2->3. But the "rest of the elements" bit is not exclusive to y, it has its own name x.
And so it is that you have two lists x and y, 3 and 4 elements respectively, but together they occupy just 4 cells of memory, not 7.
And another thing to note is that when I created the y list, I did not have to recreate the whole list from scratch, I did not have to copy 1, 2, and 3 from x to y. Those cells stayed right where they are, and y only got a reference to them.
And a third thing to note is that this means that prepending an element to a list is an O(1) operation. No copying of the list involved.
And a fourth (and hopefully final) thing to note is that this approach is only possible because of immutability. It is only because I know that the x list will never change that I can take a reference to it. If it was subject to change, I would be forced to copy it just in case.
This sort of arrangement, where each iteration of a data structure is built "on top of" the previous one is called "persistent data structure" (well, to be more precise, it's one kind of a persistent data structure).
The way it works is very easy to see for linked lists, but it also works for more involved data structures, including maps (which are represented as trees).

We can change immutable variable in Elixir. Can we not say rebind equals mutable? [duplicate]

This question already has answers here:
Are Elixir variables really immutable?
(5 answers)
Closed 1 year ago.
I am new for function language. i practised some thing but i wonder one thing. Elixir says me that everything is immutable but i can change variable in elixir. Is there something that I dont know about it?
My example is
defmodule Practise do
def boxes(total) do
size_50 = div(total, 50)
total = rem(total, 50)
{"big: #{size_50} total: #{total}"}
end
end
I can change total variable with new value in same named function. So that i think it is immutable. Is it correct?
Reusing variable names (which is often referred to as rebinding) is just a convenience in Elixir - it's equivalent to using a temporary variable but with the same name. The reference to your original total gets lost in the scope of the function Practice.boxes. But that doesn't matter to you since you don't need it again - you just need the new one.
This is a rare concession made by the designers of Elixir towards imperative programming. Indeed, an expression such as x = x + 1 might be mistaken for pattern matching phrase.

Parallel iteration over array with step size greater than 1

I'm working on a practice program for doing belief propagation stereo vision. The relevant aspect of that here is that I have a fairly long array representing every pixel in an image, and want to carry out an operation on every second entry in the array at each iteration of a for loop - first one half of the entries, and then at the next iteration the other half (this comes from an optimisation described by Felzenswalb & Huttenlocher in their 2006 paper 'Efficient belief propagation for early vision'.) So, you could see it as having an outer for loop which runs a number of times, and for each iteration of that loop I iterate over half of the entries in the array.
I would like to parallelise the operation of iterating over the array like this, since I believe it would be thread-safe to do so, and of course potentially faster. The operation involved updates values inside the data structures representing the neighbouring pixels, which are not themselves used in a given iteration of the outer loop. Originally I just iterated over the entire array in one go, which meant that it was fairly trivial to carry this out - all I needed to do was put .Parallel between Array and .iteri. Changing to operating on every second array entry is trickier, however.
To make the change from simply iterating over every entry, I from Array.iteri (fun i p -> ... to using for i in startIndex..2..(ArrayLength - 1) do, where startIndex is either 1 or 0 depending on which one I used last (controlled by toggling a boolean). This means though that I can't simply use the really nice .Parallel to make things run in parallel.
I haven't been able to find anything specific about how to implement a parallel for loop in .NET which has a step size greater than 1. The best I could find was a paragraph in an old MSDN document on parallel programming in .NET, but that paragraph only makes a vague statement about transforming an index inside a loop body. I do not understand what is meant there.
I looked at Parallel.For and Parallel.ForEach, as well as creating a custom partitioner, but none of those seemed to include options for changing the step size.
The other option that occurred to me was to use a sequence expression such as
let getOddOrEvenArrayEntries myarray oddOrEven =
seq {
let startingIndex =
if oddOrEven then
1
else
0
for i in startingIndex..2..(Array.length myarray- 1) do
yield (i, myarray.[i])
}
and then using PSeq.iteri from ParallelSeq, but I'm not sure whether it will work correctly with .NET Core 2.2. (Note that, currently at least, I need to know the index of the given element in the array, as it is used as the index into another array during the processing).
How can I go about iterating over every second element of an array in parallel? I.e. iterating over an array using a step size greater than 1?
You could try PSeq.mapi which provides not only a sequence item as a parameter but also the index of an item.
Here's a small example
let res = nums
|> PSeq.mapi(fun index item -> if index % 2 = 0 then item else item + 1)
You can also have a look over this sampling snippet. Just be sure to substitute Seq with PSeq

Stackoverflow with specialized Hashtbl (via Hashtbl.make)

I am using this piece of code and a stackoverflow will be triggered, if I use Extlib's Hashtbl the error does not occur. Any hints to use specialized Hashtbl without stackoverflow?
module ColorIdxHash = Hashtbl.Make(
struct
type t = Img_types.rgb_t
let equal = (==)
let hash = Hashtbl.hash
end
)
(* .. *)
let (ctable: int ColorIdxHash.t) = ColorIdxHash.create 256 in
for x = 0 to width -1 do
for y = 0 to height -1 do
let c = Img.get img x y in
let rgb = Color.rgb_of_color c in
if not (ColorIdxHash.mem ctable rgb) then ColorIdxHash.add ctable rgb (ColorIdxHash.length ctable)
done
done;
(* .. *)
The backtrace points to hashtbl.ml:
Fatal error: exception Stack_overflow Raised at file "hashtbl.ml",
line 54, characters 16-40 Called from file "img/write_bmp.ml", line
150, characters 52-108 ...
Any hints?
Well, you're using physical equality (==) to compare the colors in your hash table. If the colors are structured values (I can't tell from this code), none of them will be physically equal to each other. If all the colors are distinct objects, they will all go into the table, which could really be quite a large number of objects. On the other hand, the hash function is going to be based on the actual color R,G,B values, so there may well be a large number of duplicates. This will mean that your hash buckets will have very long chains. Perhaps some internal function isn't tail recursive, and so is overflowing the stack.
Normally the length of the longest chain will be 2 or 3, so it wouldn't be surprising that this error doesn't come up often.
Looking at my copy of hashtbl.ml (OCaml 3.12.1), I don't see anything non-tail-recursive on line 54. So my guess might be wrong. On line 54 a new internal array is allocated for the hash table. So another idea is just that your hashtable is just getting too big (perhaps due to the unwanted duplicates).
One thing to try is to use structural equality (=) and see if the problem goes away.
One reason you may have non-termination or stack overflows is if your type contains cyclic values. (==) will terminates on cyclic values (while (=) may not), but Hash.hash is probably not cycle-safe. So if you manipulate cyclic values of type Img_types.rgb_t, you have to devise your one cycle-safe hash function -- typically, calling Hash.hash on only one of the non-cyclic subfields/subcomponents of your values.
I've already been bitten by precisely this issue in the past. Not a fun bug to track down.

Resources