/*
Generic swap (Rosetta code) in Picat.
http://rosettacode.org/wiki/Generic_swap
"""
Write a generic swap function or operator which exchanges the values of two
variables (or, more generally, any two storage places that can be assigned),
regardless of their types.
If your solution language is statically typed please describe the way your
language provides genericity.
If variables are typed in the given language, it is permissible that the two
variables be constrained to having a mutually compatible type, such that each
is permitted to hold the value previously stored in the other without a type
violation. That is to say, solutions do not have to be capable of exchanging,
say, a string and integer value, if the underlying storage locations are not
attributed with types that permit such an exchange.
Generic swap is a task which brings together a few separate issues in programming
language semantics.
Dynamically typed languages deal with values in a generic way quite readily, but
do not necessarily make it easy to write a function to destructively swap two
variables, because this requires indirection upon storage places or upon the
syntax designating storage places.
Functional languages, whether static or dynamic, do not necessarily allow a
destructive operation such as swapping two variables regardless of their
generic capabilities.
Some static languages have difficulties with generic programming due to a
lack of support for (Parametric Polymorphism).
Do your best!
"""
This program was created by Hakan Kjellerstrand, hakank@gmail.com
See also my Picat page: http://www.hakank.org/picat/
*/
% import v3_utils.
% import util.
% import cp.
/*
Picat supports re-assignment (:=
) but it will not work for
directly swapping two variables.
A = 1,
B = 2
Swapping via a temporary variable works (but is general enough):
A = 1,
B = 2,
T = A, % assuming that T is not used elsewhere in the program
A := B,
B := T
The following will NOT work and throws an error ("invalid left-hand side of assignment"):
[A,B] := [B,A]
One way to swap is to place the values in a list and use inline swapping of the list
% Swapping positions in a list/array
swap2(L) =>
swap_list(L,1,2).
% Swap two elements in a list
swap_list(L,I,J) =>
T = L[I],
L[I] := L[J],
L[J] := T.
Usage:
L = [1,2],
swap2(L),
% ...
L is now [2,1]
Note: Placing the variables A, B in swap2
swap2([A,B])
will NOT change the values of A and B.
Another way is to place the swapped values in a second list
swap_pair([A,B],[B,A]).
Usage:
% ...
A = 1,
B = 2,
swap_pair([A,B],X),
% ...
X is now [2,1] (and A is still 1 and B is still 2).
A variant of this is {{trans|Prolog}}
swap(A,B,B,A)..
Usage:
A = 1,
B = 2,
swap(A,B,NewB,NewA),
% ...
*/
main => go.
go =>
println("swap/2:"),
L = [1,2],
println(l_before=L),
swap2(L),
println(l_after=L),
nl,
println("swap_pair/2:"),
A = 1,
B = 2,
swap_pair([A,B],[NewA,NewB]),
println([a=A,b=B,new_a=NewA,new_b=NewB]),
nl.
% Swapping positions in a list/array
swap2(L) =>
swap_list(L,1,2).
% Swap two elements in a list
swap_list(L,I,J) =>
T = L[I],
L[I] := L[J],
L[J] := T.
swap_pair([A,B],[B,A]).