Format TeXForm at several levels - wolfram-mathematica

In Mathematica, Format can be used to alter the output formats like TeXForm, OutputForm or TraditionalForm.
This is an example of how one can redefine the TeXForm of a function T.
In[1]:= Format[T[a_], TeXForm] := "\[Del]" a
The result is
In[2]:= TeXForm[T[x]]
Out[1]= x \nabla
This is what I expected. Now apply the same format on T[T[x]]
In[3]:= TeXForm[T[T[x]]]
Out[2]= \nabla T(x)
However, the output I would like is
Out[2]= \nabla \nabla x
Why does Mathematica not give this output? And what can I change to get this as output?
I tried to find more information about formatting in the Mathematica Help and on Stack Overflow, but I could not find many clues.

It will work if you don't restrict to TeXForm.
In[100] := Format[T[a_]] := \[Del] a
In[101] := TeXForm[T[T[x]]]
Out[101]//TexForm =
\nabla \nabla x
Why use T when you could use Del?
In[7] := Del[a]
Out[7] = ∇a
In[8] := TeXForm[Del[Del[a]]]
Out[8]//TeXForm =
\nabla \nabla a

You may want to do the formatting manually.
myTeX = TeXForm[# /. T -> (Row[{"\[Del]", #}] &)]&;
T[T[a]] //myTeX
\n abla \n abla a

The reason this fails is that the Format[arg, TeXForm] pattern doesn't recursively distribute Format over the arguments. This isn't unusual. Consider:
Clear[f];
f[T[a_]] := "\[Del]" a;
yields f[T[T[a]]] = "\[Del]" T[a], but
Clear[f];
f[T[a_]] := "\[Del]" f[a];
yields f[T[T[a]]] = ("\[Del]")^2 f[a], which is closer to what you want.
So define
Format[T[a_], TeXForm] := f[T[a]]
using the second choice of f[T[a_]] above, and you'll be off to a good start.

Type the following:
Needs["Notation`"]
ESCAPE notation ESCAPE
(or choose "Notation" from the palette that opens when you load the package)
In the first placeholder, insert
ESCAPE del ESCAPE a_
In the second placeholder, enter
T[a_]
Before the closing bracket of the Notation line, insert the option
, WorkingForm -> TraditionalForm
Now you can try your example:
T[T[a]]//TeXForm
and it should give you what you want, except with parentheses (which is advisable in order to maintain your sanity in most cases, anyway):
\nabla (\nabla a)
You may be able to go further by looking at the Help documents under "Notation/tutorial/OptionsAndAuxiliaryFunctions"

Related

How to convert Mathematica binary dump file to list of definitions?

As the Documentation says, "DumpSave writes out definitions in a binary format that is optimized for input by Mathematica." Is there a way to convert a Mathematica binary dump file back to the list of definitions without evaluating them? Import["file.mx","HeldExpression"] does not work...
DumpSave stores values associated with the symbol, i.e. OwnValues, DownValues, UpValues, SubValues, DefaultValues, NValues, FormatValues.
All the evaluation was done in the session on Mathematica, and then DumpSave saved the result of it.
These values are stored in internal formal. Reading the MX files only creates symbols and populates them with these values by reading this internal format back, bypassing the evaluator.
Maybe you could share the problem that prompted you to ask this question.
[EDIT] Clarifying on the issue raised by Alexey. MX files save internal representation of symbol definitions. It appears that Mathematica internally keeps track of:
f[x_Real] := x^2 + 1
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}],
f];
Remove[f]
f[x_Real] = x^2 + 1;
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], f];
setBytes =
Import[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], "Byte"];
setDelayedBytes =
Import[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}],
"Byte"];
One can, then, use SequenceAlignment[setBytes, setDelayedBytes] to see the difference. I do not know why it is done that way, but my point stands. All the evaluation on values constructed using Set has already been done in Mathematica session before they were saved by DumpSave. When MX file is read the internal representation is read back into Mathematica sessions, and no evaluation of loaded definitions is actually performed.
You can assign Rules instead of RuleDelayed's to DownValues, which is equivalent to the immediate definitions. The right-hand side of the assignment stays unevaluated and is copied literally, so the command corresponding to
Clear[f];
f[x_Real] = x^2 + 1;
DumpSave["f.mx", f];
Clear[f];
f = a;
<< f.mx;
Definition[f]
would be
Clear[f];
f = a;
DownValues[f] := {f[x_Real] -> x^2 + 1}
Definition[f]
f = a
f[x_Real] = x^2+1
(cf. with your example of Clear[f]; f = a; f[x_Real] = x^2 + 1; Definition[f] which does not work, assigning a rule for a[x_Real] instead). This is robust to prior assignments to x as well.
Edit: It is not robust to side effects of the right-hand side, as an example in the comments below shows. To assign a downvalue avoiding any evaluation one can use the undocumented System`Private`ValueList like in the following:
Clear[f];
f := Print["f is evaluated!"];
DownValues[f] := System`Private`ValueList[f[x_Real] -> Print["definition is evaluated!"]];
(no output)
Note that the assignment got seemingly converted to delayed rules:
DownValues[f]
{HoldPattern[f[x_Real]] :> x^2 + 1}
but Definition (and Save) show that the distinction from a := has internally been kept. I don't know why DownValues don't display the truth.
To answer the original question, you would probably do best with importing the dump file and exporting the relevant symbols using Save, then, if expecting this to be loaded into a kernel tainted by prior definitions, convert the assignments into assignments to DownValues as above programatically. It might be easier to scope the variables in a private context before the export, though, which is what the system files do to prevent collisions.

