Introducing Polyglot Notebooks

Mixing together documentation and dotnet into an analytics notebook

Introducing Polyglot Notebooks

I’ve loved dotnet development since beta 2 of dotnet back in 2001. One of the things I love about being a dotnet developer is that dotnet continues to grow and evolve over the years. Last fall I discovered something new in dotnet that I want to share with you all now: Polyglot Notebooks.

What is Polyglot Notebooks?

Polyglot Notebooks allows you to create notebooks composed of multiple cells. These cells can be either markdown cells for documentation or code cells containing code in either C#, F#, PowerShell, SQL, KQL, HTML, JavaScript, or mermaid markdown for diagramming.

This allows you to mix together rich documentation supported by little pieces of code that progressively expand upon an idea, tell a story, or otherwise provide insight or information to you as a developer.

Code and Markdown Cells

Because cells are typically small and display results below them, this means you can iteratively develop new ideas, illustrate truths with code, and concisely make your point by combining markdown and code together.

Polyglot Notebooks in Action

Let’s take a look at Polyglot Notebooks in action.

Imagine you had a notebook cell that was defined as follows:

public class Point
{
    public Point(int x, int y) {
        this.X = x;
        this.Y = y;
    }

    public int X {get; set;}
    public int Y {get; set;}

    public override string ToString() => $"Point({X}, {Y})";
}

This cell contains just the C# code needed to declare a new class called Point and its basic behavior.

When the cell runs, a new Type is defined in C#, just like it would be when a program is compiled in Visual Studio.

Note: this code will only work if you have installed Polyglot Notebooks. See my article on Installing Polyglot Notebooks for more details on getting started.

After this cell you might have some markdown documentation or you might immediately go to the next code cell where we can use the class we just defined:

Point p = new(4,2);

p

Here we instantiate the Point class using the target-typed new keyword and store the instance in a new variable named p.

The final line of this cell is just the variable p without a semicolon after it. In a normal C# program this would do nothing, but since we’re in a Polyglot Notebook, the last item in a cell can be used to display a value below that cell. In this case, we get to see the current state of that Point object:

Polyglot Cell Result

Note how the ToString method is called for the first line of the output while the table representing our object displays the value for every public property on the object. This helps you quickly understand even complex objects just by ending your cells with their value.

From this point on we can continue to run C# code, refer to our existing variable, define new classes, and intermix markdown cells to provide additional supporting information or helpful resources to our readers.

All-told, we have a very minimal editing experience that focuses the reader just on the code we want to show them.

Uses for Polyglot Notebooks

I personally view Polyglot Notebooks as a new type of application for dotnet developers. These notebooks are the equivalent of a Word document or spreadsheet and contain code you might want to run periodically to accomplish some analytics task, some infrequent semi-manual workflow, or other specific task.

I find that Polyglot Notebooks shine when you use them for the following types of tasks:

  • Interactive Documentation where you want to illustrate something complex and embed code samples that others can interact with and modify to experiment and understand your objects.
  • Teaching and Independent Guided Learning where you share notebooks with learners who can interact with prepared documentation and code examples in small task-based scenarios.
  • Analytics Workloads that allow you to sift through data sources and gain insight from the data via statistical distributions and data visualizations.
  • Prototyping External API Interactions where you create the objects required by external APIs, make a REST request to the API, and explore the resulting object.
  • Machine Learning where you train and fit a machine learning model using something like ML .NET, evaluate its effectiveness, and then possibly deploy the trained model.
  • Artificial Intelligence experimentation with computer vision, language analysis, or things like OpenAI on Azure.
  • Running Infrequent Tasks that require configuration. This one is more of a catch-all, but might include PowerShell tasks you need to run very infrequently and might need to provide custom configuration settings before running it each time.

There are a lot of potential uses for Polyglot Notebooks, but more and more I’m finding myself avoiding creating the simple console applications I used to create to experiment with concepts and instead go directly to a Polyglot Notebook.

Understanding the Architecture of Polyglot Notebooks

Before we close, let’s talk about the architecture of Polyglot Notebooks and the relationship between Polyglot Notebooks and Jupyter Notebooks as well as something called .NET Interactive.

If you’ve been involved in Python development in the past, it’s quite likely you’ve heard of Project Jupyter and Jupyter Notebooks. Jupyter Notebooks were the original data science notebook experience that mixed together code and markdown cells using a kernel running either Julia, Python, or R (leading to the name Jupyter from the names of these 3 languages).

Polyglot Notebooks is built on top of Jupyter Notebooks and runs using a custom notebook kernel called .NET Interactive. The .NET Interactive kernel integrates into Jupyter Notebooks and allows it to run code from any of the languages supported by Polyglot Interactive.

In fact, Polyglot Notebooks and .NET Interactive offers not one but many different kernels - one per every major programming language supported by Polyglot Notebooks. These kernels can share variables and values between each other, allowing you to write code in one language and then hand off the resulting data to the next language.

However, variable sharing is not something you’re likely to use in your first notebook, so I’ll save it for a future article.

Finally, I should note that Polyglot Notebooks is built with extensibility in mind. You can extend Polyglot by authoring your own extensions and custom formatters that allow you to customize how data is formatted in a notebook and introduce really interesting new capabilities. Personally, I feel like we’re only starting to realize the full potential of what can be achieved with a notebook and I look forward to showing a few deep dives in extension development over the coming summer.

Next Steps

I’d encourage you to install Polyglot Notebooks into VS Code and give it a try. Start thinking about little tasks and scenarios that you and your team bump into and see if introducing interactive notebooks might help clarify your code and open up new types of applications for you and your team.

Personally I’m finding myself getting more and more value out of Polyglot Notebooks the more I use it and I’m so excited to explore it more and share it with the community.