There are three *distinct *ways to interpret your Question. By "distinct", I mean that your Question is not vague; the different interpretations are based on different definitions of *function *and *input*, which are words that you used in your Question. @tomleslie and @dharr have each given correct solutions (although Tom's is far more elaborate than need be) to exactly one of those interpretations (each picking a different interpretation). But I am convinced that it's that third as-yet-unmentioned interpretation that you're really interested in, although you may not realize that yet.

First, we need precise definitions of *function*, *procedure*, *parameter*, and *argument *in the specific context of Maple __code__ and this Question.

*Function *and *procedure *(which are fairly common words of technical English) are often used somewhat interchangeably in computer science, in the Maple community (such as this forum), and even in Maple documentation. However, when they are used as **type** names in Maple __code__, they are completely distinct, mutually exclusive, without overlap [I realize that that's redundant; I'm just emphasizing]. Both **function** and **procedure*** *are keywords that can be used as *type* names in Maple code.

__Function__: Suppose that **f** is an unassigned variable (aka, a **symbol** or **name**). Then expressions such as **f()**, **f(a,b,c)**, and **f(1,2,3) **are of *type *function. The **a, b, c, 1, 2, 3, **etc. are called *arguments*. Functions (in this sense) are simply static data structures; they don't "do" any computations; rather, they are objects upon which computations are done. (In the complete definition of *type* **function**, the **f** can be more general than just a **symbol** or **name**; however, those cases alone are adequate to complete this discussion.) Note that **f** by itself is *not* a **function**. A **function** must have an argument sequence, even if it's empty as with **f()**.

__Procedure__: An expression such as **(x, y, z)-> (x+y)/z **is a **procedure**. (There are other ways to make procedures, but the arrow **-> **is sufficient for our purposes.) The items on the left side of the **-> **are called *parameters*; unlike arguments, they are always **name**s (and, more specifically, **symbol**s).

Usually (but certainly not always) a procedure will be assigned to a name, as in **p:= (x, y, z)-> (x + y + z)**. Then the procedure can be "called" (aka "invoked", "run", "used", "executed") via **p(a, b, c)**, **p(1, 2, 3)**, etc. The **a, b, c, 1, 2, 3, **etc. are called *arguments*, just like with a function. Procedures can be called in other ways, but the values substituted for (or *passed to*) the parameters are still called arguments. Note that the **procedure **is the assigned value of **p **itself and alone; in contrast to a **function**, it's not the presence of arguments that makes it a **procedure**; rather it's the presence of a parameter sequence (which is possibly the empty sequence) in the assigned value that does that.

So, the word "input" that you used in your Question could mean either *parameters *or *arguments*, and the word "function" that you used could mean either **function** or **procedure**. You haven't used the words incorrectly; rather, the issue is that their common definitions in technical English aren't precise enough for this Question. The three possible interpretations of your Question are that you want to count

- the arguments of a
**function**,
- the arguments passed to a
**procedure**, or
- the parameters of a
**procedure**.

So, you may be thinking that there's a fourth possibily---the parameters of a **function**---but there's no such thing under the precise definition of **function** being used here.

Maple syntax allows a procedure to be passed a different number of arguments than it has parameters. The count of arguments or parameters is called *arity*, which is a noun derived from the adjectival suffix *-ary* used in words such as *binary*, *unary*, *nullary*, *ternary*, etc. In other words, *arity* is the formal word for what you've called "input number" and "domain number".

- Tom's Answer shows an excessively elaborate method to count the arguments of a
**function**. It's excessive because it can be done simply with the command **nops**, e.g., **nops(f(a, b, c)) **returns **3**. The command name **nops** stands for **n**umber of **op**erand**s**.

- The Answer by dharr shows a method to count the number of arguments passed to a procedure. The keywords
**_npassed **or **nargs** can be used for this. They mean exactly the same thing. These keywords are only meaningful when used within the code of the procedure.

- But I think that you want to count (and also, to list) the parameters of a procedure. That's the only way to perform the operation that you pseudo-coded in your Reply to dharr's Answer.

A procedure created with the arrow **-> **is also of *type* **operator**. The code I give in the rest of this Answer is only meant to be used with that type of procedure. Other procedures allow for far-more-complicated kinds of parameter specifications for which this code will not always work.

The parameters of an operator-procedure (such as **p** given above) can be counted by

**nops([op](1, eval(p)))**

The **symbol**s of its parameters can be listed by

**convert~(op~(1, [op](1, eval(p))), `local`)**

Using this, your pseudo-coded example can be written in Maple like this:

**F:= (x,y,z)-> (r[x]+r[y])*r[z]:**

**G:= proc(f::And(procedure, operator), n::nonnegint)**

local params:= convert~(op~(1, [op](1, eval(f))), `local`)[];

(`+`(params) + f(params)/2)*n

end proc

:

**G(F, 3);**

This is a generalization of the procedure dharr gave for the same puspose. It'll work for some cases for which his will not, (although I think it's likely that his will work for all the cases that you're actually interested in). The 3 problematic cases are

**procedure**s that aren't **operator**s: my code specifically rejects them;
- parameter
**symbol**s** **which have been assigned values as global variables: these will work superficially with dharr's code, but the output value will change when it's "evaluated", which is very likely to happen automatically;
- parameters with a type specification, such as
**n::nonnegint**.