3
$\begingroup$

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.

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

1 Answer 1

5
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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