Skip to content

Commit 2f4c2a8

Browse files
authored
Add cpp notebooks and CI to check them (#7)
1 parent 6019f47 commit 2f4c2a8

13 files changed

Lines changed: 3358 additions & 0 deletions

xeus-cpp/01_verification.ipynb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "333cda22-5985-44ed-9bcc-5f34378c1bec",
6+
"metadata": {},
7+
"source": [
8+
"# Environment setup and basic verification\n",
9+
"\n",
10+
"---"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": 1,
16+
"id": "884a03ad-230a-4725-90fd-939990e123da",
17+
"metadata": {},
18+
"outputs": [
19+
{
20+
"name": "stdout",
21+
"output_type": "stream",
22+
"text": [
23+
"C++ Version: 202302\n",
24+
"42\n"
25+
]
26+
}
27+
],
28+
"source": [
29+
"#include <iostream>\n",
30+
"\n",
31+
"std::cout << \"C++ Version: \" << __cplusplus << std::endl; //Checks C++ version\n",
32+
"\n",
33+
"int a = 10;\n",
34+
"int b = 32;\n",
35+
"std::cout << a + b << std::endl;\n",
36+
"//Conducts a basic mathematical operation\n",
37+
"//Checks kernel responsiveness"
38+
]
39+
}
40+
],
41+
"metadata": {
42+
"kernelspec": {
43+
"display_name": "C++23",
44+
"language": "cpp",
45+
"name": "xcpp23"
46+
},
47+
"language_info": {
48+
"codemirror_mode": "text/x-c++src",
49+
"file_extension": ".cpp",
50+
"mimetype": "text/x-c++src",
51+
"name": "C++",
52+
"version": "23"
53+
}
54+
},
55+
"nbformat": 4,
56+
"nbformat_minor": 5
57+
}

xeus-cpp/02_persistence.ipynb

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "bbff0978-540f-4307-96fb-6a4692e4fd4d",
6+
"metadata": {},
7+
"source": [
8+
"# State persistence across cells in xeus-cpp\n",
9+
"\n"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"id": "35740592-c29e-4c7b-87e8-52cc0060cd59",
15+
"metadata": {},
16+
"source": [
17+
"#### In a standard C++ development invironment, each time you run a program, the memory is allocated, the `main()` function executes, and then the memory is completely wiped. In **xeus-cpp**, the execution model is **persistent**\n",
18+
"\n",
19+
"---"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"id": "ed28c993-b195-4eb1-85cc-fee63cb04470",
25+
"metadata": {},
26+
"source": [
27+
"\n",
28+
"### What is state persistence?\n",
29+
"\n",
30+
"The Jupyter notebook acts as a single, ongoing C++ session. When you execute a cell, the kernel compiles that specific snippet and integrates it into the current process memory. This means, that any variable, function or object defined in a cell remains alive and accessible in any other cell.\n",
31+
"\n",
32+
"***NB! The order in which you run cells matters. Running cells out of order can cause errors and unexpected behaviour***"
33+
]
34+
},
35+
{
36+
"cell_type": "markdown",
37+
"id": "b493b694-04f1-4a01-997f-ceb4ef8d1499",
38+
"metadata": {},
39+
"source": [
40+
"\n",
41+
"### The following program demonstrates how state persistence in xeus-cpp works exactly:"
42+
]
43+
},
44+
{
45+
"cell_type": "code",
46+
"execution_count": 1,
47+
"id": "b2d303a7-96ee-4aeb-8c84-4884bba161f6",
48+
"metadata": {},
49+
"outputs": [],
50+
"source": [
51+
"int counter = 0;"
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": 2,
57+
"id": "d541cb78-b2ae-4175-b9ae-a76014a37e28",
58+
"metadata": {},
59+
"outputs": [],
60+
"source": [
61+
"#include <iostream>\n",
62+
"\n",
63+
"void inc()\n",
64+
"{\n",
65+
" counter++;\n",
66+
" std::cout << \"Current Value: \" << counter << std::endl;\n",
67+
"}"
68+
]
69+
},
70+
{
71+
"cell_type": "code",
72+
"execution_count": 3,
73+
"id": "d2c38c70-3e92-446a-8c10-1c62edf177e1",
74+
"metadata": {},
75+
"outputs": [
76+
{
77+
"name": "stdout",
78+
"output_type": "stream",
79+
"text": [
80+
"Current Value: 1\n"
81+
]
82+
}
83+
],
84+
"source": [
85+
"inc(); //Run this cell multiple times to see persistence in action"
86+
]
87+
}
88+
],
89+
"metadata": {
90+
"kernelspec": {
91+
"display_name": "C++23",
92+
"language": "cpp",
93+
"name": "xcpp23"
94+
},
95+
"language_info": {
96+
"codemirror_mode": "text/x-c++src",
97+
"file_extension": ".cpp",
98+
"mimetype": "text/x-c++src",
99+
"name": "C++",
100+
"nbconvert_exporter": "",
101+
"pygments_lexer": "",
102+
"version": "cxx23"
103+
}
104+
},
105+
"nbformat": 4,
106+
"nbformat_minor": 5
107+
}

