From: Richard Cornford on
On Jun 16, 7:50 pm, Lasse Reichstein Nielsen wrote:
> Richard Cornford writes:
>> On Jun 16, 12:49 pm, Thomas 'PointedEars' Lahn wrote:
>>> 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.
>
> 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.

It is possible for - foo = [bar, bar = foo][0]; - to be optimised by a
complier such that no array object is ever created. The thing that
makes such an optimisation unlikely is that the construct is not that
common and javascript compliers need to be able to work quickly at
delivering an executable and so don't have much time to spend looking
at uncommon constructs to see if they could be optimised.

>>> 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.
>
> The pattern
> [x,y] = [e1,e2];
> should be detectable at compile time, so the introduction of the
> intermediate array can be optimized away.

Can be, but still the behaviour is specified in terms of objects being
created.

> 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.

Probably. This reminds me of the pre-ES5 discussions on -
Object.defineProperty - where it was suggested that the property
defining process could be heavily optimised to get rid of all of the
implied object creation. That is fine if you are using object literals
as the 'attributes' argument, but it seems likely that it will be
common to want to define numerous properties with identical property
descriptors. In that case it would seem like a good idea to create a
single object and pass it to multiple call to - Object.defineProperty
-, while it may actually be more efficient to write (copy-paste)
identical object literals for the 'attributes' argument for each call,
if an optimisation exists to treat that construct as syntax rather
than just a method call.

Richard.
From: VK on
On Jun 17, 2:22 pm, "Evertjan." <exjxw.hannivo...(a)interxnl.net> wrote:
> We could marvel doing a register exor "XOR0" with itself, sparing an extra
> processor cycle from setting 000000 in the same register, speed mattered in
> that era.

EX (SP),HL ;;EX - from EXchange obviously
;;ZX Spectrum, Zilog Z80
;;my sweet youthhood :-)

From: VK on
To summarize the main discussion on the OP question about a generic
swap method in JavaScript:
http://groups.google.com/group/comp.lang.javascript/msg/d4920b7b20b920a7

The language and DOM interface specifics imply three distinct
situations for swapping values and it currently eliminates the
possibility of having a separate polymorphic method (function)
covering all of three together. Such situations are:

1. Swap stay-alone primitive values, thus primitive values which are
not property of any JavaScript object other than Global itself.

2. Swap property values of two JavaScript objects.

3. Swap elements of HTMLCollection (DOM0) or NodeList (DOM1 and
higher). Such collections normally do not allow direct assignments to
their members so specific DOM methods usage will be needed.


1.Swap stay-alone primitive values, thus primitive values
which are not property of any JavaScript object other
than Global itself

JavaScript functions receive primitives by value and there is no
keyword/flag to alter it to by reference pass. Respectively there is
no possibility in JavaScript to make a separate subroutine for stay-
alone primitives swap. The only option remains to use an inline set of
statements for each case. If swapping needs to be done more than once
in the same script it may be suggested to pre-declare the intermediary
variable and use a uniform set of statements, possibly pretty-printed
in a block of statements to make it visually as "functional" as
possible, for instance:

var iswap = null;

// DO other stuff

var v1 = 10;
var v2 = 15;

// swap block:
{
iswap =
v1, v1 = v2, v2 =
iswap
}

Note 1: By using the fact of Global properties reflection in window
host object it is possible to move the code in a separate subroutine
and to pass arguments as identifier literals:

var v1 = 10;
var v2 = 15;

swap('v1', 'v2');

function swap(a, b) {
var tmp = self[a];
self[a] = self[b];
self[b] = tmp;
}

This approach doesn't seep too convenient or flexible but still should
be mentioned for situations where window host object is presented.

Note 2: By using the destructuring assignment introduced in JavaScript
1.7 and currently supported on newest Gecko platforms it is possible
to use a shorter syntax like

var v1 = 10;
var v2 = 15;

[v1, v2] = [v2, v1];

See also: https://developer.mozilla.org/en/new_in_javascript_1.7
The use of destructuring assignments eliminates the necessity of an
intermediary variable but possibly introduces additional objects
creation: therefore the possible productivity gain remains disputable,
see this thread for details and arguments.

Note 3: If the swapping values are non-negative integers lesser or
equal to OxFFFFFFFF (dec 4294967295) then it is possible to avoid an
intermediary variable by using the XOR swap algorithm:
http://en.wikipedia.org/wiki/XOR_swap
Such approach is much lesser universal and it may break the internal
optimization mechanics, see wiki article and Lasse Reichstein Nielsen
in this thread:
http://groups.google.com/group/comp.lang.javascript/msg/af6f0ec2d576d8c6

