# Sage Idiosyncrasies

## Sage Idiosyncrasies

This page will point out interesting or odd behaviors of Sage and areas where it is either helpful or causes issues.

### Return Type of integral and integrate

Depending on the value of the integral of a symbolic expression the return type will differ.

For example lets say we had the function and we call the integral function on it.

The Sage code would look like this:

f = x^2 + 1 result = integral( f )

The result is obviously

We can check the type of result by using the type function:

type( result )

If you input it into Sage you will see that the type is **sage.calculus.calculus.SymbolicArithmetic**.

Now let's look at another example where

Here the integral is

Sage code would look like this:

f = 1 / x result = integral( f ) type( result )

Here the type of result is **sage.calculus.calculus.SymbolicComposition** which differs from our previous example.

#### Why this is a problem

Sage's Maxima interface provides a variety of pattern matching functions, one of which is called freeof. freeof takes a pattern and an expression and returns true if the pattern is **not** found in the expression.

Sage code could look something like this:

f = x^2 + 1 maxima.freeof( x^3, integral( f ) )

Since the integral( f ) = maxima returns false like you would expect.

Now let's try it with our other example

f = 1 / x maxima.freeof( x^3, integral( f ) )

Since integral( f ) is it should return true, instead it appears the freeof function doesn't understand SymbollicComposition variables and Sage hangs requiring you to quit the worksheet before you can perform anymore calculations.

### Parameter Passing and Graphics Objects

In Python parameter passing of objects is done by reference. So if you pass a mutable object to a function and modify that object then the original is modified. This only applies to mutable objects such as a list or dictionary. Strings and tuples are immutable and therefore any modification made to them in the function must make a copy since the original does not allow change.

Example: A function that appends an item to a list

def addItem( ls, item ): ls += item myList = [1,2] addItem(myList, [3]) print myList #Output: [1,2,3]

Example 2: A function that appends to a string

def appendString( s, addition ) s += addition myString = 'hello ' appendString( myString, ' joe') print myString #Output: hello

Even though the **+=** operator is thought of as modifying the original since strings in Python are immutable **+=** is actually creating a new string object containing the string referenced by lhs concatenated with the string referenced by rhs and assigning the reference of the string newly created string to the lhs.

#### The Graphics Object

Here is Sage's description of the Graphics Object:

The Graphics object is an empty list of graphics objects It is useful to use this object when initializing a for loop where different graphics object will be added to the empty object.

Based on this description you would think that a Graphics object was mutable since they encourage use of the **+=** operator and with enough objects contained in a graphics object repeated copying could become an expensive process.

However after testing the behavior it appears that Graphics objects are immutable and **+=** is actually making a copy.

Example:

def addLine( g ): g += line( [ (0,0),(1,1) ] ) g = Graphics() addLine( g ) print g #output Graphics object consisting of 0 graphics primitives

As you can see passing a graphics object to a function and using the **+=** operator did not modify the original. This means that for a function to modify a Graphics object it must return back the copy created.

def addLine( g ): g += line( [ (0,0),(1,1) ] ) return g g = Graphics() g = addLine( g ) print g #output Graphics object consisting of 1 graphics primitive