I need to divide the mutablearray into 3 mutablesubarrays with mutable elements.
#[derive(Debug)]
struct Server {
time: i64
}
impl Server {
fn new(x: i64) -> Server {
return Server {
time: x
}
}
}
fn main() {
let mut arr = Vec::<Server>::new();
arr.push(Server::new(10));
arr.push(Server::new(20));
arr.push(Server::new(30));
arr.push(Server::new(40));
arr.push(Server::new(50));
let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
}
Next, over each subarray to carry out different manipulations that do not affect the main array. (For example, each subarray is first sorted without affecting the order of the main array. The next step is to manipulate its elements over each subarray. And these changes should be reflected in the elements of the main array).
At the moment, when dividing the array Rust when compiling, it gives the following error:
error[E0499]: cannot borrow `arr` as mutable more than once at a time
--> src/main.rs:26:18
|
25 | let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
| --- first mutable borrow occurs here
26 | let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
| ^^^ second mutable borrow occurs here
...
29 | }
| - first borrow ends here
error[E0499]: cannot borrow `arr` as mutable more than once at a time
--> src/main.rs:27:18
|
25 | let mut arr1 = arr.iter_mut().filter(|x| x.time > 20).collect::<Vec<&mut Server>>();
| --- first mutable borrow occurs here
26 | let mut arr2 = arr.iter_mut().filter(|x| x.time < 20).collect::<Vec<&mut Server>>();
27 | let mut arr3 = arr.iter_mut().filter(|x| x.time == 20).collect::<Vec<&mut Server>>();
| ^^^ second mutable borrow occurs here
28 |
29 | }
| - first borrow ends here
You can use Iterator::partition to split up your vec into two distinct vecs without cloning the inner elements.
Because you want three different splits, you have to use partition twice (the order doesn't matter).
const THRESHOLD: i64 = 20;
let mut arr = Vec::<Server>::new();
arr.push(Server::new(10));
arr.push(Server::new(20));
arr.push(Server::new(30));
arr.push(Server::new(40));
arr.push(Server::new(50));
let (greater, rest): (Vec<_>, Vec<_>) = arr.into_iter().partition(|s| s.time > THRESHOLD);
let (equal, less): (Vec<_>, Vec<_>) = rest.into_iter().partition(|s| s.time == THRESHOLD);
(playground)
Because the Vectors greater, equal and less own the corresponding elements, you have mutable access to them.
Related
This question already has answers here:
How to swap the elements of an array, slice, or Vec?
(1 answer)
How to get mutable references to two array elements at the same time?
(8 answers)
Temporarily move out of borrowed content
(3 answers)
Closed 2 years ago.
I would like to write a function fn f<A>(xs: &mut [A; 9]) that reorders an array in-place from:
[a, b, c,
d, e, f,
g, h, i]
to:
[g, d, a,
h, e, b,
i, f, c]
I can't reassign the array due to moving elements out of array:
fn f1<A>(xs: &mut [A; 9]) {
*xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
}
error[E0508]: cannot move out of type `[A; 9]`, a non-copy array
--> src/lib.rs:2:12
|
2 | *xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
| ^^^^^
| |
| cannot move out of here
| move occurs because `xs[_]` has type `A`, which does not implement the `Copy` trait
I cannot do multiple mutable borrows:
fn f2<A>(xs: &mut [A; 9]) {
std::mem::swap(&mut xs[0], &mut xs[6]);
}
error[E0499]: cannot borrow `xs[_]` as mutable more than once at a time
--> src/lib.rs:2:32
|
2 | std::mem::swap(&mut xs[0], &mut xs[6]);
| -------------- ---------- ^^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
There is no built-in function that does this transformation for me.
How to implement this?
I have a function like this:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr
| nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && CONDITION = XXX
| otherwise = YYY
The CONDITION must check that that element (1,1) of the array arr is different from 0. But to get this element, one must do
element <- readArray arr (1,1)
I don't see how to do. Except with unsafePerformIO. Is it safe to use it here ? I mean:
| k == 0 && unsafePerformIO (readArray arr (1,1)) /= 0 = XXX
Otherwise, how could I do ?
Let's make a simplified version of your question.
Let's say we want to make the following function. It tells us whether or not both of the Int values are equal to 0. Problem is, it contains an IO. Your current method is this:
-- THIS IS BAD CODE! This could easily cause unexpected behaviour.
areBothZero :: Int -> IO Int -> IO Bool
areBothZero a b
| a == 0 && unsafePerformIO b == 0 = return True
| otherwise = return False
This shows a misunderstanding of monads. In Haskell, unsafePerformIO as a general rule shouldn't be used, unless you want to achieve a certain effect that pure computation cannot achieve. However, this kind of situation is perfectly achievable using the monad operations, which are, unlike unsafePerformIO, perfectly safe.
This is how we achieve this. Firsly, write the logic outside the context of IO:
areBothZeroLogic :: Int -> Int -> Bool
areBothZeroLogic a b
| a == 0 && b == 0 = True
| otherwise = False
Then, we pipe that up to the IO logic we want:
areBothZeroIO :: Int -> IO Int -> IO Bool
areBothZeroIO a mb = do
b <- mb -- Use do-notation to work with the value 'inside' the IO:
return $ areBothZeroLogic a b
Immediately, this separates IO logic from pure logic. This is a fundamental design principle in Haskell that you should always try to follow.
Now, onto your problem.
Your problem is much more messy and has several other issues, which suggests to me that you haven't considered how best to split the problem up into smaller peices. However, a better solution may look something like this, maybe with better names:
-- Look here! vvvvvv vvvvvv
jacPure :: Int -> Int -> [Int] -> [Int] -> Double -> Double
jacPure m k mu nu arrVal
| nu!!0 == 0 = 1
| length nu > m && nu!!m > 0 = 0
| m == 1 = x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && arrVal /= 0 = XXX
| otherwise = YYY
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr = do
arrVal <- readArray arr (1,1) -- Use do-notation to work with the value 'inside' the IO:
return $ jacPure m k mu nu arrVal
You should see immediately why this is much better. When implementing logic, who cares what's going on in the IO domain? Including an IO in what should be pure logic is like telling an author about the acidity of the paper their book will be printed on—it isn't relevant to what their job is. Always separate logic and IO!
There are of course other ways of doing this, and some could very well be better than the way I have suggested. However, it is not possible to know with the code you have provided which the best path would be. You should aim to learn more about monads and get better at using them, so you can make this judgement on your own.
I suspect this question is borne from a lack of understanding of Monads and monadic operations. If you are a beginner, I recommend reading the relevant LYAH chapter, which I found helpful as a beginner too.
One option is to combine the last two cases:
jac m k mu nu arr
...
| k == 0 = do
element <- readArray arr (1,1)
case element of
0 -> YYY
_ -> XXX
| otherwise -> YYY
Suppose we have
areBothZero :: Int -> IOArray Int Int -> IO Bool
areBothZero a b
| a == 0 && unsafePerformIO (readArray b 0) == 0 = return True
| otherwise = return False
I think it's worth thinking about what can go wrong. Suppose I write
do
x <- areBothZero a b
-- Change the value in b[0]
y <- areBothZero a b
Now there are two identical function calls, so the compiler is perfectly free to rewrite this:
do
let m = areBothZero a b
x <- m
-- change b
y <- m
The first time we run m, we perform the IO, reading b and getting an action return True or return False. We run that action and bind the result to x. The next time, we already have an action, so we run it, producing the same result. Any change to b is ignored.
This is only one of the ways things can go wrong with unsafePerformIO, so watch out!
I think there are one and a half ways it's reasonable to use unsafePerformIO or (in some cases) unsafeDupablePerformIO routinely. The entirely reasonable one is to wrap an "essentially pure" FFI call that just performs a mathematical calculation in another language. The less reasonable one is to create a global IORef or (more often) MVar. I think this is less reasonable because global variables have a certain tendency to turn out not to be as global as you thought once a year or two has passed. Most other uses of these unsafe IO operations require very careful thought to get right These tend to be in libraries like monad-par and reflex that introduce whole new styles of computation to Haskell. They also tend to be subtly buggy, sometimes for years, until someone figures out just what needs to happen to make them right. (Not to toot my own horn too much, but I think I'm probably one of the top handful of people in the world at reasoning about unsafe IO, and I very much prefer to avoid it when possible. This stuff has tripped up some of the best Haskell programmers and most important GHC developers.)
I've found a solution. I pass the value of the array element in addition.
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> Double -> IO Double
jac m k mu nu arr elt
| nu!!0 == 0 || m == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && elt /= 0 = XXX
| otherwise = do
e <- readArray arr (1, 1)
jck <- jac (m-1) 0 nu nu arr e
......
Maybe my question was not precise enough...
Not terribly elegant, but should do:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr
| nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| otherwise = do
v <- readArray arr (1,1)
case () of
_ | k == 0 && v /= 0 -> XXX
| otherwise -> YYY
Alternatively, read from the array at the very beginning:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr = do
v <- readArray arr (1,1)
case () of
_ | nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && v /= 0 -> XXX
| otherwise -> YYY
I've been trying to implement a function in OCaml that returns the smallest missing number (greater than 0) in a sorted list.
Here is what I've done
let getMissingNumber l =
let rec find min = function
| [] -> min
| t :: [] -> t + 1
| t1 :: t2 :: r -> if t2 - t1 > 1 then t1 + 1 else find min (t2 :: r)
in find 1 l;;
Here are the results:
# getMissingNumber [1; 4; 5];;
- : int = 2
# getMissingNumber [1; 2; 5];;
- : int = 3
# getMissingNumber [1; 2; 3];;
- : int = 4
# getMissingNumber [3; 4; 5];;
- : int = 6
All the results are correct but the last one. Any suggestions?
The problem is that if list contains more than one element, this function will never return 1, just because of | t :: [] -> t + 1 (if t > 0).
So we may replace | t :: [] -> t + 1 by | t :: [] -> min, but in this case there will be a problem with all lists of the form [1; 2; 3; ...; n], because in the | t1 :: t2 :: r branch we don't change min, so we will end up by returning 1 (even if correct response is n+1).
So we need to "update" min, but what's interesting is that if we replace find min (t2 :: r) by find (t2 + 1) (t2 :: r), we will return to your original function.
In fact this function search smallest missing number greater than smallest presented number. The main problem is that you distinguish [t] and t1::t2::r for no good reason.
let getMissingNumber l =
let rec find min = function
| [] -> min
| t::r ->
if t > min then min
else find (t + 1) r
in find 1 l
If the input list may start with values smaller than one, then you also need to skip over these.
let getMissingNumber l =
let rec find min = function
| [] -> min
| h :: t when min < t -> min
| h :: t when min = t -> find (min+1) t
| _ :: t -> find min t
in find 1 l
I have generated a matrix for my Game of Life, and I'm trying to make it so that it loops through and continuously prints out the next generation, I am using a code I found online, and it doesn't seem to work. Here is my code
let generation = ref 1
let get g x y =
try g.(x).(y)
with _ -> 0
;;
let neighbourhood g x y =
(get g (x-1) (y-1)) +
(get g (x-1) (y )) +
(get g (x-1) (y+1)) +
(get g (x ) (y-1)) +
(get g (x ) (y+1)) +
(get g (x+1) (y-1)) +
(get g (x+1) (y )) +
(get g (x+1) (y+1))
let next_cell g x y =
let n = neighbourhood g x y in
match g.(x).(y), n with
| 1, 0 | 1, 1 -> 0 (* lonely *)
| 1, 4 | 1, 5 | 1, 6 | 1, 7 | 1, 8 -> 0 (* overcrowded *)
| 1, 2 | 1, 3 -> 1 (* lives *)
| 0, 3 -> 1 (* get birth *)
| _ -> 0
let copy g = Array.map Array.copy g
let rec next g =
let width = Array.length g
and height = Array.length g.(0)
and new_g = copy g in
for x = 0 to pred width do
for y = 0 to pred height do
new_g.(x).(y) <- (next_cell g x y)
done
done;
next new_g
let print g =
let width = Array.length g
and height = Array.length g.(0) in
for x = 0 to pred width do
for y = 0 to pred height do
if g.(x).(y) = 0
then print_char '.'
else print_char 'o'
done;
print_newline()
done
;;
print_string "Width ";
let num = read_int () in
print_string "Height";
let num2 = read_int () in
while !generation < 100 do
let myArray = Array.init num (fun _ -> Array.init num2 (fun _ -> Random.int 2)) in
print_string "Generation: "; print_int !generation; print_string "\n";
print (next myArray);
generation := !generation +1;
print_newline();
done;;
It only prints out the initial one and the generation after that rather than a new one. Since the parameters is the original array, however, when I put print (next new_g) it gives me an unbound value, is there a way I can continuously print out the subsequent generations?Shouldn't it overwrite the existing new_g when I do that?
Looking just at the main while loop, it allocates and initializes a random array each time around the loop. It doesn't seem like this could be right.
I also don't see how the function next could work, as it never returns. Its last action is to call itself again, unconditionally.
Update
If you change the last line of next to this:
new_g
it returns the next generation each time you call it.
Here's a way to drive the code in a functional (rather than imperative) style:
let rec generation n array =
if n < 100 then
begin
(* Print the array *);
generation (n + 1) (next array)
end
The outermost code might look like this:
let myArray =
Array.init num
(fun _ -> Array.init num2 (fun _ -> Random.int 2))
in
generation 0 myArray
Can't understand the reason of such behavior:
let example count =
let arr = Array.create 2 (Array.zeroCreate count)
for i in [0..count - 1] do
arr.[0].[i] <- 1
arr.[1].[i] <- 2
arr
example 2 |> Array.iter(printfn "%A")
Print:
[|2; 2|]
[|2; 2|]
https://dotnetfiddle.net/borMmO
If I replace:
let arr = Array.create 2 (Array.zeroCreate count)
to:
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
Everything will work as expected:
let example count =
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
for i in [0..count - 1] do
arr.[0].[i] <- 1
arr.[1].[i] <- 2
arr
example 2 |> Array.iter(printfn "%A")
Print:
[|1; 1|]
[|2; 2|]
https://dotnetfiddle.net/uXmlbn
I think the reason is the fact that the array - a reference type. But I want to understand why this is happening. Since I didn't expect such results.
When you write:
let arr = Array.create 2 (Array.zeroCreate count)
You are creating an array where each element is a reference to the same array. This means that mutating a value using arr.[0] also mutates the value in arr.[1] - because the two array elements are pointing to the same mutable array. You end up with:
[| x ; x |]
\ /
[| 0; 0 |]
When you write:
let arr = Array.init 2 (fun _ -> Array.zeroCreate count)
The provided function is called for each position in the arr array and so you'll end up with different array for each element (and so arr.[0] <> arr.[1]). You end up with:
[| x ; y |]
/ \
[| 0; 0 |] [| 0; 0 |]