rust


How to swap elements of array?


I want to swap elements of slice data using library function, but it doesn't work because of multiple borrowing:
mem::swap(&mut data[i], &mut data[j]); //error
It could be done manually, as usual:
let temp = data[i];
data[i] = data[j];
data[j] = temp;
but I don't think using this code every time is great. Is there any other solution to use library swap for slices normally?
There's a swap method on slices: data.swap(i, j).
The original code doesn't work because the language requires that &muts do not alias, that is, if a piece of data is accessible via an &mut, then there must be no other way to use that data. In general, for successive indexes data[i], data[j], the compiler cannot guarantee that i and j are different. If they are the same then the indexing is referring to the same memory and so &mut data[i] and &mut data[j] would be two pointers to the same data: illegal!
.swap uses a bit of unsafe code internally, being sure to handle the i == j case correctly, avoiding aliasing &mut pointers. That said, it doesn't have to use unsafe, it is only to ensure this "primitive" operation has high-performance (and I could definitely imagine future language/library improvements that reduce the need for unsafe here by making the require invariants easier to express), e.g. the following is a safe implementation:
use std::cmp::Ordering;
use std::mem;
fn swap<T>(x: &mut [T], i: usize, j: usize) {
let (lo, hi) = match i.cmp(&j) {
// no swapping necessary
Ordering::Equal => return
// get the smallest and largest of the two indices
Ordering::Less => (i, j),
Ordering::Greater => (j, i)
};
let (init, tail) = x.split_at_mut(hi);
mem::swap(&mut init[lo], &mut tail[0]);
}
The key here is split_at_mut which separates the slice into two disjoint halves (this is done using unsafe internally, but Rust's standard library is built on unsafe: the language provides "primitive" features and the libraries build the rest on top of them).

Related Links

Redefine trait for infix operators
Result has no method called “unwrap()”?
Wrapping a Rust struct in a C++ class
How to create a String directly?
Acessing data from a global struct, gives error “borrowed value does not live long enough”
captured variable does not outlive the enclosing closure [duplicate]
PI constant is ambiguous
Calling an impl method from another impl method
compilation of openssl-sys fails with `openssl/hmac.h: No such file or directory`
Indexing a String
Importing mio::tcp::TcpStream but get std::net::tcp::TcpStream
It is possible to always have Cargo show warnings?
Copy files to the target directory after build
Is it ok to return in main?
Why is this trait/implementation incompatible - bound lifetime vs concrete lifetime
Cannot move out of `req` because it is borrowed

Categories

HOME
keyboard
clearcase
swi-prolog
devexpress
plaid
filesize
qooxdoo
vue-resource
swift2
haxe
tweepy
anchor
alljoyn
orc
ex
bundler
temperature
fosuserbundle
pe
bsd
bosun
altium-designer
webviewclient
tortoisehg
docx4j
steam-web-api
argv
cucumber-junit
om-next
quickcheck
db2-luw
netstat
cordys-opentext
jslint
love2d
uivisualeffectview
django-smart-selects
netapp
python-jira
plane
resampling
yoast
sendinput
gcal
roracle
gestures
maven-jaxb2-plugin
pen
mongodb-aggregation
powerpoint-2013
highlighting
maximize
django-redis
teamviewer
variable-length-array
directx-9
ora-04091
enaml
sequence-sql
nssortdescriptor
directorysearcher
jolie
inputbox
igor
jquery-mobile-flipswitch
mobile-country-code
zend-search-lucene
jack
pre
mod-perl
jmenubar
illuminate-container
progress-db
xsd2code
non-ascii-characters
disjoint-union
arel
itunes-sdk
getopt-long
fbml
drawimage
regression-testing
inversion
gtktextview
xap
word-automation

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App