List Archives > 
Maple User Group List Archive > 
Archive by date > 
This Month By Date > 
This Month By Topic
[MUG] Re: Nargs
| [MUG] Re: Nargs |
|
Author: Maple User Group
Posted: Fri, 20 Dec 2002 14:18:17 -0500
|
>> From: Maple User Group "maple_gr"
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
Date: Tue, 17 Dec 2002 15:33:32 -0500 (EST)
From: Carl Devore "devore"
To: "maple-list"
Subject: Nargs
On Mon, 16 Dec 2002, PierLuigi Zezza wrote:
> I am constructing (Maple >= 5 release 5) a procedure which has a function
> (procedure) as an input and I want to detect the number of arguments of the
> input.
Correction: You want to detect the number of parameters, not the number of
arguments. Procedures are defined with parameters and called with
arguments. Counting the arguments is trivial.
> I tried with
> > myproc:=proc(f::procedure) nops({op(1,eval(f))}) end;
>
> but I would like to have has input also linear combinations or composition
> of functions as
> > g:=x->(x+1);
> > (2*f-g)(x);
> > h:=t->(t^2,t);
> > (f@h)(t);
> but my procedure does not work and I think that the reason is that
> > type(2*f-g,procedure);
> false
Yes, that is the reason. I cannot come up with a simple type expression
that will cover all the cases. Maybe someone else can. Nonetheless, I
think that the following will cover the vast majority of cases, certainly
all your cases above.
Nparams:= proc(f)
local F,1,x;
F:= indets(f, `@`);
if F<>{} then return Nparams(op(-1, F[1])) fi;
F:= indets(f, procedure);
F1:= remove(x-> member(_syslib, {attributes(x)}, F);
if F1<>{} then nops([op(1, eval(F1[1]))])
elif F<>{} then nops([op(1, eval(F[1]))])
else 0
fi
end proc;
Since many Maple procedures like arctan and abs are weird cases with
mulitple parameters, I restrict the count, if possible, to the
user-defined procedures. But my procedure might still give unexpected
results for something like "f"
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
From: "Dr Francis J. Wright" "F.J.Wright"
To: "pzezza"
Subject: Nargs
Date: Wed, 18 Dec 2002 17:37:20 -0000
Generalize the type test to accept expressions of whatever form you want.
If the procedure is called with an argument that is not explicitly of type
procedure then analyse the expression to find its procedural components and
check their argument numbers: with a composition you presumably care only
about the rightmost procedure; with a sum or product you presumably want the
minimum number of arguments, etc. You might also want to think about how to
handle a purely symbolic function, i.e. a symbol to which no procedure has
been assigned, which you might want to trap as an error.
Francis
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
Date: Wed, 18 Dec 2002 21:21:25 -0500 (EST)
From: Stephen Forrest "saforres"
To: "maple-list"
Subject: Nargs
Right. Your procedure will have to check the type of the arguments, and
handle these cases differently. In the case of the composition @, it's
obviously the number of arguments of the innermost procedure you want, so
recurse onto that.
In the case of a sum or product of procedures, it's probably the maximum
of all numbers of arguments of each of the subprocedures that you want.
However, for whatever expression you invent, it will probably be possible
to come up with a counterexample of something acts like a procedure but
isn't handled properly. And you will never be able to handle cases that
manipulate args and nargs directly in the procedure body, like
p := proc() if nargs>1 then args[2] elsif nargs>0 args[1] else 0 fi; end:
except as very special cases. So I'm afraid don't really understand why
you'd like to do this.
Steve
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
From: "Greg Gamble" "gregg"
To: "maple-list"
Subject: Nargs
Date: Thu, 19 Dec 2002 12:21:28 +0800
There are two things to consider here:
* the *actual* number of arguments that a function is *called* with,
(this is dynamically assigned to the variable `nargs' when a function/
procedure is executed);
* the number of *named arguments* the function is *defined* with
(for want of a better name let's call this the Arity of a function,
since functions may be unary = 1-ary, binary = 2-ary, ternary = 3-ary
or, in general, n-ary)
Suppose we define f as follows:
> f := (x, y) -> (x, x^2, x^3);
2 3
f := (x, y) -> (x, x , x )
> f(1, 2);
1, 1, 1
> f(1);
1, 1, 1
> f(1, 2, 3);
1, 1, 1
As you can see, despite the fact that f was defined with 2 arguments
(so its Arity is 2), Maple is happy to execute f with any number of
arguments,
so long as it can evaluate it. Here y is not needed in the body of the
function,
so Maple does not object to f being called with 1 argument. By not checking
the number of arguments, Maple allows for the possibility of a variable
number of arguments or optional arguments. Let's define g to be functionally
equivalent
to f via proc so that we can report via `nargs' the number of arguments its
called with:
> g := proc(x, y) printf("nargs: %a\n", nargs); (x, x^2, x^3); end;
g := proc(x, y) printf("nargs: %a\n", nargs); x, x^2, x^3 end proc
> g(1, 2);
nargs: 2
1, 1, 1
> g(1);
nargs: 1
1, 1, 1
> g(1, 2, 3);
nargs: 3
1, 1, 1
Now consider:
> h := proc(x)
> local y;
> if nargs > 1 then
> y := args[2];
> fi;
> (x, x^2, x^3);
> end;
h := proc(x)
local y;
if 1 < nargs then y := args[2] end if; x, x^2, x^3
end proc
Again, h is equivalent to f but the (useless) y is an *optional argument*
that is local to the body of the function, i.e. by my definition y is not
a *named argument*: the Arity of h is 1, whereas the Arity of f or g is 2.
This makes the concept of Arity a bit nebulous in Maple.
You were hoping that Maple would somehow reduce linear combinations and
compositions to an arrow operator form which Maple doesn't do, so eval(f@h)
is just f@h, and there are other considerations e.g. Maple treats constants
as functions: 3(x, y, z) is 3. Your myproc is a rudimentary Arity but you do
not want to enforce the type `procedure' on its argument (as you
discovered).
Here's maybe something close to what you want:
> Arity := f ->
> if type(f, constant) then
> 0
> elif type(f, procedure) then
> nops({op(1, eval(f))})
> elif type(f, `@`) then
> Arity(op(2, f))
> elif type(f, {`+`, `*`}) then
> max(seq(Arity(i), i = [op(f)]))
> else
> error "arity unknown for this function type"
> fi;
Arity := proc(f)
option operator, arrow;
if type(f, constant) then 0
elif type(f, procedure) then nops({op(1, eval(f))})
elif type(f, `@`) then Arity(op(2, f))
elif type(f, {`*`, `+`}) then
max(seq(Arity(i), i = [op(f)]))
else error "arity unknown for this function type"
end if
end proc
Features of (the above) Arity:
1. Arity(f + g) = max(Arity(f), Arity(g))
2. Arity(f * g) = max(Arity(f), Arity(g))
3. Arity(f@g) = Arity(g)
My guess is that you actually want to test well-defined-ness as well i.e.
you want:
1. Arity(f + g) = Arity(f) if Arity(f) = Arity(g)
2. Arity(f * g) = Arity(g) if 0 <> Arity(f) or Arity(f) = Arity(g)
3. Arity(f@g) = Arity(g) if Arity(f) = ArityOfInverse(g)
where ArityOfInverse is defined by:
> ArityOfInverse := f -> nops([f(x['i'] $ 'i' = 1 .. Arity(f))]);
ArityOfInverse := f -> nops([f(x['i'] $ ('i' = 1 .. Arity(f)))])
Anyway, I hope those ideas are helpful.
Regards,
Greg Gamble
// Greg Gamble, Dept. of Maths & Stats //
// Curtin University, Bentley WA 6102 //
// Mailto: "gregg" //
// WWW: http://www.maths.curtin.edu.au/~gregg //
|
[View Complete Thread]
Previous by date: [MUG] Re: _EnvTryHard , _EnvSolveOverReals etc, Maple User Group
Next by date: [MUG] Re: how to implicitplot this func, Carl Devore
Previous thread: [MUG] The MAPLE 6/7/8: New Books and Software, Academy
Next thread: [MUG] how to implicitplot this func, Ruan Zhichao
|