End of stay-alone primitives situation. To be continued with two other
situations. Corrections are welcome.
From: Dmitry A. Soshnikov on
On 17.06.2010 0:41, Lasse Reichstein Nielsen wrote:
> "Dmitry A. Soshnikov"<dmitry.soshnikov(a)gmail.com> writes:

<snip>

>
> 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).
>

Yeah, logically, yes; I mentioned it the article of closures -- it can
be a general approach in any language -- if a functions do not have free
variables (with possibly analazing the whole chain), then it easily can
put arguments onto stack (or even, yes, registers), rather than use heap
for that, as generally is in languages which supports closures.

>
>>> 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.
>

Damn, really, ambiguity. This could be a good question for "quiz" also
(after everybody have learned that comma returns evaluation of its last
operand):

var a = 10, b = 20;

// everybody knows, that
// comma operator returns the
// evaluation of the last operand

20, 10; // 10

a, b // 20, the same, the last

a, b = b, a;

// or even so:

a, b = 20, 10;

console.log(a, b); // 10, 10 ? Nope, still 10, 20 of course ;)

Yes, this syntax (because of backward compats) isn't acceptable for ES;
in contrast with Python.

> But then, I think any modern type system should have arbitrary tuples.
>
> Heck, I've seen languages with a swap primitive :)
> x :=: y;
>

Interesting. Yes, why not? A good syntactic sugar, increasing the
abstraction, (even if it will cause some performance penalty) is good.

>>> 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
>
> Try that for strings :)
>

Yeah, I know sure. Just mentioned thinking about numbers at that time
(with numbers also can be overflow, by the way).

> 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,

I've checked for the interest in the MS Visual Studio, in C++ -- nope,
it either do not know such optimization at all (even if I try to declare
vars as "register", although, the compiler can ignore it) and make full
operations -- as I see in disassembly window. Or make full optimization
removing my simple code with that operations :P Maybe it can be caught
in more complex examples and it will use that "xchg", don't know. For
the interested it possible to disassemble std:swap to see what's going
on in assembler representation. Although, that's just the particular
implementation.

> so they can be swapped
> by a single xchg instruction (if on x86)).

Yeah, I remember this command, although, I don't use the assembly
language on practice.

Dmitry.
From: Dmitry A. Soshnikov on
On 17.06.2010 4:53, Thomas 'PointedEars' Lahn wrote:
> Lasse Reichstein Nielsen wrote:
>
>> "Dmitry A. Soshnikov" writes:
>>> Lasse Reichstein Nielsen wrote:
>>>> 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:
>
> No, it can't. Check your assumptions.
>

Did I say that I assume something? I confirmed. And that assertion was
related to Python. Though, I guess the word "can" made ambiguity. I mean
it "could" be as in Python. But, yeah, because of current implementation
of the comma operator, it (because of backward compats) -- can't.

>>> x, y = e1, e2;
>>
>> I'd prefer that.
>
> The two of you are missing the ambiguity here which prevents that from
> working as intended in JavaScript already. That is _not_ a destructuring
> assignment in ECMAScript implementations: it is evaluating x, assigning e1
> to y, and evaluating e2. Changing the semantics here would break a lot of
> existing scripts, and is therefore not going to happen.
>
>> Or
>> (x,y) = (e1,e2); // except it's ambiguous with the stupid comma
>> operator.
>
> That is why it should not be specified or implemented so; the LHS must
> evaluate to y, and the RHS must evaluate to e2. The Mozilla people
> (Brendan Eich?) picked the sensible way to provide this feature already.
>
>> But then, I think any modern type system should have arbitrary tuples.
>
> But thanks to the comma operator, that syntax would not be backwards
> compatible in ECMAScript implementations. It is highly doubtful that it
> would be implemented so. So we will probably have to live with Array
> initializers als tuple replacement.
>

Yep.

> the feature was designed for extracting elements from
> Arrays instead.

Possibly, it's from what is called pattern-matching in more older
languages (such as e.g. Erlang). There, if you want to extract elements
from "something" where "something", one can use that pattern matching:

[A, B] = [1, 2]

A and B will have 1 and 2 respectively. The same:

{Data, {OtherData, AndOther}} = {10, {"test", [1, 2, 3]}} to bind three
variables.

Dmitry.