Skip to content

reflect: Value.Swap(i, j) for slices? #3126

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

Closed
patrickmn opened this issue Feb 25, 2012 · 6 comments
Closed

reflect: Value.Swap(i, j) for slices? #3126

patrickmn opened this issue Feb 25, 2012 · 6 comments

Comments

@patrickmn
Copy link

There appears to be no way to swap two values in a reflect.Value for a slice, other than
allocating a holder value, e.g.:

tmp := reflect.New(t).Elem()
tmp.Set(v.Index(i))
v.Index(i).Set(v.Index(j))
v.Index(j).Set(tmp)

Is it possible/would you be interested in introducing a v.Swap(i, j)?
@remyoudompheng
Copy link
Contributor

Comment 1:

I'd personnally write
x, y := v.Index(i).Interface(), v.Index(j).Interface()
v.Index(i).Set(reflect.ValueOf(y))
v.Index(j).Set(reflect.ValueOf(x))

@patrickmn
Copy link
Author

Comment 2:

Ah, thanks.
Is this efficient? I admit I don't fully understand what's going on in memory there
compared to a multiple assignment, s[i], s[j] = s[j], s[i]. I assume that the latter is
more efficient? I'm wondering if it's possible to swap the Value.val and flag in a
similar manner inside the reflect package.

@patrickmn
Copy link
Author

Comment 3:

Remy, your approach doesn't seem to work. The first value is overwritten before setting
the next one, so they both become e.g. 7 instead of swapping 5 and 7.

@remyoudompheng
Copy link
Contributor

Comment 4:

This code snippet works for me:
A := []int{1,2}
V := reflect.ValueOf(A)
x, y := V.Index(0).Interface(), V.Index(1).Interface()
V.Index(0).Set(reflect.ValueOf(y))
V.Index(1).Set(reflect.ValueOf(x))
fmt.Println(A)
However you are right that this one doesn't:
A := []string{"world", "hello"}
V := reflect.ValueOf(A)
x, y := V.Index(0).Interface(), V.Index(1).Interface()
V.Index(0).Set(reflect.ValueOf(y))
V.Index(1).Set(reflect.ValueOf(x))
fmt.Println(A)
I tend to think it is a bug.

@ianlancetaylor
Copy link
Member

Comment 5:

I don't think that is a bug.  It's just a consequence of how interfaces values are
represented.  It's odd that it works one time but not the other, but it's not a bug.
I don't think there is any clean way to swap reflect.Value's without using a temporary
value.  The language construct x, y = y, x effectively uses two temporary values, you
just don't see them.

Labels changed: added priority-later, packagechange, removed priority-triage.

@rsc
Copy link
Contributor

rsc commented Feb 28, 2012

Comment 6:

I don't think we need to special case swap.  It's not a special case in the language, so
it doesn't need to be a special case here.  As Ian notes, you have to use a temporary
value one way or another, even for x, y = y, x.  Providing a wrapper wouldn't change
that.
The interface thing is a bug, but I see a separate issue has already been filed for that.

Status changed to WontFix.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants