|
| 1 | +Checking Parameter Counts |
| 2 | +------------------------- |
| 3 | + |
| 4 | +.. index:: parameter count checking |
| 5 | + |
| 6 | +In a programming language that allows for generic and extensible |
| 7 | +arguments, what should we do when a function parameter list does not |
| 8 | +match any of the patterns of a particular builtin function specification? |
| 9 | + |
| 10 | +In WMA and systems with rewrite rules, often what is done is the |
| 11 | +expression is returned unchanged. This allows users to write rewrite rules |
| 12 | +involving patterns that are not covered by your code. |
| 13 | + |
| 14 | +For example: |
| 15 | + |
| 16 | +.. code-block:: mathematica |
| 17 | +
|
| 18 | + In[1]:= Hello[] = "Hi, Rocky!"; |
| 19 | +
|
| 20 | + In[2]= Hello[] |
| 21 | + Out[2]= "Hi, Rocky!" |
| 22 | +
|
| 23 | +Above, in essence we've added form of *Hello* that does not need a parameter. |
| 24 | +Instead, it provides a default value when none is given. |
| 25 | + |
| 26 | +Pretty convenient and slick huh? Yes, but it can also lead to |
| 27 | +confusion in trying to find out where a problem is coming from since |
| 28 | +the definition can be spread to from many sources of definitions and |
| 29 | +rewrite rules which might be mentioned or part of other definitions: |
| 30 | + |
| 31 | +.. code-block:: mathematica |
| 32 | +
|
| 33 | + In[3]:= Rocky[Hello[]] = "Hi again, Rocky"; |
| 34 | +
|
| 35 | + In[3]= Rocky[Hello[]] |
| 36 | + Out[3]= "Hi again, Rocky" |
| 37 | +
|
| 38 | +Notice that the *In[3]* assignment takes place before the *In[1]* |
| 39 | +assignment. Here, these rewrite rules are in close proximity, but |
| 40 | +they could be spread out over time or over different files. |
| 41 | + |
| 42 | +To help you figure how what evaluation is rewriting, see *TraceEvaluation*. |
| 43 | + |
| 44 | +Many times though, at least for me and other simple-minded users, when |
| 45 | +I type a builtin-function with the wrong number of parameters, it is |
| 46 | +helpful to get an error message rather than the expression unchanged. |
| 47 | + |
| 48 | +Generally, I do not expecting (or hope not to expect) some other clever rewrite rule, |
| 49 | +doing strange things. |
| 50 | + |
| 51 | +So, it is sometimes helpful when writing a builtin function, |
| 52 | +to specify the number of parameters that are allowed, and give a standard |
| 53 | +message when the parameter counts do not match. This can be done setting class variables |
| 54 | +``eval_error`` and ``expected_args`` of a builtin function derived from ``Builtin``. |
| 55 | + |
| 56 | +Here is an example: |
| 57 | + |
| 58 | +.. code-block:: python |
| 59 | +
|
| 60 | + class Hello(Builtin): |
| 61 | +
|
| 62 | + # Set checking that the number of arguments required to exactly one. |
| 63 | + eval_error = Builtin.generic_argument_error |
| 64 | + expected_args = 1 |
| 65 | +
|
| 66 | +
|
| 67 | +Now when I call *Hello* without any arguments you will see:: |
| 68 | + |
| 69 | + In[4]:= Hello[] |
| 70 | + Hello::argx: Hello called with 0 arguments; 1 argument is expected. |
| 71 | + |
| 72 | +The value of ``expected_args`` does not have to be an integer. It can be a range, like: |
| 73 | + |
| 74 | +* ``range(5)`` one to four arguments |
| 75 | +* ``range(2,4)``: two or three arguments |
| 76 | + |
| 77 | +or a set: |
| 78 | + |
| 79 | +* ``{1, 3, 5}`` one, three, or five arguments |
0 commit comments