<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>My Blog</title>
	<subtitle>My blog site.</subtitle>
	<link href="https://debruijn.github.io/posts/feed.xml" rel="self" type="application/atom+xml"/>
    <link href="https://debruijn.github.io/posts/"/>
	<updated>2024-11-29T00:00:00+00:00</updated>
	<id>https://debruijn.github.io/posts/feed.xml</id>
	<entry xml:lang="en">
		<title>Advent of Code is coming. Why I participate again and again.</title>
		<published>2024-11-29T00:00:00+00:00</published>
		<updated>2024-11-29T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/why-adventofcode/" type="text/html"/>
		<id>https://debruijn.github.io/posts/why-adventofcode/</id>
		<content type="html">&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;www.adventofcode.com&quot;&gt;Advent of Code&lt;&#x2F;a&gt; is coming up again, starting December 1st. It is a yearly event with programming
challenges every day up until Christmas, and I have participated in it for the last few years and will do so again this
year. In case you are on the fence, let me give you some reasons on why it can be worthwhile to participate, for all
kinds of level of programming.&lt;&#x2F;p&gt;
&lt;p&gt;Note: if you read this after it has started, that is no problem! You can do the challenges retroactively, not just for
the current edition but also for the past 9 years.&lt;&#x2F;p&gt;
&lt;p&gt;TLDR:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Learn more about programming, no matter at what level you are right now&lt;&#x2F;li&gt;
&lt;li&gt;Learn new programming languages&lt;&#x2F;li&gt;
&lt;li&gt;Try out new approaches&lt;&#x2F;li&gt;
&lt;li&gt;Learn new algorithms and solutions&lt;&#x2F;li&gt;
&lt;li&gt;Learn your limits&lt;&#x2F;li&gt;
&lt;li&gt;It is fun!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;how-does-it-work&quot;&gt;How does it work?&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-it-work&quot; aria-label=&quot;Anchor link for: how-does-it-work&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Every day at midnight EST a new challenge will be available to work on. You can also always do older days if you missed
one, or do them out of order. Each challenge consists of two parts: if you complete the first one, you will get access
to the second part. Sometimes the second part is a totally different problem to solve than the first part, but in most
cases it will be a more difficult version: bigger data set, more iterations, more rules, higher dimension, or whatever
is applicable to the challenge of that day.&lt;&#x2F;p&gt;
&lt;p&gt;You can participate by joining up with an existing GitHub, Google, Twitter or Reddit account. Each challenge will have
an input that is specific to you, which you can manually download from the website (or automatically using a tool like
Python has in &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wimglenn&#x2F;advent-of-code-data&quot;&gt;advent-of-code-data&lt;&#x2F;a&gt; - whatever language you want to
use is bound to have one as well!).&lt;&#x2F;p&gt;
&lt;p&gt;There are leaderboards for the fastest to complete the challenge, but don&#x27;t worry about that if you are new to it: first
take your time and do the challenges &lt;strong&gt;well&lt;&#x2F;strong&gt; before you try to do them &lt;strong&gt;quick&lt;&#x2F;strong&gt;. So, having the background out of the
way: why should you join?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;get-started-with-programming-or-get-back-to-it&quot;&gt;Get started with programming - or get back to it&lt;a class=&quot;zola-anchor&quot; href=&quot;#get-started-with-programming-or-get-back-to-it&quot; aria-label=&quot;Anchor link for: get-started-with-programming-or-get-back-to-it&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;First of all, the event can be a great way to learn more about programming, or getting back to it. If you are 100% new to
programming, then first pick a language (if you don&#x27;t know which one, then probably Python or JavaScript are good
starters) and learn the most basic skills in that language first. If you can&#x27;t figure out how to start with such a
language on your own, then that is &lt;strong&gt;totally fine&lt;&#x2F;strong&gt;, but something like Advent of Code might not be the thing for you -
at least not now. Find someone to help you get started, and then you can always come back to this later. But if you are
already past that stage (e.g. you know how to sum a few numbers or how to print a text on screen) then this can be a
good push towards expanding your skills.&lt;&#x2F;p&gt;
&lt;p&gt;Note that the later days can become more tricky, so don&#x27;t feel bad if you will encounter days that you honestly just
can&#x27;t solve. Feel free to skip a day, to come back to this later, or to just stop at the point it is no longer worth it
for you. On the other hand: if you have the time and energy to push through a few more days, then you might have pushed
your limits further out, so it&#x27;s worth considering not giving up.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, if it has been a while since you regularly wrote some code, you can use this to refresh some of those skills.
I have done something similar recently with a similar coding event called &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;www.codingquest.io&quot;&gt;coding quest&lt;&#x2F;a&gt;, for which
I have done the first series of practice challenges all in R, a language I used to work with daily, but which I used
only rarely in recent years. I could notice a big difference between the first and last challenge in remembering the
how to do something in R, so for sure if an R project is coming up for me, I will do something similar to freshen it up.&lt;&#x2F;p&gt;
&lt;p&gt;By the way: programming can be defined very broadly in this sense. Most problems can be solved using tools that would
not normally be called programming languages, like Excel or even visualisations of the data in Minecraft! So if
something like Python looks scary to you, but you know your way around Excel: have a go with that!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;level-up-your-go-to-programming-language&quot;&gt;Level up your go-to programming language&lt;a class=&quot;zola-anchor&quot; href=&quot;#level-up-your-go-to-programming-language&quot; aria-label=&quot;Anchor link for: level-up-your-go-to-programming-language&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;On the other hand, if you already are programming every day, then the Advent of Code event can be a good motivation to
try out parts of the language you don&#x27;t tend to use a lot on a day-to-day basis but would be good to know more about.&lt;&#x2F;p&gt;
&lt;p&gt;For me, this has been the first thing I really enjoyed in Advent of Code. When I first got introduced to it, I was in a
situation in which I used Python daily, but was mostly focused on Python packages for data processing (back then,
numpy and pandas) and Bayesian modeling (pystan, numpyro), but I rarely used actual standard Python. The scripts at my
work were also mostly procedural back then, so I didn&#x27;t really use classes that often. In those first years of me doing
Advent of Code, I focused on the following topics (in roughly the following order):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Object-oriented programming and classes (on days for which this was a suitable approach)&lt;&#x2F;li&gt;
&lt;li&gt;Pure python without dependencies - so stay away from numpy and pandas which I used to tend towards&lt;&#x2F;li&gt;
&lt;li&gt;Making use of functions in standard modules like:
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;itertools.html&quot;&gt;itertools&lt;&#x2F;a&gt; (for example: cycle, chain, pairwise, combinations)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html&quot;&gt;functools&lt;&#x2F;a&gt; (for example: cache, reduce, cmp_to_key, partial)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;collections.html&quot;&gt;collections&lt;&#x2F;a&gt; (for example: Counter, deque, defaultdict)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I currently can&#x27;t imagine not having those solutions in my tool kit, even as my preferred first solutions
(when suitable), and it is because I have build up that habit over time doing all those Advent of Code challenges.
Of course, for specific use cases using packages makes a lot of sense, but having the urge to import numpy or pandas
just to sum a list of numbers was not the right habit.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learn-new-languages&quot;&gt;Learn new languages&lt;a class=&quot;zola-anchor&quot; href=&quot;#learn-new-languages&quot; aria-label=&quot;Anchor link for: learn-new-languages&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Advent of Code can also be great to start with new languages that you don&#x27;t use in your daily life. This can be a
language that you consider a good skill to obtain, but it can also purely be out of interest. Learning a new language
will always also come with learning the way of thinking of that language, which can also benefit you in your go-to
language for specific problems.&lt;&#x2F;p&gt;
&lt;p&gt;For me, this &quot;other&quot; language was always Rust. I wanted to jump on the hype train but didn&#x27;t really have a good reason
to get into it in work. In the last year, I have done so, and I have &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-00&quot;&gt;blogged about&lt;&#x2F;a&gt; before.
Advent of Code was critical in this as a motivation: there were a few days for which my Python solve was a bit too slow
for my liking, and I was curious if I could speed it up by running key calculations in Rust. With the most basic Rust
skills imaginable, I figured out how to run that with &lt;code&gt;maturin&lt;&#x2F;code&gt; in Python and got a major speed boost. But then.. I got
hooked on programming in Rust. Of course, you can gain even more speed by putting the entire process in Rust, instead of
just the key calculations. So now I have several puzzles of AoC 2020 solved in Python, in Rust, and in a combination of
both.&lt;&#x2F;p&gt;
&lt;p&gt;The nice thing about learning a new language using Advent of Code is that the challenges will present to you new
situations that require you to investigate the best way to do them in this new language; but not all at once. One day
you might be looking into how to convert characters to numbers, then after you might have to implement your own hashing
algorithm, and the day after you have to somehow navigate a grid. Different challenges at different levels, that will
all help you build up your skill set.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learn-new-programming-concepts-or-algorithms&quot;&gt;Learn new programming concepts or algorithms&lt;a class=&quot;zola-anchor&quot; href=&quot;#learn-new-programming-concepts-or-algorithms&quot; aria-label=&quot;Anchor link for: learn-new-programming-concepts-or-algorithms&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;This brings us to another benefit: all kinds of fields that make use of programming are introduced and involved into the
challenges, which means that you will build up a nice set of solutions and skills for a wide variety of topics.
Depending on your background, you might already be familiar with some of the following, but likely not all:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How to build your own hardware emulator&lt;&#x2F;li&gt;
&lt;li&gt;Working with CPU instructions&lt;&#x2F;li&gt;
&lt;li&gt;Pathfinding problems and all kinds of algorithms (Dijkstra, A*, etc)&lt;&#x2F;li&gt;
&lt;li&gt;Identifying states of convergence in a set of equations&#x2F;instructions&lt;&#x2F;li&gt;
&lt;li&gt;Various variants of Game of Life&lt;&#x2F;li&gt;
&lt;li&gt;(and many more)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Related to this, is that you can use this to more generally think about data structures: when to use a deque instead of
a list, for example. Writing your code and calculations in a way to be more efficient will surely find a way to be
worthwhile in your daily life at some point. Some people come back to the same puzzle again and again to squeeze out
another bit of performance increase. It is your choice how far you want to take that of course (if at all).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learn-your-limits-or-lack-thereof&quot;&gt;Learn your limits (or lack thereof)&lt;a class=&quot;zola-anchor&quot; href=&quot;#learn-your-limits-or-lack-thereof&quot; aria-label=&quot;Anchor link for: learn-your-limits-or-lack-thereof&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Like said before: it is totally okay if at some point you check out. Some people only do the first few days, others hang
on until halfway through, and only a small subset complete the full 25 days after 25 days. It doesn&#x27;t hurt to see which
days are easy for you, which days are hard-but-doable, and which ones are just out of your league right now. You can
use this knowledge to identify what to work on to push your limits, but you don&#x27;t have to. For example, if you learn
through Advent of Code that you really dislike pathfinding problems, then you also know to avoid those in future job
opportunities. It is good to also know the limits of your interest. For me, I have the feeling I would not enjoy
working with CPU instructions (&lt;code&gt;jump 4&lt;&#x2F;code&gt;, &lt;code&gt;goto 19&lt;&#x2F;code&gt;, etc) based on my enjoyment of those set of problems in Advent of
Code, so I know what to avoid. :)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-is-fun-to-solve-problems&quot;&gt;It is fun to solve problems!&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-is-fun-to-solve-problems&quot; aria-label=&quot;Anchor link for: it-is-fun-to-solve-problems&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Even if you have no value in learning more about programming, or if you think there is nothing to learn, there is also
that bit of enjoyment of solving a puzzle of any kind. This is why people like things like jigsaw puzzles, sudoku&#x27;s, or
puzzle video games. That same feeling of accomplishment can be had with Advent of Code and similar events. This might be
the most useful tool in evaluating how long to stick to the event: participate while you are still having fun, and when
you don&#x27;t, perhaps persevere a couple more days but don&#x27;t force yourself to stick it out if it is too much of a burden
after 5 days already.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-tips-if-you-are-new-to-it&quot;&gt;Some tips if you are new to it&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-tips-if-you-are-new-to-it&quot; aria-label=&quot;Anchor link for: some-tips-if-you-are-new-to-it&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;In most cases it is ideal to figure out a solution that would work for any input, so don&#x27;t (permanently) hard code in
some specific numbers or properties of your input. But sometimes, looking at patterns in the data is part of the
challenge, so if you can&#x27;t figure out a general solution, then it might be such a day for which you actually have to
construct a data-specific solution.&lt;&#x2F;li&gt;
&lt;li&gt;Speaking of input data: if you want to make use of Git repositories for managing your code, then don&#x27;t include the
input files within them if you make the repositories public. Eric (the creator of Advent of Code) has requested to keep
the files private, because that is his creative property. So either keep the whole repository private, or figure out
some way to not include the files (gitignore, git private submodules, caching data in a different folder, etc).&lt;&#x2F;li&gt;
&lt;li&gt;When you have a first solution of both parts, have a look back yourself at what you could have done better.
&lt;ul&gt;
&lt;li&gt;Is there some restructuring that will perform better?&lt;&#x2F;li&gt;
&lt;li&gt;Is there some calculation that is not needed?&lt;&#x2F;li&gt;
&lt;li&gt;Is there some calculation that you reuse between parts 1 and 2, and that you can refactor to deduplicate your code?&lt;&#x2F;li&gt;
&lt;li&gt;Are there other cleanups to be done?&lt;&#x2F;li&gt;
&lt;li&gt;Do you think another solution could exist that performs significantly better in the same programming language?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;.. and then: have a look at the advent of code &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;adventofcode&quot;&gt;subreddit&lt;&#x2F;a&gt; for how other people have
solved the problem.
&lt;ul&gt;
&lt;li&gt;Of course, don&#x27;t go here until you have your answer, unless you are really stuck. (But even if you are stuck, first
take a break and see if you can figure out later - you learn more from finding your own answer!)&lt;&#x2F;li&gt;
&lt;li&gt;Especially have a look at people using the same language as you: have they done basically the same approach? If so,
is there anything to learn from their coding style? If they used a different approach: do you think that would be
faster? Can you see how to include that in your code as well? Sometimes there are small things to pick up from others.
&lt;ul&gt;
&lt;li&gt;For me, an example in Rust is to make use of type declarations like &lt;code&gt;type Pt = Point&amp;lt;isize,2&amp;gt;&lt;&#x2F;code&gt; so I don&#x27;t have to
type out the full type every time. This makes coding faster but also more readable. I have picked this up from someone
else by looking at their solution.&lt;&#x2F;li&gt;
&lt;li&gt;Alternatively, you might have struggled to think of your own algorithm while there is actually a class of generic
algorithms that this falls under. Recognizing that that&#x27;s the case can help you understand future problems and see the
similarities and differences quicker.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;There will be problems with grids, especially two-dimensional grids for path-finding problems (and others). As an
example, think of a maze that you have to find the quickest route through. To work with coordinates in two dimensions,
in many languages it can be a tip to work with complex numbers instead. So for example, in Python a &lt;code&gt;(x, y)&lt;&#x2F;code&gt; tuple would
become a single &lt;code&gt;x + y*1j&lt;&#x2F;code&gt; complex number. Rotation can then be done by multiplying with &lt;code&gt;1j&lt;&#x2F;code&gt; or &lt;code&gt;-1j&lt;&#x2F;code&gt;, instead of
manually shifting the coordinates around.
&lt;ul&gt;
&lt;li&gt;Alternatively, you can also do some prep work and write your own Grid object&#x2F;struct&#x2F;class&#x2F;functions&#x2F;whatever. This
would allow you to not have to fuss around with processing the input but instead get to solving the actual problem
quickly. Such a generic Grid object might then also allow you to work with more than 2 dimensions (which is sure to
come up at least once as well!).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Another tip for grids: think about whether for this problem it makes more sense to keep track of all elements, or only
of relevant elements.
&lt;ul&gt;
&lt;li&gt;All elements: e.g. if you have a list of lists of elements, you can do: &lt;code&gt;if grid[i][j] == &#x27;.&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Only relevant elements: e.g. a set of (i, j) coordinates, &lt;code&gt;if (i, j) in grid&lt;&#x2F;code&gt;, or &lt;code&gt;if i + j*1j in grid&lt;&#x2F;code&gt; if you use complex numbers&lt;&#x2F;li&gt;
&lt;li&gt;Especially when the ruleset is such that the grid size can grow, keeping track of only relevant elements can be faster and easier&lt;&#x2F;li&gt;
&lt;li&gt;But if instead you have a fixed grid size for which you know each element is relevant, then maintaining a set can be
more cumbersome and slower&lt;&#x2F;li&gt;
&lt;li&gt;Alternatively to both, if there are a fixed number of elements for which you have to track the location, you can
also just have a list or dictionary of current locations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Final tip: don&#x27;t use AI to get to solutions. At least be responsible with it and use it in such a way that you think
you can learn something from it. The goal is not to just find the right number, but also to gain the skills such that
you can find it with less effort next time. Using AI will not help you learn to get there, and the AI doesn&#x27;t need you
to get there as well. It is much more useful to struggle with a challenge yourself, and if needed, come back to it
later. Of course, in the end it is your call what you want to get out of it.
&lt;ul&gt;
&lt;li&gt;What might be a good idea though is to show AI your solution when you are done, and see if they have any additional
suggestions. This can especially be useful if you use a language for which no other solutions are posted on Reddit.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;more-events&quot;&gt;More events&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-events&quot; aria-label=&quot;Anchor link for: more-events&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;If you are getting the taste of these coding events and you want to do them throughout the year (or you are looking for
additional challenges after you have finished the Advent of Code one of that day), consider the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Of course, old Advent of Code challenges are waiting for you to pick them up. Each year has a slightly different focus
of a type of problem that is more recurring, but overall the type of challenges across all years are quite comparable.
To find them, click &lt;code&gt;Events&lt;&#x2F;code&gt; at the top of the Advent of Code page or directly go &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;events&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I can also highly recommend &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;everybody.codes&quot;&gt;Everybody Codes&lt;&#x2F;a&gt; which had its first event this November 2024 with
puzzles that are very similar in style compared to Advent of Code (each day consists of 3 parts instead of 2 - but often
two parts are very similar).&lt;&#x2F;li&gt;
&lt;li&gt;There is also &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;www.codingquest.io&quot;&gt;Coding Quest&lt;&#x2F;a&gt;, for which I have only done the introductory set of puzzles so far
but I plan to come back to this in the new year with new languages to learn.&lt;&#x2F;li&gt;
&lt;li&gt;This December 2024 will also feature the kick-off of &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;http:&#x2F;&#x2F;www.adventofsql.com&quot;&gt;Advent of SQL&lt;&#x2F;a&gt;, which will also introduce daily puzzles
but these will be setup to be solved with (Postgres) SQL. I can&#x27;t vouch for its quality yet since it still has to launch
as of writing this page, but I hope this will be a good way to dust off those SQL skills. :)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust in Python: summary of learnings so far</title>
		<published>2024-11-04T00:00:00+00:00</published>
		<updated>2024-11-04T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/rust-python-04/" type="text/html"/>
		<id>https://debruijn.github.io/posts/rust-python-04/</id>
		<content type="html">&lt;p&gt;In the &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-01&quot;&gt;past&lt;&#x2F;a&gt; &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-02&quot;&gt;few&lt;&#x2F;a&gt; &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-03&quot;&gt;entries&lt;&#x2F;a&gt; in this blog series, I have
