# The `CalculusWithJulia` package


{{< include ../_common_code.qmd >}}

To run the commands in  these notes, some external packages must be installed and loaded.


The `Pluto` interface does this in the background, so there is nothing to do but execute the cells that call `using` or `import`. For `Julia` post version `1.7`, this installation will be initiated for you when `using` is called in the REPL terminal.


For other interfaces, to use the `CalculusWithJulia` package  requires first that it be installed. From the command line. This can be done with this key sequence:


```{julia}
#| eval: false
] add CalculusWithJulia
```

Or, using the `Pkg` package, the commands would be


```{julia}
#| eval: false
import Pkg
Pkg.add("CalculusWithJulia")
```

Installation  only needs to be done once.


---


However, for each new `Julia` session, the package must be *loaded*, as with the following command:


```{julia}
using CalculusWithJulia
```

That is all. The rest of this page just provides some details for the interested reader.


## The package concept


The `Julia` language provides the building blocks for the wider `Julia` ecosystem that enhance and extend the language's applicability.


`Julia` is extended through "packages." Some of these, such as packages for certain math constants and some linear algebra operations, are part of all `Julia` installations and must simple by loaded to be used. Others, such as packages for finding integrals or (automatic) derivatives are provided by users and must first be *installed* before being used.


### Package installation


Package installation is straightforward, as `Julia` has a package, `Pkg`, that facilitates this.


Since `Julia` version 1.7, just attempting to load a package through  `using PackageName` at the *command line* will either load an installed package *or* query for an uninstalled package to be installed before loading. So installation just requires confirming a prompt.


For more control, the command line and `IJulia` provide access to the function in `Pkg` through the escape command `]`. For example, to find the status of all currently installed packages, the following command can be executed:


```{julia}
#| eval: false
] status
```

External packages are *typically* installed from GitHub and if they are registered, installation is as easy as calling `add`:


```{julia}
#| eval: false
] add QuadGK
```

That command will consult `Julia`'s general registry for the location of the `QuadGK` package, use this location to download the necessary files, if necessary dependencies will be built and installed, and then the package available for use.


For these notes, when the `CalculusWithJulia` package is installed it will also install many of the other packages that are needed.


See [Pkg](https://docs.julialang.org/en/v1/stdlib/Pkg/index.html) for more details, such as how to update the set of available packages.


### Using a package


The features of an installed package are not available until the package is brought into the current session. A package need only be *installed* once, but must be loaded each session.


To load a package, the `using` keyword is provided:


```{julia}
using QuadGK
```

The above command will make available all *exported* function names from the `QuadGK` package so they can be directly used, as in:


```{julia}
quadgk(sin, 0, pi)
```

(A command to find an integral of $f(x) = \sin(x)$ over $[0, \pi]$.)


### Package details


When a package is *first* loaded after installation, or some other change, it will go through a *pre-compilation* process. Depending on the package size, this can take a moment to several seconds. This won't happen the second time a package is loaded.


However, subsequent times a package is loaded some further compilation is done, so it can still take some time for a package to load. Mostly this is not noticeable, though with the plotting package used in these notes, it is.


When a package is loaded, all of its dependent packages are also loaded, but their functions are not immediately available to the user.


In *typical* `Julia` usage, each needed package is loaded on demand. This is faster and also keeps the namespace (the collection of variable and function names) smaller to avoid collisions. However, for these notes, the package `CalculusWithJulia` will load a few of the packages needed for the entire set of notes, not just the current section. This is to make it a bit *easier* for the *beginning* user.


One issue with loading several packages is the possibility that more than one will export a function with the same name, causing a collision. Moreover, at times, there can be dependency conflicts between packages. A suggested workflow is to use projects and in each project use a minimal set of packages. In Pluto, this is done behind the scenes.


The `Julia` language is designed around have several "generic" functions each with many different methods depending on their usage. This design allows many different implementations for operations such as addition or multiplication yet the user only needs to call one function name. Packages can easily extend these generic functions by providing their own methods for their own new types of data. For example, `SymPy`, which adds symbolic math features to `Julia` (using a Python package) extends both `+` and `*` for use with symbolic objects.


This design works great when the "generic" usage matches the needs of the package authors, but there are two common issues that arise:


  * The extension of a generic is for a type defined outside the author's package. This is known as "type piracy" and is frowned on, as it can lead to subtle errors. The `CalculusWithJulia` package practices this for one case: using `'` to indicate derivatives for `Function` objects.
  * The generic function concept is not part of base `Julia`. An example might be the `solve` function. This name has a well-defined mathematical usage (e.g., "solve for $x$."), but the generic concept is not part of base `Julia`. As it is used by `SymPy` and `DifferentialEquations`, among others, the ecosystem has a stub package `CommonSolve` allowing the sharing of this "verb."
