Prev: FAQ Topic - How can I see in javascript if a web browser acceptscookies? (2010-06-16)
Next: FAQ Topic - How can I see in javascript if a web browser accepts cookies? (2010-06-16)
From: Richard Cornford on 17 Jun 2010 07:14 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 17 Jun 2010 07:21 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 17 Jun 2010 08:21 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 17 Jun 2010 08:51 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 17 Jun 2010 09:13
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. |