How to achieve the following behavior on a symbol f?
Background: The main goal is to use the symbol to tag an abstract data structure where downvalues are used to store information. Only defined downvalues are to be used. The bare invocation of a symbol in an expression should result in an error message.
Note: I am not asking how to design the abstract data structure. What I am asking is the following:
The context in which this symbol is to be used is something like this (a snapshot of a stack):
f := Fail;
f[_] := Fail;
f[1] = value1;
f[2] = value2;
so that only invocation on existing downvalues or when a new downvalue is defined it works, but both invocation on a non-existing downvalue fails, and the bare invocation fails. For example, assume that the stack looks like this before we start using the symbol
f := Fail
f[_] := Fail
and then we start using the f symbol like this
f = 3 (* fails due to f := $Fail *);
f[1] = value1 (* works, an assignment *);
f[2] = value2 (* ibid *);
x = f + 1 (* fails due to f := $Fail *);
x = f[3] + 1 (* fails due to f[_] := $Fail *);
x = f[1] + 1 (* works: x = value1 + 1 *);
x = f[2] + 1 (* works: x = value2 + 1 *);
f[3] = value3 (* works: an assignemnt *);
x = f[3] + 1 (* should now work since f[3] has been assigned *);
Here is an example when one actually tries to implement this
ClearAll[f];
f := fail1;
f[___] := fail2
This results in
Information[f]
Global`f
f:=fail1
which is good. We want it to fail if invoked directly without argument. However, the default invocation on non-existing downvalues is already problematic:
Information[fail1]
Global`fail1
fail1[___]:=fail2
thus something that is not wanted. (I understand why this happens: The SetDelayed
command evaluates its LHS). Everything goes down the drain right at the beginning, since one would not be able to define the SetDelayed
part.
Background[EDIT]: A mathematica code is being passed to a function which changes it slighlty. the code on input looks like, e.g.,
this@f1 = value1
this@f2 = this@f1 + 1
and the processed code should read
o@f1 = value1
o@f2 = o@f1 + 1
if the user specifies
f1 = value1
this@f2 = this@f1 + 1
the system should complain. I know how to do this on the phraser level, no problem. I wonder, is it possible to arrange for the suitable definitions for f1 and f2 so that the behavior I desired occurs, i.e. later on when f1 = value1 is evaluated that an exception occurs?
Also the following is defined silently at the same time
o[id_]@f_ := f[id]
In this way one can define a super simple data strcuture that can be instantiated like a class and operated upon. it should be very natural to write method definitions for such a class.
Stack
$\endgroup$Stack
. But most of us tend to avoid it $\endgroup$SetAttributes[dvQ, HoldFirst]; dvQ[sym_] := Stack[_]~MatchQ~{___, HoldForm[_sym], _}; ClearAll[f] f /; StackInhibit[! dvQ[f]] := fail; f[2] = 3; f[_] := fail;
$\endgroup$Stack
was implemented to provide a way to subvert basic semantics and certainly would not recommend it for that purpose. $\endgroup$