generic swap method in javascript

P

proxygeek

I could not find any worthwhile discussion on implementing a generic
swap(a,b) function in Javascript.
Please point me to a discussion/link if it's already covered there.

Problem:
I need a method swap(a,b) which I can call with two variables as
params and it would swap the values of the two vars.

<snip>
....
....
function swap(a,b){ // This would NOT work as
intended
t = a;
a = b;
b = t;
}
....
....
var x = 10, y = 20;
swap(x,y);
alert("x = " + x + ", y = " + y); // should give x =
20, y = 10
....
</snip>

Above implementation would not work as here swap() does not know a
thing about x or y.

What would be the best solution for this?

Regards,
proxygeek
 
T

Thomas 'PointedEars' Lahn

proxygeek said:
I could not find any worthwhile discussion on implementing a generic
swap(a,b) function in Javascript.

Because there isn't one.
Problem:
I need a method swap(a,b) which I can call with two variables as
params and it would swap the values of the two vars.

No, you don't.
<snip>
....
....
function swap(a,b){ // This would NOT work as
intended

Original code should be posted so that it is readable and executable when
wrapped to the customary 72 to 80 characters per line. Always use multi-
line pre-comments, not single-line post-comments, for documentation
comments.

You "forgot" to declare `t', so it leaks to the outer scope.
a = b;
b = t;
}
....
....
var x = 10, y = 20;
swap(x,y);
alert("x = " + x + ", y = " + y); // should give x =
window.alert(…);

20, y = 10

See above
....
</snip>

Above implementation would not work as here swap() does not know a
thing about x or y.

Congratulations, you have discovered call-by-value.
What would be the best solution for this?

Do not use a function/method.

JavaScript 1.7+:

/* Destructuring assignment */
[y, x] = [x, y];

Other versions/implementations: as in swap()

See also <http://PointedEars.de/es-matrix>


PointedEars
 
V

VK

JavaScript 1.7+:

  /* Destructuring assignment */
  [y, x] = [x, y];

Not "JavaScript 1.7+" but Mozilla JavaScript 1.7+ thus Gecko platforms
thus 10%-20% of average visitors. IMO way below the level of an
acceptably universal solution.
Other versions/implementations: as in swap()

? Do you imply that other platforms do implement call-by-reference for
primitives? It is not true.

To OP: to my surprise this question seems never was answered properly
in this newsgroup. The only relevant discussion I found was from
2000:
http://groups.google.com/group/comp..._frm/thread/b72a4c3346057c66/e80dfd68d712c73c
and it doesn't contain any valuablу answer.

JavaScript as currently defined by ECMA-262 3rd ed. by design doesn't
allow primitives' swap in a separate function, because the function
gets such arguments by values, not by references.

If your code requires frequent primitive swaps, you may define an
intermediary var at the beginning so do not create it over and over
again and then:

var swap = null;
// ...
var x = 10, y = 20;
// ...
swap = x, x = y, y = swap;
window.alert("x = " + x + ", y = " + y);
 
T

Thomas 'PointedEars' Lahn

VK said:
Thomas said:
JavaScript 1.7+:

/* Destructuring assignment */
[y, x] = [x, y];

Not "JavaScript 1.7+" but Mozilla JavaScript 1.7+

"Mozilla" is superfluous when talking about "JavaScript". I have explicitly
pointed out the other implementations, so there can not be ambiguity.
Unless, of course, one *wants* to misunderstand in order to have a case for
bickering and fairytales.
thus Gecko platforms

JavaScript is not limited to "Gecko platforms".
thus 10%-20% of average visitors.

That depends on the country to begin with.
IMO way below the level of an acceptably universal solution.

Your opinion is worthless as you don't know what you are talking about.
? Do you imply that other platforms do implement call-by-reference for
primitives?
No.

It is not true.

You are jumping to conclusions.
To OP: to my surprise this question seems never was answered properly
in this newsgroup. The only relevant discussion I found was from
2000:

OP: Do not listen to, and do not feed the troll.


PointedEars
 
V

VK

"Mozilla" is superfluous when talking about "JavaScript".

Do you have links to documents proving Mozilla's exclusive rights to
JavaScript standardization or/and Mozilla's extensions
"standardization priority" ?
Your opinion is worthless as you don't know what you are talking about.

I am talking about the destructuring assignment JavaScript extension
and its support across used browsers. What are you talking about
remains a mystery to the side readers.

That's good to know.
OP: Do not listen to, and do not feed the troll.

You worthless trolling is annoying. Make your *working* version of
swap() for an ECMA-262 3rd ed. compliant platforms other than newest
Fx or just stop the tread pollution.
 
V

VK

If your code requires frequent primitive swaps, you may define an
intermediary var at the beginning so do not create it over and over
again and then:

var swap = null;
// ...
var x = 10, y = 20;
// ...
swap = x, x = y, y = swap;
window.alert("x = " + x + ", y = " + y);

The other option is to not use stay-alone primitives but object
properties as objects being passed to functions by reference values:

var foo = {'a' : 10};
var bar = {'a' : 20};

swap(foo, bar, 'a');

window.alert(foo.a + ' ' + bar.a);

function swap(obj1, obj2, prop) {
var tmp = obj1[prop];
obj1[prop] = obj2[prop];
obj2[prop] = tmp;
}

Whichever is more (dis)convenient depends on your actual project.
 
A

Asen Bozhilov

VK said:
var foo = {'a' : 10};
var bar = {'a' : 20};

swap(foo, bar, 'a');

window.alert(foo.a + ' ' + bar.a);

function swap(obj1, obj2, prop) {
 var tmp = obj1[prop];
 obj1[prop] = obj2[prop];
 obj2[prop] = tmp;

}

The whole point of thread is useless and as Thomas pointed out, he
does not need function/method especially "generic". He can use
standard approach, for example:

var foo = 10,
bar = 20;

foo = [bar, bar = foo][0];
 
T

Thomas 'PointedEars' Lahn

VK said:
The other option is to not use stay-alone primitives but object
properties as objects being passed to functions by reference values:

Which is neither generic nor the best way to do it. Thanks for playing.
 
V

VK

The whole point of thread is useless and as Thomas pointed out, he
does not need function/method especially "generic". He can use
standard approach, for example:

var foo = 10,
    bar = 20;

foo = [bar, bar = foo][0];

Let's not reproduce the infamous "The Fox and the Grapes"
situation ;-)
http://en.wikipedia.org/wiki/The_Fox_and_the_Grapes
so like if something cannot be done in that way then it doesn't need
to be done in that way. There is nothing particularly strange in the
necessity to swap some values. If it needs to be done more than once
in the same program then there is nothing strange in the desire to
make it as a subroutine. The fact that it is not possible for stay
alone primitives in JavaScript is far of being obvious for people
coming from some other programming platforms. Yes, the task can be
still accomplished in a number of ways like yours or mine. No, it
cannot be accomplished in a subroutine for stay alone primitives.
 
T

Thomas 'PointedEars' Lahn

Asen said:
The whole point of thread is useless and as Thomas pointed out, he
does not need function/method especially "generic". He can use
standard approach, for example:

var foo = 10,
bar = 20;

foo = [bar, bar = foo][0];

That is generic, but the non-obvious code style aside, I would not want to
rely on that it works. The Specifications imply that the /ElementList/ is
evaluated from left to right [11.1.4], but does it follow that all
implementations must do that?

I would also be positively surprised if the creation of an Array instance, a
property lookup and two assignments was more efficient than a variable
declaration and three assignments. That said, I would like very much other
implementations to adopt the desctructuring assignment and ES 6 "Harmony" to
specify it.


PointedEars
 
R

Richard Cornford

Asen Bozhilov wrote:
foo = [bar, bar = foo][0];

That is generic, but the non-obvious code style aside, I would not
want to rely on that it works. The Specifications imply that the
/ElementList/ is evaluated from left to right [11.1.4], but does
it follow that all implementations must do that?

The specification doesn't imply that the evaluation order is left to
right, it mandates it, or at least that implementations behave as if
they do evaluate the element list from left to right, and that order
does matter. So it does follow that implementations must do that.
I would also be positively surprised if the creation of an Array
instance, a property lookup and two assignments was more efficient
than a variable declaration and three assignments.

So would I, but it should be cheaper than a function call (as that
implies the creation of a couple of objects) and if this could be done
with a function call (which it cannot) there aren't that many people
who would worry about implementing it as one.
That said, I would like very much other implementations to adopt
the desctructuring assignment and ES 6 "Harmony" to specify it.

Which itself implies the creation of very temporary objects.

Richard.
 
J

John G Harris

Problem:
I need a method swap(a,b) which I can call with two variables as
params and it would swap the values of the two vars.
<snip>

A way that works in javascript is to switch to a C++ mind-set and tell
yourself it's got to be an 'inline' function so it goes faster.

Now you copy-and-paste
var t = a; a = b; b = t;
from a handy text file and change a,b to x,y or whatever is needed at
that point in the code. Maybe your source-code editor will make this
easier.

John
 
T

Thomas 'PointedEars' Lahn

John said:
A way that works in javascript is to switch to a C++ mind-set and tell
yourself it's got to be an 'inline' function so it goes faster.
*g*

Now you copy-and-paste
var t = a; a = b; b = t;
from a handy text file and change a,b to x,y or whatever is needed at
that point in the code. Maybe your source-code editor will make this
easier.

Good idea. In fact, in Eclipse JSDT you can define this code template:

var ${temp} = ${a};
${a} = ${b};
${b} = ${temp};${cursor}

(Insert with Ctrl+Space, navigate with Tab.)


PointedEars
 
T

Thomas 'PointedEars' Lahn

Richard said:
Thomas said:
Asen said:
foo = [bar, bar = foo][0];

That is generic, but the non-obvious code style aside, I would not
want to rely on that it works. The Specifications imply that the
/ElementList/ is evaluated from left to right [11.1.4], but does
it follow that all implementations must do that?

The specification doesn't imply that the evaluation order is left to
right, it mandates it, or at least that implementations behave as if
they do evaluate the element list from left to right, and that order
does matter. So it does follow that implementations must do that.

*Conforming* implementations. Tests pending…
So would I, but it should be cheaper than a function call (as that
implies the creation of a couple of objects)

No doubt about that.
and if this could be done with a function call (which it cannot) there
aren't that many people who would worry about implementing it as one.

You've lost me here.
Which itself implies the creation of very temporary objects.

Yes. Your point being?


PointedEars
 
L

Lasse Reichstein Nielsen

VK said:
Not "JavaScript 1.7+" but Mozilla JavaScript 1.7+ thus Gecko platforms
thus 10%-20% of average visitors.

JavaScript is the name for the Mozilla (nee Netscape) specified family
of languages. Adding "Mozilla" doesn't change anything (and it's not
part of the name of the language, that's just "JavaScript 1.7").
IMO way below the level of an acceptably universal solution.

What is the reasonable limit for a universal solution? 100% seems
required.
(Not that I disagree with the conclusion).


To OP: to my surprise this question seems never was answered properly
in this newsgroup. The only relevant discussion I found was from
2000:
http://groups.google.com/group/comp..._frm/thread/b72a4c3346057c66/e80dfd68d712c73c
and it doesn't contain any valuablу answer.

JavaScript as currently defined by ECMA-262 3rd ed. by design doesn't
allow primitives' swap in a separate function, because the function
gets such arguments by values, not by references.

Incorrect use of the "JavaScript" name. ECMA-262 doesn't specifiy
JavaScript (Mozilla does that).
If your code requires frequent primitive swaps, you may define an
intermediary var at the beginning so do not create it over and over
again and then:

var swap = null;
// ...
var x = 10, y = 20;
// ...
swap = x, x = y, y = swap;

Ick. What's wrong with semicolons now?
window.alert("x = " + x + ", y = " + y);

/L
 
L

Lasse Reichstein Nielsen

VK said:
Do you have links to documents proving Mozilla's exclusive rights to
JavaScript standardization or/and Mozilla's extensions
"standardization priority" ?

I don't know if there is a reason that somebody else can't make a
competing specification also called JavaScript (if they can get
permission to use the trademark from Oracle, and if Mozilla doesn't
already have some exclusive agreement), but so far, nobody have.

That means that JavaScript is, so far, only used for the familiy of
languages created first by Netscape and later continued by Mozilla.

http://ejohn.org/blog/versions-of-javascript/

There are other ECMAScript implementations that call the language
they implement JavaScript, but at best they are extensions of
JavaScript 1. There are no non-Mozilla implementations of
JavaScript 1.6 and above (well, maybe Tamarin, since it is the
only non-Mozilla engine to support E4X).

/L
 
V

VK

I don't know if there is a reason that somebody else can't make a
competing specification also called JavaScript

The reason was already given, see
http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/dc32e329ae85d989

For the opposite there is so far no reason why I cannot make a BASIC
version and call it ECMAScript(tm). I am really getting closer and
closer to the decision of doing it for the US and the EU at least. The
usage will be free for anywhere except mozilla.org and c.l.j. where
I'll require a solid royalty fee for each use.
(if they can get
permission to use the trademark from Oracle, and if Mozilla doesn't
already have some exclusive agreement), but so far, nobody have.

Being a wholly owned subsidiary doesn't mean patent and trademark
transfer to the parent company unless spelled in the purchase
documents. It is not the case for Sun, so JAVASCRIPT in any case or
any case mixture remains Sun property as of now.
That means that JavaScript is, so far, only used for the family of
languages created first by Netscape and later continued by Mozilla.

The issue was described in depth in the linked thread. If you insist
on a purely genealogical lineage then the most authoritative
JavaScript body then is AOL who bought Netscape, Inc. with all their
stuff back in November 24, 1998 ;-)
 
L

Lasse Reichstein Nielsen

Richard Cornford said:
On Jun 16, 12:49 pm, Thomas 'PointedEars' Lahn wrote:

So would I, but it should be cheaper than a function call (as that
implies the creation of a couple of objects) and if this could be done
with a function call (which it cannot) there aren't that many people
who would worry about implementing it as one.

Function calls don't necessarily have to create any objects.
Most function calls can be handled by just putting the arguments on
the stack and using them from there.
Which itself implies the creation of very temporary objects.

The pattern
[x,y] = [e1,e2];
should be detectable at compile time, so the introduction of the
intermediate array can be optimized away.
If the deconstructing assignment is introduced, it's likely to
be used exactly for swapping variable values, and then I'll bet
that optimization will be made.

/L
 
D

Dmitry A. Soshnikov

Function calls don't necessarily have to create any objects.
Most function calls can be handled by just putting the arguments on
the stack and using them from there.

Well, you have to choose which level to discuss -- the specification or
implementation(s). The later is harder in respect that you should
examine several/all implementations to statement this. Although, only
one implementation is enough to assume.

But by the specification, some "system" objects are created every time
on entering the execution context with the "function" type of code (it
can be activation object in ES3, or lexical/variable environment(s) and
environment record(s) in ES5).
Which itself implies the creation of very temporary objects.

The pattern
[x,y] = [e1,e2];
should be detectable at compile time, so the introduction of the
intermediate array can be optimized away.

Moreover, it can be done syntactically without brackets, as in Python:

x, y = e1, e2;
If the deconstructing assignment is introduced, it's likely to
be used exactly for swapping variable values,

Swapping without "third" can be done with simple arithmetic operations:

A = A - B
B = A + B
A = B - A
and then I'll bet
that optimization will be made.

Yes, it's quite logical.

Dmitry.
 
L

Lasse Reichstein Nielsen

Dmitry A. Soshnikov said:
Well, you have to choose which level to discuss -- the specification
or implementation(s). The later is harder in respect that you should
examine several/all implementations to statement this. Although, only
one implementation is enough to assume.

Agreed. In this case, the statement was that "it should be
cheaper". That means that we are talking implementation, not
specification (the specification has no performance characteristics).
But by the specification, some "system" objects are created every time
on entering the execution context with the "function" type of code (it
can be activation object in ES3, or lexical/variable environment(s)
and environment record(s) in ES5).

True. But many javascript functions don't actually need a physical
representation of these "objects". Environments are purely
specification tools, since they are never exposed, as objects, to user
code. The arguments object is interesting because it can never be
accessed from outside its scope. That means that you can determine (or
approximate safely) whether it is ever used, and if it isn't, you also
don't need to actually create an object for that.

Example:
function foo(a,b) { return a + b; }
This function doesn't contain any closure constructions.
It doesn't access any scoped variables.
It doesn't use the arguments object.
There is nothing preventing an implementation from just reading
parameters off the stack, add them together, and return the
result (on the stack or in a register).

The pattern
[x,y] = [e1,e2];
should be detectable at compile time, so the introduction of the
intermediate array can be optimized away.

Moreover, it can be done syntactically without brackets, as in Python:

x, y = e1, e2;

I'd prefer that.
Or
(x,y) = (e1,e2); // except it's ambiguous with the stupid comma operator.

But then, I think any modern type system should have arbitrary tuples.

Heck, I've seen languages with a swap primitive :)
x :=: y;
Swapping without "third" can be done with simple arithmetic operations:

A = A - B
B = A + B
A = B - A

Try that for strings :)

It's generally a bad idea to be "too smart" in a high-level language.
If you do:
int x,y;
...
x^=y;y^=x;x^=y;
to swap integers in, say, C++, then the compiler might not be able to
do as good a job as if it could recognize that you were doing a
swap. It might know low-level tricks for swapping that can't be
expressed directly in the high-level language (like knowing that
both values are in registers at the moment, so they can be swapped
by a single xchg instruction (if on x86)).

/L
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top