D - The 'interchange' operator
- bodan k.ro (10/10) Jan 14 2003 I just heard about D, and I read that new features can still be added, s...
- Scott Pigman (9/20) Jan 19 2003 a couple of us in another thread have stated a desire for a tuple
- Russell Lewis (2/11) Jan 21 2003 I believe that you can do something like that in perl with lists...
- Antti Sykari (7/12) Jan 22 2003 While this form might look elegant, it
- Scott Pigman (9/26) Jan 22 2003 the original post was a request for an interchange operator, which to th...
- Daniel Yokomiso (13/39) Jan 22 2003 Given ints a and b, one can swap them without using a temporary variable...
- Ilya Minkov (18/23) Jan 22 2003 What's the sanity of this? This code does the following:
- Mike Wynn (10/19) Jan 22 2003 the usual form is
- Ilya Minkov (6/10) Jan 22 2003 This math is not better, IMO. Same 3 operations, all of them atomic (1
- Mike Wynn (20/30) Jan 22 2003 this maths is a lot better, 1, it's bitwise so carry flag does not effec...
- Scott Wood (14/19) Jan 22 2003 Which you would never want to use unless you need atomicity (or
- Daniel Yokomiso (11/21) Jan 22 2003 variable:
- Sean L. Palmer (44/48) Jan 22 2003 What I'm saying is that Joe Programmer should not have to implement this
-
Carlos Santander B.
(28/28)
Jan 23 2003
"Sean L. Palmer"
escribiσ en el mensaje - Russell Lewis (6/18) Jan 23 2003 Importing a library does not cause the functions of that library to be
- Antti Sykari (26/30) Jan 22 2003 Or, if you want to avoid the tedious and error-prone arithmetic
- Daniel Yokomiso (48/79) Jan 22 2003 variable:
- Walter (7/11) Feb 07 2003 If one did this as a generic operation on types, it would screw up the
- factory (32/40) Jan 24 2003 I might point out that in mathematics my experience is that
I just heard about D, and I read that new features can still be added, so I thought I'd suggest an 'interchange' operator (for example, ><), that exhanges the two operands, such that a><b is equivalent to aux=a; a=b; b=aux. It seemed useful to me on many ocasions, it is very easy to implement, and it makes code simpler to write and read. It is also quicker (it elimnates the need for aux and, for references, it can be implemented with two xor's). So, why isn't there one yet? Anyway, I've been looking for a few minutes and couldn't find any place better to send this suggestion, so if you guys now where it should go, please forward it there.
Jan 14 2003
a couple of us in another thread have stated a desire for a tuple construct in order to allow multiple return values from a function. the reason i mention it is that such a construct would also allow you to exchange values w/out adding a new operator: a,b = b,a btw, this is blatently plagerized from python (which may well have stole it from an earlier source ;-) scott On Tue, 14 Jan 2003 12:19:44 +0000, boda wrote:I just heard about D, and I read that new features can still be added, so I thought I'd suggest an 'interchange' operator (for example, ><), that exhanges the two operands, such that a><b is equivalent to aux=a; a=b; b=aux. It seemed useful to me on many ocasions, it is very easy to implement, and it makes code simpler to write and read. It is also quicker (it elimnates the need for aux and, for references, it can be implemented with two xor's). So, why isn't there one yet? Anyway, I've been looking for a few minutes and couldn't find any place better to send this suggestion, so if you guys now where it should go, please forward it there.
Jan 19 2003
Scott Pigman wrote:a couple of us in another thread have stated a desire for a tuple construct in order to allow multiple return values from a function. the reason i mention it is that such a construct would also allow you to exchange values w/out adding a new operator: a,b = b,a btw, this is blatently plagerized from python (which may well have stole it from an earlier source ;-)I believe that you can do something like that in perl with lists...
Jan 21 2003
"Scott Pigman" <scottpig1 attbi.com> writes:a couple of us in another thread have stated a desire for a tuple construct in order to allow multiple return values from a function. the reason i mention it is that such a construct would also allow you to exchange values w/out adding a new operator: a,b = b,aWhile this form might look elegant, it - hides the creation of a temporary value and makes the compiler responsible for creating one so that it would work properly - forces you to write the expressions a and b twice (-> redundancy) - is actually longer to type than "swap(a,b)" -Antti
Jan 22 2003
On Wed, 22 Jan 2003 11:46:51 +0200, Antti Sykari wrote:"Scott Pigman" <scottpig1 attbi.com> writes:the original post was a request for an interchange operator, which to the best of my knowledge would also create a temporary variable that the compiler would be responsible for. i was just pointing out that the tuple idea brought up elsewhere would eliminate the need for a special operator used just for swapping. as for swap(a,b) - are functions pass-by-reference or pass-by-value? and couldn't swap(a,b){ a,b = b,a;} be a possible implementation of it <g>? -sa couple of us in another thread have stated a desire for a tuple construct in order to allow multiple return values from a function. the reason i mention it is that such a construct would also allow you to exchange values w/out adding a new operator: a,b = b,aWhile this form might look elegant, it - hides the creation of a temporary value and makes the compiler responsible for creating one so that it would work properly - forces you to write the expressions a and b twice (-> redundancy) - is actually longer to type than "swap(a,b)" -Antti
Jan 22 2003
"Scott Pigman" <scottpig some.where.com> escreveu na mensagem news:b0mbtg$17nr$1 digitaldaemon.com...On Wed, 22 Jan 2003 11:46:51 +0200, Antti Sykari wrote:Given ints a and b, one can swap them without using a temporary variable: b = a + b; a = b - a; b = b - a; The same thing goes to anything else, because you just need to cast them back and forth to ints. So an "interchange" operator can be defined without using temporary variables. --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 10/1/2003"Scott Pigman" <scottpig1 attbi.com> writes:the original post was a request for an interchange operator, which to the best of my knowledge would also create a temporary variable that the compiler would be responsible for. i was just pointing out that the tuple idea brought up elsewhere would eliminate the need for a special operator used just for swapping. as for swap(a,b) - are functions pass-by-reference or pass-by-value? and couldn't swap(a,b){ a,b = b,a;} be a possible implementation of it <g>? -sa couple of us in another thread have stated a desire for a tuple construct in order to allow multiple return values from a function. the reason i mention it is that such a construct would also allow you to exchange values w/out adding a new operator: a,b = b,aWhile this form might look elegant, it - hides the creation of a temporary value and makes the compiler responsible for creating one so that it would work properly - forces you to write the expressions a and b twice (-> redundancy) - is actually longer to type than "swap(a,b)" -Antti
Jan 22 2003
Daniel Yokomiso wrote:Given ints a and b, one can swap them without using a temporary variable: b = a + b; a = b - a; b = b - a;What's the sanity of this? This code does the following: - load a, b into registers; - perform stoopid math; - save registers into variables. Note, if the variables are already in the registers, they can be exchanged with 1 asm command. Or not exchanged at all, but accounted for at further operation and when saving them later. If both are in memory, they have to be simply loaded and saved, and the rest is not requiered. Obviously, there is no C operation which maps to the exchange of two variables in a normal manner, but when you use a temporary even a simple compiler (LCC!) detects it and makes the most optimal decision, which mathematical wizardry is not. However, it would be sweet not to specify the variable explicitly. Or to be able to write an exchange elegantly and legibly in one line using tuples, which also have a number of other uses. -i.
Jan 22 2003
variable:Given ints a and b, one can swap them without using a temporarythe usual form is a = a ^ b; b = a ^ b; a = a ^ b; it's use is to swap to cpu registers without a 3rd or a store+load but otherwise its pointless most cpus have a swap op these days x86 has reg, mem exchange anyway (though it does lock) Arm has reg, [reg] exchange I'm sure PPC and MIPS have similar.b = a + b; a = b - a; b = b - a;What's the sanity of this? This code does the following: - load a, b into registers; - perform stoopid math; - save registers into variables.
Jan 22 2003
Mike Wynn wrote:the usual form is a = a ^ b; b = a ^ b; a = a ^ b;This math is not better, IMO. Same 3 operations, all of them atomic (1 m-op), and execute in any pipe. So on intel, and all the others shouldn't be very different. And when doing such things, originality matters more, since the *usual* way would be to swap registers with a dedicated command!
Jan 22 2003
"Ilya Minkov" <midiclub 8ung.at> wrote in message news:b0n2c8$1m2s$1 digitaldaemon.com...Mike Wynn wrote:this maths is a lot better, 1, it's bitwise so carry flag does not effect the op and the op does not effect the carry. and 2 its the same op rather 3 times, due to the self inverse behaviour of xor.the usual form is a = a ^ b; b = a ^ b; a = a ^ b;This math is not better, IMO. Same 3 operations, all of them atomic (1 m-op), and execute in any pipe. So on intel, and all the others shouldn't be very different.And when doing such things, originality matters more, since the *usual* way would be to swap registers with a dedicated command!by *usual* I mean the usual swap 2 reg only usung 2 reg's is done with xor, not I usually swap that way I totally agree (please read my comments) BUT most CPU's that have swap/exchange ONLY have reg, [reg] not reg, reg and in the old days there where no exchange op's and less registers, no pipelines, only one alu etc etc etc. mov r2, r1; mov r1, r0; mov r0, r2; <- 3 op's uses 3 regs xor r1, r1, r0; xor r0, r1, r0; xor r1, r1, r0 <- 3 ops uses 2 regs that's the only reason, apart from being a mathmatical curiosity xchg on the x86 asserts the lock, which stall things so it is avoided unless needed and how often do you need to swap 2 values ? I've got more code that uses rotates `a = ((b<<c)|(b>>-c));` than used swaps
Jan 22 2003
On Wed, 22 Jan 2003 20:43:02 -0000, Mike Wynn <mike.wynn l8night.co.uk> wrote:it's use is to swap to cpu registers without a 3rd or a store+load but otherwise its pointless most cpus have a swap op these days x86 has reg, mem exchange anyway (though it does lock) Arm has reg, [reg] exchangeWhich you would never want to use unless you need atomicity (or perhaps if optimizing for space is your primary concern); otherwise, it's faster to do it manually. Plus, on some ARMs, SWP bypasses the cache. In fact, on non-super-scalar chips such as most if not all ARMs, the math tricks might actually be the best way to do the exchange, since you never have to spill a register for a temporary, and the chained result dependencies aren't an issue. It's three instructions either way...I'm sure PPC and MIPS have similar.They don't; they use a load locked/store conditional mechanism to achieve atomicity. They also have enough registers that using a third is unlikely to be a problem. :-) -Scott
Jan 22 2003
"Ilya Minkov" <midiclub 8ung.at> escreveu na mensagem news:b0mrht$1i24$1 digitaldaemon.com...Daniel Yokomiso wrote:variable:Given ints a and b, one can swap them without using a temporaryIt's not intended to be sane, fast or easy to understand, but it doesn't use ANY temporary variables. It's just to prove that it can be written without extra storage. I'm not saying that D should do this, or that this is good programming. --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 10/1/2003b = a + b; a = b - a; b = b - a;What's the sanity of this? This code does the following: - load a, b into registers; - perform stoopid math; - save registers into variables.
Jan 22 2003
What I'm saying is that Joe Programmer should not have to implement this *crap*, for any type, let alone all types. Swap is a basic intrinsic operation and should be defined by the language for everything that's assignable. Then the compiler can generate whatever wierd code is needed to perform the swap optimally for the platform. Think semantics, not implementation. Same goes for min, and max. If you have to have the compiler "figure out what you meant" after the fact, it can't be depended upon. Better to just tell it exactly what you intend. Hell, C even has abs() (and labs(), and fabs()) and yet hordes of code I've seen has stupid if (f < 0) f = -f; or (f<0 ? -f : f) crap gumming up the works. That might be a counterargument, in fact. ;) But you should be able to trust the compiler to generate good code if you call abs() or fabs(); I wouldn't expect a compiler to turn (f < 0 ? -f : f) into something that has no branches. But if it does, great. I'm just not gonna depend on it. There should be a certain baseline for functionality; all machines either support swap, min, max, abs natively, or have the mechanisms to implement them. That's fundamental computing. Look at the mess Windows made with MIN and MAX #defines (actually it also #define's min and max as well, confounding ISO std::C++) It would pay to do a thorough job of covering the fundamentals, up front. Rotate is also a good candidate. It's in C library for most platforms anyway even if it's not standard. As someone pointed out, it can be implemented easily with two shifts and an or, *if* the cpu happens to lack such an operation. I think that would be rare. Anyone that can implement a compiler can do code generation for rotate, no problem. It wouldn't burden implementors one bit. It would be a useful addition to the D language. Any other common low level stuff that isn't in D? clamp (just a wrapper around a min and max combo). test if in range. Inexact comparison for floats (f1 ?= f2 generates abs(f1 - f2) < epsilon, though specifying what epsilon should be would be an issue). div+mod combination converting from float to int with various forms of rounding, at bare minimum truncate and round nearest, which are implementable in terms of each other. power function x**y or pow(x,y) I'm running out of them. There aren't that many. The upside to this is that if new operators are added for these, that's just that many more operators we can overload later. ;) Sean "Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:b0mvt1$1kjh$1 digitaldaemon.com...It's not intended to be sane, fast or easy to understand, but it doesn'tuseANY temporary variables. It's just to prove that it can be written without extra storage. I'm not saying that D should do this, or that this is good programming.
Jan 22 2003
"Sean L. Palmer" <seanpalmer directvinternet.com> escribiσ en el mensaje news:b0o345$27ls$1 digitaldaemon.com... | Hell, C even has abs() (and labs(), and fabs()) and yet hordes of code I've | seen has stupid if (f < 0) f = -f; or (f<0 ? -f : f) crap gumming up the Actually, that brings me to this question: if I import, let's say, c.stdio and I only use printf(), does dmd still compile the other functions? I know that if I don't use anything from the module, dmd ignores it, but what about specific things? The reasoning behind doing what you said is the same: why would I import (include, in this case) sqrt, sin, cos, etc., when I only need abs? Carlos Santander http://carlos3.netfirms.com/ "Sean L. Palmer" <seanpalmer directvinternet.com> escribiσ en el mensaje news:b0o345$27ls$1 digitaldaemon.com... | Hell, C even has abs() (and labs(), and fabs()) and yet hordes of code I've | seen has stupid if (f < 0) f = -f; or (f<0 ? -f : f) crap gumming up the Actually, that brings me to this question: if I import, let's say, c.stdio and I only use printf(), does dmd still compile the other functions? I know that if I don't use anything from the module, dmd ignores it, but what about specific things? The reasoning behind doing what you said is the same: why would I import (include, in this case) sqrt, sin, cos, etc., when I only need abs? Carlos Santander http://carlos3.netfirms.com/
Jan 23 2003
Carlos Santander B. wrote:"Sean L. Palmer" <seanpalmer directvinternet.com> escribiσ en el mensaje news:b0o345$27ls$1 digitaldaemon.com... | Hell, C even has abs() (and labs(), and fabs()) and yet hordes of code I've | seen has stupid if (f < 0) f = -f; or (f<0 ? -f : f) crap gumming up the Actually, that brings me to this question: if I import, let's say, c.stdio and I only use printf(), does dmd still compile the other functions? I know that if I don't use anything from the module, dmd ignores it, but what about specific things? The reasoning behind doing what you said is the same: why would I import (include, in this case) sqrt, sin, cos, etc., when I only need abs?Importing a library does not cause the functions of that library to be included in your binary - unless, of course, the compiler chooses to inline the function. Instead, each function exists in the .o (or library file) that corresponds with where the function was defined.
Jan 23 2003
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:Given ints a and b, one can swap them without using a temporary variable: b = a + b; a = b - a; b = b - a;Or, if you want to avoid the tedious and error-prone arithmetic operations, you can use the classic alternative: a ^= b; b ^= a; a ^= b; Enough with jokes... To be serious, I thought about the tuples a while and decided that probably it would be the best to implement tuple assignments as a following translation: // assume Type1 t1, Type2 t2, ..., TypeN tN; t1, t2, ..., tN = expr1, expr2, ..., exprN; would be translated to Type1 tmp1; Type2 tmp2; ...; TypeN tmpN; tmp1 = expr1; ...; tmpN = exprN; t1 = tmp1; ...; tN = exprN; So that even "a, b = b, a" would work intuitively and unnecessary temporaries would be removed by the compiler. Tuples don't come free. With the above-mentioned syntax they might cause slight parsing problems. Most visibly, they might would make the comma operator unusable because it would be indistinguishable from the tuples. So the alternatives seem to be "keep the comma operator and use a different syntax for tuples", "introduce special cases where comma operator can be used in tuples (for example inside parens)", and "change the comma operator to a different form or otherwise render it unusable". Antti
Jan 22 2003
"Antti Sykari" <jsykari gamma.hut.fi> escreveu na mensagem news:86u1g0dfyu.fsf hoastest1-8c.hoasnet.inet.fi..."Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> writes:variable:Given ints a and b, one can swap them without using a temporaryHi, This work for this particular case of tuple construction/deconstruction, but usually people will use that with functions, like: ComparableCollection numbers = ...; int min, max = numbers.bounds(); So generic tuples must work like structs, accessing defined stack areas (nothing forbids the compiler to generate code like what you did for this special case). Of course all this talk about tuples would make in/out/inout kind of obsolete. About tuple syntax, we can force people using parenthesis in tuples, so it should look like: (a,b) = (b,a); And defined method call based on tuple passing, so calling "foo(a,b,c);" is giving foo the tuple (a,b,c). Empty tuples would come free, and single element tuples too. With this in mind we could say that every single value is equivalent to a single element tuple, so we can still use parenthesis to reorder expressions, but it'll just create single element tuples. That could render the comma operator useless. It's semantics could be emulated by a simple (but strange) rule for tuples: tuples are pruned from left to right to fit in their targets: int a = (1,2,3,4); // a is 4 int (a,b) = (1,2,3,4); // a is 3, b is 4 int (a,b,c) = (1,2,3,4); // a is 2, b is 3, c is 4 int (a,b,c,d) = (1,2,3,4); // a is 1, b is 2, c is 3, d is 4 But I think this is most likely to cause bugs. There is any idiom that the comma operator (as is stands today) makes clearer? As a side note if we unify this tuple construction/deconstruction rules with function call we can end with functional languages syntax, so: omparableCollection numbers = ...; Range bounds = new Range numbers.bounds(); // function application or we can force the parenthesis: Range bounds = new Range(numbers.bounds()); Which can also lead to unmaintainable code. Also with single value = single element tuple paradigm, we'll flatten more tuples than usual: ((((1))),((2,3),((4))),(5)) // I feel lispish today ;-) will become: (1,((2,3),4),5) Which may be a good thing. Or not ;-) Best regards, Daniel Yokomiso. "The consumer is not an idiot, she is your wife." - David Ogilvy, founder of Ogilvy & Mather --- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 10/1/2003b = a + b; a = b - a; b = b - a;Or, if you want to avoid the tedious and error-prone arithmetic operations, you can use the classic alternative: a ^= b; b ^= a; a ^= b; Enough with jokes... To be serious, I thought about the tuples a while and decided that probably it would be the best to implement tuple assignments as a following translation: // assume Type1 t1, Type2 t2, ..., TypeN tN; t1, t2, ..., tN = expr1, expr2, ..., exprN; would be translated to Type1 tmp1; Type2 tmp2; ...; TypeN tmpN; tmp1 = expr1; ...; tmpN = exprN; t1 = tmp1; ...; tN = exprN; So that even "a, b = b, a" would work intuitively and unnecessary temporaries would be removed by the compiler. Tuples don't come free. With the above-mentioned syntax they might cause slight parsing problems. Most visibly, they might would make the comma operator unusable because it would be indistinguishable from the tuples. So the alternatives seem to be "keep the comma operator and use a different syntax for tuples", "introduce special cases where comma operator can be used in tuples (for example inside parens)", and "change the comma operator to a different form or otherwise render it unusable". Antti
Jan 22 2003
"Daniel Yokomiso" <daniel_yokomiso yahoo.com.br> wrote in message news:b0mq5b$1h7f$1 digitaldaemon.com...Given ints a and b, one can swap them without using a temporary variable: b = a + b; a = b - a; b = b - a;If one did this as a generic operation on types, it would screw up the garbage collector. This is because if the thread was halted in the middle of such a calculation to check for pointers, one of the pointers would be scrambled, and would be missed. A generic implementation would have to use temporaries.
Feb 07 2003
On Tue, 14 Jan 2003 12:19:44 +0000, boda wrote:I might point out that in mathematics my experience is that mathematicians generally use max( 1,2..n ) style of notation and do not generally use a symbol. (although I have seen the traditional union symbol used as max in a web page on trinary arithmetic) I would argue that using mathematical symbols in languages is a positive thing, commonly accepted mathematical symbols are 'useful' (especially for numerical computing), and also tend to map well into code construction. So thus every language almost universally uses mathematical equality symbols (=,>,<, etc), and basic arithmetic symbols (+,-,*, etc). But for symbols that are not in ascii there is less agreement on how to represent them in a programming language. Most languages just use ascii symbols, or just use the names of the operation written out (ie. AND and OR). I say that we should reinstate the 'proper' mathematical symbols. Add U+00f7 for /, add U+2264 and U+2265 for <= and >=, etc. Cons: some mathematical symbols do not distinguish between binary and logical operations, ie U+2227 could be used for bitwise or logical AND. Oh and it's also a pain in the arse to type, well for most ppl who use latin keyboards. And bring in all the set notation too, with all the generics going on nowadays, those would be quite useful. Or at the very least, allow unicode to be in identifiers and allow the user to define binary operators, with the operator defined by a user keyword. Hmm dunno what the syntax would be for something like that, the standard way of writing binary operations only allows for overloading operators. hmm maybe something like: T operator xor( T, T ) Ohh, I've gone all C++.. - FactoryI just heard about D, and I read that new features can still be added, so I thought I'd suggest an 'interchange' operator (for example, ><), that exhanges the two operands, such that a><b is equivalent to aux=a; a=b; b=aux. It seemed useful to me on many ocasions, it is very easy to implement, and it makes code simpler to write and read. It is also quicker (it elimnates the need for aux and, for references, it can be implemented with two xor's). So, why isn't there one yet?
Jan 24 2003