# Getting “Null” output from package?

I have a script written to test a package as follows:

SetDirectory[NotebookDirectory[]];
<< test

A = {{1, 2}, {3, 4}}
cp = CharacteristicPolynomial[A, L]
sol = Sum[L[n, cp], {n, 0, 1}]


Which outputs "L+ Null".

The package is as follows:

BeginPackage["test"]

L::usage="description goes here"

Begin["Private"]

ClearAll["Global*"]

L[n0_,cp0_]:=
Module[{n=n0,cp=cp0},
L[n_,cp_]:=
L[n,cp]=
Which[
n==0,L[0]=1,
n==1,L[1]=L,
n==2,L[2]=Simplify[-(cp-L^2)],
n>2 && EvenQ[n]==True,L[n]=Simplify[L[n/2] L[n/2]],
n>2 && EvenQ[n]==False,L[n]=Simplify[L[n-1] L[1]]
]
]

End[]
EndPackage[]


Essentially, my function "L[ ]" has 4 possible outputs:
when n=0 L[0]=1,
when n=1, L[1]=L,
when n=2, L[2]=Simplify[-(cp-L^2)]
when n>2 and even, L[n]=Simplify[L[n/2] L[n/2]]
when n>2 and odd, L[n]=Simplify[L[n-1] L[1]]

Why is L[0,cp]= Null, when all of the other possibilities work?
If I try just L[0,cp] (no Sum[ ]) I receive no output. What does that mean?
Is Which[ ] the best method of approach in this situation?

-
I would start with a single question and a minimal working example. Does having it as a package change anything? Are you sure you know, what are you doing with L[0]=1 etc.? –  Johu May 28 '14 at 22:03
Check Definition["L"] and see, if it outputs what you expect. –  Johu May 28 '14 at 22:12
ClearAll["Global*"] in a package??? –  Sjoerd C. de Vries May 28 '14 at 23:34
The function looks rather bizarre to me. Memoization (L[n_,cp_]:= L[n,cp]=...)inside a scoping construct using the same variable names and then the whole Module SetDelayed to L again... Note that the n in Which is bound to the n in L[n_,cp_] and is not the same as the n in the Module variable list. So the first time it is called non of the Which tests is true and it returns Null. –  Sjoerd C. de Vries May 28 '14 at 23:55
If I implement as just a function: L[n_, cp_] := L[n, cp] = Which[ n == 1, L[1] = L, n == 0, L[0] = 1, n == 2, L[2] = Simplify[-(cp - L^2)], n > 2 && EvenQ[n] == True, L[n] = Simplify[L[n/2] L[n/2]], n > 2 && EvenQ[n] == False, L[n] = Simplify[L[n - 1] L[1]] ] I get the correct output for any n. @Sjoerd C. de Vries I'm going to be honest, I have no idea what you are talking about. I'm be the first to admit I'm a beginner when it comes to Mathematica. Can you elaborate? –  gKirkland May 29 '14 at 0:02

There are a few issues here. I'll start with the little problems.

First, EvenQ returns True or False. You don't need to test whether EvenQ is true, so EvenQ[n]==True is redundantly redundant.

Next, what is L compared to L[n,cp]? Or L[1]? If your output in the second case of the Which is meant to be the function symbol L without any arguments specified, okay, but do you really mean L0 or some other initial value? Because you should use another symbol for that.

This need not be a module. A module allows you to define a routine that uses local variables and more complex programming techniques that operate on local variables. The only local variables you use are the inputs -- reassigned to be local variables.

The reason you don't want this to be a module, especially, is that your definition is:

