{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[![xeus-cling](images/xeus-cling.png)](https://github.com/jupyter-xeus/xeus-cling/)\n", "\n", "A Jupyter kernel for C++ based on the `cling` C++ interpreter and the `xeus` native implementation of the Jupyter protocol, xeus.\n", "\n", "- GitHub repository: https://github.com/jupyter-xeus/xeus-cling/\n", "- Online documentation: https://xeus-cling.readthedocs.io/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Usage\n", "\n", "
\n", " \n", " \n", "
\n", " To run the selected code cell, hit
Shift + Enter
\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Output and error streams\n", "\n", "`std::cout` and `std::cerr` are redirected to the notebook frontend." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "std::cout << \"some output\" << std::endl;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "std::cerr << \"some error\" << std::endl;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "throw std::runtime_error(\"Unknown exception\");" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Omitting the `;` in the last statement of a cell results in an output being printed" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "int j = 5;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "j" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Interpreting the C++ programming language\n", "\n", "`cling` has a broad support of the features of C++. You can define functions, classes, templates, etc ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "double sqr(double a)\n", "{\n", " return a * a;\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "double a = 2.5;\n", "double asqr = sqr(a);\n", "asqr" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Classes" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class Foo\n", "{\n", "public:\n", "\n", " virtual ~Foo() {}\n", " \n", " virtual void print(double value) const\n", " {\n", " std::cout << \"Foo value = \" << value << std::endl;\n", " }\n", "};" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Foo bar;\n", "bar.print(1.2);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Polymorphism" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class Bar : public Foo\n", "{\n", "public:\n", "\n", " virtual ~Bar() {}\n", " \n", " virtual void print(double value) const\n", " {\n", " std::cout << \"Bar value = \" << 2 * value << std::endl;\n", " }\n", "};" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Foo* bar2 = new Bar;\n", "bar2->print(1.2);\n", "delete bar2;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Templates" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "template \n", "class FooT\n", "{\n", "public:\n", " \n", " explicit FooT(const T& t) : m_t(t) {}\n", " \n", " void print() const\n", " {\n", " std::cout << typeid(T).name() << \" m_t = \" << m_t << std::endl;\n", " }\n", " \n", "private:\n", " \n", " T m_t;\n", "};" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "FooT foot(1.2);\n", "foot.print();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## C++11 / C++14 / C++17 support" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class Foo11\n", "{\n", "public:\n", " \n", " Foo11() { std::cout << \"Foo11 default constructor\" << std::endl; }\n", " Foo11(const Foo11&) { std::cout << \"Foo11 copy constructor\" << std::endl; }\n", " Foo11(Foo11&&) { std::cout << \"Foo11 move constructor\" << std::endl; }\n", "};" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Foo11 f1;\n", "Foo11 f2(f1);\n", "Foo11 f3(std::move(f1));" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "std::vector v = { 1, 2, 3};\n", "auto iter = ++v.begin();\n", "v" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "*iter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... and also lambda, universal references, `decltype`, etc ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Documentation and completion\n", "\n", " - Documentation for types of the standard library is retrieved on cppreference.com.\n", " - The quick-help feature can also be enabled for user-defined types and third-party libraries. More documentation on this feature is available at https://xeus-cling.readthedocs.io/en/latest/inline_help.html.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "?std::vector" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using the `display_data` mechanism" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a user-defined type `T`, the rich rendering in the notebook and JupyterLab can be enabled by by implementing the function `nl::json mime_bundle_repr(const T& im)`, which returns the JSON mime bundle for that type.\n", "\n", "More documentation on the rich display system of Jupyter and Xeus-cling is available at https://xeus-cling.readthedocs.io/en/latest/rich_display.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Image example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include \n", "\n", "#include \"nlohmann/json.hpp\"\n", "\n", "#include \"xtl/xbase64.hpp\"\n", "\n", "namespace nl = nlohmann;\n", "\n", "namespace im\n", "{\n", " struct image\n", " { \n", " inline image(const std::string& filename)\n", " {\n", " std::ifstream fin(filename, std::ios::binary); \n", " m_buffer << fin.rdbuf();\n", " }\n", " \n", " std::stringstream m_buffer;\n", " };\n", " \n", " nl::json mime_bundle_repr(const image& i)\n", " {\n", " auto bundle = nl::json::object();\n", " bundle[\"image/png\"] = xtl::base64encode(i.m_buffer.str());\n", " return bundle;\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "im::image marie(\"images/marie.png\");\n", "marie" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Audio example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include \n", "\n", "#include \"nlohmann/json.hpp\"\n", "\n", "#include \"xtl/xbase64.hpp\"\n", "\n", "namespace nl = nlohmann;\n", "\n", "namespace au\n", "{\n", " struct audio\n", " { \n", " inline audio(const std::string& filename)\n", " {\n", " std::ifstream fin(filename, std::ios::binary); \n", " m_buffer << fin.rdbuf();\n", " }\n", " \n", " std::stringstream m_buffer;\n", " };\n", " \n", " nl::json mime_bundle_repr(const audio& a)\n", " {\n", " auto bundle = nl::json::object();\n", " bundle[\"text/html\"] =\n", " std::string(\"\";\n", " return bundle;\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "au::audio drums(\"audio/audio.wav\");\n", "drums" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \"xcpp/xdisplay.hpp\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xcpp::display(drums);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Update-display" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include \"xcpp/xdisplay.hpp\"\n", "\n", "#include \"nlohmann/json.hpp\"\n", "\n", "namespace nl = nlohmann;\n", "\n", "namespace ht\n", "{\n", " struct html\n", " { \n", " inline html(const std::string& content)\n", " {\n", " m_content = content;\n", " }\n", " std::string m_content;\n", " };\n", "\n", " nl::json mime_bundle_repr(const html& a)\n", " {\n", " auto bundle = nl::json::object();\n", " bundle[\"text/html\"] = a.m_content;\n", " return bundle;\n", " }\n", "}\n", "\n", "// A blue rectangle\n", "ht::html rect(R\"(\n", "
\n", "Original\n", "
)\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xcpp::display(rect, \"some_display_id\");" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "// Update the rectangle to be red\n", "rect.m_content = R\"(\n", "
\n", "Updated\n", "
)\";\n", "\n", "xcpp::display(rect, \"some_display_id\", true);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Clear output" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include \n", "#include \n", "\n", "#include \"xcpp/xdisplay.hpp\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "std::cout << \"hello\" << std::endl;\n", "std::this_thread::sleep_for(std::chrono::seconds(1));\n", "xcpp::clear_output(); // will flicker when replacing \"hello\" with \"goodbye\"\n", "std::this_thread::sleep_for(std::chrono::seconds(1));\n", "std::cout << \"goodbye\" << std::endl;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "std::cout << \"hello\" << std::endl;\n", "std::this_thread::sleep_for(std::chrono::seconds(1));\n", "xcpp::clear_output(true); // prevents flickering\n", "std::this_thread::sleep_for(std::chrono::seconds(1));\n", "std::cout << \"goodbye\" << std::endl;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Magics\n", "\n", "Magics are special commands for the kernel that are not part of the C++ language.\n", "\n", "They are defined with the symbol `%` for a line magic and `%%` for a cell magic.\n", "\n", "More documentation for magics is available at https://xeus-cling.readthedocs.io/en/latest/magics.html." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "std::vector to_shuffle = {1, 2, 3, 4};" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%timeit std::random_shuffle(to_shuffle.begin(), to_shuffle.end());" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[![xtensor](images/xtensor.png)](https://github.com/xtensor-stack/xtensor/)\n", "\n", "- GitHub repository: https://github.com/xtensor-stack/xtensor/\n", "- Online documentation: https://xtensor.readthedocs.io/\n", "- NumPy to xtensor cheat sheet: http://xtensor.readthedocs.io/en/latest/numpy.html\n", "\n", "`xtensor` is a C++ library for manipulating N-D arrays with an API very similar to that of numpy." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "#include \"xtensor/xarray.hpp\"\n", "#include \"xtensor/xio.hpp\"\n", "#include \"xtensor/xview.hpp\"\n", "\n", "xt::xarray arr1\n", " {{1.0, 2.0, 3.0},\n", " {2.0, 5.0, 7.0},\n", " {2.0, 5.0, 7.0}};\n", "\n", "xt::xarray arr2\n", " {5.0, 6.0, 7.0};\n", "\n", "xt::view(arr1, 1) + arr2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Together with the C++ Jupyter kernel, `xtensor` offers a similar experience as `NumPy` in the Python Jupyter kernel, including broadcasting and universal functions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#include \"xtensor/xarray.hpp\"\n", "#include \"xtensor/xio.hpp\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xt::xarray arr\n", " {1, 2, 3, 4, 5, 6, 7, 8, 9};\n", "\n", "arr.reshape({3, 3});\n", "\n", "std::cout << arr;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \"xtensor-blas/xlinalg.hpp\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xt::xtensor m = {{1.5, 0.5}, {0.7, 1.0}};\n", "std::cout << \"Matrix rank: \" << std::endl << xt::linalg::matrix_rank(m) << std::endl;\n", "std::cout << \"Matrix inverse: \" << std::endl << xt::linalg::inv(m) << std::endl;\n", "std::cout << \"Eigen values: \" << std::endl << xt::linalg::eigvals(m) << std::endl;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "xt::xarray arg1 = xt::arange(9);\n", "xt::xarray arg2 = xt::arange(18);\n", "\n", "arg1.reshape({3, 3});\n", "arg2.reshape({2, 3, 3});\n", "\n", "std::cout << xt::linalg::dot(arg1, arg2) << std::endl;" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "C++17", "language": "C++17", "name": "xcpp17" }, "language_info": { "codemirror_mode": "text/x-c++src", "file_extension": ".cpp", "mimetype": "text/x-c++src", "name": "c++", "version": "17" } }, "nbformat": 4, "nbformat_minor": 2 }