oldValue= array[index];
array[index]= newValue;
doSomethingWith(oldValue)
If instead wanted to post-increment/decrement it I could have written
just :
doSomethingWith( array[index]++ );
which is shorter, clearer, and does not need any temp. var.
So, my question/idea (I hope it's not too dumb) is, why not to have a
"post-assignment" operator ? One that given the expression:
`aReference *postAssignmentOperator* newValue` would assign newValue
to aReference but would return the value that it had before the
assignment.
doSomethingWith( array[index] := newValue );
It may serve too to swap(a, b) :
a= ( b:= a )
?
--
Jorge.
I don't really see how your initial rationale supports the new :=
operator - first you talk about incrementing/decrementing (which is
supported), and then you talk about swapping variables, something that
can easily be done within the existing language
a = [b, b=a][0];
Sean
That's awesome. Even beautiful :-) But it's not too efficient, is it ?
Must create a dummy temporary array and then lookup the first element.
I said *post* increment/decrement, because what it returns is the -
old- value, the one that was before the operation. As in a "post-
assignment" operator.
Using your example, you would swap array[x] with array [y] so :
array[x]= [ array[y], array[y]= array[x] ][0];
That's awesome, but it's 5 lookups + a tmp array creation, instead:
tmp= array[x];
array[x]= array[y];
array[y]= tmp;
Is just 4 lookups + a tmp var. But:
array[x]= ( array[y]:= array[x] );
Is shorter, clearer and would do only 3 lookups and no tmp var nor
array creation.
--
Jorge.
Perhaps something like this will do?
array[index] = (doSomethingWith(array[index]), newValue);
Can you provide some objective criteria by which the outcome can be
judged? That will make it easier to determine whether it is an
improvement or not.
The code above could be:
doSomethingWith(array[index]);
array[index] = newValue;
unless you want to remember the original value for some further use,
in which case you have to assign it for storage anyway (say a variable
or object property). So what benefit does a post assignment operator
have?
> If instead wanted to post-increment/decrement it I could have written
> just :
>
> doSomethingWith( array[index]++ );
>
> which is shorter, clearer, and does not need any temp. var.
And which you can already do. No need for a post assignment operator
in that example (ignoring the fact that it doesn't fit your criteria
of returning or storing the original value, which is why no temp
variable is used).
> So, my question/idea (I hope it's not too dumb) is, why not to have a
> "post-assignment" operator ? One that given the expression:
>
> `aReference *postAssignmentOperator* newValue` would assign newValue
> to aReference but would return the value that it had before the
> assignment.
Please identify the benefits ("clearer" is entirely subjective,
whether fewer characters necessarily means more concise is moot).
> doSomethingWith( array[index] := newValue );
Which is exactly equivalent to:
doSomethingWith(array[index]);
array[index] = newValue;
It is a few more characters to type, but I can't see how it is less
clear. To paraphrase Richard Cornford, writing less code is, of
itself, rarely a good reason for doing anything.
In any case, the original requirement was to store the old value for
later use, which the above doesn't do.
> It may serve too to swap(a, b) :
>
> a= ( b := a )
Which is done infrequently. When required, it is usually combined with
a logic test to see if a and b need to be swapped, so compare:
if ( <test> ){
a = b := a;
}
with
if ( <test. ) {
var c = b;
b = a;
a = c;
}
which is not really *that* much more code. If a and b meet certain
criteria (e.g. integers between certain values), they might be able to
be swapped without creating a temporary variable using:
a = b - a;
b = b - a;
a = a + b;
though I would likely never do that as I don't see the issue with
creating temporary variables for such purposes. Another option if a
meets suitable criteria (such as a having a truthy value) is:
a = (b = a) && <new value for a>;
Without objective criteria for evaluation, the navel gazing could be
endless.
--
Rob
That if you need the oValue just once, it avoids the need to store it
anywhere, like in a while (n--)
In the code I was writing when I thought this the array update had to
happen before the call to doSomethingWith(oValue), it was :
callBack= queue(i);
queue[i]= nop;
callBack();
> > If instead wanted to post-increment/decrement it I could have written
> > just :
>
> > doSomethingWith( array[index]++ );
>
> > which is shorter, clearer, and does not need any temp. var.
>
> And which you can already do. No need for a post assignment operator
> in that example (ignoring the fact that it doesn't fit your criteria
> of returning or storing the original value, which is why no temp
> variable is used).
There's no tmp var, it updates the array item before the call, and
passes oValue doSomethingWith(). It does the things in exactly the
same order as the other snippet, only that it assigns oValue + 1;
> > So, my question/idea (I hope it's not too dumb) is, why not to have a
> > "post-assignment" operator ? One that given the expression:
>
> > `aReference *postAssignmentOperator* newValue` would assign newValue
> > to aReference but would return the value that it had before the
> > assignment.
>
> Please identify the benefits ("clearer" is entirely subjective,
> whether fewer characters necessarily means more concise is moot).
>
> > doSomethingWith( array[index] := newValue );
>
> Which is exactly equivalent to:
>
> doSomethingWith(array[index]);
> array[index] = newValue;
It isn't.
Thanks, Rob.
--
Jorge.
callBack= queue[i];
--
Jorge.
With a post-assignment operator it could have written:
(queue[i] := nop)();
--
Jorge.
Grrr, s/it could/I could/
--
Jorge.
This is like Rob's: it updates the array *after* the call. :-/
--
Jorge.
> That's awesome. Even beautiful :-) But it's not too efficient, is it ?
> Must create a dummy temporary array and then lookup the first element.
Leave interpret to do optimizations. This code allows for
optimizations and there is not reason for creation of temporary array
object.
> array[x] = [ array[y], array[y]= array[x] ][0];
>
> That's awesome, but it's 5 lookups + a tmp array creation, instead:
Actually lookups are 13. 8 against Scope chain for identifiers
`array', `x', `y' and 5 lookups against Prototype chain.
> tmp = array[x];
> array[x]= array[y];
> array[y]= tmp;
>
> Is just 4 lookups + a tmp var. But:
Lookups are 14. 10 against Scope chain for identifiers `tmp', `array',
`x', `y' and 4 against Prototype chain for property accesses.
> array[x]= ( array[y]:= array[x] );
>
> Is shorter, clearer and would do only 3 lookups and no tmp var nor
> array creation.
Lookups are 9. 6 against Scope chain for identifiers `array', `x', `y'
and 3 for property accesses.
The last approach seems exactly as approach which use temporary
variable. The value of `array[y]' must be kept somewhere and after
evaluation of assignment expression must be return and old value. So
this assignment will create temporary variable on implementation
level.
Isn't it a bit strange thing to index an array that doesn't exist ?
> > array[x] = [ array[y], array[y]= array[x] ][0];
>
> > That's awesome, but it's 5 lookups + a tmp array creation, instead:
>
> Actually lookups are 13. 8 against Scope chain for identifiers
> `array', `x', `y' and 5 lookups against Prototype chain.
>
> > tmp = array[x];
> > array[x]= array[y];
> > array[y]= tmp;
>
> > Is just 4 lookups + a tmp var. But:
>
> Lookups are 14. 10 against Scope chain for identifiers `tmp', `array',
> `x', `y' and 4 against Prototype chain for property accesses.
>
> > array[x]= ( array[y]:= array[x] );
>
> > Is shorter, clearer and would do only 3 lookups and no tmp var nor
> > array creation.
>
> Lookups are 9. 6 against Scope chain for identifiers `array', `x', `y'
> and 3 for property accesses.
You know I meant the -array- property lookups.
> The last approach seems exactly as approach which use temporary
> variable. The value of `array[y]' must be kept somewhere and after
> evaluation of assignment expression must be return and old value. So
> this assignment will create temporary variable on implementation
> level.
Yes, the same semantics somehow means that in the end they're going to
be doing ~ the same things. But implemented natively there's a chance
for it to be at least slightly faster. And, the source code would be
shorter and nicer and cleaner, which is a Good Thing™.
You might want to benchmark it ?
var i= 0;
function a () {
var tmp= i;
i= i+ 1;
return tmp;
}
function b () { return i++ }
function c () { return [i, i= i+ 1][0] }
function test (f) {
i= 0;
var n= 1e6;
var t= Date.now();
while (n--) f(), f(), f(), f(), f(), f(), f(), f();
t= Date.now()- t;
console.log([t, i]);
}
test(a)
--> [9038, 8000000]
test(b)
--> [5318, 8000000]
test(c)
--> [13955, 8000000]
navigator.userAgent
--> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:
1.9.2.9) Gecko/20100824 Firefox/3.6.9"
--
Jorge.
No love for this ? no one ?
--
Jorge.
I'm indifferent on it. I can see some advantages, but not sure it's
worth an extra op. About the only time I swap values like this is when
I'm sorting, and there are functions to do that.
--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstu...@attglobal.net
==================
>> `aReference *postAssignmentOperator* newValue` would assign newValue
>> to aReference but would return the value that it had before the
>> assignment.
>>
>> (...) swap(a, b) :
>>
>> a= ( b:= a )
>
> No love for this ? no one ?
No love at all.
Swapping should be done like:
(a,b) = (b,a)
Even in JavaScript there is no tuples, so it uses the bastardized
array notation:
[a,b] = [b,a]
but that's still better than using a "post assignment operator" for.
it.
There could be other uses for it, though, but none that I really
need.
/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'
What does that expression evaluate to ?
> Even in JavaScript there is no tuples, so it uses the bastardized
> array notation:
> [a,b] = [b,a]
> but that's still better than using a "post assignment operator" for.
> it.
How many more property lookups does it take to swap array[i] and
array[n] with that ?
> There could be other uses for it, though, but none that I really
> need.
A callbacks queue:
( queue[i] := nop )();
To insert an item in a linked list:
newItem.nextItem= (item.nextItem := newItem);
And more.
--
Jorge.
Ok. Thanks.
--
Jorge.
> On Sep 9, 6:37 pm, Lasse Reichstein Nielsen <lrn.unr...@gmail.com>
> wrote:
>>
>> No love at all.
>> Swapping should be done like:
>> (a,b) = (b,a)
>
> What does that expression evaluate to ?
To the tuple containing both values, preferably.
It requires tuples to be first class values (like in ML or Haskel),
but then simultaneous assignment is just working by default.
>> Even in JavaScript there is no tuples, so it uses the bastardized
>> array notation:
>> [a,b] = [b,a]
>> but that's still better than using a "post assignment operator" for.
>> it.
>
> How many more property lookups does it take to swap array[i] and
> array[n] with that ?
True, a direct implementation would use four where an explicit swap
would only need two (and your post assignment operator would use
three).
You might recognize a swap and optimizing it - as long as there
aren't any side effects in the lookup.
>> There could be other uses for it, though, but none that I really
>> need.
>
> A callbacks queue:
>
> ( queue[i] := nop )();
[queue[i], popped] = [nop, queue[i]];
popped();
Bigger, but more readable. But just make a function for that:
(queue.pop())()
> To insert an item in a linked list:
>
> newItem.nextItem= (item.nextItem := newItem);
[newItem.nextItem, item.nextItem] = [item.nextItem, newItem];
> And more.
I bet simultaneous assignment will handle most of them as well.
What else can you use a tuple for ?
How do you access the tuple's items individually ?
> >> Even in JavaScript there is no tuples, so it uses the bastardized
> >> array notation:
> >> [a,b] = [b,a]
> >> but that's still better than using a "post assignment operator" for.
> >> it.
>
> > How many more property lookups does it take to swap array[i] and
> > array[n] with that ?
>
> True, a direct implementation would use four where an explicit swap
> would only need two (and your post assignment operator would use
> three).
> You might recognize a swap and optimizing it - as long as there
> aren't any side effects in the lookup.
>
> >> There could be other uses for it, though, but none that I really
> >> need.
>
> > A callbacks queue:
>
> > ( queue[i] := nop )();
>
> [queue[i], popped] = [nop, queue[i]];
> popped();
>
> Bigger, but more readable.
LOL, you must be joking.
> But just make a function for that:
>
> (queue.pop())()
That's semantically !== ( queue[i] := nop )();
> > To insert an item in a linked list:
>
> > newItem.nextItem= (item.nextItem := newItem);
>
> [newItem.nextItem, item.nextItem] = [item.nextItem, newItem];
1 more unneeded property lookup.
> > And more.
>
> I bet simultaneous assignment will handle most of them as well.
I'm all for it. But face it, it's no better than my "post-assignment"
operator, not in any of the examples we've seen so far.
--
Jorge.
> I've had the need to save an array element just before
> updating it to a new value:
>
> oldValue= array[index];
> array[index]= newValue;
> doSomethingWith(oldValue)
>
> If instead wanted to post-increment/decrement it I could
> have written just :
>
> doSomethingWith( array[index]++ );
>
> which is shorter, clearer, and does not need any temp. var.
Two out of three. --Antony
Two out of three ?
--
Jorge.
"The limits of my language mean the limits of my world"