How to Convert an Alphanumeric (Reference) Number Containing a Decimal Point to a String in Mathematica

I have a reference number of the following type DAA76647.1 which I want to convert unchanged to a string in Mathematica.
That is
myfn[DAA76647.1]
gives as output
"DAA76647.1"
Is there an easy way to do this? (The input cannot be a string and, other than conversion to a string, I do not want to change the input in any other way).
Update
ToString /# {A1234, 1234.1, A1234 .5}
gives the following output (where I have simply entered everything from the keyboard)
{"A1234", "1234.1", "0.5 A1234"}
It appears that if what goes before the decimal point is alphanumeric, there is a problem.
Possible Workaround
Based on a suggested solution by David Carraher, a possible method is as follows:
ToString[# /.a_ b_ :> ToString[b] <> StringDrop[ToString[a], 1]] & /# {A1234,
1234.1, A1234 .5}
giving as output:
{"A1234", "1234.1", "A1234.5"}
This seems to work OK provided that what comes after the decimal point is not alphanumeric, and provided that what comes before does not begin with zero (0A123.1, for example).
If alphanumerics occur only after the decimal point, this may be incorporated
StringReplace[ToString[123.45 B55c], Whitespace -> ""]
but if alphanumerics occur before and after the decimal point the number still needs to be entered as a string.
David Carraher's original suggestion
f[Times[a_, b_]] := ToString[b] <> ToString[a]
The call for myfn[DAA76647.1] should be intercepted at the stage of converting Input to an expression.
You can see that Input has the form RowBox[{"myfn", "[", RowBox[{"DAA76647", ".1"}], "]"}]:
In[1]:= myfn[DAA76647 .1]
DownValues[InString]
Out[1]= myfn[0.1 DAA76647]
Out[2]= {HoldPattern[InString[1]] :>
ToString[RowBox[{"myfn", "[", RowBox[{"DAA76647", ".1"}], "]"}],
InputForm],
HoldPattern[InString[2]] :>
ToString[RowBox[{"DownValues", "[", "InString", "]"}], InputForm]}
We could create a special case definition for MakeExpression:
MakeExpression[RowBox[{"myfn", "[", RowBox[{"DAA76647", ".1"}], "]"}],
f_] := MakeExpression[RowBox[{"myfn", "[", "\"DAA76647.1\"", "]"}],
f]
You can see that now myfn[DAA76647 .1] works as desired:
In[4]:= myfn[DAA76647 .1]//FullForm
Out[4]//FullForm= myfn["DAA76647.1"]
This approach can be generalized to something like
MakeExpression[RowBox[{"myfn", "[", expr:Except[_String], "]"}], form_] :=
With[{mexpr = StringJoin[expr /. RowBox -> List]}, Hold[myfn[mexpr]]]
myfn[expr_String] := (* what ever you want to do here *)
Note that the Except[_String] part is not really needed... since the following code won't do anything wrong with a String.
At the moment, the code only works with simple examples with one-dimensional box structure. If you want something that handles more general input, you might want to add error checking or extra rules for things like SuperscriptBox and friends. Or hit it with the hammer of Evaluate[Alternatives ## Symbol /# Names["*Box"]] -> List to make all Box objects become lists and flatten everything down.
If you enter DAA76647DAA76647.1 via an input cell in a Mma notebook, Mma will interpret the characters as a multiplication. It even automatically inserts a space between the 7 and the .1 (at least in Mma 8) when you input it.
DAA76647DAA76647 .1 // FullForm
(*Out= Times[0.1`,DAA76647DAA76647] *)
This looks promising:
f[Times[a_, b_]] := ToString[b] <> ToString[a]
EDIT:
However, as TomD noted (and I somehow missed), it adds an additional zero to the solution!
f[Times[DAA76647DAA76647 .1]]
(*Out= DAA76647DAA766470.1 *)
%//FullForm
"DAA76647DAA766470.1"
TomD later showed how it is possible to handle this by StringDropping the zero.
This corrected solution will work if only numbers appear to the right of the decimal point and if the left-hand part is not interpreted as a product.
If you try to enter DAA76647.01A Mma will parse it as
(*Out= Times[".01",A,DAA76647] *)
Notice that it changes the order of the components.
I cannot see a way to handle this reordering.
I don't think you can directly type this between the brackets of a function call, but would
myfn[InputString[]]
work for you?

Checking if a symbol is defined

Is there an easy way to check if there's a definition for x? I need a function that takes
something of the form f,f[_] or f[_][_] and returns True if there's a definition for it
To be really concrete, I'm storing things using constructs like f[x]=b, and g[x][y]=z and I need to check if f[x] has definition for every x in some list and if g[x][y] has a definition for every x,y in some set of values
Actually, the ValueQ function is not innocent, since it leaks evaluation for code with side effects. Examples:
ClearAll[f, g];
f[x_] := Print[x];
g[x_][0] := Print[x];
{ValueQ[f[1]],ValueQ[g[2][0]]}
If you remove the ReadProtected Attribute of ValueQ and look at the code, you will see why - the code is very simplistic and does a decent job for OwnValues only. Here is a more complex version which I developed to avoid this problem (you can test that, at least for the examples above, it does not leak evaluation):
ClearAll[symbolicHead];
SetAttributes[symbolicHead, HoldAllComplete];
symbolicHead[f_Symbol[___]] := f;
symbolicHead[f_[___]] := symbolicHead[f];
symbolicHead[f_] := Head[Unevaluated[f]];
ClearAll[partialEval];
SetAttributes[partialEval, HoldAllComplete];
partialEval[a_Symbol] /; OwnValues[a] =!= {} :=
Unevaluated[partialEval[a]] /. OwnValues[a];
partialEval[a : f_Symbol[___]] /; DownValues[f] =!= {} :=
With[{dv = DownValues[f]},
With[{eval = Hold[partialEval[a]] /. dv},
ReleaseHold[eval] /;
(First[Extract[eval, {{1, 1}}, HoldComplete]] =!=
HoldComplete[a])]];
partialEval[a_] :=
With[{sub = SubValues[Evaluate[symbolicHead[a]]]},
With[{eval = Hold[partialEval[a]] /. sub},
ReleaseHold[eval] /;
(First[Extract[eval, {{1, 1}}, HoldComplete]] =!=
HoldComplete[a])]];
ClearAll[valueQ];
SetAttributes[valueQ, HoldAllComplete];
valueQ[expr_] := partialEval[expr] =!= Unevaluated[partialEval[expr]];
This is not complete either, since it does not account for UpValues, NValues, and FormatValues, but this seems to be enough for your stated needs, and also, rules for these three extra cases can perhaps also be added along the same lines as above.
If I understood correctly I think the function ValueQ is what you are looking for. It will return true if a variable or a function has been defined and false if it has not been defined.
Read more at http://reference.wolfram.com/mathematica/ref/ValueQ.html
For symbols in System`, check SyntaxInformation for a ArgumentsPattern option.
For other symbols, check DownValues, UpValues, SubValues, etc...
What's the intended use?
Here's a nice, simple solution which works if the object in question has enough internal structure.
You can use
Length[variable]
to detect whether variable has been assigned to something with more than one part. Thus:
Remove[variable]
Length[variable]
(*---> 0*)
variable={1,2,3};
Length[variable]
(*---> 3*)
You can then use Length[variable]>0 to get True in the latter case.
This fails, though, if there's a chance that variable be assigned to an atomic value, such as a single string or number:
variable=1
Length[variable]
(*---> 0*)

Preventing avalanche of runtime errors in Mathematica

A typical situation I run into when notebook grows beyond a couple of functions -- I evaluate an expression, but instead of correct answer I get Beep followed by dozens of useless warnings followed by "further Output of ... will be suppressed"
One thing I found useful -- use Python-like "assert" inside functions to enforce internal consistency. Any other tips?
Assert[expr_, msg_] := If[Not[expr], Print[msg]; Abort[], None]
edit 11/14
A general cause of a warning avalanche is when a subexpression evaluates to "bad" value. This causes the parent expression to evaluate to a "bad" value and this "badness" propagates all the way to the root. Built-ins evaluated along the way notice the badness and produce warnings. "Bad" could mean an expression with wrong Head, list with wrong number of elements, negative definite matrix instead of positive definite, etc. Generally it's something that doesn't fit in with the semantics of the parent expression.
One way do deal with this is to redefine all your functions to return unevaluated on "bad input." This will take care of most messages produced by built-ins. Built-ins that do structural operations like "Part" will still attempt to evaluate your value and may produce warnings.
Having the debugger set to "break on Messages" prevents an avalanche of errors, although it seems like an overkill to have it turned on all the time
As others have pointed out, there are three ways to deal with errors in a consistent manner:
correctly typing parameters and setting up conditions under which your functions will run,
dealing correctly and consistently with errors generated, and
simplifying your methodology to apply these steps.
As Samsdram pointed out, correctly typing your functions will help a great deal. Don't forget about the : form of Pattern as it is sometimes easier to express some patterns in this form, e.g. x:{{_, _} ..}. Obviously, when that isn't sufficient PatternTests (?) and Conditions (/;) are the way to go. Samdram covers that pretty well, but I'd like to add that you can create your own pattern test via pure functions, e.g. f[x_?(Head[#]===List&)] is equivalent to f[x_List]. Note, the parentheses are necessary when using the ampersand form of pure functions.
The simplest way to deal with errors generated is obviously Off, or more locally Quiet. For the most part, we can all agree that it is a bad idea to completely shut off the messages we don't want, but Quiet can be extremely useful when you know you are doing something that will generate complaints, but is otherwise correct.
Throw and Catch have their place, but I feel they should only be used internally, and your code should communicate errors via the Message facilities. Messages can be created in the same manner as setting up a usage message. I believe the key to a coherent error strategy can be built using the functions Check, CheckAbort, AbortProtect.
Example
An example from my code is OpenAndRead which protects against leaving open streams when aborting a read operation, as follows:
OpenAndRead[file_String, fcn_]:=
Module[{strm, res},
strm = OpenRead[file];
res = CheckAbort[ fcn[strm], $Aborted ];
Close[strm];
If[res === $Aborted, Abort[], res] (* Edited to allow Abort to propagate *)
]
which, Until recently, has the usage
fcn[ file_String, <otherparams> ] := OpenAndRead[file, fcn[#, <otherparams>]&]
fcn[ file_InputStream, <otherparams> ] := <fcn body>
However, this is annoying to do every time.
This is where belisarius solution comes into play, by creating a method that you can use consistently. Unfortunately, his solution has a fatal flaw: you lose support of the syntax highlighting facilities. So, here's an alternative that I came up with for hooking into OpenAndRead from above
MakeCheckedReader /:
SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
fcn[file_Symbol, symbols] := a), {RuleDelayed::"rhs"}]
which has usage
MakeCheckedReader[ myReader, a_, b_ ] := {file$, a, b} (*as an example*)
Now, checking the definition of myReader gives two definitions, like we want. In the function body, though, file must be referred to as file$. (I have not yet figured out how to name the file var as I'd wish.)
Edit: MakeCheckedReader works by not actually doing anything itself. Instead, the TagSet (/:) specification tells Mathematica that when MakeCheckedReader is found on the LHS of a SetDelayed then replace it with the desired function definitions. Also, note the use of Quiet; otherwise, it would complain about the patterns a_ and b_ appearing on the right side of the equation.
Edit 2: Leonid pointed out how to be able to use file not file$ when defining a checked reader. The updated solution is as follows:
MakeCheckedReader /:
SetDelayed[MakeCheckedReader[fcn_Symbol, symbols___], a_] :=
Quiet[(fcn[file_String, symbols] := OpenAndRead[file, fcn[#, symbols] &];
SetDelayed ## Hold[fcn[file_Symbol, symbols], a]),
{RuleDelayed::"rhs"}]
The reasoning for the change is explained in this answer of his. Defining myReader, as above, and checking its definition, we get
myReader[file$_String,a_,b_]:=OpenAndRead[file$,myReader[#1,a_,b_]&]
myReader[file_Symbol,a_,b_]:={file,a,b}
I'm coming late to the party, with an accepted answer and all, but I want to point out that definitions of the form:
f[...] := Module[... /; ...]
are very useful in this context. Definitions of this kind can perform complex calculations before finally bailing out and deciding that the definition was not applicable after all.
I will illustrate how this can be used to implement various error-handling strategies in the context of a specific case from another SO question. The problem is to search a fixed list of pairs:
data = {{0, 1}, {1, 2}, {2, 4}, {3, 8}, {4, 15}, {5, 29}, {6, 50}, {7,
88}, {8, 130}, {9, 157}, {10, 180}, {11, 191}, {12, 196}, {13,
199}, {14, 200}};
to find the first pair whose second component is greater than or equal to a specified value. Once that pair is found, its first component is to be returned. There are lots of ways to write this in Mathematica, but here is one:
f0[x_] := First # Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f0[100] (* returns 8 *)
The question, now, is what happens if the function is called with a value that cannot be found?
f0[1000]
error: First::first: {} has a length of zero and no first element.
The error message is cryptic, at best, offering no clues as to what the problem is. If this function was called deep in a call chain, then a cascade of similarly opaque errors is likely to occur.
There are various strategies to deal with such exceptional cases. One is to change the return value so that a success case can be distinguished from a failure case:
f1[x_] := Cases[data, {t_, p_} /; p >= x :> t, {1}, 1]
f1[100] (* returns {8} *)
f1[1000] (* returns {} *)
However, there is a strong Mathematica tradition to leave the original expression unmodified whenever a function is evaluated with arguments outside of its domain. This is where the Module[... /; ...] pattern can help out:
f2[x_] :=
Module[{m},
m = Cases[data, {t_, p_} /; p >= x :> t, {1}, 1];
First[m] /; m =!= {}
]
f2[100] (* returns 8 *)
f2[1000] (* returns f2[1000] *)
Note that the f2 bails out completely if the final result is the empty list and the original expression is returned unevaluated -- achieved by the simple expedient of adding a /; condition to the final expression.
One might decide to issue a meaningful warning if the "not found" case occurs:
f2[x_] := Null /; Message[f2::err, x]
f2::err = "Could not find a value for ``.";
With this change the same values will be returned, but a warning message will be issued in the "not found" case. The Null return value in the new definition can be anything -- it is not used.
One might further decide that the "not found" case just cannot occur at all except in the case of buggy client code. In that case, one should cause the computation to abort:
f2[x_] := (Message[f2::err, x]; Abort[])
In conclusion, these patterns are easy enough to apply so that one can deal with function arguments that are outside the defined domain. When defining functions, it pays to take a few moments to decide how to handle domain errors. It pays in reduced debugging time. After all, virtually all functions are partial functions in Mathematica. Consider: a function might be called with a string, an image, a song or roving swarms of nanobots (in Mathematica 9, maybe).
A final cautionary note... I should point out that when defining and redefining functions using multiple definitions, it is very easy to get unexpected results due to "left over" definitions. As a general principle, I highly recommend preceding multiply-defined functions with Clear:
Clear[f]
f[x_] := ...
f[x_] := Module[... /; ...]
f[x_] := ... /; ...
The problem here is essentially one of types. One function produces a bad output (incorrect type) which is then fed into many subsequent functions producing lots of errors. While Mathematica doesn't have user defined types like in other languages, you can do pattern matching on function arguments without too much work. If the match fails the function doesn't evaluate and thus doesn't beep with errors. The key piece of syntax is "/;" which goes at the end of some code and is followed by the test. Some example code (and output is below).
Input:
Average[x_] := Mean[x] /; VectorQ[x, NumericQ]
Average[{1, 2, 3}]
Average[$Failed]
Output:
2
Average[$Failed]
If the test is simpler, there is another symbol that does similar pattern testing "?" and goes right after an argument in a pattern/function declaration. Another example is below.
Input:
square[x_?NumericQ] := x*x
square[{1, 2, 3}]
square[3]
Output:
square[{1, 2, 3}]
9
It can help to define a catchall definition to pick up error conditions and report it in a meaningful way:
f[x_?NumericQ] := x^2;
f[args___] := Throw[{"Bad Arguments: ", Hold[f[args]]}]
So your top level calls can use Catch[], or you can just let it bubble up:
In[5]:= f[$Failed]
During evaluation of In[5]:= Throw::nocatch: Uncaught Throw[{Bad Args: ,Hold[f[$Failed]]}] returned to top level. >>
Out[5]= Hold[Throw[{"Bad Args: ", Hold[f[$Failed]]}]]
What I'd love to get is a way to define a general procedure to catch error propagation without the need to change radically the way I write functions right now, preferentially without adding substantial typing.
Here is a try:
funcDef = t_[args___] :c-: a_ :> ReleaseHold[Hold[t[args] :=
Check[a, Print#Hold[a]; Abort[]]]];
Clear#v;
v[x_, y_] :c-: Sin[x/y] /. funcDef;
?v
v[2, 3]
v[2, 0]
The :c-: is of course Esc c- Esc, an unused symbol (\[CircleMinus]), but anyone would do.
Output:
Global`v
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]
Out[683]= Sin[2/3]
During evaluation of In[679]:= Power::infy: Infinite expression 1/0 encountered. >>
During evaluation of In[679]:= Hold[Sin[2/0]]
Out[684]= $Aborted
What we changed is
v[x_, y_] := Sin[x/y]
by
v[x_, y_] :c-: Sin[x/y] /. funcDef;
This almost satisfies my premises.
Edit
Perhaps it's also convenient to add a "nude" definition for the function, that does not undergo the error checking. We may change the funcDef rule to:
funcDef =
t_[args___] \[CircleMinus] a_ :>
{t["nude", args] := a,
ReleaseHold[Hold[t[args] := Check[a, Print#Hold[a]; Abort[]]]]
};
to get for
v[x_, y_] :c-: Sin[x/y] /. funcDef;
this output
v[nude,x_,y_]:=Sin[x/y]
v[x_,y_]:=Check[Sin[x/y],Print[Hold[Sin[x/y]]];Abort[]]

Define Custom Notation in Mathematica

I often need to extract to restrict value lists to sublists, ie if vals gives values of vars={x1,x2,x3,x4}, and I need values of svars={x2,x4} I do restrict[list,vars,svars] where
restrict[vars_, svars_, vals_] :=
Extract[vals, Flatten[Position[vars, #] & /# svars, 1]]
I'd like to improve code readability, perhaps by defining following custom notation for restrict[vars,svars,vals]
(source: yaroslavvb.com)
My questions are
What is a good way to implement this?
Is this a good idea altogether?
Good notations can be very useful - but I'm not sure that this particular one is needed...
That said, the Notation package makes this pretty easy. As there are many hidden boxes when you use the Notation palette, I'll use a screenshot:
You can see the underlying NotationMake* downvalues construct by using the Action -> PrintNotationRules option. In[4] in the screenshot generates
NotationMakeExpression[
SubscriptBox[vals_, RowBox[{vars_, "|", svars_}]], StandardForm] :=
MakeExpression[
RowBox[{"restrict", "[", RowBox[{vars, ",", svars, ",", vals}],
"]"}], StandardForm]
NotationMakeBoxes[Subscript[vals_, vars_ | svars_], StandardForm] :=
SubscriptBox[MakeBoxes[vals, StandardForm],
RowBox[{Parenthesize[vars, StandardForm, Alternatives], "|",
Parenthesize[svars, StandardForm, Alternatives]}]]
With regard to 2: I would pass the rule list Thread[vars -> vals] instead of keeping track of names and values separately.
One of my favorite Mathematica idioms is to use rule lists together with WithRules as defined below: This construct evaluates an expression in a With block where all the replacement symbols have been (recursively defined). This allow you to do stuff like
WithRules[{a -> 1, b -> 2 a + 1}, b]
and gets you quite far towards named arguments.
SetAttributes[WithRules, HoldRest]
WithRules[rules_, expr_] := Module[{notSet}, Quiet[
With[{args = Reverse[rules /. Rule[a_, b_] -> notSet[a, b]]},
Fold[With[{#2}, #1] &, expr, args]] /. notSet -> Set,
With::lvw]]
Edit: The WithRules construct is based on these two usenet threads (thanks to Simon for digging them up):
A version of With that binds variables sequentially
Add syntax highlighting to own command

Resources