presented my approach to incorporate Rust in Python projects. So, what are my current views about learning Rust simply
to speed up some critical functions? Would I do it again if I had to start from scratch now? And where do I see the
practical use for it in day to day work?&lt;&#x2F;p&gt;
&lt;h3 id=&quot;not-as-big-of-an-effort-as-you-might-think&quot;&gt;Not as big of an effort as you might think&lt;a class=&quot;zola-anchor&quot; href=&quot;#not-as-big-of-an-effort-as-you-might-think&quot; aria-label=&quot;Anchor link for: not-as-big-of-an-effort-as-you-might-think&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Learning Rust to a point where it is enough to do this at all does not take a lot of time. Of course, you can learn
way more Rust, but the gains can already be achieved quite quickly. The key help in that is the Rust compiler, being
nitpicky (in a good way) to limit the issues you might have when you just want it to work reliably.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-like-rusts-tooling-and-existing-packages&quot;&gt;I like Rusts tooling and existing packages&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-like-rusts-tooling-and-existing-packages&quot; aria-label=&quot;Anchor link for: i-like-rusts-tooling-and-existing-packages&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Next to the nitpicky compiler, I like the rest of the common Rust tools: so far, &lt;code&gt;cargo&lt;&#x2F;code&gt; seems very smooth to me, and I
like &lt;code&gt;crates.io&lt;&#x2F;code&gt; although it helps I was already familiar with PyPI. A lot of features that I would use to solve
particular issues in Python have analogue packages in Rust (where that makes sense), like &lt;code&gt;itertools&lt;&#x2F;code&gt; for efficiently
iterating in various ways. So you don&#x27;t have to reimplement logic if your brain thinks &lt;code&gt;pairwise&lt;&#x2F;code&gt; or &lt;code&gt;combinations&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-enjoy-rust&quot;&gt;I enjoy Rust&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-enjoy-rust&quot; aria-label=&quot;Anchor link for: i-enjoy-rust&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;I actually enjoy using it so far. Next to going through the entire Book and the rustlings project, I have also applied
it to about half a year of Advent of Code challenges (with and without Python integration!), and I have also set up a
Rust runner for the upcoming Advent of SQL event (here are the &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.adventofsql.com&#x2F;&quot;&gt;event website&lt;&#x2F;a&gt; and
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;adventofsql&quot;&gt;my repo&lt;&#x2F;a&gt; for it). Even though for that latter Rust will just act as a
potential SQL runner, it will be interesting to see how that compares with my Python implementation for the bigger
challenges later on in the month.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;speed-impact-can-be-big&quot;&gt;Speed impact can be big&lt;a class=&quot;zola-anchor&quot; href=&quot;#speed-impact-can-be-big&quot; aria-label=&quot;Anchor link for: speed-impact-can-be-big&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The impact on the speed can be big. In the previous blog posts I have shown speed increases up to a factor of 1000
compared to my Python implementations (in which the quality of the Python implementation is a factor as well of course),
and in general in doing more Advent of Code challenges in both Rust and Python, I get about a times 10 increase in most
cases. Of course, it will depend on the specifics. The gain will be lower if the Python alternative is already written
in C or Rust itself, and also if you have to transfer&#x2F;convert a lot of data compared to the coding effort. In the latter
case, it might be worth it to find another spot for the switch to Rust, potentially even the entire task, to avoid any
Python-Rust communication delay.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keep-limitations-in-mind&quot;&gt;Keep limitations in mind&lt;a class=&quot;zola-anchor&quot; href=&quot;#keep-limitations-in-mind&quot; aria-label=&quot;Anchor link for: keep-limitations-in-mind&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;It is more work, not just to write, but also to maintain, extend, test, etc. Each time you will have to build, you will
have to wait a bit, and that might add up over time. There will be new packages to explore if you want to slowly extend
the Rust component in the project, which also takes time.&lt;&#x2F;p&gt;
&lt;p&gt;A potential big limitation depending on your work setup is the creation of multiplatform wheels, although I still have
to test the &lt;code&gt;ci_buildwheel&lt;&#x2F;code&gt; tool that in theory would overcome all those issues.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;type-of-projects-and-parts-where-this-might-work-best&quot;&gt;Type of projects and parts where this might work best&lt;a class=&quot;zola-anchor&quot; href=&quot;#type-of-projects-and-parts-where-this-might-work-best&quot; aria-label=&quot;Anchor link for: type-of-projects-and-parts-where-this-might-work-best&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;A list of project properties that could make using this easier:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is a clear core function that is used a lot but takes a lot of time, for which a potential time gain would
matter. This function is rarely updated since it just is what it is, but also has no Python implementation in C or Rust
available already.&lt;&#x2F;li&gt;
&lt;li&gt;This core function is already tested well with unit tests that will immediately also test the Rust implementation.&lt;&#x2F;li&gt;
&lt;li&gt;You use this internally in a controlled environment, such as in a project-specific Docker image - this immediately
skips most of the wheel issues.&lt;&#x2F;li&gt;
&lt;li&gt;Alternatively, you use this as part of a package that has only a few maintainers that need to coordinate on this, and
you can get the multiplatform (or the optional part) to work.&lt;&#x2F;li&gt;
&lt;li&gt;There is not already an expertise available in your team for implementing this functionality in C or other
alternatives instead. Of course, Rust can then still be an option as well.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;personal-plan-of-approach&quot;&gt;Personal plan of approach&lt;a class=&quot;zola-anchor&quot; href=&quot;#personal-plan-of-approach&quot; aria-label=&quot;Anchor link for: personal-plan-of-approach&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;So how do I plan to incorporate this into my coding work in the future? Some thoughts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;To maintain my Rust skill, I plan on regularly doing some coding challenge in Rust. This might be next to another
primary implementation or it might the only one. For example, I plan on doing the upcoming Advent of Code 2024 in
Python primarily, but secondarily in Rust as well, especially for days where I am curious on how that would work or
how much that would matter.&lt;&#x2F;li&gt;
&lt;li&gt;In my other side projects, I will stay on the lookout for functions that are noticably slow to see if I can speed
them up with Rust. In the case of &lt;code&gt;intervalues&lt;&#x2F;code&gt; in &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-03&quot;&gt;blog post 3&lt;&#x2F;a&gt; I simply really want to try it for
the experience; otherwise I don&#x27;t know if I would have explored it since I don&#x27;t know if it is very likely the practical
use cases of the package would involve such large datasets. But for other future side projects, who knows?&lt;&#x2F;li&gt;
&lt;li&gt;In my work as a Data Scientist &#x2F; Econometrician, Rust does not have a direct use for the key modeling components,
since either they are models for which run-time is not a factor (say, linear regressions or principal component
analyses), or there are dedicated Python packages that efficiently run this in some other optimized framework
(Tensorflow, JAX, Torch, etc; for stuff like neural networks and Bayesian MCMC models).&lt;&#x2F;li&gt;
&lt;li&gt;That doesn&#x27;t mean there can&#x27;t be a step in the data processing or postmodeling for which Rust can&#x27;t be used. In one
of my previous roles I worked on a product that had both a key Bayesian model and a key data matching step that would
generate input for that model. The latter is something I now think would gain a lot from being implemented in Rust,
especially since regularly there would be projects for which this step would be computationally more involved than the
actual model step.&lt;&#x2F;li&gt;
&lt;li&gt;In future endeavours I hope these situations will present themselves. I just have to make sure I keep this option in
the back of my mind, and make sure I don&#x27;t get rusty in Rust.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust in Python part 3: publish a Python package</title>
		<published>2024-11-03T00:00:00+00:00</published>
		<updated>2024-11-03T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/rust-python-03/" type="text/html"/>
		<id>https://debruijn.github.io/posts/rust-python-03/</id>
		<content type="html">&lt;p&gt;In the previous entries in this series, the concept of moving functionality from Python to Rust was illustrated using
examples out of real-life application. On this page, I want to talk about my experience of doing a similar addition to
my &lt;code&gt;intervalues&lt;&#x2F;code&gt; package, which can be found &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;intervalues&quot;&gt;here&lt;&#x2F;a&gt;. I will not fully discuss
the Rust implementation details, but just the overall learnings and suggestions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-intervalues&quot;&gt;What is intervalues?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-intervalues&quot; aria-label=&quot;Anchor link for: what-is-intervalues&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;intervalues&lt;&#x2F;code&gt; is a Python package aimed at processing valued intervals efficiently. With valued intervals, I mean
something like &quot;All values between 2 and 4, with a value of 3&quot;. Say you note this down as &lt;code&gt;[2-4; 3]&lt;&#x2F;code&gt;, and you have
any valued interval &lt;code&gt;[1-3; 2]&lt;&#x2F;code&gt;. Then you might want to add these together, which would produce the three valued
intervals &lt;code&gt;[1-2; 2]&lt;&#x2F;code&gt;, &lt;code&gt;[2-3; 5]&lt;&#x2F;code&gt; and &lt;code&gt;[3-4; 3]&lt;&#x2F;code&gt; that would summarize for each input the total value. Tasks like this
have popped up in some previous Advent of Code challenges, and I can imagine practical applications as well, with the
value part often being interpreted as &quot;counts&quot;. For example, how many planes are there on an airfield at any given time
for a recurring daily or weekly schedule? In that case, each input interval would be a 1-count interval with bounds set
to the landing and departure time of the plane. For planes that land at the end of the schedule and depart at the
beginning, there would be two intervals for both parts. Then, all these intervals could be combined to find the overlaps
and counts across the schedule in an exact and efficient way, which can be used to identify potential bottlenecks or
expansion opportunities.&lt;&#x2F;p&gt;
&lt;p&gt;Although other interval-themed Python packages exist, the &#x27;count&#x27; or &#x27;value&#x27; perspective of it was not represented.
Instead, these other packages are often limited to looking at it from a Set perspective, so finding either the union or
the intersection of the input intervals. Translated to the airfield example above: &quot;At what times is there at least
one plane on the airfield?&quot; and &quot;At what times are all scheduled planes on the airfield simultaneously?&quot;. These
questions can be useful as well (&quot;When should the airfield be open?&quot; for the first case for example) but could be
answered by &lt;code&gt;intervalues&lt;&#x2F;code&gt; as well by looking at all intervals with a count &amp;gt;= 1 for the first case, and all intervals
with the count equal to the number of planes for the second case.&lt;&#x2F;p&gt;
&lt;p&gt;The package provides functionality for all kinds of data management-like tasks you might want to do with one or more
intervals: adding together, shifting, finding the most-common interval in an interval collection, finding the value of
a particular input, etc.
At the core of this, there is an algorithm for combining the intervals together, appropriately called
&lt;code&gt;combine_intervals&lt;&#x2F;code&gt;. This algorithm is the key thing that could slow the package down in case of a huge dataset, and
because of that it is the key candidate to consider for porting over to Rust for a potential speed boost.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-rust-implementation&quot;&gt;The Rust implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-rust-implementation&quot; aria-label=&quot;Anchor link for: the-rust-implementation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Implementing &lt;code&gt;combine_intervals&lt;&#x2F;code&gt; in Rust was a task that I tackled from the core up. An interesting challenge in this
was that the types of the numbers have to be defined beforehand as Rust is a typed language. First, I avoided that by
implementing the function just for &lt;code&gt;isize&lt;&#x2F;code&gt; input for both the bounds and the value, and then I made variations of it
where either could be &lt;code&gt;f32&lt;&#x2F;code&gt; as well, as proof of concepts. It was good to start with this, because a potential blocker
quickly became apparent: the &lt;code&gt;combine_intervals&lt;&#x2F;code&gt; algorithm requires the bounds to be used as index in a &lt;code&gt;HashMap&lt;&#x2F;code&gt; (the
Rust version of a &lt;code&gt;dict&lt;&#x2F;code&gt; in Python) but the standard floats in Rust are not hashable. So first, this challenge had to
be solved, for which I ended up with two solutions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;using &lt;code&gt;Decimals&lt;&#x2F;code&gt; from &lt;code&gt;rust_decimals&lt;&#x2F;code&gt;, which is an alternative numeric implementation for (among other) floats&lt;&#x2F;li&gt;
&lt;li&gt;creating my own &lt;code&gt;intfloat&lt;&#x2F;code&gt; &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;intfloat&#x2F;&quot;&gt;package&lt;&#x2F;a&gt; and Struct, which is faster than Decimals but
also less reliable for accuracy
&lt;ul&gt;
&lt;li&gt;the issue with the latter is in how numbers are stored: as 2 integers, a base integer and a power-of-10 integer. In
the conversion of, say, 2 x 10^-4 back to a float there is a risk of a small error to be introduced, for example
to get 0.00020000001 instead of 0.0002. Since the &#x27;4&#x27; above is an input on the Python side, you can simply round it
again in Python to the same number of digits - but this might be a problem in a more generic use of &lt;code&gt;intfloat&lt;&#x2F;code&gt; so
in that case using &lt;code&gt;Decimals&lt;&#x2F;code&gt; might be smart.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then, as next steps I slowly generalized the functions by making use of the Numeric trait (if you don&#x27;t know about
Rust traits yet: don&#x27;t worry about it): first combining all integer inputs into one function call, and all float inputs
into another; and then generalizing that to end up with a single function that is reused across all potential input
types. It supports the above mentioned &lt;code&gt;Decimal&lt;&#x2F;code&gt; and &lt;code&gt;IntFloat&lt;&#x2F;code&gt; together with all default integer types.&lt;&#x2F;p&gt;
&lt;p&gt;At first, the combined result was just a &lt;code&gt;Vec&lt;&#x2F;code&gt; containing the relevant numeric values for each aggregated valued
subinterval. It simply made sense to also collect this in a well-defined Struct, and so also the Rust version of having
an IntervalCollection. Because of this, the Rust code is also available and usable by itself without Python on
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;intervalues&#x2F;&quot;&gt;crates.io&lt;&#x2F;a&gt;, although the main goal of the project remains the Python code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speed-comparison&quot;&gt;Speed comparison&lt;a class=&quot;zola-anchor&quot; href=&quot;#speed-comparison&quot; aria-label=&quot;Anchor link for: speed-comparison&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The main motivation of both the Rust version of &lt;code&gt;intervalues&lt;&#x2F;code&gt; and of the &lt;code&gt;intfloat&lt;&#x2F;code&gt; package is speed, so we need to
actually verify that both provide a speed boost compared to the Python version of &lt;code&gt;intervalues&lt;&#x2F;code&gt; and the &lt;code&gt;Decimals&lt;&#x2F;code&gt;
struct respectively.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;intfloat-vs-decimal&quot;&gt;Intfloat vs Decimal&lt;a class=&quot;zola-anchor&quot; href=&quot;#intfloat-vs-decimal&quot; aria-label=&quot;Anchor link for: intfloat-vs-decimal&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;For this comparison, I use the demo implementation of the &lt;code&gt;intervalues&lt;&#x2F;code&gt; Rust package in its &lt;code&gt;main.rs&lt;&#x2F;code&gt;. This runs 4
setups in which one million intervals are generated and combined, with its inputs being:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;i32&lt;&#x2F;code&gt; for both integer bounds and value -&amp;gt; runs in 38.1 ms&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;i32&lt;&#x2F;code&gt; for integer bounds and &lt;code&gt;Decimal&lt;&#x2F;code&gt; for float value -&amp;gt; runs in 60.6 ms&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Decimal&lt;&#x2F;code&gt; for both float bounds and value -&amp;gt; runs in 143.6 ms&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;IntFloat&lt;&#x2F;code&gt; for both float bounds and value -&amp;gt; runs in 68.4 ms&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This shows that using &lt;code&gt;IntFloat&lt;&#x2F;code&gt; is roughly twice as slow as using &lt;code&gt;i32&lt;&#x2F;code&gt; but twice as fast as using &lt;code&gt;Decimal&lt;&#x2F;code&gt;, at least
for this setup. On the one hand, this shows the added value of the existence of &lt;code&gt;IntFloat&lt;&#x2F;code&gt;. On the other hand, in the
rare situation you would need to combine one million intervals, having to wait 0.1s is not too bad, so &lt;code&gt;Decimal&lt;&#x2F;code&gt; is
still a good option even if it&#x27;s the slowest.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;combine-intervals-python-vs-rust&quot;&gt;combine_intervals: Python vs Rust&lt;a class=&quot;zola-anchor&quot; href=&quot;#combine-intervals-python-vs-rust&quot; aria-label=&quot;Anchor link for: combine-intervals-python-vs-rust&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;For the secondary speed check, I had to make my Rust package available for Python again using maturin, and then
make a wrapper to use either the Python or the Rust implementation depending on some input flag. To test for speed,
I added an example script that runs both of them, for both integer and float inputs.&lt;&#x2F;p&gt;
&lt;p&gt;The results are (for one million intervals) as follows:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;integers: 1774 ms (Python) vs 900 ms (Rust)&lt;&#x2F;li&gt;
&lt;li&gt;floats: 1976 ms (Python) vs 857 ms (Rust)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This pattern holds for smaller number of intervals as well: Rust is about as fast for integers and floats whereas Python
is about twice as slow for integers, and a bit extra slow for floats. Also note that this call of Rust via Python is
significantly slower than the 38.1ms or 68.4ms for the same setup in pure Rust above. Again the same two factors appear
like in the previous entry in this blog series: there is the extra overhead of code that is needed to get this
translation to work, and next to that there are a million intervals (so 3 million values) that needs to be transferred
from Python to Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Together, this shows that for the Python package, the Rust implementation of the core functionality can result in a
good speedup, but that it is also worthwhile to maintain the pure Rust version of the package for cases where extra
speed is absolutely critical. Having it confirmed that all these efforts are worth it, now we move on to the next step:
including the Rust code in my published PyPI package as well.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-a-python-package-with-rust-code&quot;&gt;Building a Python package with Rust code&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-a-python-package-with-rust-code&quot; aria-label=&quot;Anchor link for: building-a-python-package-with-rust-code&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In order to build &lt;code&gt;intervalues&lt;&#x2F;code&gt; with the Rust code in it as well in the way I did it, there were a few things I had
to do:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Update my &lt;code&gt;pyproject.toml&lt;&#x2F;code&gt; to include &lt;code&gt;setuptools-rust&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Add a rust folder to my Python repo with a Rust-to-Python wrapper in it&lt;&#x2F;li&gt;
&lt;li&gt;Add a MANIFEST.in to make the build process aware of the above files&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s go over them one by one!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;updating-pyproject-toml&quot;&gt;Updating pyproject.toml&lt;a class=&quot;zola-anchor&quot; href=&quot;#updating-pyproject-toml&quot; aria-label=&quot;Anchor link for: updating-pyproject-toml&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;To adjust the build process to make use of the Rust packages as well, we need to update the file that is the input to
the build process: &lt;code&gt;pyproject.toml&lt;&#x2F;code&gt; (of an alternative to that if you use it). In this toml, we need to update the
&lt;code&gt;build-system&lt;&#x2F;code&gt; section:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;build-system&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;requires&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;setuptools&amp;gt;=61.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-array z-toml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;setuptools-rust&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;build-backend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;setuptools.build_meta&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also, we need to add a new section specifically for &lt;code&gt;setuptools-rust&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-array z-begin z-toml&quot;&gt;[[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-array z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;tool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;setuptools-rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;ext-modules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-array z-end z-toml&quot;&gt;]]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Private Rust extension module to be nested into the Python package&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;intervalues_pyrust&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;   &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Name of the package&#x2F;module as defined in Cargo.toml&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;rust&#x2F;Cargo.toml&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;        &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; The location of the Cargo.toml&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;binding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;PyO3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;                &lt;span class=&quot;z-comment z-line z-number-sign z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-toml&quot;&gt;#&lt;&#x2F;span&gt; Default value, can be omitted&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see here already a peak of the name and location of the rust files in the next subsection. Next to this, you
can specify which binding to use, which is here defined as the default &lt;code&gt;PyO3&lt;&#x2F;code&gt; (which is that same technology as what
maturin uses).&lt;&#x2F;p&gt;
&lt;p&gt;Finally, an issue I encountered was that I specified my version in a &lt;code&gt;version.py&lt;&#x2F;code&gt;. For my setup, this will not work,
since the python modules can&#x27;t be imported before the rust-wrapper has been made available to Python. If you are in the
same situation, you have two basic choices: overhaul your code to delay the import of the rust wrapper, or instead put
your version information in a non-Python file. I have chosen the latter using the good old &lt;code&gt;VERSION&lt;&#x2F;code&gt; setup:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;tool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;setuptools&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;dynamic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-inline-table z-begin z-toml&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;VERSION&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-inline-table z-end z-toml&quot;&gt;}&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;add-a-rust-folder-with-the-wrapper-functionality&quot;&gt;Add a rust folder with the wrapper functionality&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-a-rust-folder-with-the-wrapper-functionality&quot; aria-label=&quot;Anchor link for: add-a-rust-folder-with-the-wrapper-functionality&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;I created a very simple &lt;code&gt;rust&lt;&#x2F;code&gt; folder in the root of my Python repository containing (in essence) not much more than
a &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; and a &lt;code&gt;src&#x2F;lib.rs&lt;&#x2F;code&gt; file with all its functionality. In the &lt;code&gt;lib.rs&lt;&#x2F;code&gt; file the two &lt;code&gt;combine_intervals&lt;&#x2F;code&gt;
functions for int and float input are defined, which both call the same &lt;code&gt;combine_intervals&lt;&#x2F;code&gt; from the actual Rust
&lt;code&gt;intervalues&lt;&#x2F;code&gt; package but with different before steps (the ints are &lt;code&gt;isize&lt;&#x2F;code&gt;, whereas the floats are converted to
&lt;code&gt;IntFloat&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;This is confirmed by the associated &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; as well, which is setup using the same changes as needed for a Maturin
build: the &lt;code&gt;dependencies.pyo3&lt;&#x2F;code&gt; section with the specified ABI, the &lt;code&gt;crate_type&lt;&#x2F;code&gt; being set to &lt;code&gt;cdylib&lt;&#x2F;code&gt;, and the
&lt;code&gt;opt-level&lt;&#x2F;code&gt; set to 3. Next to that, it has dependencies set to the main &lt;code&gt;intervalues&lt;&#x2F;code&gt; and &lt;code&gt;intfloat&lt;&#x2F;code&gt; since it uses
them both (and also &lt;code&gt;itertools&lt;&#x2F;code&gt;). The name is specified as &lt;code&gt;intervalues_pyrust&lt;&#x2F;code&gt; in both the package and lib section
of the toml.&lt;&#x2F;p&gt;
&lt;p&gt;Note that these two files are all that is technically needed (plus the automatically generated &lt;code&gt;Cargo.lock&lt;&#x2F;code&gt;), but I also
included a LICENSE and README.md file for publishing this &lt;code&gt;intervalues_pyrust&lt;&#x2F;code&gt; to crates.io as well, and a separate
&lt;code&gt;pyproject.toml&lt;&#x2F;code&gt; with all the Maturin-specific definitions in case I want to try out something quickly without fully
building the Python wheel.&lt;&#x2F;p&gt;
&lt;p&gt;Why all of this work for this separate wrapper with a new name? A couple of reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I wanted to split the Rust and Python work as much as possible in separate repositories.&lt;&#x2F;li&gt;
&lt;li&gt;I also wanted to split the functionality of the pure Rust version and the wrapper, such that I can individually
maintain and update those&lt;&#x2F;li&gt;
&lt;li&gt;With the default &lt;code&gt;intervalues&lt;&#x2F;code&gt; name for the rust package, there was some potential for conflict with the folder with
my Python code having the same name (and during the Maturin test phase, this really was an issue). Of course, I can also
just rename that folder without impacting the name of the package, but I prefer not to overhaul the Python part due to
some non-Python reason.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I didn&#x27;t have to publish this &lt;code&gt;intervalues_pyrust&lt;&#x2F;code&gt; on crates.io as well, but I felt like doing that anyway, at the very
least to claim that name.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;add-a-manifest-in-file&quot;&gt;Add a MANIFEST.in file&lt;a class=&quot;zola-anchor&quot; href=&quot;#add-a-manifest-in-file&quot; aria-label=&quot;Anchor link for: add-a-manifest-in-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, the shortest addition is a MANIFEST.in file at the project root. This file will make sure the build process
can find and use the files in the rust folder. It is in my case defined as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include rust&#x2F;Cargo.toml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;recursive-include rust&#x2F; *.rs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The result of all this is a buildable Python wheel that contains the Rust code. Before uploading to PyPI I did the basic
checks: can I install it locally on my system? Can I install it in a Docker image? In both cases, can I also use it to
run the Rust specific functions? All systems were go, so let&#x27;s publish to PyPI using twine like I normally do. And then
it happens: the error that I can&#x27;t upload my wheel because it is compiled specifically for my system. (Like the issue
described &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;59451069&#x2F;binary-wheel-cant-be-uploaded-on-pypi-using-twine&quot;&gt;here&lt;&#x2F;a&gt; on
StackOverflow).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;publishing-a-python-package-with-rust-code&quot;&gt;Publishing a Python package with Rust code&lt;a class=&quot;zola-anchor&quot; href=&quot;#publishing-a-python-package-with-rust-code&quot; aria-label=&quot;Anchor link for: publishing-a-python-package-with-rust-code&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;So, the main lesson from the problem above: by compiling my Rust code, I can&#x27;t share it in the same way I can share my
Python packages. Since &quot;normal&quot; &lt;code&gt;intervalues&lt;&#x2F;code&gt; is written in Pure Python, it can be made available in the broadest way
possible, with the only restriction due to me using some syntax introduced in Python 3.10. But now, in the way I have
build my Python&amp;amp;Rust combined &lt;code&gt;intervalues&lt;&#x2F;code&gt;, it can only be used on a Linux system setup similar to mine, and that is
not acceptable for PyPI.&lt;&#x2F;p&gt;
&lt;p&gt;So, how to solve this? Like mentioned on the StackOverflow link above, for this we can use the &lt;code&gt;manylinux&lt;&#x2F;code&gt; project and
the &lt;code&gt;auditwheel&lt;&#x2F;code&gt; tool.&lt;&#x2F;p&gt;
&lt;p&gt;This project has as goal to make tools available that will make it you can build a Python package with
compiled code and still make it available across &quot;many linux setups&quot; (hence the name). They do this by offering Docker
images that have been configured with compiler toolchains from some time ago, making sure that all recent Linux
distributions support the output of it. They offer multiple versions depending on how far back you want to go.&lt;&#x2F;p&gt;
&lt;p&gt;One of the other software in these Docker images is the &lt;code&gt;auditwheel&lt;&#x2F;code&gt; tool to be used to make sure the wheels that are
built indeed conform to all requirements needed for uploading to PyPI.&lt;&#x2F;p&gt;
&lt;p&gt;In order to use this, download the &lt;code&gt;build-wheels.sh&lt;&#x2F;code&gt; file on
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;setuptools-rust.readthedocs.io&#x2F;en&#x2F;latest&#x2F;building_wheels.html&quot;&gt;this link&lt;&#x2F;a&gt; and adjust it to your project needs.
For &lt;code&gt;intervalues&lt;&#x2F;code&gt; you can see this in the &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;intervalues&quot;&gt;repository&lt;&#x2F;a&gt;. My adjustments are
to target Python 3.10 and up, together with Pypy 3.10. Next to that, of course, I had to adjust the example project
name to &lt;code&gt;intervalues&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then, to use this with the Docker image, pull the one you want to use (e.g.
&lt;code&gt;docker pull quay.io&#x2F;pypa&#x2F;manylinux2014_x86_64&lt;&#x2F;code&gt;) and from the project root run the script above using this Docker image
with the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;docker run --rm -v `pwd`:&#x2F;io quay.io&#x2F;pypa&#x2F;manylinux2014_x86_64 bash &#x2F;io&#x2F;build-wheels.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that this will take more time than a normal Python package build, because it will do the build and checks for all
specified versions of CPython and PyPy. The result is also a set of wheels for each of these, instead of a single one
for Python in general. These need to all be uploaded to PyPI to make available for installation.&lt;&#x2F;p&gt;
&lt;p&gt;But then after all this.. it works! I can &lt;code&gt;pip install&lt;&#x2F;code&gt; the new version of &lt;code&gt;intervalues&lt;&#x2F;code&gt; and make use of the Rust
functionality in both Python 3.10 and PyPy 3.10. The only downside is that it is now (afaik) Linux specific: this newest
version (as of writing) can&#x27;t be installed on Windows whereas the version before can. I can&#x27;t verify this since I don&#x27;t
have a Windows box available right now, but this is what I have been able to gather from what I read about it. To be
honest, I personally don&#x27;t really care about that. But if there is an &lt;code&gt;intervalues&lt;&#x2F;code&gt; user who wants me to find out if&#x2F;how
it can still be used on Windows even with this Rust functionality, let me know (or, of course, submit a PR yourself).
Alternatively, the old version still works on Windows and there are no real changes from that version to this one
outside of the Rust wrapper.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alternative-setups&quot;&gt;Alternative setups&lt;a class=&quot;zola-anchor&quot; href=&quot;#alternative-setups&quot; aria-label=&quot;Anchor link for: alternative-setups&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There are several alternatives to consider to some of the steps that I have taken, which I might experiment with in the
future. Experiences from readers are also welcome, especially if these alternatives work really good or really bad.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Maturin allows you to directly publish the Python package with Rust functionality using &lt;code&gt;maturin publish&lt;&#x2F;code&gt; instead of
&lt;code&gt;maturin develop&lt;&#x2F;code&gt;. I have not tried this, so I don&#x27;t know whether the result is OS-agnostic or if it uses some kind of
&lt;code&gt;manylinux&lt;&#x2F;code&gt; restriction as well, or something else. Also, this feels like it would make most sense if the wrapper was
included in the base Rust &lt;code&gt;intervalues&lt;&#x2F;code&gt; package, since it will introduce another package itself (a Python package that
the main Python &lt;code&gt;intervalues&lt;&#x2F;code&gt; package can include as a dependency).&lt;&#x2F;li&gt;
&lt;li&gt;I want to look into how to make the Rust component optional, and if that makes the core Python functionality still
usable on Windows.
&lt;ul&gt;
&lt;li&gt;I could (either by using Maturin as above, or manually) publish the Python side of the Python&#x2F;Rust layer separately
from the rest of the Python code, and make it an optional dependency of the main &lt;code&gt;intervalues&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Perhaps there also other ways of doing this&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Ideally, I want to have the Rust setup also usable on Windows. Like discussed in the previous section, I will likely
not look into this myself until a Windows user requests this, especially if I can figure out how to create non-Rust
future versions as well that are more universally usable.
&lt;ul&gt;
&lt;li&gt;Probably the first candidate to explore for this functionality is to use the &lt;code&gt;cibuildwheel&lt;&#x2F;code&gt; as mentioned in the
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;setuptools-rust.readthedocs.io&#x2F;en&#x2F;latest&#x2F;building_wheels.html&quot;&gt;setuptools-rust&lt;&#x2F;a&gt; docs as well.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Let me know if you have other suggestions as well for how to best set this up!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Depending on these investigations and&#x2F;or suggestions, there might be a future entry in this series to discuss them. But
for now, the next (and potentially final) entry in this series will be on my
&lt;a href=&quot;&#x2F;posts&#x2F;rust-python-04&quot;&gt;overall learnings and experience&lt;&#x2F;a&gt; of using Rust in Python. Alternatively, have a look at some of the
links down below for further reading.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;a class=&quot;zola-anchor&quot; href=&quot;#links&quot; aria-label=&quot;Anchor link for: links&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Some of the other Python interval packages:
&lt;ul&gt;
&lt;li&gt;portion&lt;&#x2F;li&gt;
&lt;li&gt;pyinterval&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;My repo&#x27;s and packages related to intervals:
&lt;ul&gt;
&lt;li&gt;Python intervalues: &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;intervalues&quot;&gt;github&lt;&#x2F;a&gt; and &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;intervalues&#x2F;&quot;&gt;PyPI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Rust intervalues: &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;intervalues_rust&quot;&gt;github&lt;&#x2F;a&gt; and &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;intervalues&#x2F;&quot;&gt;crates.io&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;intervalues_pyrust: &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;intervalues_pyrust&quot;&gt;crates.io&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;intfloat: &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;intfloat&quot;&gt;github&lt;&#x2F;a&gt; and &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;intfloat&#x2F;&quot;&gt;crates.io&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;More resources on setuptools-rust:
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;setuptools-rust.readthedocs.io&#x2F;en&#x2F;latest&#x2F;README.html&quot;&gt;Overall doc on setuptools-rust&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;setuptools-rust.readthedocs.io&#x2F;en&#x2F;latest&#x2F;setuppy_tutorial.html&quot;&gt;If you want to use setup.py instead of pyproject.toml&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;setuptools-rust.readthedocs.io&#x2F;en&#x2F;latest&#x2F;building_wheels.html&quot;&gt;Building wheels&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;More resources on manylinux and auditwheel:
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pypa&#x2F;manylinux&quot;&gt;The manylinux repository&lt;&#x2F;a&gt; with details on what the different &lt;code&gt;manylinux&lt;&#x2F;code&gt;
versions imply for Python and distribution support.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pypa&#x2F;auditwheel&quot;&gt;The auditwheel tool&lt;&#x2F;a&gt; showing examples of other commands that can be supplied
to it, for example for only checking (not repairing) existing wheels for PyPI compatibility.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust in Python part 2: more detailed example</title>
		<published>2024-10-30T00:00:00+00:00</published>
		<updated>2024-10-30T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/rust-python-02/" type="text/html"/>
		<id>https://debruijn.github.io/posts/rust-python-02/</id>
		<content type="html">&lt;p&gt;After the instructions on setting up Maturin for the &quot;simple&quot; Fibonacci example, you might have questions how well this
generalizes to bigger actual problems. Of course, the answer will be &quot;it depends&quot;, and to get some more intuition on
what it might depend on, let&#x27;s first look into a bigger example that is still not an actual problem: day 5 of Advent
of Code 2018.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-is-advent-of-code&quot;&gt;What is Advent of Code?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-advent-of-code&quot; aria-label=&quot;Anchor link for: what-is-advent-of-code&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;First, in case you don&#x27;t know: what is &lt;a href=&quot;https:&#x2F;&#x2F;debruijn.github.io&#x2F;posts&#x2F;rust-python-02&#x2F;www.adventofcode.com&quot;&gt;Advent of Code&lt;&#x2F;a&gt;? It is a yearly fun coding event in which
every day gives a new two-part programming puzzle to solve for all days from December 1st to 25th. Sometimes the
problems themselves are already the challenge to solve (like finding a good algorithm with the right assumptions -
that would be mostly language-agnostic). But other days, especially in the beginning, can be easy or difficult
depending on what restrictions you put on yourself. Throughout my participation, I had several phases of my focus:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Pure Python&quot; focus, after years of mostly working in pandas and numpy for these kind of steps&lt;&#x2F;li&gt;
&lt;li&gt;Integrating more and more of itertools, functools and collections into my solutions&lt;&#x2F;li&gt;
&lt;li&gt;Getting all the backlog of old years (before I joined) done&lt;&#x2F;li&gt;
&lt;li&gt;Converting some of these puzzles to pure Rust or Rust-in-Python versions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can see that there can be plenty of ways to approach this, depending on what you want to improve. Do you want to
write very clean code to make sure you are used to that for work-related coding tasks? Feel free to do that. Do you
instead want to write the most unreadable, undocumented code ever, simply because you can? Sure, go ahead. I would set
a goal and&#x2F;or some restrictions in order to learn or develop some skills, but don&#x27;t make it to hard since it should
also still be something you can find fun.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-what-is-the-problem-on-day-5-of-2018&quot;&gt;So.. what is the problem on day 5 of 2018?&lt;a class=&quot;zola-anchor&quot; href=&quot;#so-what-is-the-problem-on-day-5-of-2018&quot; aria-label=&quot;Anchor link for: so-what-is-the-problem-on-day-5-of-2018&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Of course, if you plan on still doing the 2018 run of the event, this page will contain spoilers. I don&#x27;t think this
matters much for day 5, but reading on is your own choice.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;debruijn.github.io&#x2F;posts&#x2F;rust-python-02&#x2F;www.adventofcode.com&#x2F;2018&#x2F;day&#x2F;5&quot;&gt;Day 5&lt;&#x2F;a&gt; deals with a fictional version of polymerization, which is represented here by
a long string of letters being reduced by removing subsequent lowercase and uppercase letters of the same type (so
&#x27;Aa&#x27; or &#x27;rR&#x27;). After removing one such combination, the surrounding letters might form a new pair that can be removed.
At some point, no letters remain that are immediately next to the same letter but in the opposite case, and the length
of that result gives the answer... for part a.&lt;&#x2F;p&gt;
&lt;p&gt;Like I said in the introduction of Advent of Code, each puzzle consists of two parts, and part b is often similar to
part a but with a twist that makes it more complicated, exponentially bigger, or something else. In this case: what is
the shortest final reduced string length you get if in the starting string all letters (upper and lowercase) of a single
letter of the alfabet was removed. For example, all p&#x27;s and P&#x27;s would be removed before the start of the procedure
above. Out of all possible letters to remove, the one that seemed to be the biggest blocker is the one that will lead
to the answer for this part.&lt;&#x2F;p&gt;
&lt;p&gt;This basically means that the same &#x27;polymerization&#x27; step needs to be done 27 times: once in part a, and 26 times
in part b, once for each letter in the alfabet. Next to that, the majority of the compute time is in the call to that
function. Also, as I will show in the next section, the Python code was not really efficient (from a run-time
perspective) which means that significant gains can be made. That makes this a good situation for potential gains by
replacing this function with a Rust implementation. But let&#x27;s first have a look at the Python code we start out with..&lt;&#x2F;p&gt;
&lt;h3 id=&quot;initial-python-implementation&quot;&gt;Initial Python implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#initial-python-implementation&quot; aria-label=&quot;Anchor link for: initial-python-implementation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The initial Python implementation for the polymerization step was programmed just in the context of the Advent of Code
event. Especially for the initial days of a year, my personal goal is to just get through them. In most cases I will
have a vague side goal of having decent performance, but in this particular case I skipped that since running this
using Python 3.10 takes about 9 seconds (and using PyPy takes about 7.5 seconds). For whatever reason, I chose to not
speed this up, even though I can see things that I could have done. This makes this a good candidate for replacing this
part of the code with a Rust implementation.&lt;&#x2F;p&gt;
&lt;p&gt;So what was my initial Python implementation?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python z-code&quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-function z-python&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-python&quot;&gt;&lt;span class=&quot;z-keyword z-declaration z-function z-python&quot;&gt;def&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;run_polymerization&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-python&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;stop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-python&quot;&gt;False&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;curr_len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-statement z-loop z-while z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-while z-python&quot;&gt;while&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt;not&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;stop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-loop z-while z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;        &lt;span class=&quot;z-meta z-statement z-loop z-for z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-for z-python&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pair&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-for z-in z-python&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-loop z-for z-python&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pairwise&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-loop z-for z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-loop z-for z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;            &lt;span class=&quot;z-meta z-statement z-conditional z-if z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-python&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;ord&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pair&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-arguments z-python&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;ord&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pair&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-arguments z-python&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-python&quot;&gt;in&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-sequence z-list z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-conditional z-if z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;                &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pair&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-arguments z-python&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;pair&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-arguments z-python&quot;&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-item-access z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-brackets z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;        &lt;span class=&quot;z-meta z-statement z-conditional z-if z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-python&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-python&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;curr_len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-conditional z-if z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;            &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;stop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-python&quot;&gt;True&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;        &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;curr_len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;polymer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-return z-python&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;curr_len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some notes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The variable &lt;code&gt;polymer&lt;&#x2F;code&gt; contains the string we try to collapse.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;pairwise&lt;&#x2F;code&gt; refers to &lt;code&gt;itertools.pairwise&lt;&#x2F;code&gt; which loops over a iterable by presenting two subsequent elements in a
tuple, e.g. pairwise(&quot;abcd&quot;) -&amp;gt; (&#x27;a&#x27;, b&#x27;), (&#x27;b&#x27;, &#x27;c&#x27;), (&#x27;c&#x27;, &#x27;d&#x27;)&lt;&#x2F;li&gt;
&lt;li&gt;To check if there is a pair, I converted the characters to their Unicode representation using &lt;code&gt;ord(.)&lt;&#x2F;code&gt;. The difference
between an uppercase and a lowercase letter is 32.
&lt;ul&gt;
&lt;li&gt;Note that this implicitly uses the assumption that the string only contains letters, otherwise there would be other
Unicode representations that can differ 32 from a letter. Example: ord(&#x27;A&#x27;) = 65 and ord(&#x27;a&#x27;) = 97, but ord(&#x27;!&#x27;) =
33, so not just the pair &#x27;Aa&#x27; would be detected but also the pair &#x27;A!&#x27; would be removed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;I iterate on this in the while loop until there are no changes anymore, and then the length of the remaining polymer
is returned.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Fairly straightforward, but also some optimizations could be done. But we are not here to be smart, at least not in that
way. Let&#x27;s see what we can gain by reimplementing in Rust!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;doing-the-core-calculations-in-rust&quot;&gt;Doing the core calculations in Rust&lt;a class=&quot;zola-anchor&quot; href=&quot;#doing-the-core-calculations-in-rust&quot; aria-label=&quot;Anchor link for: doing-the-core-calculations-in-rust&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Reimplementing this in Rust, I initially came up with this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;pyfunction&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;run_polymerization_u8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-lifetime z-rust&quot;&gt;&amp;#39;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;&lt;span class=&quot;z-support z-type z-rust&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-rust&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;mut&lt;&#x2F;span&gt; v &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;new&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;c &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;in&lt;&#x2F;span&gt; input&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;match&lt;&#x2F;span&gt; v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;last&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-support z-type z-rust&quot;&gt;None&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-bitwise z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; d&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;to_ascii_lowercase&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; c&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;to_ascii_lowercase&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; d &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;!=&lt;&#x2F;span&gt; c &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;pop&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                    v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;                &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;            &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    v&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This follows a different approach than in Python since I did not know of a good &lt;code&gt;pairwise&lt;&#x2F;code&gt; alternative:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I build up the vector (e.g. the polymer) that would result after the process in variable &lt;code&gt;v&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;For each entry that I get from the input, I compare it to the last entry in &lt;code&gt;v&lt;&#x2F;code&gt; to see if it would collapse&lt;&#x2F;li&gt;
&lt;li&gt;The collapse I do with a &lt;code&gt;match&lt;&#x2F;code&gt; statement:
&lt;ul&gt;
&lt;li&gt;if there is a &lt;code&gt;v.last()&lt;&#x2F;code&gt; and converted to lowercase it is the same but otherwise not (e.g. one is lowercase and the
other is uppercase of the same letter), then that last element of &lt;code&gt;v&lt;&#x2F;code&gt; is removed (popped)&lt;&#x2F;li&gt;
&lt;li&gt;otherwise (so either there is no &lt;code&gt;v.last()&lt;&#x2F;code&gt; or this one is a different letter or the same letter in the same case),
then instead add (push) the new element to &lt;code&gt;v&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;When all elements in input are processed, &lt;code&gt;v&lt;&#x2F;code&gt; is stable and I return its length.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Would this implementation in Python be faster as well? Probably, but not to the extend that this one is (see next
section). Alternatively, a keen eye might have spotted that the input is already converted to u8 (e.g. &#x27;encoded&#x27; in
Python), which I have later on tested to confirm that it has no noticable impact on runtime.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;run-time-comparison-incl-a-full-rust-implementation&quot;&gt;Run-time comparison, incl a full Rust implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#run-time-comparison-incl-a-full-rust-implementation&quot; aria-label=&quot;Anchor link for: run-time-comparison-incl-a-full-rust-implementation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The above Rust-function is made accessible with a &lt;code&gt;wrap_pyfunction&lt;&#x2F;code&gt; statement and can be imported in Python (see
&lt;code&gt;aoc_2018&#x2F;aoc_rust_2018&#x2F;src&#x2F;lib.rs&lt;&#x2F;code&gt; in my &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;adventofcode&quot;&gt;advent of code&lt;&#x2F;a&gt; repository for
details on that). Then, after adjusting my Python function (&lt;code&gt;aoc_2018&#x2F;aoc_5.py&lt;&#x2F;code&gt; in the above repository) to alternatively
make use of that version of &lt;code&gt;run_polymerization&lt;&#x2F;code&gt;, the runtimes can be compared:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pure Python: 9.07s&lt;&#x2F;li&gt;
&lt;li&gt;PyPy: 7.55s&lt;&#x2F;li&gt;
&lt;li&gt;Rust-in-Python: 0.09s&lt;&#x2F;li&gt;
&lt;li&gt;Pure Rust: 0.0082s&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This also includes a pure Rust implementation, which is out of scope for these series of blog posts, but for which the
details can also be seen in the above repository. Some insights from this example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is a massive gain from going from pure Python to using Rust for the calculations&lt;&#x2F;li&gt;
&lt;li&gt;There is another massive gain from using Rust for everything. This is due to 2 reasons:
&lt;ul&gt;
&lt;li&gt;My Python wrapper that I use for orchestrating my function executions does more unrelated stuff in its importing and
printing of the results than the Rust wrapper.&lt;&#x2F;li&gt;
&lt;li&gt;Passing the 50000 character String over from Python to Rust is not for free&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That last point is an important factor to keep in mind in determing the best spot for passing the work over to Rust:
if your implementation requires a lot of copy-overhead, it might be slower than if you put it slightly before or after
that point and you only pass over a small digit. In this case: it is faster to let Rust read in the file than to let
Python read in the file and pass it over, because then you are sort-of reading it in twice. How much this matters in
practice depends on details.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;additional-tweaks-or-just-compilation-flags-if-no-other-pops-up-not-mentioned-on-previous-page-since-it-didn-t-work-there&quot;&gt;Additional tweaks (or just compilation flags if no other pops up + not mentioned on previous page since it didn&#x27;t work there)&lt;a class=&quot;zola-anchor&quot; href=&quot;#additional-tweaks-or-just-compilation-flags-if-no-other-pops-up-not-mentioned-on-previous-page-since-it-didn-t-work-there&quot; aria-label=&quot;Anchor link for: additional-tweaks-or-just-compilation-flags-if-no-other-pops-up-not-mentioned-on-previous-page-since-it-didn-t-work-there&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Without much effort, there is another speed increase that can be gained in Rust by setting the compilation flag to 3 in
your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;opt-level&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-toml&quot;&gt;3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;opt-level&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-toml&quot;&gt;3&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The compilation optimization level determines how much effort the compiler will put into trying to optimize the result
for execution speed. By default, the dev flag is 0 while the release flag is 3, but you can set it using the setup
above to any value from 0 to 3. Often, for more complicated projects, a level of 2 or 3 can be significantly faster
than a level of 0. Whether 2 or 3 is the fastest can depend on details (the compiler can try to &quot;overoptimize&quot; on level
3), so it&#x27;s good to try both when performance is critical.&lt;&#x2F;p&gt;
&lt;p&gt;After applying level 3 to the comparison above:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust-in-Python: 0.01s instead of 0.09s&lt;&#x2F;li&gt;
&lt;li&gt;Pure Rust: 0.0081s instead of 0.0082s&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In this particular case, there is almost no gain in the pure Rust implementation, but in the Rust-in-Python one there is
a very significant increase bringing it much closer to the pure Rust version. Apparently, in the Maturin or Py03 wrapper
there is some code that the compiler can optimize well.&lt;&#x2F;p&gt;
&lt;p&gt;Note that for the Fibonacci example I did not touch this compiler flag. This is because in that case it does not matter
at all, even for the Rust-in-Python version: in that particular case, the code is already so straightforward that the
level-0 compilation is (close to) optimal. This shows that the complexity of the code can be a factor in how much the
compiler can gain by these extra levels of optimization. So how does that show itself when looking at the performance
of an actual Python package? Let&#x27;s have a look at the &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-03&quot;&gt;next entry&lt;&#x2F;a&gt; in this series, or have a
look at some of the links below for further background reading.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;links&quot;&gt;Links&lt;a class=&quot;zola-anchor&quot; href=&quot;#links&quot; aria-label=&quot;Anchor link for: links&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;debruijn.github.io&#x2F;posts&#x2F;rust-python-02&#x2F;www.adventofcode.com&quot;&gt;Advent of Code&lt;&#x2F;a&gt; website&lt;&#x2F;li&gt;
&lt;li&gt;My Advent of Code &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;adventofcode&quot;&gt;personal repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The section in the Rust book that discusses compiler flags in more detail is
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch14-01-release-profiles.html&quot;&gt;section 14.1&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust in Python part 1: getting started</title>
		<published>2024-10-23T00:00:00+00:00</published>
		<updated>2024-10-23T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/rust-python-01/" type="text/html"/>
		<id>https://debruijn.github.io/posts/rust-python-01/</id>
		<content type="html">&lt;p&gt;On this page, I will talk you through how to get started with using Rust in Python. For this, I will assume you know
some basic components of Python (defining a function, importing a package, etc). To add on that, this page will present:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust, &amp;amp; how to get started with that up to a sufficient level for the goal of a single Python function call&lt;&#x2F;li&gt;
&lt;li&gt;An example Python project&lt;&#x2F;li&gt;
&lt;li&gt;The same functionality written in Rust&lt;&#x2F;li&gt;
&lt;li&gt;How to compile and expose Rust code for use in Python&lt;&#x2F;li&gt;
&lt;li&gt;How to adjust Python code to use this Rust code&lt;&#x2F;li&gt;
&lt;li&gt;Comparison of run time&lt;&#x2F;li&gt;
&lt;li&gt;More links and references&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The goal of this is to present a single solution that you can just copy to get started. Later on I will introduce some
choices and alternatives that you might consider, but I want you to get to the power Rust from Python as fast as
possible. So let&#x27;s dive in!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-started-with-rust&quot;&gt;Getting started with Rust&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-started-with-rust&quot; aria-label=&quot;Anchor link for: getting-started-with-rust&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If you are 100% new to Rust (like I was a couple of weeks ago), there are two things you need to do to get started up
to the level needed for this blog series: install Rust, and learn some basic Rust. For both of these, I suggest to
follow &quot;The Book&quot; of Rust &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;title-page.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To install Rust, follow instructions on &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch01-01-installation.html&quot;&gt;section 1.1&lt;&#x2F;a&gt; of the
book. In case you are using Linux like I do, that amounts to running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;curl --proto &amp;#39;=https&amp;#39; --tlsv1.2 https:&#x2F;&#x2F;sh.rustup.rs -sSf | sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This downloads a shell script that installs the &lt;code&gt;rustup&lt;&#x2F;code&gt; tool which is used to maintain versions of Rust. More details
can be found on the linked page.&lt;&#x2F;p&gt;
&lt;p&gt;The next step is to &quot;just learn Rust&quot;. But don&#x27;t feel that this is too big of a hurdle! As mentioned on the introduction
page, you don&#x27;t need to know all concepts of the Rust language to get to a stage where you can already replace a
specific Python function with Rust calculations - often the ones for which this matter the most can be written using the
most basic components of the language. More complicated stuff will only be relevant when more of your codebase will be
written in Rust, which will come later together with learning those details later.&lt;&#x2F;p&gt;
&lt;p&gt;So to get that basic level of Rust as needed for this series, continue reading &quot;The Book&quot; up to (and including)
chapter 4. This means you will learn about how to compile and run a piece of Rust code, how to work with variables,
functions, if-statements, for-loops and comments, which are all things that should be familiar to you from the Python
world, although some things in Rust are defined stricter. Next to that, you will be introduced to a thing that almost
uniquely defines Rust: its ownership rules and borrowing system.&lt;&#x2F;p&gt;
&lt;p&gt;Then, you can come back here. Or, you can continue on reading about Rust. If you do, you will learn more about how Rust
works which allows you to write more advanced stand-alone or library code. I can suggest combining that with doing the
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rustlings&quot;&gt;Rustlings&lt;&#x2F;a&gt; exercises, which mostly follow along with The Book.&lt;&#x2F;p&gt;
&lt;p&gt;In any case, at some point I hope you will be back here, either with some basic or more advanced knowledge of Rust. (If
you decide to just read along without knowing Rust, I think you will be able to understand most concepts as well,
although some terms might not make sense to you).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-project&quot;&gt;Example project&lt;a class=&quot;zola-anchor&quot; href=&quot;#example-project&quot; aria-label=&quot;Anchor link for: example-project&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;On this page, we will show an example project in Python, that we will adjust to make use of calculations in Rust
instead. In this, for instructive purposes, suppose we want to calculate the nth number in the&lt;br &#x2F;&gt;
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fibonacci_sequence&quot;&gt;Fibonacci&lt;&#x2F;a&gt; sequence, defined by the sum of the previous two values
with 0 and 1 (or 1 and 1) as first two values. We will do this in a stupid way in both Python and Rust, which will help
to demonstrate the speed gain without being &lt;a href=&quot;&#x2F;blog&#x2F;rust-python-00&quot;&gt;smart in the first way&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;initialize-the-project&quot;&gt;Initialize the project&lt;a class=&quot;zola-anchor&quot; href=&quot;#initialize-the-project&quot; aria-label=&quot;Anchor link for: initialize-the-project&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;To start out, first go into the folder in which you put your projects and run &lt;code&gt;cargo new rust_in_python&lt;&#x2F;code&gt;. This will
create a folder of that name with in it a few Rust related files that we will adjust along the way. But first, let&#x27;s
make sure our Python setup that we will aim to replace is there.&lt;&#x2F;p&gt;
&lt;p&gt;Note: in this setup we will make use of Maturin for building our Python packages with Rust compute. Make sure in your
Python setup you have &lt;code&gt;maturin&lt;&#x2F;code&gt; and &lt;code&gt;patchelf&lt;&#x2F;code&gt; available, either by running &lt;code&gt;pip install maturin[patchelf]&lt;&#x2F;code&gt; or
separately installing both packages. I recommend installing these not for your system python interpreter, but using
a virtual environment or something similar (which is outside the scope of this series, but if you are new to it, you
can read up on it &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;packaging.python.org&#x2F;en&#x2F;latest&#x2F;guides&#x2F;installing-using-pip-and-virtual-environments&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;python-implementation&quot;&gt;Python implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#python-implementation&quot; aria-label=&quot;Anchor link for: python-implementation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The function that we will use to calculate the nth entry in the Fibonacci sequence in an inefficient (&quot;stupid&quot;) way is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python z-code&quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-function z-python&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-python&quot;&gt;&lt;span class=&quot;z-keyword z-declaration z-function z-python&quot;&gt;def&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-parameters z-python&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-python&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-function z-begin z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-statement z-conditional z-if z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-python&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-python&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-conditional z-if z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-return z-python&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-statement z-conditional z-if z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-python&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-python&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-conditional z-if z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-return z-python&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-return z-python&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I can talk about what the stupid approach is: this approach will recalculate the same fibonacci number multiple
times. The number at &lt;code&gt;n-1&lt;&#x2F;code&gt; is calculated 1, but the number at &lt;code&gt;n-2&lt;&#x2F;code&gt; is calculated twice: once for calculating &lt;code&gt;n-1&lt;&#x2F;code&gt;, and
once in the final sum for &lt;code&gt;n&lt;&#x2F;code&gt;. It only gets worse from here: &lt;code&gt;n-3&lt;&#x2F;code&gt; is calculated three times (two times for &lt;code&gt;n-2&lt;&#x2F;code&gt;, and
then once more for &lt;code&gt;n-1&lt;&#x2F;code&gt;), &lt;code&gt;n-4&lt;&#x2F;code&gt; five times, &lt;code&gt;n-5&lt;&#x2F;code&gt; eight times, et cetera. (Do you see the pattern in here?)&lt;&#x2F;p&gt;
&lt;p&gt;A more efficient calculation would store the already-calculated values in some way or avoid having to do the calculation
multiple times in another way. But remember: we are not trying to be type-1 smart here. So, we use the calculation above
to calculate, say, the 40th entry in the sequence:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python z-code&quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-python&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;40&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;after&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;Result in Python after &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;after&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-format-spec z-python&quot;&gt;&lt;span class=&quot;z-constant z-other z-format-spec z-python&quot;&gt;:.2f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt; seconds is: &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which prints on my PC&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Result in Python after 19.07 seconds is: 102334155.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s see what this looks like in Rust!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rust-implementation&quot;&gt;Rust implementation&lt;a class=&quot;zola-anchor&quot; href=&quot;#rust-implementation&quot; aria-label=&quot;Anchor link for: rust-implementation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The analogue function definition in Rust could be written like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;||&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that if you got further than chapter 4 in the Book of Rust, you will have been introduced to the &lt;code&gt;match&lt;&#x2F;code&gt; syntax
which is an alternative and possibly more &quot;rustonic&quot;; but this version works as well and contains no Rust syntax
that is not introduced in the first 4 chapters.&lt;&#x2F;p&gt;
&lt;p&gt;To run the above as pure Rust code, you could put the above directly in &lt;code&gt;main.rs&lt;&#x2F;code&gt; in your &lt;code&gt;src&#x2F;&lt;&#x2F;code&gt; folder. The result
could be like what follows, which also includes &lt;code&gt;Instant&lt;&#x2F;code&gt; from the standard Rust library to create a simple timer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;use&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;std&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;time&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;Instant&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;||&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; before &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Instant&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;now&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; res &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;40&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;let&lt;&#x2F;span&gt; after &lt;span class=&quot;z-keyword z-operator z-assignment z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;Instant&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;now&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-support z-macro z-rust&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Result in Rust after &lt;span class=&quot;z-constant z-other z-placeholder z-rust&quot;&gt;{:?}&lt;&#x2F;span&gt; is: &lt;span class=&quot;z-constant z-other z-placeholder z-rust&quot;&gt;{}&lt;&#x2F;span&gt;.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; after &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; before&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; res&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On my PC executing this with &lt;code&gt;cargo run&lt;&#x2F;code&gt; results in the output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Result in Rust after 650.475884ms is: 102334155.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Two important observations:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Happy to see the answer is the same! Otherwise we&#x27;d have a problem..&lt;&#x2F;li&gt;
&lt;li&gt;Also, happy to see that Rust is much faster! Otherwise, we&#x27;d be doing this without gain.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;rust-adjustments-for-use-in-python&quot;&gt;Rust adjustments for use in Python&lt;a class=&quot;zola-anchor&quot; href=&quot;#rust-adjustments-for-use-in-python&quot; aria-label=&quot;Anchor link for: rust-adjustments-for-use-in-python&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;To convert the above to something that can be used in Python, some things have to be changed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Move the &lt;code&gt;fibo&lt;&#x2F;code&gt; function above to &lt;code&gt;lib.rs&lt;&#x2F;code&gt; in the &lt;code&gt;src&#x2F;&lt;&#x2F;code&gt; folder&lt;&#x2F;li&gt;
&lt;li&gt;In &lt;code&gt;main.rs&lt;&#x2F;code&gt;, add &lt;code&gt;use fibo_rust::fibo;&lt;&#x2F;code&gt; to the top&lt;&#x2F;li&gt;
&lt;li&gt;In &lt;code&gt;lib.rs&lt;&#x2F;code&gt;, adjust &lt;code&gt;fibo&lt;&#x2F;code&gt; to be a pyfunction (see below)&lt;&#x2F;li&gt;
&lt;li&gt;Also add &lt;code&gt;fiborust&lt;&#x2F;code&gt; as a pymodule (also see below)&lt;&#x2F;li&gt;
&lt;li&gt;Update the &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; to make use of pyo3 (see even further below)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The resulting &lt;code&gt;lib.rs&lt;&#x2F;code&gt; becomes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; class=&quot;language-rust z-code&quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-keyword z-other z-rust&quot;&gt;use&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-path z-rust&quot;&gt;pyo3&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-path z-rust&quot;&gt;prelude&lt;span class=&quot;z-punctuation z-accessor z-rust&quot;&gt;::&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;pyfunction&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-rust&quot;&gt;usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;if&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-rust&quot;&gt;||&lt;&#x2F;span&gt; n &lt;span class=&quot;z-keyword z-operator z-comparison z-rust&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-rust&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;        &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-rust&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;n &lt;span class=&quot;z-keyword z-operator z-arithmetic z-rust&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-rust&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;pymodule&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-annotation z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-annotation z-rust&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-annotation z-rust&quot;&gt;pyo3&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;name &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;fibo_rust&lt;span class=&quot;z-punctuation z-definition z-string z-end z-rust&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-annotation z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-rust&quot;&gt;pub&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-function z-rust&quot;&gt;fn&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-rust&quot;&gt;fiborust&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-rust&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;Bound&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&amp;#39;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;_&lt;&#x2F;span&gt;, PyModule&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-parameters z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parameters z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt; &lt;span class=&quot;z-meta z-function z-return-type z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic z-rust&quot;&gt;PyResult&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-rust&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-rust&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-rust&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    m&lt;span class=&quot;z-punctuation z-accessor z-dot z-rust&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-rust&quot;&gt;add_function&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-macro z-rust&quot;&gt;wrap_pyfunction!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;fibo&lt;span class=&quot;z-punctuation z-separator z-rust&quot;&gt;,&lt;&#x2F;span&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-rust&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-rust&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;    &lt;span class=&quot;z-support z-type z-rust&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-begin z-rust&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-group z-end z-rust&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-rust&quot;&gt;&lt;span class=&quot;z-meta z-function z-rust&quot;&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-rust&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-rust&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this, the name &lt;code&gt;fibo_rust&lt;&#x2F;code&gt; is used to make clear what you will import from in Python. What additionally is important
to note:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;we are importing from &lt;code&gt;pyo3&lt;&#x2F;code&gt; on top, which is the package Maturin uses behind the scenes for the Rust-Python
integration&lt;&#x2F;li&gt;
&lt;li&gt;each function you want to use in Python needs to be flagged with &lt;code&gt;#[pyfunction]&lt;&#x2F;code&gt;. This will (among other things) make
sure the Rust compiler will check whether this Rust variable can be converted to a Python variable (which is fine for
builtin variable types like &lt;code&gt;usize&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;each function you want to use in Python also needs to be included in the &lt;code&gt;#[pymodule]&lt;&#x2F;code&gt; section using the
&lt;code&gt;add_function&lt;&#x2F;code&gt; call. The other syntax used in the &lt;code&gt;fiborust&lt;&#x2F;code&gt; definition is outside the scope of this blog.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The updated &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; will have to contain the following lines:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;lib&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;fibo_rust&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;crate-type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;cdylib&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-array z-toml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;lib&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;pyo3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0.22.5&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;abi3-py310&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This specifies:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the name the library will have in Python (as a module) - I can recommend something different than the folder name&lt;&#x2F;li&gt;
&lt;li&gt;the library-type, which next to normal &lt;code&gt;lib&lt;&#x2F;code&gt; now also needs to be &lt;code&gt;cdylib&lt;&#x2F;code&gt; (you can also leave out &lt;code&gt;lib&lt;&#x2F;code&gt; but then
the result is no longer runnable in Rust by itself using &lt;code&gt;cargo run&lt;&#x2F;code&gt;; in that case, you can remove &lt;code&gt;main.rs&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;the version of pyo3 to use&lt;&#x2F;li&gt;
&lt;li&gt;which Python ABI to use as a lowerbound - I have selected Python 3.10 here but other values can be used as well
(up from py38 for Python 3.8 as the lowest)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;compiling-the-rust-package-for-python-use&quot;&gt;Compiling the Rust package for Python use&lt;a class=&quot;zola-anchor&quot; href=&quot;#compiling-the-rust-package-for-python-use&quot; aria-label=&quot;Anchor link for: compiling-the-rust-package-for-python-use&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;Next, we will finally be using Maturin for actually making the Rust function available to be called in Python. From
the same directory as that contains your &lt;code&gt;src&lt;&#x2F;code&gt; folder and your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, run the command &lt;code&gt;maturin develop&lt;&#x2F;code&gt; (with
your virtual environment active, if you are choosing to make use of that setup). This will automatically compile the
Rust code, wrap it with some Python-to-Rust and Rust-to-Python variable converters, and put it in your &lt;code&gt;site-packages&lt;&#x2F;code&gt;
in the currently used Python interpreter. That means it is importable from Python!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adjustments-in-python-code&quot;&gt;Adjustments in Python code&lt;a class=&quot;zola-anchor&quot; href=&quot;#adjustments-in-python-code&quot; aria-label=&quot;Anchor link for: adjustments-in-python-code&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;To import and use the package in Python, adjust the above Python script to the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python z-code&quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-from z-python&quot;&gt;from&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-meta z-import-source z-python&quot;&gt; &lt;span class=&quot;z-meta z-import-path z-python&quot;&gt;&lt;span class=&quot;z-meta z-import-name z-python&quot;&gt;fibo_rust&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-python&quot;&gt;import&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-python&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;fibo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-python&quot;&gt;40&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;after&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;Result in Python with Rust after &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;after&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-format-spec z-python&quot;&gt;&lt;span class=&quot;z-constant z-other z-format-spec z-python&quot;&gt;:.2f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt; seconds is: &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that this is the same code as above, with just the &lt;code&gt;fibo&lt;&#x2F;code&gt; function definition replaced with importing &lt;code&gt;fibo&lt;&#x2F;code&gt; from
the &lt;code&gt;fibo_rust&lt;&#x2F;code&gt; module. As a Python user, nothing would make it seem that this module is not just a native Python
function. Except for the second note, namely that your IDE might not (immediately) recognize this new module and flag
it as an import that shouldn&#x27;t work, even though it does work. Your mileage may vary.&lt;&#x2F;p&gt;
&lt;p&gt;On my computer, running the above code prints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Result in Python with Rust after 0.67 seconds is: 102334155.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It works! The runtime of 0.67 seconds is roughly comparable with the 650ms reported by Rust, and significantly lower
than the initial 19.07 seconds from the first Python version. For this, we needed only very basic Rust knowledge,
a very simple reimplementation of the calculation in Rust without changing the internal logic, and the setup with
Maturin and the adjustments in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;. Not too much effort for around a 30x speed boost. Great!&lt;&#x2F;p&gt;
&lt;p&gt;At least.. as long as this actually is a realistic representation of what you might achieve in practice. Is it?
It can be, but by how much can differ. Let&#x27;s look at a different example that illustrates a potential limitation in
&lt;a href=&quot;&#x2F;posts&#x2F;rust-python-02&quot;&gt;the next part&lt;&#x2F;a&gt;, or check out some additional background and reading below first.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;a class=&quot;zola-anchor&quot; href=&quot;#links&quot; aria-label=&quot;Anchor link for: links&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;For full code used in this example, have a look at the &lt;code&gt;rust_in_python&lt;&#x2F;code&gt; folder in my
&lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;debruijn&#x2F;website_examples&quot;&gt;websites_examples&lt;&#x2F;a&gt; repository.&lt;&#x2F;p&gt;
&lt;p&gt;In case you&#x27;d like to view some other examples of using Maturin, have a look at these links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On the main website of maturin, there is a different &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;www.maturin.rs&#x2F;tutorial&quot;&gt;tutorial&lt;&#x2F;a&gt; to get you started.
This one uses a bit more advanced Rust syntax, but can be helpful if you are also a bit further in your Rust journey.&lt;&#x2F;li&gt;
&lt;li&gt;Some well-known Python packages use Rust and Maturin under the hood, like &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pola-rs&#x2F;polars&quot;&gt;polars&lt;&#x2F;a&gt;
and &lt;a rel=&quot;nofollow noreferrer&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;ruff&quot;&gt;ruff&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Rust in Python part 0: why and how?</title>
		<published>2024-10-18T00:00:00+00:00</published>
		<updated>2024-10-18T00:00:00+00:00</updated>
		<link href="https://debruijn.github.io/posts/rust-python-00/" type="text/html"/>
		<id>https://debruijn.github.io/posts/rust-python-00/</id>
		<content type="html">&lt;p&gt;When coding in Python, you will occasionally be in a situation where a single function or a few functions are
responsible for the majority of your execution time. In most cases, that is fine: if for a particular task, 95% of your
time is spent in a single function but the total run time is less than a second, and this particular task is not ran
frequently, then there is no reason to worry about speed improvements.&lt;&#x2F;p&gt;
&lt;p&gt;But of course, the opposite will happen as well: this 1 second task needs to be ran 1000 or 1000000 times each time
you do a particular broader task (say, a model run in your data science research; or a ingestion of data in your
pipeline; or every time a page loads on your website). Bringing down this 1 second to a tenth of second will be worth it
in aggregate. If for this or another reason you want to speed it up, there are roughly two categories of things you
can do:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Be smart in a classical way&lt;&#x2F;li&gt;
&lt;li&gt;Be smart in a different way&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One way of being smart is looking at your process, and figure out if there are ways to avoid some of these calculations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Are you recalculating a variable in a loop that could be precalculated once?&lt;&#x2F;li&gt;
&lt;li&gt;Can you use a cache to store the output for particular input states? And if so, can you be smarter about defining what
a state is, say when a permutation of the same inputs doesn&#x27;t matter for the output value?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a faster implementation of what you try to do out there that you can use? Does that meet your requirements?&lt;&#x2F;li&gt;
&lt;li&gt;Can you make some assumptions to skip over some of the calculations, and get to, say, 99% of the result in 1% of the
time?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This way of being smart requires you to think, which sometimes you don&#x27;t want to do. You might also have to convince
other people that this is actually worth it. And: there is no guarantee that refactoring in such a way will lead to a
speed improvement: sometimes an alternative approach turns out to be slower.&lt;&#x2F;p&gt;
&lt;p&gt;So, what is that other way of being smart? Of course, given the title of this series of blog posts, the answer involves
implementing your Python functionality in Rust, and using that in Python. Ideally, from a Python user perspective, they
wouldn&#x27;t even know they use Rust under the hood. In fact, an alternative way to spell this other way of being smart
would be l-a-z-y: instead of thinking if a better algorithm exists and what that would be, you just reimplement the
current one. The next pages in this series will show my experience in learning how to do that (without knowing Rust
beforehand!) and also the limitations to this approach.&lt;&#x2F;p&gt;
&lt;p&gt;A few remarks to discuss beforehand, to get some of the caveats out of the way..&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-is-rust-faster-than-python&quot;&gt;Why is Rust faster than Python?&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-is-rust-faster-than-python&quot; aria-label=&quot;Anchor link for: why-is-rust-faster-than-python&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The main relevant difference between Rust and Python in this regard is that Rust is a compiled and statically-typed
language and Python is not. This makes it that some of the complexities in what needs to happen can be solved or
optimized by the Rust syntax and compiler during writing or compiling your code, while the Python interpreter has to do
that live while running the code. Think of adding two integers x and y together. In the case of Rust, the compiler will
have made sure that the exact procedure that has to be followed has been defined, so when you run your code, it can just
do that procedure. In the case of Python, a lot of questions (might*) have to be answered: are both x and y really
numbers, and are they really integers? What do we do in case the answer is no? This results in more decision points
needing to be figured out at every step, and decision points slow every process down (this is also true for processes
outside programming).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;does-this-only-hold-for-rust&quot;&gt;Does this only hold for Rust?&lt;a class=&quot;zola-anchor&quot; href=&quot;#does-this-only-hold-for-rust&quot; aria-label=&quot;Anchor link for: does-this-only-hold-for-rust&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;No, there are many other choices you could make instead of Rust as well. An obvious one is C, which is the language used
for a lot of core Python functions themselves (Python is not written in Python, or, not only in Python). There are some
advantages and disadvantages of Rust over C. The main disadvantage of Rust is that for C, due to its historic presence,
there are more resources out there than for Rust: more example code, more IDE integration, and also more fellow
programmers that can help you out.&lt;&#x2F;p&gt;
&lt;p&gt;The main advantage (although it depends on who you ask) is that Rust is annoying. And annoying is good if you are new to
statically-typed languages. There are also moments where the harsh rules of Rust could slow you down compared to using
something like C, but these are less likely if you are just aiming to replace a single core Python function with a piece
of external code in Rust or C. Instead, if you aim to use such a language only for these critical speed-up situations,
you are likely to have forgotten about the details of this lower-level language, and then it helps you that Rust and its
compiler will remind you of everything that you are doing wrong.&lt;&#x2F;p&gt;
&lt;p&gt;In a different use case, your choice of language might be different, but my experience was that within half a day I was
able to learn some basic Rust, and learn how to call Rust from Python to speed-up a pre-existing function to less than
10% of its run time. Even more, because of the Rust compiler (and me shutting down its complaints) I was already quite
confident that this solution actually works for a variety of input values and not just the ones that I tried.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-is-coming-up&quot;&gt;What is coming up?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-coming-up&quot; aria-label=&quot;Anchor link for: what-is-coming-up&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;This page tries to answer the &quot;Why Rust?&quot; question. What follows will be answers to the &quot;How to Rust&quot; question:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How to get started with Rust, and Rust in Python&lt;&#x2F;li&gt;
&lt;li&gt;How to apply this to a pre-existing function&lt;&#x2F;li&gt;
&lt;li&gt;How to include Rust code in your Python package&lt;&#x2F;li&gt;
&lt;li&gt;How to incorporate this into your Python toolset going forward&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These pages will be more code-based and less text-based, but they will also involve my own experiences and suggestions.
You can use them together with existing documentation (which can be a bit scattered all over the place).&lt;&#x2F;p&gt;
&lt;p&gt;Of course, you can use this series as a starting point of learning more Rust (which is also what I did!). Or as a
starting point for learning other languages and integrate them in Python (which is also what I have planned!). But you
have to start somewhere, and it&#x27;s nice to get to some tangible gain that you can incorporate into an existing codebase
or workflow. So for that first step, go to the &lt;a href=&quot;&#x2F;posts&#x2F;rust-python-01&quot;&gt;first page&lt;&#x2F;a&gt; of this series.&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>