xeus-cpp/03_redefinition.ipynb

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "d7a1b687-3743-4786-84b0-71b6eed7d62e",
6+
"metadata": {},
7+
"source": [
8+
"# Testing redefinition behaviour\n",
9+
"\n",
10+
"\n",
11+
"#### In a traditional C++ workflow, you write code in a `.cpp` file, compile it all at once, and run it. If you want to change a variable type, you simply edit the file and recompile. However, **xeus-cpp**'s cell-based workflow enables several workarounds\n",
12+
"---"
13+
]
14+
},
15+
{
16+
"cell_type": "markdown",
17+
"id": "96f3d068-6433-472a-a4b7-02f253a22600",
18+
"metadata": {},
19+
"source": [
20+
"In this example, we declare a variable with an `int` type, which we will name `a`, and assign a value to it"
21+
]
22+
},
23+
{
24+
"cell_type": "code",
25+
"execution_count": 1,
26+
"id": "216e746c-4eae-4655-a18d-8e1fb6da4327",
27+
"metadata": {},
28+
"outputs": [
29+
{
30+
"name": "stdout",
31+
"output_type": "stream",
32+
"text": [
33+
"Initial declaration: 100\n"
34+
]
35+
}
36+
],
37+
"source": [
38+
"#include <iostream>\n",
39+
"\n",
40+
"int a = 100;\n",
41+
"std::cout << \"Initial declaration: \" << a << std::endl;"
42+
]
43+
},
44+
{
45+
"cell_type": "markdown",
46+
"id": "991adb4c-e105-4f58-8b5d-1147c2ac8d6d",
47+
"metadata": {},
48+
"source": [
49+
"Next, we try to redeclare the variable, this time to `double`, and assign a new value to it"
50+
]
51+
},
52+
{
53+
"cell_type": "code",
54+
"execution_count": null,
55+
"id": "54d35e14-c256-4692-8a7c-f5b7e3815030",
56+
"metadata": {},
57+
"outputs": [],
58+
"source": [
59+
"double a = 55.5;\n",
60+
"std::cout << \"New declaration: \" << a << std::endl;"
61+
]
62+
},
63+
{
64+
"cell_type": "markdown",
65+
"id": "df0fdee0-4747-4ba9-b242-76d8c870cdc5",
66+
"metadata": {},
67+
"source": [
68+
"This action of redefinition is **illegal** in standard C++, because the variable `a` already exists as an `int`.\n",
69+
"\n",
70+
"Two workarounds exist:\n",
71+
"- overwriting the value **without redeclaring the type**\n",
72+
"- creating a temporary \"bubble\" by redeclaring it in a **different scope**, so the variables don't interfere. This method doesn't change the value or the type of the global variable\n",
73+
" \n",
74+
"***NB!*** It is advised that unless you absolutely must use the same name for a variable, you simply pick a new name"
75+
]
76+
},
77+
{
78+
"cell_type": "markdown",
79+
"id": "f52dad1c-3374-438b-9e6f-50e19470a057",
80+
"metadata": {},
81+
"source": [
82+
"---\n",
83+
"\n",
84+
"### First method - overwriting the value"
85+
]
86+
},
87+
{
88+
"cell_type": "code",
89+
"execution_count": 4,
90+
"id": "0a466dd1-9301-4bd0-a981-491c7906ba8f",
91+
"metadata": {},
92+
"outputs": [
93+
{
94+
"name": "stdout",
95+
"output_type": "stream",
96+
"text": [
97+
"Updated value: 20\n"
98+
]
99+
}
100+
],
101+
"source": [
102+
"a = 20.8;\n",
103+
"std::cout << \"Updated value: \" << a << std::endl;"
104+
]
105+
},
106+
{
107+
"cell_type": "markdown",
108+
"id": "90a1c883-bb3a-402f-bb12-d6aaa4f886db",
109+
"metadata": {},
110+
"source": [
111+
"When using the first method to assign a floating point value to an `int`, the new value is floored to the closest integer\n",
112+
"\n",
113+
"As shown in this example \n",
114+
"\n",
115+
"> 20.8 --> 20"
116+
]
117+
},
118+
{
119+
"cell_type": "markdown",
120+
"id": "87b8d709-e706-4edd-888a-6d0a6a788b8a",
121+
"metadata": {},
122+
"source": [
123+
"### Second method - redeclaring in a different scope"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": 6,
129+
"id": "0c765722-7a41-4b25-92df-c10dea32f5e3",
130+
"metadata": {},
131+
"outputs": [
132+
{
133+
"name": "stdout",
134+
"output_type": "stream",
135+
"text": [
136+
"Updated value (scoped): 12.34\n",
137+
"Global value: 20\n"
138+
]
139+
}
140+
],
141+
"source": [
142+
"{\n",
143+
" float a = 12.34f; //safe because it's inside a local scope\n",
144+
" std::cout << \"Updated value (scoped): \" << a << std::endl;\n",
145+
"}\n",
146+
"\n",
147+
"//Outside the brackets, the original int still exists\n",
148+
"std::cout << \"Global value: \" << a << std::endl;"
149+
]
150+
}
151+
],
152+
"metadata": {
153+
"kernelspec": {
154+
"display_name": "C++23",
155+
"language": "cpp",
156+
"name": "xcpp23"
157+
},
158+
"language_info": {
159+
"codemirror_mode": "text/x-c++src",
160+
"file_extension": ".cpp",
161+
"mimetype": "text/x-c++src",
162+
"name": "C++",
163+
"version": "23"
164+
}
165+
},
166+
"nbformat": 4,
167+
"nbformat_minor": 5
168+
}

0 commit comments

Comments
 (0)