L[n0_, cp0_] := Module[{n = n0, cp = cp0}, L[n_, cp_] := L[n, cp] =


That's one := too many. You don't even need memoization because (as far as I can tell) this is not meant to be recursive. The function L[_][_] seems to be constructed in a way that it assigns values to the (overloaded) function L[_]. Other comments have addressed this issue and have noted this is why you are not getting any output.

If you make the following changes, you'll have something functional (pun intended?):

L[n_?IntegerQ, cp_?IntegerQ] :=
Which[
n == 0, L[0] = 1,
n == 1, L[1] = L,
n == 2, L[2] = Simplify[-(cp - L^2)],
n > 2 && EvenQ[n], L[n] = Simplify[L[n/2] L[n/2]],
n > 2, L[n] = Simplify[L[n - 1] L[1]]
]


This function will only take integer inputs (that's what the ?IntegerQ will do). It will output some expression of other L functions. For example, L[3,7] will output L[1]L[2].

Now, you've still overloaded the symbol L substantially. Why is a two-argument L[3,7] giving us L[1]L[2], which is a product of some other type of L that takes only one argument?

I'm under the impression that we can fix this code so that it works, but it's not really doing what we want. I hope we've cleared up the technical issues, but we need to start from scratch.

Mathematically, you seem to just one a single sequence L that is determined by some integer parameter cp. You can do this in a much more reasonable way by thinking of it this way:

For any integer $cp$, you have a sequence $L_n^{cp}$ that is defined recursively. You can write the appropriate code as follows:

L[cp_?IntegerQ][n_?IntegerQ] := L[cp][n] =
Which[
n == 0, 1,
n == 1, L[cp][0],
n == 2, L[cp][0]^2 - cp,
n > 2 && EvenQ[n], Simplify[L[cp][n/2]^2],
True, L[cp][n - 1] L[cp][1]
]


I've taken some liberty by using L[cp][0] instead of the no-argument L. You'll have to figure out what goes there. If that is some other parameter, you probably ought to give it a different name like \[Lambda] or something. (It would play a similar role as cp.)

This uses a sort of double-function, rather than two-argument function, for technical reasons. You could replace every occurrence of L[_][_] with L[_,_], but for programmatic reasons I think it's better the [_][_] way.

Try this to experiment:

Manipulate[Table[L[cp][n], {n, 1, 10}], {{cp, 1}, -10, 10, 1}]


On second thought, I'd like to pretend now that maybe this L with no arguments is a parameter. Let's not call it L to avoid confusion. Your code might look like:

L[cp_?IntegerQ, \[Lambda]_?IntegerQ][n_?IntegerQ] :=
L[cp, \[Lambda]][n] =
Which[
n == 0, 1,
n == 1, \[Lambda],
n == 2, \[Lambda]^2 - cp,
n > 2 && EvenQ[n], Simplify[L[cp, \[Lambda]][n/2]^2],
True, L[cp, \[Lambda]][n - 1] L[cp, \[Lambda]][1]
]

Manipulate[
Table[L[cp, \[Lambda]][n], {n, 1, 10}],
{{cp, 1}, -10, 10, 1}, {{\[Lambda], 1}, -10, 10, 1}
]


Upon further review, I didn't even read your example code (sorry, I am lazy sometimes in the worst ways). Apparently cp is a polynomial. In this case, why does it not have an argument? Based on this, here is my revised code:

I will say, in my opinion, this probably doesn't belong in an external file/package. And if it does, I think I would be cautious with the ClearAll[Global*]. I suggest you remove that, at least, if not just putting everything into a single notebook for now.

I think I have finally deciphered exactly what you're trying to do.

Let's start from scratch, mathematically. You have a matrix $A$. This matrix has a characteristic polynomial, a function of $\lambda$. You have integers $n$ that will define some functions of $\lambda$ for each $n$. These are not functions of $cp$. They are functions of $A$ and $n$.

The sequence of polynomial functions of $\lambda$ you want are defined by:

$L_{A,0}(\lambda)=0$

$L_{A,1}(\lambda)=\lambda$

$L_{A,2}(\lambda)=\lambda^2-p_A(\lambda)$

$L_{A,2n}(\lambda)=L_{A,n}(\lambda)^2$

$L_{A,2n+1}(\lambda)=L_{A,2n}(\lambda)L_{A,1}(\lambda)$

This can be achieved by:

L[A_, n_] := L[A, n] =
Function[\[Lambda],
Which[
n == 0, 1,
n == 1, \[Lambda],
n == 2, \[Lambda]^2 - CharacteristicPolynomial[A, \[Lambda]],
n > 2 && EvenQ[n], Simplify[L[A, n/2][\[Lambda]]^2],
True, L[A, n - 1][\[Lambda]] L[A, 1][\[Lambda]]
]
]

A = {{1, 2}, {3, 4}}
Table[L[A, n][\[Lambda]], {n, 0, 10}]
sol = Plus @@ %
Expand[%]
`

That should do whatever it is you're trying to do... I think.

-
Thank you! That's exactly what I wanted. I'll just forget about the package for now, and place everything into a notebook. Thanks also for showing how to use [Lambda], I didn't know you could do that (hence the use of "L"). –  gKirkland Jun 3 '14 at 3:49