Generic swap: Difference between revisions
m Fixed flaw in boxing display. |
|||
Line 182: | Line 182: | ||
=={{header|MAXScript}}== |
=={{header|MAXScript}}== |
||
swap a b |
swap a b |
||
=={{header|Nial}}== |
|||
Like J |
|||
|reverse 1 2 |
|||
=2 1 |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
Revision as of 22:49, 7 October 2008
![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.
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;
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.
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); }
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.
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:
template<typename T> void swap(T& left, T& right) { T tmp(left); left = right; right = tmp; }
Note that this function requires that the type T has an accessible copy constructor and assignment operator.
Clojure
(defn swap [[a b]] (list b a))
This implementation will always return a list, regardless of whether the input is a vector.
ColdFusion
This is another standard swap.
<cfset temp = a /> <cfset a = b /> <cfset b = temp />
D
The solution for D is quite similar to that for C++:
void swap(T)(ref T left, ref T right) { auto temp = left; left = right; right = temp; }
Common Lisp
(rotatef a b)
(psetq a b b a)
E
(slots)
def swap(&left, &right) { def t := left left := right right := t }
(functional)
def swap([left, right]) { return [right, left] }
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.
swap :: (a, b) -> (b, a) swap (x, y) = (y, x)
J
J is dynamically typed so the generic swap has a simple solution: the easiest way to handle this is using the monad 'reverse' |. on a two item array.
|. 1 2 2 1 |. 'ab' ba ('ab';5);<'YUIJK';6 +------+---------+ |+--+-+|+-----+-+| ||ab|5|||YUIJK|6|| |+--+-+|+-----+-+| +------+---------+ |. ('ab';5);<'YUIJK';6 +---------+------+ |+-----+-+|+--+-+| ||YUIJK|6|||ab|5|| |+-----+-+|+--+-+| +---------+------+ [ a=:(i.2 3); i.3 4 +-----+---------+ |0 1 2|0 1 2 3| |3 4 5|4 5 6 7| | |8 9 10 11| +-----+---------+ |. a +---------+-----+ |0 1 2 3|0 1 2| |4 5 6 7|3 4 5| |8 9 10 11| | +---------+-----+
Another possibility is using the dyad 'passive' with verb 'append' in combination with adverb 'insert' acting on a two item array argument:
passive with append: x ,~ y <==> y , x ,~/ 1 2 2 1 1 2 3; 8 9 7 +-----+-----+ |1 2 3|8 9 7| +-----+-----+ ,~/ 1 2 3; 8 9 7 +-----+-----+ |8 9 7|1 2 3| +-----+-----+ Composite data: ('ab';5);<'YUIJK';6 +------+---------+ |+--+-+|+-----+-+| ||ab|5|||YUIJK|6|| |+--+-+|+-----+-+| +------+---------+ ,~/ ('ab';5);<'YUIJK';6 +---------+------+ |+-----+-+|+--+-+| ||YUIJK|6|||ab|5|| |+-----+-+|+--+-+| +---------+------+
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; }
Mathematica
Mathematica functions are generic by default; however, it has to be told not to evaluate the arguments before executing the function.
swap[a_, b_] := {a, b} = {b, a} SetAttributes[swap, HoldAll]
MAXScript
swap a b
Nial
Like J
|reverse 1 2 =2 1
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.
let swap (x, y) = (y, x)
Perl
<perl>sub swap {@_[0, 1] = @_[1, 0]}</perl>
Pop11
Swap is easily done via multiple assignment:
(a, b) -> (b, a);
Pop11 is dynamically typed, so the code above is "generic".
Python
Python has support for swapping built in:
a, b = b, a
But the task calls for a "generic swap method" to be written, so here it is:
def swap(a, b): return b, a
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.
Seed7
A generic template to generate swap functions is defined with:
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;
An instance of a swap function can be generated with:
generate_swap(integer); generate_swap(string);
A swap function can be called with:
swap(a, b);
V
Using the view to shuffle the stack.
[swap [a b : b a] view].
1 2 swap = 2 1 'hello' 'hi' swap ='hi' 'hello'