Generic swap: Difference between revisions
→{{header|CMake}}: Show 2 limitations of swap(). |
→{{header|Delphi}}: Does not implement anything generic. |
||
Line 262:
=={{header|Delphi}}==
{{incorrect|Delphi|Option 1 demonstrates a dubious arithmetic trick for swapping integers that works on two's complement hardware thanks to wrapping behavior of arithmetic overflow. Neither option demonstrates generic programming: swapping two variables using the same function or operator, regardless of their type.}}
Option 1:
<lang Delphi>
|
Revision as of 22:35, 26 September 2011
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Many statically typed languages provide a generic programming capability. In C++ this capability is called templates. In Ada it is called generics. Such generic capabilities are simply the natural approach to programming for dynamically typed languages.
This task asks you to create a generic swap method that can be used for a wide variety of data types. If your solution language is statically typed please describe the way your language provides genericity. (This is actually a simple example of Parametric Polymorphism)
Ada
The generic parameters for an Ada generic procedure are defined in a procedure specification, while the algorithm is defined in a procedure body. The first code snippet is the procedure instantiation. The second code snippet is the procedure body.
<lang ada>generic
type Swap_Type is private; -- Generic parameter
procedure Generic_Swap(Left : in out Swap_Type; Right : in out Swap_Type);
procedure Generic_Swap(Left : in out Swap_Type; Right : in out Swap_Type) is
Temp : Swap_Type := Left;
begin
Left := Right; Right := Temp;
end Generic_Swap;</lang>
ALGOL 68
A generic swap operator =:= was proposed in ALGOL Bulletin for standard ALGOL 68 so that the compiler could optimise the operation. However such an operator was not adopted and needs to be manually defined for each mode required.
<lang algol68>MODE GENMODE = STRING;
GENMODE v1:="Francis Gary Powers", v2:="Vilyam Fisher";
PRIO =:= = 1;
OP =:= = (REF GENMODE v1, v2)VOID: (
GENMODE tmp:=v1; v1:=v2; v2:=tmp
);
v1 =:= v2;
print(("v1: ",v1, ", v2: ", v2, new line))</lang> Output:
v1: Vilyam Fisher, v2: Francis Gary Powers
AmigaE
The simpler way to write a swap is to use the Amiga E ability to return multiple values. All basic data type in Amiga E can be held by its LONG type, and complex data type (like lists) are indeed pointers (which fits into a LONG too); so, because of the fact that Amiga E is not strongly typed, this solution works for any type. <lang amigae>PROC swap(a,b) IS b,a
PROC main()
DEF v1, v2, x v1 := 10 v2 := 20 v1, v2 := swap(v1,v2) WriteF('\d \d\n', v1,v2) -> 20 10 v1 := [ 10, 20, 30, 40 ] v2 := [ 50, 60, 70, 80 ] v1, v2 := swap(v1,v2) ForAll({x}, v1, `WriteF('\d ',x)) -> 50 60 70 80 WriteF('\n') ForAll({x}, v2, `WriteF('\d ',x)) -> 10 20 30 40 WriteF('\n')
ENDPROC</lang>
AppleScript
AppleScript has built-in support for swapping. This is generic and works for all combinations of data types. <lang AppleScript>set {x,y} to {y,x}</lang>
AutoHotkey
<lang autohotkey>Swap(ByRef Left, ByRef Right) {
temp := Left Left := Right Right := temp
}</lang>
Batch File
Swap using pass-by-name
<lang dos>@echo off setlocal enabledelayedexpansion set a=1 set b=woof echo %a% echo %b% call :swap a b echo %a% echo %b% goto :eof
- swap
set temp1=!%1! set temp2=!%2! set %1=%temp2% set %2=%temp1% goto :eof</lang>
C
This has a restriction that a and b must be the same size. I think you could do better with preprocessor voodoo, but I am not enlightened enough to use it. I'm being cute here, so please don't hate me too much, and if a C guru could check it, I'd appreciate it (I tried it and it worked for me). It won't work for something like a linked list if you want all references to middle nodes to be translated, but it'll swap the heads just fine.
<lang c>void swap(void *a, void *b, size_t size) {
char *ca, *cb; int i; ca = (char *)a; cb = (char *)b; for(i=0;i<size;*(ca+i)^=*(cb+i),*(cb+i)^=*(ca+i),*(ca+i)^=*(cb+i),++i);
}</lang>
You could also do it with a third buffer but then it wouldn't work for extremely large void pointers. It'd be faster to use a larger pointer than char *, but I wanted to keep it simple.
If you have gcc, you can write a preprocessor macro with __typeof__.
- Caution: __typeof__ is a gcc extension, not part of standard C. __typeof__ does not conflict with C89 because the standard allows compilers to add keywords with underscores like __typeof__.
<lang c>#define Swap(X,Y) do{ __typeof__ (X) _T = X; X = Y; Y = _T; }while(0)</lang>
Usage examples are:
<lang c>#include <stdio.h>
- define Swap(X,Y) do{ __typeof__ (X) _T = X; X = Y; Y = _T; }while(0)
struct test {
int a, b, c;
};
int main()
{
struct test t = { 1, 2, 3 }; struct test h = { 4, 5, 6 }; double alfa = 0.45, omega = 9.98; struct test *pt = &t; struct test *th = &h; printf("%d %d %d\n", t.a, t.b, t.c ); Swap(t, h); printf("%d %d %d\n", t.a, t.b, t.c ); printf("%d %d %d\n", h.a, h.b, h.c ); printf("%lf\n", alfa); Swap(alfa, omega); printf("%lf\n", alfa); printf("%d\n", pt->a); Swap(pt, th); printf("%d\n", pt->a);
}</lang>
This is tested with GCC with -std=c89 option.
C++
Generic programming in C++ is provided through templates. Templates in C++ are quite powerful: They form a Turing-complete compile-time sub-language. However, that power isn't needed for swap. Note that the C++ standard library already provides a swap function which contains optimized implementations for standard library types; thus it's advisable to use that instead of a self-written variant like the one below.
While the standard allows to separate declaration and definition of templates into different files using the export keyword, most compilers (including the most used ones) don't implement that. Therefore in practice, templates declared in header files also have to be defined there.
The implementation of the swap function template is straightforward:
<lang cpp>template<typename T> void swap(T& left, T& right) {
T tmp(left); left = right; right = tmp;
}</lang> Note that this function requires that the type T has an accessible copy constructor and assignment operator.
The standard utility 'swap' can be used to swap two values:
<lang cpp>std::swap(x,y);</lang>
It will work with any types.
C#
C# 2.0 introduced the concept of generics to the language. Generics are outwardly similar to C++ templates, but are implemented quite differently: generics are maintained generically at runtime rather than being substitued with definite types by the compiler. Generics are intended to promote reusable, efficient, type-safe code, and are used widely throughout the .NET framework and 3rd party libraries, especially in collections. C# generics are less flexible than C++ templates, but are more strongly typed and arguably easier to deal with.
<lang csharp>static void Swap<T>(ref T a, ref T b) {
T temp = a; a = b; b = temp;
}</lang>
Clojure
<lang lisp> (defn swap [pair] (reverse pair)) ; returns a list (defn swap a b '(b a)) ; returns a list (defn swap a b [b a]) ; returns a vector </lang>
The latter two implementations use destructured binding to define local names for the two elements.
CMake
CMake has only one data type: the string.
<lang cmake>function(swap var1 var2)
set(_SWAP_TEMPORARY "${${var1}}") set(${var1} "${${var2}}" PARENT_SCOPE) set(${var2} "${_SWAP_TEMPORARY}" PARENT_SCOPE)
endfunction(swap)</lang>
<lang cmake>set(x 42) set(y "string") swap(x y) message(STATUS ${x}) # -- string message(STATUS ${y}) # -- 42</lang>
Because of limitations in CMake, there are a few specific situations where swap() will fail to swap the variables.
- When _SWAP_TEMPORARY is the name of the second variable: <lang cmake>set(x 42)
set(_SWAP_TEMPORARY "string") swap(x _SWAP_TEMPORARY) message(STATUS ${x}) # -- 42 message(STATUS ${_SWAP_TEMPORARY}) # -- 42</lang> Inside swap(), its local variable _SWAP_TEMPORARY shadows the original _SWAP_TEMPORARY from the parent scope, preventing access to the original value.
- When value of either variable is "CACHE" or "PARENT_SCOPE": <lang cmake>string(TOUPPER CACHE x)
set(y "string") swap(x y) # CMake Error... set given invalid arguments for CACHE mode.</lang> swap() can never set a variable to "CACHE" or "PARENT_SCOPE", because these are keywords of set() command.
Common Lisp
<lang lisp>(rotatef a b)
(psetq a b b a)</lang>
ColdFusion
This is another standard swap.
<lang cfm><cfset temp = a /> <cfset a = b /> <cfset b = temp /></lang>
D
The solution for D is quite similar to that for C++:
<lang d>void swap(T)(ref T left, ref T right) {
auto temp = left; left = right; right = temp;
}</lang> The std.algorithm standard library module contains a generic swap.
dc
We use two registers to swap in POSIX dc. <lang dc>1 2 SaSbLaLb f =2 1</lang> Reverse (r) is a built-in stack command available as a GNU extension for dc. <lang dc>1 2 r f =2 1</lang>
Delphi
Option 1: <lang Delphi> procedure Swap(var a, b: Integer); begin
a := a + b; b := a - b; a := a - b;
end; </lang> Option 2: <lang Delphi> procedure Swap(var a, b: Integer); var
temp: Integer;
begin
temp := a; a := b; b := temp;
end; </lang>
E
(slots)
<lang e>def swap(&left, &right) {
def t := left left := right right := t
}</lang>
(functional)
<lang e>def swap([left, right]) {
return [right, left]
}</lang>
Erlang
Erlang variables are single assignment and Erlang is dynamically typed, so this task doesn't really apply.
The closest thing would be to swap the items in a list (shown in the shell).
<lang Erlang> 1> L = [a, 2]. [a,2] 2> lists:reverse(L). [2,a] </lang>
Or swap the items in a tuple (also shown in the shell).
<lang Erlang> 1> T = {2,a}. {2,a} 2> list_to_tuple(lists:reverse(tuple_to_list(T))). {a,2} </lang>
F#
<lang fsharp>let swap (a,b) = (b,a)</lang>
Factor
Depending on how you look at it: this task doesn't apply, or it's trivial: <lang factor>swap</lang>
Falcon
<lang falcon> a = 1 b = 2 a,b = arr = b,a </lang> Reading right to left: Assign b & a into an array variable called arr, then assign into a & b
Fortran
<lang fortran>MODULE Genericswap
IMPLICIT NONE
INTERFACE Swap MODULE PROCEDURE Swapint, Swapreal, Swapstring END INTERFACE
CONTAINS
SUBROUTINE Swapint(a, b) INTEGER, INTENT(IN OUT) :: a, b INTEGER :: temp temp = a ; a = b ; b = temp END SUBROUTINE Swapint
SUBROUTINE Swapreal(a, b) REAL, INTENT(IN OUT) :: a, b REAL :: temp temp = a ; a = b ; b = temp END SUBROUTINE Swapreal
SUBROUTINE Swapstring(a, b) CHARACTER(*), INTENT(IN OUT) :: a, b CHARACTER(len(a)) :: temp temp = a ; a = b ; b = temp END SUBROUTINE Swapstring
END MODULE Genericswap
PROGRAM EXAMPLE
USE Genericswap IMPLICIT NONE INTEGER :: i1 = 1, i2 = 2 REAL :: r1 = 1.0, r2 = 2.0 CHARACTER(3) :: s1="abc", s2="xyz"
CALL Swap(i1, i2) CALL Swap(r1, r2) CALL Swap(s1, s2)
WRITE(*,*) i1, i2 ! Prints 2 and 1 WRITE(*,*) r1, r2 ! Prints 2.0 and 1.0 WRITE(*,*) s1, s2 ! Prints xyz and abc
END PROGRAM EXAMPLE</lang>
Frink
The following example will work on all Frink data types:
<lang frink> [b,a] = [a,b] </lang>
Gecho
<lang gecho> 1 !0 2 !1 </lang> Now tape[0] and tape[1] are set to 1 and 2, respectively. <lang gecho> &0 &1 !0 pop !1 </lang> This pushes the value of tape[0] to the stack, tape[1] to the stack, sets tape[0] to the top element, and then pops it, then tape[1] to the top element.
Go
Go is statically typed and does not have what most think of as "generics." While generic features are limited, Go does have several features for solving problems that are often solved with generics in other languages.
- A number of built-in features are generic, working with multiple, or even all, types in the language. The assignment operator, for example works with all types. If a and b are of identical type, then either can be assigned to the other. This is true for all types.
- "Duck typing" allows the type to be inferred in many situations. Given variables a and b for example,
<lang go>c := a a = b b = c</lang> is valid code that does not require the type of c to be specified. The type is inferred statically, but nevertheless does not have to be typed by the programmer.
Go has multiple assignment. While it is no more generic than single assignment, it does thus provide fully generic swap without specification of a temporary variable: <lang go>a, b = b, a</lang>
Other features useful in contexts of multiple types:
- Interfaces allow a very useful sort of polymorphism. They allow methods with the same signature to be written for multiple concrete types and then called through an abstract interface.
- Type assertions and type switches allow code to conditionally handle multiple types.
- A type reflection package has multiple features for inspecting and working with types at run time.
The task asks to implement swap as a method. Even considering a Go function as satisfying the task request for a "method," this is not trivial in Go. The unsafe package allows direct manipulation of arbitrary memory and so enables efficient if cryptic solutions. A more readable and type-safe solution is possible with the reflect package, as shown here. <lang go>package main
import (
"fmt" "os" "reflect"
)
func swap(a, b interface{}) os.Error {
ta := reflect.TypeOf(a) tb := reflect.TypeOf(b) if ta != tb { return fmt.Errorf("swap args are different types: %v and %v", ta, tb) } if ta.Kind() != reflect.Ptr { return fmt.Errorf("swap args must be pointers") } ea := reflect.ValueOf(a).Elem() eb := reflect.ValueOf(b).Elem() temp := reflect.New(ea.Type()).Elem() temp.Set(ea) ea.Set(eb) eb.Set(temp) return nil
}
func main() {
a, b := 3, "cats" fmt.Println("a b:", a, b) err := swap(a, b) fmt.Println(err, "\n")
c, d := 3, 4 fmt.Println("c d:", c, d) err = swap(c, d) fmt.Println(err, "\n")
e, f := 3, 4 fmt.Println("e f:", e, f) swap(&e, &f) fmt.Println("e f:", e, f, "\n")
type mult struct { int string }
g, h := mult{3, "cats"}, mult{4, "dogs"} fmt.Println("g h:", g, h) swap(&g, &h) fmt.Println("g h:", g, h)
}</lang> Output:
a b: 3 cats swap args are different types: int and string c d: 3 4 swap args must be pointers e f: 3 4 e f: 4 3 g h: {3 cats} {4 dogs} g h: {4 dogs} {3 cats}
Groovy
Groovy has support for swapping built in:
<lang groovy>(a, b) = [b, a]</lang>
But the task calls for a "generic swap method" to be written, so here it is:
<lang groovy>def swap(a, b) {
[b, a]
}</lang> This function doesn't mutate anything, but simply returns a new list with the order of the elements switched. It can be used like shown below: <lang groovy>def (x, y) = swap(1, 3) assert x == 3 assert y == 1</lang>
Some examples here show an in-place swap of indexed elements in an array or collection, so for completeness here is an in-place swap of arbitrary indexed elements in a list: <lang groovy>def listSwap = { a, i, j ->
assert (0..(a.size())).containsAll([i,j]); aj,i = ai,j
}
def list = [2,4,6,8] listSwap(list, 1, 3) assert list == [2,8,6,4]</lang>
Haskell
Like everything else in Haskell, tuples are immutable. This function doesn't mutate anything, but simply returns a new pair with the order of the elements switched.
The type signature, the first line, is optional; it may be inferred.
<lang haskell>swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)</lang>
This swap
function is available in the Data.Tuple
standard library module in GHC 7.0+
Icon and Unicon
Icon provides a :=: operator for this. Additionally, there is a reversible exchange operator <-> that reverses the exchange if resumed. <lang icon>procedure main()
x := 1 y := 2 x :=: y write(x," ",y) # swap that will reverse if surrounding expression fails if x <-> y & x < y then write(x, " ", y)
end </lang>
IDL
IDL is dynamically typed and array-centric, so swapping is quite easy for any data type. The TEMPORARY function sets its argument to "undefined", and allows us to swap without any large copying.
<lang IDL>pro swap, a, b
c = temporary(a) a = temporary(b) b = temporary(c)
end</lang>
J
J is dynamically typed and J's cycle primitive (C.
) will swap elements of an arbitrary list. See also J's reference documentation on C.
Shown here are a list of prime numbers and the result of J's parser on some random text (inverting the parsing process on the swapped result):
<lang J> (<2 4) C. 2 3 5 7 11 13 17 19 2 3 11 7 5 13 17 19
(<0 3)&C.&.;:'Roses are red. Violets are blue.'
Violets are red. Roses are blue.</lang>
Also, if the argument list can be guaranteed to be a pair, J's reverse primitive will swap the pair.
<lang J> |.2 3 3 2
|.&.;:'one two'
two one</lang>
Java
Java uses references, so it can't swap the values of two variables that don't belong to a class.
<lang java>class Pair<T> {
T first; T second;
} public static <T> void swap(Pair<T> p) {
T temp = p.first; p.first = p.second; p.second = temp;
}</lang>
JavaScript
JavaScript uses references, but if a function reassigns a parametric reference, the new object only has a local reference. However, if we wrap the variables to be switched in some other structure, like an object or an array, we can easily swap the values.
There's no actual "generics", since all variables are just that, variables of some kind.
The below function expects an array of length 2 (or longer), and switches the first two values in place, in the same array. This is closely related to how the Java solution works.
<lang javascript>function swap(arr) {
var tmp = arr[0]; arr[0] = arr[1]; arr[1] = tmp;
}</lang>
Joy
Provided that the stack contains at least two elements and/or aggregates: <lang joy>swap</lang> changes the order of those elements and/or aggregates.
Lisaac
<lang Lisaac>(a, b) := (b, a);</lang>
Logo
<lang logo> to swap :s1 :s2
localmake "t thing :s1 make :s1 thing :s2 make :s2 :t
end
make "a 4 make "b "dog swap "a "b ; pass the names of the variables to swap show list :a :b ; [dog 4] </lang>
Logtalk
<lang logtalk>:- object(paws).
:- public(swap/4). swap(First, Second, Second, First).
- - end_object.</lang>
Usage examples: <lang logtalk>| ?- paws::swap(apples, oranges, X, Y). X = oranges Y = apples yes
| ?- paws::swap(3.14, ext(lgt), X, Y). X = ext(lgt) Y = 3.14</lang> yes
Lua
Lua evaluates the values on the right-hand side before assigning them to the variables on the left-hand side. This behaviour allows the following notation to be used to swap two values: <lang lua> x, y = y, x -- swap the values inside x and y t[1], t[2] = t[2], t[1] -- swap the first and second values inside table t </lang>
Usage example: <lang lua> x, y = 3, 4 print(x, y) --> 3 4 x, y = y, x -- swap print(x, y) --> 4 3 </lang>
M4
<lang m4>define(`def2', `define(`$1',`$2')define(`$3',`$4')')dnl define(`swap', `def2(`$1',defn(`$2'),`$2',defn(`$1'))')dnl dnl define(`a',`x')dnl define(`b',`y')dnl a b swap(`a',`b') a b</lang>
Output:
x y y x
Mathematica
Mathematica functions are generic by default; however, it has to be told not to evaluate the arguments before executing the function. <lang mathematica>swap[a_, b_] := {a, b} = {b, a} SetAttributes[swap, HoldAll]</lang>
MATLAB
It is unnecessary to define a "swap" function in MATLAB because swaps are trivial operations. In fact, they are so natural to the language that multiple swaps can be performed simultaneously.
Example: <lang MATLAB>>> a = [30 40 50 60 70]
a =
30 40 50 60 70
>> a([1 3]) = a([3 1]) %Single swap
a =
50 40 30 60 70
>> a([1 2 4 3]) = a([2 3 1 4]) %Multiple swap, a.k.a permutation.
a =
40 30 60 50 70</lang>
MAXScript
<lang maxscript>swap a b</lang>
Metafont
In Metafont, only numeric declarations can be omitted; any other type, must be explicitly given. So our swap, in order to declare and use a proper temporary variable(? in this code), must check the type of the variable passed (we check only for a; if b is of another kind, an error will occur)
<lang metafont>vardef swap(suffix a, b) =
save ?; string s_; if boolean a: boolean ? elseif numeric a: numeric ? % this one could be omitted elseif pair a: pair ? elseif path a: path ? elseif pen a: pen ? elseif picture a: picture ? elseif string a: string ? elseif transform a: transform ? fi; ? := a; a := b; b := ?
enddef;</lang>
Examples:
<lang metafont>j := 10; i := 5; show j, i; swap(j,i); show j, i;
boolean truth[]; truth1 := true; truth2 := false; show truth1, truth2; swap(truth1,truth2); show truth1, truth2;</lang>
Modula-3
<lang modula3>GENERIC INTERFACE GenericSwap(Elem);
PROCEDURE Swap(VAR left: Elem.T; VAR right: Elem.T);
END GenericSwap.</lang> <lang modula3>GENERIC MODULE GenericSwap(Elem);
PROCEDURE Swap(VAR left: Elem.T; VAR right: Elem.T) =
VAR temp: Elem.T := left; BEGIN left := right; right := temp; END Swap;
BEGIN END GenericSwap.</lang>
Here is an example usage for integers: <lang modula3>INTERFACE IntSwap = GenericSwap(Integer) END IntSwap.</lang> <lang modula3>MODULE IntSwap = GenericSwap(Integer) END IntSwap.</lang> <lang modula3>MODULE Main;
IMPORT IntSwap, IO, Fmt;
VAR left := 10;
right := 20;
BEGIN
IO.Put("Left = " & Fmt.Int(left) & "\n"); IntSwap.Swap(left, right); IO.Put("Left = " & Fmt.Int(left) & "\n");
END Main.</lang>
Output:
Left = 10 Left = 20
Nemerle
For pairs, namespace Nemerle.Utility.Pair contains Swap(): <lang Nemerle>def coords = (1, -1); def invcoords = Swap(coords);</lang> Or to swap two mutable variables of the same type:<lang Nemerle>a <-> b;</lang> But, enough about built in functionality, let's demonstrate using generics: <lang Nemerle>Swap[T, U] (a : T, b : U) : U * T {
(b, a)
}</lang>
Nial
Like J <lang nial>|reverse 1 2 =2 1</lang>
OCaml
Tuples are immutable in OCaml. This function doesn't mutate anything, but simply returns a new pair with the order of the elements switched. <lang ocaml>let swap (x, y) = (y, x)</lang> If the arguments are constrained to be reference values, a swap function is simple: <lang ocaml>let swapref x y =
let temp = !x in x := !y; y := temp</lang>
Octave
GNU Octave has no way to pass a value by reference to a function; so to define a swap we must do as follow:
<lang octave>function [a, b] = swap(ia, ib)
a = ib; b = ia;
endfunction
% testing va = 2; vb = 5; printf("%d %d\n", va, vb); [va, vb] = swap(va, vb); printf("%d %d\n", va, vb);</lang>
Oz
Oz variables are dataflow variables and cannot be changed once a value has been assigned. So a swap operation on dataflow variables does not make sense.
We can write a swap procedure for cells, though. Cells are mutable references. <lang oz> proc {SwapCells A B}
Tmp = @A in A := @B B := Tmp end</lang>
Or shorter, if we exploit the fact that the assignment operator :=
returns the old value of the cells:
<lang oz> proc {SwapCells A B}
B := A := @B end</lang>
A functional swap, operating on pairs: <lang oz> fun {SwapPair A#B}
B#A end</lang>
PARI/GP
Pari is near-typeless—everything is a GEN. <lang parigp>my(tmp=a); a=b; b=tmp;</lang>
Perl
Perl has support for swapping built-in
<lang perl>($y, $x) = ($x, $y);</lang>
Here's a generic swap routine:
<lang perl>sub swap {@_[0, 1] = @_[1, 0]}</lang>
Perl 6
As Perl 5. Perl 6 supports type constraints for variables and subroutines, unlike Perl 5, but the default is still to permit all values.
PHP
<lang php>function swap(&$a, &$b) {
list($a, $b) = array($b, $a);
}</lang>
PicoLisp
xchg works with any data type <lang PicoLisp>(let (A 1 B 2)
(xchg 'A 'B) (println A B) )
(let (Lst1 '(a b c) Lst2 '(d e f))
(xchg (cdr Lst1) (cdr Lst2)) (println Lst1 Lst2) )</lang>
Output:
2 1 (a e c) (d b f)
PL/I
Using the preprocessor
<lang PL/I>%swap: procedure (a, b);
declare (a, b) character; return ( 't=' || a || ';' || a || '=' || b || ';' || b '=t;' );
%end swap; %activate swap;
The statement:-
swap (p, q);
is replaced, at compile time, by the three statements:
t = p; p = q; q = t;</lang>
Using generic procedures
<lang pli>declare swap generic (
swapf when (float, float), swapc when (char, char));
swapf: proc (a, b);
declare (a, b, t) float; t = a; a = b; b = t;
end swapf; swapc: proc (a, b);
declare (a, b) character(*); declare t character (length(b)); t = a; a = b; b = t;
end swapc;
declare (r, s) character (5); call swap (r, s);</lang>
Both of the above are not completely generic, but depend on either the presence of
- a temporary variable with the same attributes of the variables to be swapped, OR
- data-attribute specific procedures for the swap
The following code is completely generic, but, in line with the usual safety offered by PL/I, swaps only the contents up to the storage occupied by the smallest of the two variables: Prino 01:24, 11 February 2011 (UTC)
Completely generic code using the pre-processor
<lang pli>%swap: proc(x,y); dcl (x, y) char;
x = trim(x); /* Just for neatness sake */ y = trim(y);
ans('begin; ') skip; ans(' dcl c char (1); ') skip; ans(' dcl sx char (1) based(px); ') skip; ans(' dcl sy char (1) based(py); ') skip; ans(' dcl i fixed bin (31); ') skip; ans(' dcl px ptr init (addr(' || x || ')); ') skip; ans(' dcl py ptr init (addr(' || y || ')); ') skip; ans(' do i = 1 to min(stg(' || x || '), stg(' || y || '));') skip; ans(' c = sx; ') skip; ans(' sx = sy; ') skip; ans(' sy = c; ') skip; ans(' px = px + 1; ') skip; ans(' py = py + 1; ') skip; ans(' end; ') skip; ans('end; ') skip; %end swap; %act swap;
dcl c1 char (10) init ('1234567890'); dcl c2 char (10) init ('ABCDEFGHIJ'); dcl f1 fixed bin (31) init (12345); dcl f2 fixed bin (31) init (98765);
put data(c1, c2, f1, f2); swap(c1, c2); swap(f1, f2); put data(c1, c2, f1, f2); f1 = -656877352; /* '5a5a5a5a'x, aka 'QQQQ' */ swapper(c1, f1); put data(c1,f1);</lang>
The code generated by 'swap(c1, c2);' looks like
<lang pli> begin;
dcl c char (1); dcl sx char (1) based(px); dcl sy char (1) based(py); dcl i fixed bin (31); dcl px ptr init (addr(C1)); dcl py ptr init (addr(C2)); do i = 1 to min(stg(C1), stg(C2)); c = sx; sx = sy; sy = c; px = px + 1; py = py + 1; end;
end;</lang>
and, because declarations in PL/I begin blocks are local to that block, generating several blocks with the same variables will not cause any problems.
The result of compiling, linking and executing the above code:
C1='1234567890' C2='ABCDEFGHIJ' F1= 12345 F2= 98765; C1='ABCDEFGHIJ' C2='1234567890' F1= 98765 F2= 12345; C1='QQQQEFGHIJ' F1= -1044200508;
Pop11
Swap is easily done via multiple assignment:
<lang pop11>(a, b) -> (b, a);</lang>
Pop11 is dynamically typed, so the code above is "generic".
PostScript
Works with anything you can put on the operand stack:<lang PostScript>exch</lang>
PowerShell
PowerShell allows swapping directly, through tuple assignment: <lang powershell>$b, $a = $a, $b</lang> But one can also define a function which swaps the values of two references: <lang powershell>function swap ([ref] $a, [ref] $b) {
$a.Value, $b.Value = $b.Value, $a.Value
}</lang> When using this function the arguments have to be explicitly given as references: <lang powershell>swap ([ref] $a) ([ref] $b)</lang>
Prolog
<lang prolog> swap(A,B,B,A).
?- swap(1,2,X,Y). X = 2, Y = 1. </lang>
PureBasic
Built in function: <lang PureBasic>Swap a, b</lang>
Python
Python has support for swapping built in:
<lang python>a, b = b, a</lang>
But the task calls for a "generic swap method" to be written, so here it is:
<lang python>def swap(a, b):
return b, a</lang>
Note that tuples are immutable in Python. This function doesn't mutate anything, but simply returns a new pair with the order of the elements switched.
REBOL
<lang REBOL>REBOL [ Title: "Generic Swap" Author: oofoe Date: 2009-12-06 URL: http://rosettacode.org/wiki/Generic_swap Reference: [1] ]
swap: func [ "Swap contents of variables." a [word!] b [word!] /local x ][ x: get a set a get b set b x ]
answer: 42 ship: "Heart of Gold" swap 'answer 'ship ; Note quoted variables. print rejoin ["The answer is " answer ", the ship is " ship "."]</lang>
Output:
The answer is Heart of Gold, the ship is 42.
REXX
REXX has no primitive for swapping, but it can easily be performed using a termporary variable. <lang rexx> a='some value' b=6
_temp_=a
a=b b=_temp_
</lang> If it is known that there are no leading, trailing, or imbedded blanks in the values, the following method can be used: <lang rexx> a=-199e-12 b=12.
parse value a b with b a /*swaps A and B */ </lang>
RLaB
RLaB does not have a built-in function for swapping the content of two variables. However, there is a workaround which comes from the fact that the global variable space $$ contains all the variables var1, var2 and so forth as $$.var1, ...
Let we want to swap the content of two variables, which names are a and b, then the following function would do the trick <lang RLaB> swap = function(x,y) {
if (!exist($$.[x])) { return 0; } if (!exist($$.[y])) { return 0; } local (t); t = $$.[x]; $$.[x] = $$.[y]; $$.[y] = t; return 1;
};
>> a=1 1 >> b = "fish" fish >> swap( "a" , "b" ); >> a fish >> b 1 </lang>
Ruby
Ruby has support for swapping built in:
<lang ruby>a, b = b, a</lang>
But the task calls for a "generic swap method", so here it is:
<lang ruby>def swap(a, b)
return b, a
end</lang>
This method does not swap the original variables, because Ruby passes parameters by value. Instead, this method returns simply a new array with the order of the elements switched. The caller may assign the original variables with the return value:
<lang ruby>x = 42 y = "string" x, y = swap x, y puts x # prints string puts y # prints 42</lang>
Sather
A possible way that needs the type of the objects to be specified:
<lang sather>class SWAP{T} is
swap(inout a, inout b:T) is t ::= a; a := b; b := t; end;
end;</lang>
<lang sather>class MAIN is
main is x ::= 10; y ::= 20; SWAP{INT}::swap(inout x, inout y); #OUT + x + ", " + y + "\n"; end;
end;</lang>
Scala
Scala has type parameters and abstract types (not to be confused with abstract data types). The swap example is about as simple as such things can be, with no variance or high-order type parameters.
The return type need not be declared in the example below, but it is shown for clarity. However, as Scala does not pass parameters by reference, it cannot swap values in-place. To make up for that, it receives two values, and returns a tuple with the values inverted.
<lang scala>def swap[A,B](a: A, b: B): (B, A) = (b, a)</lang>
Scheme
This must be done with macros, since the parameters inside a procedure are copies of the actual parameters. <lang scheme>(define-syntax swap!
(syntax-rules () ((_ a b) (let ((tmp a)) (set! a b) (set! b tmp)))))</lang>
Seed7
A generic template to generate swap functions is defined with: <lang seed7>const proc: generate_swap (in type: aType) is func
begin
const proc: swap (inout aType: left, inout aType: right) is func local var aType: temp is aType.value; begin temp := left; left := right; right := temp; end func;
end func;</lang>
An instance of a swap function can be generated with: <lang seed7>generate_swap(integer); generate_swap(string);</lang> A swap function can be called with: <lang seed7>swap(a, b);</lang>
Slate
This must be done with a macro method in Slate, but is in the standard library: <lang slate>x@(Syntax LoadVariable traits) swapWith: y@(Syntax LoadVariable traits) &environment: env "A macro that expands into simple code swapping the values of two variables in the current scope." [
env ifNil: [error: 'Cannot swap variables outside of a method']. tmpVar ::= env addVariable. {tmpVar store: x variable load. x variable store: y variable load. y variable store: tmpVar load} parenthesize
].</lang>
Usage: <lang slate>a `swapWith: b</lang>
Smalltalk
An OrderedCollection can collect any kind of objects; so this swap implementend extending the OrderedCollection class is really generic. <lang smalltalk>OrderedCollection extend [
swap: a and: b [
|t| t := self at: a. self at: a put: (self at: b). self at: b put: t
]
]</lang>
SNOBOL4
The "canonical" version from M. Emmers tutorial:
<lang snobol4>* SWAP(.V1, .V2) - Exchange the contents of two variables.
- The variables must be prefixed with the name operator
- when the function is called.
DEFINE('SWAP(X,Y)TEMP') :(SWAP_END)
SWAP TEMP = $X
$X = $Y $Y = TEMP :(RETURN)
SWAP_END</lang>
Standard ML
Tuples are immutable in Standard ML. This function doesn't mutate anything, but simply returns a new pair with the order of the elements switched. <lang sml>fun swap (x, y) = (y, x)</lang> If the arguments are constrained to be reference values, a swap function is simple: <lang sml>fun swapref (x, y) =
let temp = !x in x := !y; y := temp end</lang>
Tcl
<lang tcl>proc swap {aName bName} {
upvar 1 $aName a $bName b lassign [list $a $b] b a
}</lang>
<lang tcl>proc swap {aName bName} {
upvar 1 $aName a $bName b foreach {b a} [list $a $b] break
}</lang>
<lang tcl>set a 1 set b 2 puts "before\ta=$a\tb=$b" swap a b puts "after\ta=$a\tb=$b"</lang>
Outputs:
before a=1 b=2 after a=2 b=1
ThinBASIC
Generic function, swap the content of two variables. <lang ThinBASIC>Swap Var1, Var2</lang>
TI-89 BASIC
TI-89 BASIC is dynamically typed, so the genericity is implicit. It has no pass by reference, so we must pass the variable names as strings. It is dynamically scoped, so we must choose hopefully distinct names for the variables.
<lang ti89b>Define swap(swapvar1, swapvar2) = Prgm
Local swaptmp #swapvar1 → swaptmp #swapvar2 → #swapvar1 swaptmp → #swapvar2
EndPrgm
1 → x 2 → y swap("x", "y") x
2
y
1</lang>
Trith
As with other stack-based languages (e.g. Factor and Joy), the solution to this task is a trivial matter of swapping the top two operands on the stack: <lang trith>swap</lang>
Ursala
Most functions are polymorphic without any special provision to that effect. Swapping a pair is a very inexpensive operation because no actual copying or overwriting is performed. <lang Ursala>pmgs("x","y") = ("y","x") # the pattern matching way
ugs = ~&rlX # the idiosyncratic Ursala way
- cast %sWL
test = <pmgs ('a','b'),ugs ('x','y')></lang>
output:
<('b','a'),('y','x')>
V
Using the view to shuffle the stack.
<lang v>[swap [a b : b a] view].
1 2 swap = 2 1 'hello' 'hi' swap</lang>
='hi' 'hello'
VBScript
This works for everything: strings, dates, booleans ... The fact is, with everything being a Variant, it's always generic.
<lang vb>sub swap( byref x, byref y ) dim temp temp = x x = y y = temp end sub</lang>
Usage: <lang vb>dim a a = "woof" dim b b = now() swap a,b wscript.echo a wscript.echo b</lang>
Output: <lang vb>5/02/2010 2:35:36 PM woof</lang>
Visual Basic
Visual Basic can use the VBScript example above, with the caveat that it won't work if any DEFtype
(except DefVar
) has been used. (The default data type is Variant
, which can be used as a stand-in for any variable type.)
Also, the sub will fail if one arg is a string containing non-numeric data and the other arg is numeric.
Yorick
Yorick has a built-in function swap for exchanging the contents of two variables without requiring a temporary copy. Example of use:
> a = 1 > b = "foo" > swap, a, b > a "foo" > b 1
Swapping elements in an array can be accomplished using index lists. Arbitrary permutations of swaps are also straightforward. Example:
> foo = [10,20,30,40,50] > foo([1,2]) = foo([2,1]) > foo [20,10,30,40,50] > foo([3,4,5]) = foo([4,5,3]) > foo [20,10,40,50,30]
- Programming Tasks
- Basic language learning
- Ada
- ALGOL 68
- AmigaE
- AppleScript
- AutoHotkey
- Batch File
- C
- C++
- C sharp
- Clojure
- CMake
- Common Lisp
- ColdFusion
- D
- Dc
- Delphi
- Delphi examples needing attention
- Examples needing attention
- E
- Erlang
- Euphoria/Omit
- F Sharp
- Factor
- Forth/Omit
- Falcon
- Fortran
- Frink
- Gecho
- Go
- Groovy
- Haskell
- Icon
- Unicon
- IDL
- J
- Java
- JavaScript
- Joy
- Lisaac
- Logo
- Logtalk
- Lua
- M4
- Mathematica
- MATLAB
- MAXScript
- Metafont
- Modula-3
- Nemerle
- Nial
- OCaml
- Octave
- Oz
- PARI/GP
- Perl
- Perl 6
- PHP
- PicoLisp
- PL/I
- Pop11
- PostScript
- PowerShell
- Prolog
- PureBasic
- Python
- REBOL
- REXX
- RLaB
- Ruby
- Sather
- Scala
- Scheme
- Seed7
- Slate
- Smalltalk
- SNOBOL4
- Standard ML
- Tcl
- ThinBASIC
- TI-89 BASIC
- Trith
- Ursala
- V
- VBScript
- Visual Basic
- Yorick