Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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]

and Mathematica will reply

{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]

Mathematica would reply

{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.

share|improve this question
1  
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
add comment

1 Answer 1

up vote 5 down vote accepted

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.