# How to implement Condition programmatically?

I am writing my own symbolic functions with custom symbolic properties.

So often I wish to introduce some automatic simplifications or evaluations, which return the same head as it's argument. This means I can't use normal function definition to avoid infinite recursion.

Suppose I with to create library for naive set theory. I am introducing MySet head to represent sets.

For example, to create a set with a, b and c elements, I will write

MySet[a,b,c]


{a,b,c}


since I defined head MySet to be displayed in curly braces.

Of course

MySet[a,b,c] // FullForm


will give

MySet[a,b,c]


Now suppose I wish to remove duplicates automatically, since sets do not care of duplicates. So that if I wrote

MySet[a,b,b,c]


{a,b,c}


How to accomplish that?

Currently I am writing two helper functions, like HasDuplicates and RemoveDuplicates and write something like that

MySet[x__] :=
MySet@@DeleteDuplicates[{x}] /;
HasDuplicates[{x}];


But this approach requires me to code nearly the same things in two places -- HasDuplicates and RemoveDuplicates functions.

How to avoid this? Is it possible to write this in some following manner:

MySet[x__] := Block[{...},
(* search for duplicates and remove them *)
If[ someweremoved,
MySet[y], (* with removed duplicates *)
MySet[x] (* with no modifications *)
];
];


The problem is that I can't prevent infinite recursion here since MySet is called again and again in any case.

Can I prevent recursion by force? I.e. tell somehow, that expression returning should not be reevaluated?

Or may be I can implement Condition somehow in programming style?

Or may be there is a way to code simplifications somehow?

UPDATE

The set is just a sample. My question is about general solution, suitable for ANY case of simplifications. The general sign of simplification is just was it done something or not. We can't assume we can compare some short list or count some.

-
See this answer –  Rojo Oct 28 '12 at 19:47
@Rojo, @SuzanCioc you might want to add to Rojo's definition the rule Format[set[aa__]] = {aa}; so it looks more mathematical? –  chris Oct 28 '12 at 20:37
@chris, yes, or ´Interpretation[{aa}, set[aa]]´ –  Rojo Oct 28 '12 at 20:44
@Rojo but condition used there! –  Suzan Cioc Oct 28 '12 at 20:57
Suzan, sorry, I am not understanding what you mean with Condition. I thought that that answer would clarify your doubts. It didn't? –  Rojo Oct 28 '12 at 21:01

A combination of Module and Condition acts very much like the proposed Block / If pseudo-code:

mySet[x___] :=
Module[{n = DeleteDuplicates @ {x}}
, mySet @@ n /; Length @ n =!= Length @ {x}
]

mySet[a, b, c]
(* mySet[a, b, c] *)

mySet[a, a, a, b, b, b, c, c]
(* mySet[a, b, c] *)


We compare the lengths of the original and final lists in order to determine whether any elements were deleted -- a less expensive operation than scanning the list again. A few more operations could be trimmed out by introducing additional temporary variables and helper functions, but I'll leave that as an exercise for the concerned reader.

We are exploiting the special handling of Condition within Module as documented in the More Information section of the Condition documentation.

Block would work too, but Module is generally safer as it introduces a local variable instead of temporarily hijacking a global one.

-