<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>danigm.net - blog</title><link>https://danigm.net/</link><description></description><lastBuildDate>Fri, 14 Nov 2025 12:00:00 +0100</lastBuildDate><item><title>openSUSE: The new git workflow</title><link>https://danigm.net/git-workflow.html</link><description>&lt;p&gt;openSUSE is migrating the package source management from &lt;strong&gt;osc&lt;/strong&gt; to
&lt;strong&gt;git&lt;/strong&gt;. I will try to explain here what it is the "git workflow" in
openSUSE and give some practical information for contributors and
maintainers.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/opensuse-git.png" /&gt;
&lt;/p&gt;

&lt;p&gt;You can find some documentation in the &lt;a href="https://en.opensuse.org/openSUSE:Git_Packaging_Workflow"&gt;openSUSE wiki&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;openSUSE uses &lt;a href="https://openbuildservice.org/"&gt;Open Build Service&lt;/a&gt; to
store package sources (.spec files and patches). The source control is
similar to &lt;a href="https://subversion.apache.org/"&gt;subversion&lt;/a&gt;, so you can
&lt;em&gt;osc checkout&lt;/em&gt;, &lt;em&gt;osc commit&lt;/em&gt;, &lt;em&gt;osc log&lt;/em&gt;, etc. to work with any package
source.&lt;/p&gt;
&lt;p&gt;I don't know all the reasons to do the change, and different people
will find different reasons, to support the change or to be against
it. I will just write here what I consider a good reason to migrate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Almost everyone has moved to git now, so today,
  &lt;a href="https://git-scm.com"&gt;git&lt;/a&gt; is the default source code management
  (scm) tool, almost all the people knows about
  &lt;a href="https://github.com"&gt;github&lt;/a&gt;, so it's good to be "&lt;em&gt;standard&lt;/em&gt;".&lt;/li&gt;
&lt;li&gt;With the concept of "&lt;em&gt;cheap&lt;/em&gt;" branches in git, it &lt;strong&gt;could&lt;/strong&gt; be
  easier to maintain different versions of the same package, same
  repository, different branches, instead of actual forks.&lt;/li&gt;
&lt;li&gt;Decouple the package source management from build. OBS does a lot of
  things, moving source code and review process to
  &lt;a href="https://gitea.com"&gt;gitea&lt;/a&gt; could reduce the complexity (but requires
  some integration).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;From OBS to gitea&lt;/h2&gt;
&lt;p&gt;All the development happens in &lt;a href="https://build.opensuse.org"&gt;OBS&lt;/a&gt;, so the
&lt;strong&gt;classic&lt;/strong&gt; workflow happens entirely there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;developer: branch -&amp;gt; checkout -&amp;gt; modify -&amp;gt; commit -&amp;gt; submit request&lt;/li&gt;
&lt;li&gt;maintainer: review -&amp;gt; accept/decline&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And everything is integrated in OBS that does the corresponding build
of the sources, checks with services, forward, etc.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;new&lt;/strong&gt; workflow changes almost all the interaction from
&lt;a href="https://build.opensuse.org"&gt;OBS&lt;/a&gt; to &lt;a href="https://src.opensuse.org"&gt;gitea&lt;/a&gt;. OBS is still
a really important piece of software in the process, but in the new
workflow it's a build backend, so the user interaction will be with
the git repo in &lt;a href="https://src.opensuse.org"&gt;gitea&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new &lt;strong&gt;git workflow&lt;/strong&gt; happens in &lt;a href="https://src.opensuse.org"&gt;gitea&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;developer: fork -&amp;gt; clone -&amp;gt; modify -&amp;gt; commit -&amp;gt; push -&amp;gt; pull request&lt;/li&gt;
&lt;li&gt;maintainer: review -&amp;gt; approve/decline&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you may notice, the "&lt;em&gt;default&lt;/em&gt;" workflow is very similar, the
difference is in the tools, the &lt;strong&gt;classic&lt;/strong&gt; workflow occurs in
&lt;a href="https://build.opensuse.org"&gt;build.opensuse.org&lt;/a&gt; and the &lt;strong&gt;new&lt;/strong&gt; workflow in
&lt;a href="https://src.opensuse.org"&gt;src.opensuse.org&lt;/a&gt;. And the tools to work with the
sources are also different, &lt;strong&gt;osc&lt;/strong&gt; in the first one and &lt;strong&gt;git&lt;/strong&gt; in
the new workflow.&lt;/p&gt;
&lt;p&gt;And with this new workflow, there are some bots in gitea that sends
the changes to OBS, so for any pull request created you will have the
build results and approval from the bot if everything is building.&lt;/p&gt;
&lt;h2&gt;How to modify a package (leap 16.0)&lt;/h2&gt;
&lt;p&gt;Notice that you should have a &lt;a href="https://idp-portal.suse.com/univention/self-service/#page=createaccount"&gt;openSUSE account&lt;/a&gt; to work with the
gitea instance, and don't forget to &lt;a href="https://src.opensuse.org/user/settings/keys"&gt;configure your ssh key&lt;/a&gt; to be
able to push using the gitea@src.opensuse.org remote.&lt;/p&gt;
&lt;p&gt;So as a contributor, this is the basic workflow to follow to update a
package in openSUSE:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Look for the source package in the pool
   (&lt;a href="https://src.opensuse.org/pool"&gt;https://src.opensuse.org/pool&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fork it in your user space, click the top right button. Skip this
   step if you have forked before&lt;/li&gt;
&lt;li&gt;Clone your fork and work on that repo, create a new branch, modify
   the spec file, add new soures, etc. And make sure to update the
   .changes file accordingly, you can still use &lt;code&gt;osc vc&lt;/code&gt; to do that.&lt;/li&gt;
&lt;li&gt;You can build locally your package with &lt;code&gt;osc build&lt;/code&gt;, as usual, but
   you will need to specify the build project:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;obs&lt;span class="w"&gt; &lt;/span&gt;meta&lt;span class="w"&gt; &lt;/span&gt;pull
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;obs&lt;span class="w"&gt; &lt;/span&gt;meta&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--project&lt;span class="w"&gt; &lt;/span&gt;openSUSE:Backports:SLE-16.0
$&lt;span class="w"&gt; &lt;/span&gt;osc&lt;span class="w"&gt; &lt;/span&gt;build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Once you are happy with your changes, you can commit, push to your
   fork and then you can create a Pull Request. The pull request
   should target the &lt;strong&gt;pool&lt;/strong&gt; repo and desired product branch. Right
   now you can just target &lt;code&gt;leap-16.0&lt;/code&gt;, as factory is not migrated
   yet.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Devel projects&lt;/h2&gt;
&lt;p&gt;Some devel projects have been migrated now to git, so a similar
workflow is available to modify these packages in Tumbleweed. The
development of these packages is not happening in the &lt;em&gt;pool&lt;/em&gt;, so you
need to find first the devel project.&lt;/p&gt;
&lt;p&gt;There's no simple way to discover the actual package devel source, as
far as I know the easier way is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Look for the devel project of the package in the &lt;a href="https://src.opensuse.org/openSUSE/Factory/src/branch/main/pkgs/_meta/devel_packages"&gt;Factory list&lt;/a&gt;,
   (ex python-pytest)&lt;/li&gt;
&lt;li&gt;Go to the devel project in &lt;a href="1"&gt;OBS&lt;/a&gt; (ex &lt;a href="https://build.opensuse.org/project/show/devel:languages:python:pytest"&gt;devel:languages:python:pytest&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Click on the link &lt;a href="https://src.opensuse.org/python-pytest/_ObsPrj.git#main"&gt;This project is managed in SCM&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once you have located the desired package to modify, the workflow is
similar to what I explained before, but instead of forking from
&lt;strong&gt;pool&lt;/strong&gt;, you should fork from the devel project. For example if you
want to modify &lt;strong&gt;python-pytest&lt;/strong&gt; you should fork from
&lt;a href="https://src.opensuse.org/python-pytest/python-pytest"&gt;https://src.opensuse.org/python-pytest/python-pytest&lt;/a&gt;, 
and create the pull request for that repo, to the main branch.&lt;/p&gt;
&lt;p&gt;Adding a new package follows a different process that's documented in
the &lt;a href="https://en.opensuse.org/openSUSE:OBS_to_Git#How_to_create_a_new_package?"&gt;wiki&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What's migrated?&lt;/h2&gt;
&lt;p&gt;As I said, the migration is happening right now, so not everything is
migrated. The first project migrated was the Leap 16.0. And we are
slowly migrating some devel projects.&lt;/p&gt;
&lt;p&gt;Right now from the python-maintainers team, we've started the
migration of two subprojects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://src.opensuse.org/python-interpreters"&gt;python-interpreters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://src.opensuse.org/python-pytest"&gt;python-pytest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find more information about the migration current state in the
wiki: &lt;a href="https://en.opensuse.org/openSUSE:OBS_to_Git#Codestream_Project_Status_table"&gt;https://en.opensuse.org/opensuse:obs_to_git#codestream_project_status_table&lt;/a&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 14 Nov 2025 12:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2025-11-14:/git-workflow.html</guid><category>blog</category><category>suse</category><category>opensuse</category><category>git</category><category>packaging</category><category>python</category></item><item><title>GNOME Tour in openSUSE and welcome app</title><link>https://danigm.net/gnome-tour-opensuse.html</link><description>&lt;p&gt;As a follow up of the &lt;a href="https://danigm.net/hackweek24.html"&gt;Hackweek 24 project&lt;/a&gt;, I've continued working
on the gnome-tour fork for openSUSE with custom pages to replace the
welcome application for openSUSE distributions.&lt;/p&gt;
&lt;h2&gt;GNOME Tour modifications&lt;/h2&gt;
&lt;p&gt;All the modifications are on top of &lt;a href="https://gitlab.gnome.org/GNOME/gnome-tour/"&gt;upstream gnome-tour&lt;/a&gt; and
stored in the &lt;a href="https://github.com/openSUSE/gnome-tour"&gt;openSUSE/gnome-tour repo&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom &lt;strong&gt;initial page&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gnome-tour-opensuse.png" /&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A new donations page&lt;/strong&gt;. In openSUSE we remove the popup from GNOME
   shell for donations, so it's fair to add it in this place.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gnome-tour-donation.png" /&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Last page with custom openSUSE links&lt;/strong&gt;, this one is the used for
   opensuse-welcome app.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;opensuse-welcome package&lt;/h2&gt;
&lt;p&gt;The &lt;a href="github.com/openSUSE/openSUSE-welcome"&gt;original opensuse-welcome&lt;/a&gt; is a qt application, and this one
is used for all desktop environments, but it's more or less
unmaintained and looking for a replacement, we can use the gnome-tour
fork as the default welcome app for all desktop without a custom app.&lt;/p&gt;
&lt;p&gt;To do a minimal desktop agnostic opensuse-welcome application, I've
modified the gnome-tour to also generate a second binary but just with
the last page.&lt;/p&gt;
&lt;p&gt;The new opensuse-welcome rpm package is built as a subpackage of
&lt;a href="https://src.opensuse.org/pool/gnome-tour"&gt;gnome-tour&lt;/a&gt;. This new application is minimal and it doesn't have
lots of requirements, but as it's a gtk4 application, it requires gtk
and libadwaita, and also depends on gnome-tour-data to get the
resoures of the app.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/opensuse-welcome.png" /&gt;
&lt;/p&gt;

&lt;p&gt;To improve this welcome app we need to review the translations,
because I added three new pages to the gnome-tour and that specific
pages are not translated, so I should regenerate the .po files for all
languages and upload to &lt;a href="https://l10n.opensuse.org/"&gt;openSUSE Weblate&lt;/a&gt; for translations.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 21 Oct 2025 12:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2025-10-21:/gnome-tour-opensuse.html</guid><category>blog</category><category>gnome-tour</category><category>welcome</category><category>suse</category><category>gsoc</category><category>gnome</category></item><item><title>Log Detective: GSoC 2025 (part 2)</title><link>https://danigm.net/gsoc-2025-2.html</link><description>&lt;p&gt;This week is the last week of Google Summer of Code for this year
edition, and I'll do a summary of what we have been doing and future
plans for the Log Detective integration in openSUSE.&lt;/p&gt;
&lt;p&gt;I wrote a blog post about this project when it starts, so if you
didn't read, you can &lt;a href="https://danigm.net/gsoc-2025.html"&gt;take a look&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All the work and code was done in the
&lt;a href="https://github.com/openSUSE/logdetective-obs/"&gt;logdetective-obs github repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aazam, aka the intern, also wrote
&lt;a href="https://alcadeus.hashnode.dev/tag/gsoc"&gt;some blog post about his work&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gsoc.png" /&gt;
&lt;/p&gt;

&lt;h2&gt;Initial Research&lt;/h2&gt;
&lt;p&gt;The idea of the project was to explore ways of integration of
&lt;a href="https://log-detective.com"&gt;LogDetective&lt;/a&gt; with the openSUSE dev
workflow. So we started collecting some build failures in the openSUSE
build service and testing with log detective to check if the output is
smart or even relevant.&lt;/p&gt;
&lt;p&gt;The intern creates a script to collect log from build failures and we
store the LLM answer.&lt;/p&gt;
&lt;p&gt;Doing this we detected that the log-detective.com explain is very slow
and the &lt;a href="https://pypi.org/project/logdetective/"&gt;local tool&lt;/a&gt; is less
accurate.&lt;/p&gt;
&lt;p&gt;The results that we got weren't too good, but at this point of the
project is something expected. The model is being trained and will
improve with every new log that users send.&lt;/p&gt;
&lt;h2&gt;Local vs Remote, model comparison&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;logdetective&lt;/code&gt; command line tool is nice, but LLM requires a lot
of resources to run locally. This tool also uses the models published
by fedora in &lt;a href="https://huggingface.co/fedora-copr"&gt;huggingface.co&lt;/a&gt;, so
it's not as accurate as the remote instance that has a better trained
model and is up to date.&lt;/p&gt;
&lt;p&gt;In any case, the local &lt;code&gt;logdetective&lt;/code&gt; tool is interesting and, at this
moment, it's faster than the deployed log-detective.com.&lt;/p&gt;
&lt;p&gt;Using this tool, Aazam did some research, comparing the output with
&lt;a href="https://github.com/openSUSE/logdetective-obs/tree/main/model-testing"&gt;different models&lt;/a&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;logdetective apache-arrow_standard_x86_64.log\
  --model unsloth/Qwen2.5-Coder-7B-Instruct-128K-GGUF\
  -F Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf\
  --prompt ~/prompt.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So using other specific models, the logdetective tool can return
better results.&lt;/p&gt;
&lt;h2&gt;The plugin&lt;/h2&gt;
&lt;p&gt;openSUSE packagers uses the &lt;a href="https://github.com/openSUSE/osc"&gt;osc&lt;/a&gt;
tool, to build packages in build.opensuse.org. This tool can be
extended with plugins and we created a
&lt;a href="https://pypi.org/project/osc_ld_plugin/"&gt;new plugin&lt;/a&gt; to use
log-detective.&lt;/p&gt;
&lt;p&gt;So a packager can get some AI explanation about a build failure with a
simple command:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;osc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ld&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;devel&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;languages&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openSUSE_Tumbleweed&lt;/span&gt;
&lt;span class="err"&gt;🔍&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;logdetective&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;openSUSE_Tumbleweed&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="p"&gt;)...&lt;/span&gt;
&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opensuse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;devel&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;languages&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openSUSE_Tumbleweed&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pygame&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;_log&lt;/span&gt;
&lt;span class="err"&gt;🌐&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;LogDetective&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RPM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`python-pygame`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;during&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;
&lt;span class="n n-Quoted"&gt;`%check`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;indicated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bad exit status from /var/tmp/rpm-&lt;/span&gt;
&lt;span class="s2"&gt;tmp.hiddzT (%check)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;occurred&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;due&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seven&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;six&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skipped&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;suite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;



&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;primary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;causing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`surface_test.py`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;following&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;snippets&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;



&lt;span class="err"&gt;[[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/abuild/rpmbuild/BUILD/python-&lt;/span&gt;
&lt;span class="s2"&gt;pygame-2.6.1-build/BUILDROOT/usr/lib64/python3.11/site-&lt;/span&gt;
&lt;span class="s2"&gt;packages/pygame/tests/surface_test.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;284&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_copy_rle&lt;/span&gt;
&lt;span class="err"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;[[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/abuild/rpmbuild/BUILD/python-&lt;/span&gt;
&lt;span class="s2"&gt;pygame-2.6.1-build/BUILDROOT/usr/lib64/python3.11/site-&lt;/span&gt;
&lt;span class="s2"&gt;packages/pygame/tests/surface_test.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;274&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="n"&gt;test_mustlock_surf_alpha_rle&lt;/span&gt;
&lt;span class="err"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;[[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;278s&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/abuild/rpmbuild/BUILD/python-&lt;/span&gt;
&lt;span class="s2"&gt;pygame-2.6.1-build/BUILDROOT/usr/lib64/python3.11/site-&lt;/span&gt;
&lt;span class="s2"&gt;packages/pygame/tests/surface_test.py&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;342&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_solarwolf_rle_usage&lt;/span&gt;
&lt;span class="err"&gt;]&lt;/span&gt;



&lt;span class="n"&gt;These&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;errors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;suggest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;there&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;
&lt;span class="n n-Quoted"&gt;`test_copy_rle`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`test_mustlock_surf_alpha_rle`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`test_solarwolf_rle_usage`&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`surface_test.py`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;To&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resolve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;



&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Identify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cause&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;errors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;each&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;found&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;modifying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;correcting&lt;/span&gt;
&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;underlying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;problem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;they&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Re&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RPM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n n-Quoted"&gt;`surface_test.py`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;



&lt;span class="n"&gt;It&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s also recommended to review the other test failures and skipped steps, as&lt;/span&gt;
&lt;span class="s1"&gt;they might indicate other issues with the package or its dependencies that&lt;/span&gt;
&lt;span class="s1"&gt;should be addressed.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or if we are building locally, it's possible to run using the
installed &lt;code&gt;logdetective&lt;/code&gt; command line. But this method is less
accurate, because the model used is not smart enough, yet:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;osc&lt;span class="w"&gt; &lt;/span&gt;build
&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;osc&lt;span class="w"&gt; &lt;/span&gt;ld&lt;span class="w"&gt; &lt;/span&gt;--local-log&lt;span class="w"&gt; &lt;/span&gt;--repo&lt;span class="w"&gt; &lt;/span&gt;openSUSE_Tumbleweed
Found&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;log:&lt;span class="w"&gt; &lt;/span&gt;/var/tmp/build-root/openSUSE_Tumbleweed-x86_64/.build.log
🚀&lt;span class="w"&gt; &lt;/span&gt;Analyzing&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;log:&lt;span class="w"&gt; &lt;/span&gt;/tmp/tmpuu1sg1q0
INFO:logdetective:Loading&lt;span class="w"&gt; &lt;/span&gt;model&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;fedora-copr/Mistral-7B-Instruct-v0.3-GGUF
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Future plans&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Adding &lt;code&gt;submit-log&lt;/code&gt; functionality to &lt;code&gt;osc-ld-plugin&lt;/code&gt;.
   &lt;a href="https://github.com/openSUSE/logdetective-obs/pull/17/"&gt;In-progress&lt;/a&gt;.
   This will make it easier to collaborate with log-detective.com,
   allowing openSUSE packagers to send new data for model training.&lt;/li&gt;
&lt;li&gt;Gitea bot. openSUSE development workflow is moving to
   &lt;a href="https://src.opensuse.org/products/PackageHub"&gt;git&lt;/a&gt;, so we can
   create a bot that comment on Pull Request with packages that fails
   to build. Something similar to what fedora people have for
   &lt;a href="https://gitlab.com/redhat/centos-stream/rpms/gimp/-/merge_requests/9#note_2514178124"&gt;centos gitlab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Add a new tab to &lt;a href="https://log-detective.com"&gt;log-detective.com&lt;/a&gt; website to submit logs directly
   &lt;a href="https://github.com/fedora-copr/logdetective-website/issues/292"&gt;from OBS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This was an interesting Summer of Code project. I learned a bit about
LLM. I think that this project has a lot of potential, this can be
integrated in different workflows and an expert LLM can be a great
tool to help packagers, summarizing big logs, tagging similar
failures, etc.&lt;/p&gt;
&lt;p&gt;We have a lot of packages and a lot of data in
&lt;a href="https://build.opensuse.org"&gt;OBS&lt;/a&gt;, so we should start to feed the LLM with
this data, and in combination with the fedora project, the
log-detective could be a real expert in open source RPM packaging.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 27 Aug 2025 07:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2025-08-27:/gsoc-2025-2.html</guid><category>blog</category><category>ai</category><category>rpm</category><category>suse</category><category>gsoc</category><category>gnome</category></item><item><title>Log Detective: Google Summer of Code 2025</title><link>https://danigm.net/gsoc-2025.html</link><description>&lt;p&gt;I'm glad to say that I'll participate again in the &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt;, as
mentor. This year we will try to improve the RPM packaging workflow
using AI, as part of the &lt;a href="https://www.opensuse.org/"&gt;openSUSE&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;So this summer I'll be mentoring an intern that will research how to
integrate &lt;a href="https://log-detective.com/"&gt;Log Detective&lt;/a&gt; with openSUSE tooling to improve the
packager workflow to maintain rpm packages.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gsoc.png" /&gt;
&lt;/p&gt;

&lt;h2&gt;Log Detective&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://log-detective.com/"&gt;Log Detective&lt;/a&gt; is an initiative created by the &lt;a href="https://fedoraproject.org/"&gt;Fedora project&lt;/a&gt;,
with the goal of&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Train an AI model to understand RPM build logs and explain the
failure in simple words, with recommendations how to fix it. You
won't need to open the logs at all."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/log-detective.png" /&gt;
&lt;/p&gt;

&lt;p&gt;As a project that was promoted by Fedora, it's highly integrated with
the build tools around this distribution and RPM packages. But RPM
packages are used in a lot of different distributions, so this
"expert" LLM will be helpful for everyone doing RPM, and everyone
doing RPM, &lt;em&gt;should&lt;/em&gt; contribute to it.&lt;/p&gt;
&lt;p&gt;This is open source, so if, at openSUSE, we want to have something
similar to improve the &lt;a href="https://build.opensuse.org/"&gt;OBS&lt;/a&gt;, we don't need to reimplement it, we
can collaborate. And that's &lt;a href="https://github.com/fedora-copr/logdetective-website/issues/213"&gt;the idea&lt;/a&gt; of this GSoC project.&lt;/p&gt;
&lt;p&gt;We want to use Log Detective, but also collaborate with failures from
openSUSE to improve the training and the AI, and this should benefit
openSUSE but also will benefit Fedora and all other RPM based
distributions.&lt;/p&gt;
&lt;h2&gt;The intern&lt;/h2&gt;
&lt;p&gt;The selected intern is &lt;a href="https://summerofcode.withgoogle.com/programs/2025/projects/SZ1Va8yZ"&gt;Aazam Thakur&lt;/a&gt;. He studies at University of
Mumbai, India. He has experience in using SUSE as he has previously
worked on SLES 15.6 during his previous &lt;a href="https://openmainframeproject.org/blog/summer-mentorship-2024-automating-feilong-packaging-a-technical-odyssey/"&gt;summer mentorship&lt;/a&gt; at
OpenMainFrame Project for RPM packaging.&lt;/p&gt;
&lt;p&gt;I'm sure that he will be able to achieve great things during these
three months. The project looks very promising and it's one of the
things where AI and LLM will shine, because digging into logs is
always something difficult and if we train a LLM with a lot of data it
can be really useful to categorize failures and give a short
description of what's happening.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 09 Jun 2025 12:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2025-06-09:/gsoc-2025.html</guid><category>blog</category><category>ai</category><category>rpm</category><category>suse</category><category>gsoc</category><category>gnome</category></item><item><title>Python 2</title><link>https://danigm.net/python2.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/python2.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;In 2020, the
&lt;a href="https://www.python.org/doc/sunset-python-2/"&gt;Python foundation declared Python 2 as not maintained anymore&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python 2 is really old, not maintained and should not be used by
anyone in any modern environment, but software is complex and python2
still exists in some modern Linux distributions like Tumbleweed.&lt;/p&gt;
&lt;p&gt;The past week the &lt;a href="https://build.opensuse.org/request/show/1240106"&gt;request to delete Python 2&lt;/a&gt; from Tumbleweed was
created and is going through the staging process.&lt;/p&gt;
&lt;p&gt;The main package keeping Python 2 around for Tumbleweed was Gimp 2,
that doesn't depends directly on Python 2, but some of the plugins
depends on it. Now that we've Gimp 3 in Tumbleweed, we are able to
finally remove it.&lt;/p&gt;
&lt;h2&gt;Python 2&lt;/h2&gt;
&lt;p&gt;The first version of Python 2 was released around 2000, so it's now 25
years old. That's not true, because software is a living creature, so
as you may know, Python 2 grew during the following years with patch
and minor releases until 2020 that was the final release 2.7.18.&lt;/p&gt;
&lt;p&gt;But even when it was maintained until 2020, it was deprecated for a
long time so everyone "should" have time to migrate to python 3.&lt;/p&gt;
&lt;h2&gt;Py3K&lt;/h2&gt;
&lt;p&gt;I started to write python code around the year 2006. I was bored
during a summer internship at my third year of computer science, and I
decided to learn something new. In the following months / years I
heard a lot about the futurist &lt;a href="https://peps.python.org/pep-3000/"&gt;Python 3000&lt;/a&gt;, but I didn't worry too
much until it was officially released and the &lt;a href="https://docs.python.org/3.10/library/2to3.html"&gt;migration&lt;/a&gt; started to be
a thing.&lt;/p&gt;
&lt;p&gt;If you have ever write python2 code you will know about some of the
main differences with python3:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;print vs print()&lt;/li&gt;
&lt;li&gt;raw_input() vs input()&lt;/li&gt;
&lt;li&gt;unicode() vs str&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some tools appeared to make it easier to migrate from python2 to
python3, and even it was possible to have code compatible with both
versions at the same time using the &lt;code&gt;__future__&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;You should have heard about the &lt;a href="https://pypi.org/project/six/"&gt;six&lt;/a&gt; package, 2 * 3 = 6. Maybe the
name should be five instead of six, because it was a Python "2 and 3"
compatibility library.&lt;/p&gt;
&lt;h2&gt;Python in Linux command line&lt;/h2&gt;
&lt;p&gt;When python3 started to be the main python, there were some discussion
about how to handle that in different Linux distributions. The
/usr/bin/python binary was present and everyone expect that to be
python2, so almost everyone decided to keep that relation forever and
distribute python3 as /usr/bin/python3, so you can have both installed
without conflicts and there's no confusion.&lt;/p&gt;
&lt;p&gt;But python is an interpreted language, and if you have python code,
you can't tell if it's python2 or python3. The shebang line in the
executable python scripts should point to the correct interpreter and
that should be enough like &lt;code&gt;#!/usr/bin/python3&lt;/code&gt; will use the python3
interpreter and &lt;code&gt;#!/usr/bin/python&lt;/code&gt; will use python2.&lt;/p&gt;
&lt;p&gt;But this is not always true, some distributions uses python3 in
&lt;code&gt;/usr/bin/python&lt;/code&gt; like Archlinux or if you create a virtualenv with
python3, the &lt;code&gt;python&lt;/code&gt; binary points to the python3 interpreter, so a
shebang like &lt;code&gt;#!/usr/bin/python&lt;/code&gt; could be something valid for a
python3 script.&lt;/p&gt;
&lt;p&gt;In any case, the recommended and safest way is to always use &lt;code&gt;python3&lt;/code&gt;
binary because that way it'll work correctly "everywhere".&lt;/p&gt;
&lt;h2&gt;Goodbye&lt;/h2&gt;
&lt;p&gt;It's time to say goodbye to &lt;code&gt;python2&lt;/code&gt;, at least we can remove it now
from Tumbleweed. It'll be around for some more time in Leap, but it's
the time to let it go.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 27 Jan 2025 12:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2025-01-27:/python2.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category></item><item><title>Hackweek 24</title><link>https://danigm.net/hackweek24.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek24.png" width="50%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;It's the time for a new &lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt;. The Hack Week 24 was from
November 18th to November 22th, and I've decided to join the &lt;a href="https://hackweek.opensuse.org/projects/opensuse-welcome"&gt;New openSUSE-welcome&lt;/a&gt;
project this time.&lt;/p&gt;
&lt;p&gt;The idea of this project is to revisit the existing openSUSE welcome
app, and I've been trying to help here, specifically for the GNOME
desktop installation.&lt;/p&gt;
&lt;h2&gt;openSUSE-welcome&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/opensuse-welcome.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;Right now after installing any openSUSE distribution with a graphical
desktop, the user is welcomed on first login with a &lt;a href="https://github.com/openSUSE/openSUSE-welcome/"&gt;custom welcome app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This custom application is a Qt/QML with some basic information and
useful links.&lt;/p&gt;
&lt;p&gt;The same generic application is used for all desktops, and for popular
desktops right now exists upstream applications for this purpose, so
we were talking on Monday morning about it and decided to use specific
apps for desktops.&lt;/p&gt;
&lt;p&gt;So for GNOME, we can use the &lt;a href="https://gitlab.gnome.org/GNOME/gnome-tour/"&gt;GNOME Tour&lt;/a&gt; application.&lt;/p&gt;
&lt;h2&gt;gnome-tour&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;GNOME Tour is a simple rust/gtk4 application with some fancy images in
a slideshow.&lt;/p&gt;
&lt;p&gt;This application is generic and just shows information about GNOME
desktop, so I created a &lt;a href="https://github.com/openSUSE/gnome-tour"&gt;fork for openSUSE&lt;/a&gt; to do some openSUSE
specific customization and use this application as openSUSE welcome in
GNOME desktop for Tumbleweed and Leap.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour-opensuse.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Desktop patterns, the welcome workflow&lt;/h2&gt;
&lt;p&gt;After some testing and investigation about the current workflow for
the welcome app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://code.opensuse.org/package/patterns-base/blob/master/f/patterns-base.spec#_861"&gt;x11_enhanced&lt;/a&gt; pattern recommends opensuse-welcome app.&lt;/li&gt;
&lt;li&gt;We can add a &lt;code&gt;Recommends: gnome-tour&lt;/code&gt; to the &lt;a href="https://code.opensuse.org/package/patterns-gnome/blob/master/f/patterns-gnome.spec#_240"&gt;gnome pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The application run using &lt;a href="https://specifications.freedesktop.org/autostart-spec/latest/"&gt;xdg autostart&lt;/a&gt;, so gnome-tour package
   should put the file in &lt;code&gt;/etc/xdg/autostart&lt;/code&gt; and set to hidden on
   close.&lt;/li&gt;
&lt;li&gt;In the case of having a system with multiple desktops, we can
   choose the specific welcome app using the &lt;code&gt;OnlyShowIn/NotShowIn&lt;/code&gt;
   &lt;a href="https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html"&gt;config in desktop file&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I've created a &lt;a href="https://github.com/openSUSE/openSUSE-welcome/pull/43"&gt;draft PR&lt;/a&gt; to do not show the openSUSE-welcome
app in GNOME, and I've also the &lt;a href="https://build.opensuse.org/package/show/home:dgarcia:branches:GNOME:Next/gnome-tour"&gt;gnome-tour fork&lt;/a&gt; in my home OBS
project.&lt;/p&gt;
&lt;p&gt;I've been testing this configuration in Tumbleweed with GNOME, KDE and
XFCE installed and it works as expected. The openSUSE-welcome is shown
in KDE and XFCE and the gnome-tour app is only shown in GNOME.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-tour-tumbleweed.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The next steps to have the GNOME Tour app as default welcome for
openSUSE GNOME installation are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Send forked &lt;code&gt;gnome-tour&lt;/code&gt; package to &lt;code&gt;GNOME:Next&lt;/code&gt; project in OBS.&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;Recommends: gnome-tour&lt;/code&gt; to &lt;code&gt;patterns-gnome&lt;/code&gt; to &lt;code&gt;GNOME:Next&lt;/code&gt; project in OBS.&lt;/li&gt;
&lt;li&gt;Make sure that any other welcome application is &lt;a href="https://github.com/openSUSE/openSUSE-welcome/pull/43"&gt;not shown in GNOME&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Review openQA tests that expect opensuse-welcome and adapt for the
   new application.&lt;/li&gt;
&lt;/ol&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 22 Nov 2024 12:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2024-11-22:/hackweek24.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category><category>hackweek</category></item><item><title>rpmlint: Google Summer of Code 2024</title><link>https://danigm.net/gsoc-2024.html</link><description>&lt;p&gt;I'm glad to say that I'll participate again in the &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt;, as
mentor. This year we will continue the work done during the past year,
as part of the &lt;a href="https://www.opensuse.org/"&gt;openSUSE&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;So this summer I'll be mentoring an intern and we'll continue working
on improving the testing framework of the &lt;a href="https://github.com/openSUSE/mentoring/issues/204"&gt;rpmlint project&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gsoc.png" /&gt;
&lt;/p&gt;

&lt;p&gt;This year we've a better testing framework, thanks to the work done
during the past Summer of Code, by Afrid. So the goal for this year is
to try to modernize existing tests and remove as much files as
possible from &lt;code&gt;test/binary&lt;/code&gt; directory, replacing those with mock
packages defined with python code.&lt;/p&gt;
&lt;p&gt;The selected intern is &lt;a href="https://blog-gsoc-2024.blogspot.com/2024/05/gsoc-improve-test-coverage-in-rpmlint.html"&gt;Luz Marina Montilla Marín&lt;/a&gt;. She has done
some initial work in the rpmlint project, creating the mock packages
for some tests and we've just started with the work to do during the
GSoC program, evaluating the tests that we've right now and planning
were to start.&lt;/p&gt;
&lt;p&gt;She studies at Córdoba, Spain, my hometown. Every year I try to reach
young people at different local universities, here in Andalucía, and
sometimes I'm able to convince some students to participate, like the
&lt;a href="https://danigm.net/gsoc-2020.html"&gt;GSoC 2020&lt;/a&gt;, when Alejandro Dominguez, from Seville, were working
on Fractal. So I'm happy that I'm increasing the number of free
software developers in my local community :D&lt;/p&gt;
&lt;p&gt;I'm sure that she will be able to achieve great things during these
three months, so I'm looking forward to start to code and see how far
can we go.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 30 May 2024 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2024-05-30:/gsoc-2024.html</guid><category>blog</category><category>gnome</category><category>software</category><category>rpmlint</category><category>suse</category><category>gsoc</category></item><item><title>Python 3.13 Beta 1</title><link>https://danigm.net/python313-beta1.html</link><description>&lt;p&gt;&lt;img src="/pictures/python-logo-master-v313-TM.png" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;Python &lt;a href="https://www.python.org/downloads/release/python-3130b1/"&gt;3.13 beta 1 is out&lt;/a&gt;, and I've been working on the openSUSE
Tumbleweed package to get it ready for the release.&lt;/p&gt;
&lt;h2&gt;Installing python 3.13 beta 1 in Tumbleweed&lt;/h2&gt;
&lt;p&gt;If you are adventurous enough to want to test the python 3.13 and you
are using openSUSE Tumbleweed, you can give it a try and install the
current devel package:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# zypper addrepo -p 1000 https://download.opensuse.org/repositories/devel:languages:python:Factory/openSUSE_Tumbleweed/devel:languages:python:Factory.repo&lt;/span&gt;
&lt;span class="c1"&gt;# zypper refresh&lt;/span&gt;
&lt;span class="c1"&gt;# zypper install python313&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;What's new in Python 3.13&lt;/h2&gt;
&lt;p&gt;Python interpreter is pretty stable nowadays and it doesn't change too
much to keep code compatible between versions, so if you are writing
modern Python, your code should continue working whit this new
version. But it's actively developed and new versions have cool new
functionalities.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3.13/whatsnew/3.13.html#a-better-interactive-interpreter"&gt;New and improved interactive interpreter&lt;/a&gt;, colorized prompts,
   multiline editing with history preservation, interactive help with
   &lt;code&gt;F1&lt;/code&gt;, history browsing with &lt;code&gt;F2&lt;/code&gt;, paste mode with &lt;code&gt;F3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A set of performance improvements.&lt;/li&gt;
&lt;li&gt;Removal of many deprecated modules: aifc, audioop, chunk, cgi,
   cgitb, crypt, imghdr, mailcap, msilib, nis, nntplib, ossaudiodev,
   pipes, sndhdr, spwd, sunau, telnetlib, uu, xdrlib, lib2to3.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Enabling Experimental JIT Compiler&lt;/h2&gt;
&lt;p&gt;The python 3.13 version will arrive with an &lt;a href="https://docs.python.org/3.13/whatsnew/3.13.html#experimental-jit-compiler"&gt;experimental functionality&lt;/a&gt;
to improve performance. We're building with the
&lt;code&gt;--enable-experimental-jit=yes-off&lt;/code&gt; so it's disabled by default but it
can be enabled with a virtualenv before launching:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PYTHON_JIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3.13
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Free-threaded CPython&lt;/h2&gt;
&lt;p&gt;The python 3.13 has another build option to disable the Global
Interpreter Lock (&lt;code&gt;--disable-gil&lt;/code&gt;), but we're not enabling it because
in this case it's not possible to keep the same behavior. Building
with &lt;code&gt;disabled-gil&lt;/code&gt; will break compatibility.&lt;/p&gt;
&lt;p&gt;In any case, maybe it's interesting to be able to provide another
version of the interpreter with the GIL disabled, for specific cases
where the performance is something critical, but that's something to
evaluate.&lt;/p&gt;
&lt;p&gt;We can think about having a &lt;code&gt;python313-nogil&lt;/code&gt; package, but it's not
something trivial to be able to have &lt;code&gt;python313&lt;/code&gt; and &lt;code&gt;python313-nogil&lt;/code&gt;
at the same time in the same system installation, so I'm not planning
to work on that for now.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 22 May 2024 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2024-05-22:/python313-beta1.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>python</category></item><item><title>Where's my python code?</title><link>https://danigm.net/wheres-my-python-code.html</link><description>&lt;p&gt;&lt;img src="/pictures/python-logo-master-v3-TM.png" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;Python is a interpreted language, so the python code are just text
files with the &lt;code&gt;.py&lt;/code&gt; extension. For simple scripts it's really easy to
have your files located, but when you starts to use dependencies and
different projects with different requirements the thing starts to get
more complex.&lt;/p&gt;
&lt;h2&gt;PYTHONPATH&lt;/h2&gt;
&lt;p&gt;The Python interpreter uses a list of paths to try to locate python
modules, for example this is what you can get in a modern GNU/Linux
distribution by default:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="mf"&gt;3.11.7&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dec&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GCC&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;linux&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;help&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;copyright&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;credits&amp;quot;&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;license&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python311.zip&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/lib-dynload&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/site-packages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib64/python3.11/_import_failed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s1"&gt;&amp;#39;/usr/lib/python3.11/site-packages&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These are the default paths where the python modules are installed. If
you install any python module using your linux packaging tool, the
python code will be placed inside the &lt;code&gt;site-packages&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;So system installed python modules can be located in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/usr/lib/python3.11/site-packages&lt;/code&gt; for modules that are
   architecture independent (pure python, all &lt;code&gt;.py&lt;/code&gt; files)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/usr/lib64/python3.11/site-packages&lt;/code&gt; for modules that depends on
   the arquitecture, that's something that uses low level libraries
   and needs to build so there are some &lt;code&gt;.so&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;pip&lt;/h2&gt;
&lt;p&gt;When you need a new python dependency you can try to install from your
GNU/Linux distribution using the default package manager like
&lt;code&gt;zypper&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt; or &lt;code&gt;apt&lt;/code&gt;, and those python files will be placed in the
system paths that you can see above.&lt;/p&gt;
&lt;p&gt;But distributions doesn't pack all the python modules and even if they
do, you can require an specific version that's different from the one
packaged in your favourite distribution, so in python it's common to
install dependencies from the &lt;a href="https://pypi.org/"&gt;Python Package Index (PyPI)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python has a tool to install and manage Python packages that looks for
desired python modules in PyPI.&lt;/p&gt;
&lt;p&gt;You can install new dependencies with &lt;code&gt;pip&lt;/code&gt; just like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;django
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that command looks for the &lt;code&gt;django&lt;/code&gt; python module in the PyPI,
downloads and install it, in your user
&lt;code&gt;$HOME/.local/lib/python3.11/site-packages&lt;/code&gt; folder if you
use &lt;code&gt;--user&lt;/code&gt;, or in a global system path like &lt;code&gt;/usr/local/lib&lt;/code&gt; or
&lt;code&gt;/usr/lib&lt;/code&gt; if you run pip as root.&lt;/p&gt;
&lt;p&gt;But the usage of &lt;code&gt;pip&lt;/code&gt; directly in the system is something &lt;strong&gt;not
recommended today&lt;/strong&gt;, and even &lt;a href="https://packaging.python.org/en/latest/specifications/externally-managed-environments/#externally-managed-environments"&gt;it's disabled&lt;/a&gt; in some
distributions, like openSUSE Tumbleweed.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;danigm&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;django&lt;/span&gt;
&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;externally&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;managed&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;

&lt;span class="err"&gt;×&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;externally&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;managed&lt;/span&gt;
&lt;span class="err"&gt;╰─&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;To&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;wide&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;try&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;zypper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python311&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;trying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rpm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packaged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python3&lt;/span&gt;&lt;span class="m m-Double"&gt;.11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;Then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rpm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;packaged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;may&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;easiest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;xyz&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;manage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;virtual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;via&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="nx"&gt;zypper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;python311&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;pipx&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;note&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;believe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mistake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;please&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;installation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;distribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;override&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;risk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;breaking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;installation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;passing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;See&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PEP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;668&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;detailed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;specification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;virtualenvs&lt;/h2&gt;
&lt;p&gt;Following the current recommendation, the correct way of installing
third party python modules is to use &lt;code&gt;virtualenvs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;virtualenvs&lt;/code&gt; are just specific folders where you install your
python modules and some scripts that make's easy to use it in
combination with your system libraries so you don't need to modify the
&lt;code&gt;PYTHONPATH&lt;/code&gt; manually.&lt;/p&gt;
&lt;p&gt;So if you've a custom project and want to install python modules you
can create your own virtualenv and use pip to install dependencies
there:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm@localhost tmp&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;
&lt;span class="n"&gt;Collecting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;Successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;asgiref&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;3.7.2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;5.0.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sqlparse&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.4.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So all dependencies are installed in my new virtualenv folder and if I
use the python from the virtualenv it's using those paths, so all the
modules installed there are usable inside that virtualenv:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="mf"&gt;.11&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;apps&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;contrib&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;shortcuts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;templatetags&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;
&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;__main__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;__pycache__&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;utils&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;import django; print(django.__version__)&amp;quot;&lt;/span&gt;
&lt;span class="mf"&gt;5.0.1&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;danigm&lt;/span&gt;&lt;span class="nd"&gt;@localhost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deactivate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With virtualenvs you can have multiple python projects, with different
dependencies, isolated, so you use different dependencies when you
activate your desired virtualenv:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;activate &lt;code&gt;$ . ./myenv/bin/activate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;deactivate &lt;code&gt;$ deactivate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;High level tools to handle virtualenvs&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/venv.html#module-venv"&gt;venv&lt;/a&gt; module is a default Python module and as you can see
above, it's really simple to use, but there are some tools that
provides some tooling around it, to make it easy for you, so usually
you don't need to use &lt;code&gt;venv&lt;/code&gt; directly.&lt;/p&gt;
&lt;h3&gt;pipx&lt;/h3&gt;
&lt;p&gt;For final python tools, that you are not going to use as dependencies
in your python code, the recommended tool to use is &lt;a href="https://github.com/pypa/pipx"&gt;pipx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/pictures/pipx_demo.gif" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;The tool creates virtualenv automatically and links the binaries so
you don't need to worry about anything, just use as a way to install
third party python applications and update/uninstall using it. The
&lt;code&gt;pipx&lt;/code&gt; won't mess your system libraries and each installation will use
a different virtualenv, so even tools with incompatible dependencies
will work nicely together in the same system.&lt;/p&gt;
&lt;h3&gt;Libraries, for Python developers&lt;/h3&gt;
&lt;p&gt;In the case of Python developers, when you need to manage dependencies
for your project, there are a lot of nice high level tools for
&lt;a href="https://packaging.python.org/en/latest/tutorials/managing-dependencies/#other-tools-for-application-dependency-management"&gt;managing dependencies&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pdm-project/pdm"&gt;PDM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pypa/hatch"&gt;hatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/thoth-station/micropipenv"&gt;micropipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jazzband/pip-tools"&gt;pip-tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packaging.python.org/en/latest/key_projects/#pipenv"&gt;pipenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/python-poetry/poetry"&gt;poetry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tools provides different ways of managing dependencies, but all
of them relies in the use of &lt;code&gt;venv&lt;/code&gt;, creating the virtualenv in
different locations and providing tools to enable/disable and manage
dependencies inside those virtualenvs.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;poetry&lt;/code&gt; creates virtualenvs by default inside the
&lt;code&gt;.cache&lt;/code&gt; folder, in my case I can find all poetry created virtualenvs
in:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/home/danigm/.cache/pypoetry/virtualenvs/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most of these tools add other utilities on top of the dependency
management. Just for installing python modules easily you can always
use default &lt;code&gt;venv&lt;/code&gt; and &lt;code&gt;pip&lt;/code&gt; modules, but for more complex projects
it's worth to investigate high level tools, because it'll make easy to
manage your project dependencies and virtualenvs.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There are a lot of python code inside any modern Linux distribution
and if you're a python developer it's possible to have a lot of python
code. Make sure to know the source of your modules and do not mix
different environments to avoid future headaches.&lt;/p&gt;
&lt;p&gt;As a final trick, if you don't know where's the actual code of some
python module in your running python script, you can always ask:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;django&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;/tmp/myenv/lib64/python3.11/site-packages/django/__init__.py&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This could be even more complicated if you start to use containers
and different python versions, so keep you dependencies clean and up
to date and make sue that you know &lt;strong&gt;where is your Python code&lt;/strong&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 03 Feb 2024 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2024-02-03:/wheres-my-python-code.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>python</category></item><item><title>Hackweek 23</title><link>https://danigm.net/hackweek23.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek23.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt; is the time SUSE employees experiment, innovate &amp;amp; learn
interruption-free for a whole week! Across teams or alone, but always without
limits.&lt;/p&gt;
&lt;p&gt;The Hack Week 23 was from November 6th to November 10th, and my project was to
gvie some &lt;a href="https://hackweek.opensuse.org/23/projects/gnome-love"&gt;love to the GNOME Project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before the start of the Hack week I asked in the GNOME devs Matrix channel,
what project needs some help and they gave me some ideas. At the end I decided
to work on the &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/"&gt;GNOME Calendar&lt;/a&gt;, more specifically, improving the test suite
and fixing &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1093"&gt;issues related to timezones&lt;/a&gt;, DST, etc.&lt;/p&gt;
&lt;h2&gt;GNOME Calendar&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-calendar.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;GNOME Calendar is a &lt;a href="https://gtk.org/"&gt;Gtk4 application&lt;/a&gt;, written in C, that heavily uses the
&lt;a href="https://gitlab.gnome.org/GNOME/evolution-data-server"&gt;evolution-data-server&lt;/a&gt; library. It's a desktop calendar application with a
modern user interface that can connect handle local and remote calendars. It's
integrated in the GNOME desktop.&lt;/p&gt;
&lt;p&gt;The current gnome-calendar project has some unit tests, using the &lt;a href="https://docs.gtk.org/glib/testing.html"&gt;GLib testing
framework&lt;/a&gt;. But right now there are just a few tests, so the main goal right
now is to increase the number of tests as much as possible, to detect new
problems and regressions.&lt;/p&gt;
&lt;p&gt;Testing a desktop application is not something easy to do. The unit tests can
check basic operations, structures and methods, but the user interaction and
how it's represented is something hard to test. So the best approach is to try
replicate user interactions and check the outputs.&lt;/p&gt;
&lt;p&gt;A more sophisticated approach could be to start to use the accessibility stack
in tests, so it's possible to verify the UI widgets output without the need of
rendering the app.&lt;/p&gt;
&lt;p&gt;With gnome-calendar there's another point of complexity for tests because it
relies on the evolution-data-server to be running, the app communicates with it
using dbus, so to be able to do more complex tests we should mock the
evolution-data-server and we should create fake data for testing.&lt;/p&gt;
&lt;h2&gt;My contribution&lt;/h2&gt;
&lt;p&gt;By the end of the week I've created four &lt;a href="https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests?scope=all&amp;amp;state=all&amp;amp;author_username=danigm&amp;amp;label_name%5B%5D=Timezones"&gt;Merge requests&lt;/a&gt;, three of them
have been merged now, and I'll continue working on this project in the
following weeks/months.&lt;/p&gt;
&lt;p&gt;I'm happy with the work that I was able to do during this Hack Week. I've
learned a bit about testing with GLib in C, and a lot about the
evolution-data-server, timezones and calendar problems.&lt;/p&gt;
&lt;p&gt;It's just a desktop calendar application, how hard it could be? Have you ever
deal with dates, times and different regions and time zones? It's a nightmare.
There are a lot of edge cases working with dates that can cause problems,
operations with dates in different time zones, changes in dates for daylight
saving, if I've an event created for October 29th 2023 at 2:30 it will happens
two times?&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/gnome-calendar-issues.png" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;A lot of problems could happen and there are a lot of bugs reported for
gnome-calendar related to this kind of issues, so working on this is not
something simple, it requires a lot of edge case testing and that's the plan,
to cover most of them with automated tests, because any small change could lead
to a bug related to time zones that won't be noticed until someone has an
appointment at a very specific time.&lt;/p&gt;
&lt;p&gt;And this week was very productive thanks to the people working on
gnome-calendar. Georges Stavracas reviews my MR very quickly and it was
possible to merge during the week, and Jeff Fortin does a great work with the
issues in gitlab and leading me to most relevant bugs.&lt;/p&gt;
&lt;p&gt;So after a week of going deep into the gnome-calendar source code it could be a
pity to just forget about it, so I'll try to keep the momentum and continue
working on this project, of course, I'll have just a few hours per week, but
any contribution is better than nothing. And maybe for the next summer I can
propose a Google Summer of Code project to get an intern working on this full
time.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 10 Nov 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-11-10:/hackweek23.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>opensuse</category><category>hackweek</category></item><item><title>Updating GNOME shell extensions to GNOME 45</title><link>https://danigm.net/gnome-45-extensions.html</link><description>&lt;p&gt;&lt;img src="/pictures/GNOME45.webp" width="100%" /&gt;&lt;/p&gt;
&lt;p&gt;The new version of the &lt;a href="https://www.gnome.org/"&gt;GNOME desktop&lt;/a&gt; was released &lt;a href="https://foundation.gnome.org/2023/09/20/introducing-gnome-45/"&gt;more than one month&lt;/a&gt;
ago. It takes some time to arrive to the final user, because distributions
should integrate, tests and release the new desktop, and that's not something
simple, and it should integrate in the distribution release planning.&lt;/p&gt;
&lt;p&gt;So right now, it's possible that there's just a few people with the latest
version of the desktop right now, just people with rolling release distros or
people using testing versions of mayor distributions.&lt;/p&gt;
&lt;p&gt;This is one of the reasons because a lot of gnome-shell extensions aren't
updated to work with the latest version of GNOME, even after a few months,
because even developers doesn't have the latest version of the desktop and
it's not something "easy" to install, without a virtual machine or something
like that. Even if the update is just a change in the metadata.json, there
should be someone to test the extension, and even someone to request this
update, and that will happen once the mayor distributions release a new
version.&lt;/p&gt;
&lt;p&gt;I'm using Tumbleweed, that's a rolling release and GNOME 45 is here just after
the official release, but of course, a lot of extensions are not working, and
in the infamous list of non working extensions there where the three that I'm
&lt;a href="https://extensions.gnome.org/accounts/profile/danigm"&gt;maintaining right now&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/spotify-ad-blocker"&gt;mute-spotify-ads&lt;/a&gt;, extension to mute the spotify app when it's playing ads.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/gnome-shell-calculator"&gt;calc&lt;/a&gt;, a simple calculator in the alt+F2 input.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/danigm/hide-minimized"&gt;hide-minimized&lt;/a&gt;, hide minimized windows from alt+tab and overview.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/GNOME45-desktop.webp" /&gt;
&lt;/p&gt;

&lt;h2&gt;The correct way&lt;/h2&gt;
&lt;p&gt;The correct way to maintain and update a gnome-shell extension should be to
test and update "before" the official release of GNOME. It should be something
easy for me, using Tumbleweed I can just add the &lt;a href="https://build.opensuse.org/project/show/GNOME:Next"&gt;GNOME Next&lt;/a&gt; repository,
install the new desktop when it's in beta stage, and update the extension
there.&lt;/p&gt;
&lt;p&gt;But that's something that require an active maintainership... And right now
what I do is to update the extensions when they are broken for me, so just when
I need them, and that's after I get the new desktop and I find some time to
update.&lt;/p&gt;
&lt;p&gt;I know that's not the correct way and this produces a bad experience for other
people using the extensions, but this is the easier thing to do for me. Maybe
in the future I can do it correctly, and provide a tested update before the
official release, maybe using snapper to be able to go back to stable, without
the need of using virtual machines.&lt;/p&gt;
&lt;h2&gt;Update your extension to GNOME 45&lt;/h2&gt;
&lt;p&gt;The update to GNOME 45 was a bit more complex than previous ones. This version
of the shell and gjs change a lot of things, so the migration it's not just to
add a new number to the metadata.json, but requires incompatible changes, so
extensions that works for GNOME 45 won't work for previous versions and
vice versa.&lt;/p&gt;
&lt;p&gt;But the people working in gnome-shell does a great work documenting and there's
a really nice guide about &lt;a href="https://gjs.guide/extensions/upgrading/gnome-shell-45.html"&gt;how to upgrade your extension&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most important part is the import section, that now it has a different syntax.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Before&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GNOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imports&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GNOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resource:///org/gnome/shell/ui/main.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And some changes in the extension class, that now can inherit from existing
ones to provide common usage, like preferences window:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;Adw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gi://Adw&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ExtensionPreferences&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gettext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;MyExtensionPreferences&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ExtensionPreferences&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;fillPreferencesWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getSettings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PreferencesPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Adw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PreferencesGroup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Group Title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 03 Nov 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-11-03:/gnome-45-extensions.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>linux</category><category>javascript</category></item><item><title>One year of Tumbleweed</title><link>https://danigm.net/tumbleweed.html</link><description>&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://www.opensuse.org/#Tumbleweed"&gt;
        &lt;img src="/pictures/tumbleweed.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;More than a year has passed since I switched to &lt;a href="https://www.opensuse.org/#Tumbleweed"&gt;openSUSE Tumbleweed&lt;/a&gt;
Linux distribution, in both, my work computer (for obvious reasons)
and in my personal computer and I can say that I'm really happy with
the change.&lt;/p&gt;
&lt;p&gt;Tumbleweed is a &lt;a href="https://en.wikipedia.org/wiki/Rolling_release"&gt;rolling release&lt;/a&gt; distribution, and in this kind of
distributions there are a lot of changes every week, if you want the
latest software, this kind of distribution is the way to go. But with
high update frequency you are exposed to some kind of instability,
it's impossible to have the latest changes without some broken program
here and there, because not everyone is able to follow upstream
changes without some weeks or months to update.&lt;/p&gt;
&lt;h2&gt;My distro history&lt;/h2&gt;
&lt;p&gt;I've been always a Linux user, since I get my first computer at 2003.
In those days I was using a &lt;a href="https://www.debian.org/"&gt;debian&lt;/a&gt; base distribution called
&lt;a href="https://www.knopper.net/knoppix/index-en.html"&gt;knoppix&lt;/a&gt;. Then I switched to &lt;a href="https://ubuntu.com/"&gt;ubuntu&lt;/a&gt; when it appeared around 2004.
But at that time I was a computer science student and I was exploring
the whole free software and Linux ecosystem, so I was changing my
distribution every time that I found a new one.&lt;/p&gt;
&lt;p&gt;Like a lot of distro-hoppers, at some point I landed at &lt;a href="https://archlinux.org/"&gt;ArchLinux&lt;/a&gt;
and there I discovered the rolling release concept. And that was my
home for some time, it was nice to have the latest available software
just after the release.&lt;/p&gt;
&lt;p&gt;At some point I bough a new computer and it was too new to work
correctly with the kernel distributed in ArchLinux, so I tried
different distributions and at that moment &lt;a href="https://fedoraproject.org/"&gt;Fedora&lt;/a&gt; was the distro
that works without too much complications with that computer, so I
picked that one.&lt;/p&gt;
&lt;p&gt;In 2019 I started to work at Endless and at that time I should try the
&lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, so I played a bit with &lt;a href="https://danigm.net/endlessos-dual-boot.html"&gt;the dual boot&lt;/a&gt;, having
Fedora and EndlessOS at the same time. That was the first time that I
get in contact with immutable distributions, something that's getting
more popular everyday, but this distributions rely a lot on containers
(flatpak, podman) and, even being something that could work, as a
software engineer, I don't feel comfortable enough needing a container
with another distribution to do something that could be in my system.&lt;/p&gt;
&lt;p&gt;In 2022 I started to &lt;a href="https://danigm.net/suse.html"&gt;work at SUSE&lt;/a&gt; and for the first time I tried
the openSUSE distribution until today.&lt;/p&gt;
&lt;h2&gt;The Tumbleweed&lt;/h2&gt;
&lt;p&gt;Today I've three different computers with Tumbleweed running. One for
work, Thinkpad T14s, one for personal usage, Dell inspiron 5490, and
another one as a personal media server, Libre computer &lt;a href="https://libre.computer/products/aml-s805x-ac/"&gt;La-frite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The best thing of having Tumbleweed for me is that I get the latest
&lt;strong&gt;GNOME&lt;/strong&gt; as soon as it's released. And another big thing for this
distribution is how easy it's to fix something upstream thanks to the
&lt;a href="https://build.opensuse.org/project/show/openSUSE:Factory"&gt;Open Build Service&lt;/a&gt;, but I work everyday with that, so I'm
biased. For sure, any other community distribution has different ways
to contribute, but I find this one easy enough.&lt;/p&gt;
&lt;p&gt;Even being a rolling release distro, Tumbleweed doesn't break a lot. I
can't say that it's stable, because the API of everything is broken
everyday, but the &lt;a href="https://openqa.opensuse.org/group_overview/1"&gt;distribution is tested&lt;/a&gt; for every release and
at least some level of package compatibility check is done. That makes
Tumbleweed a good distribution and I can update without fearing some
weird package breakage.&lt;/p&gt;
&lt;p&gt;I usually update my work and personal laptops once a week, and
la-frite not so often, maybe every 6 months.&lt;/p&gt;
&lt;p&gt;With the default installation, Tumbleweed uses btrfs with snapshots,
and it's really easy to go back and forward using the
&lt;a href="https://en.opensuse.org/openSUSE:Snapper_Tutorial"&gt;snapper tool&lt;/a&gt;. So it's really easy to go back to a good state if
the distribution is broken for some reason, and wait for a fix.&lt;/p&gt;
&lt;h2&gt;The problems that I found during this year&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some problems with the NVidia graphic card in my Dell laptop, some
   times the kernel and the driver were not working correctly. I had
   to use snapper to get the NVidia working again, but fixed a few
   days later.&lt;/li&gt;
&lt;li&gt;Currently I'm having some random crashes because some bug with
   &lt;a href="https://bugzilla.suse.com/show_bug.cgi?id=1215695"&gt;amdgpu&lt;/a&gt; and wayland and mutter, but it's not too annoying for
   me to go back, so I didn't use snapper this time and I'm facing
   this random crashes waiting for the fix.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Long live the Tumbleweed&lt;/h2&gt;
&lt;p&gt;So far so good. Tumbleweed is a nice distribution that I'm enjoying.
It's not getting in the way and I can find almost anything that I need
for work, programming, gaming, media, etc. I'm really happy with this
distribution and it's the perfect distribution for people like me,
that want to have the latest things.&lt;/p&gt;
&lt;p&gt;I know that there are other openSUSE flavors that are interesting,
like the &lt;a href="https://en.opensuse.org/Portal:Aeon"&gt;immutable ones&lt;/a&gt;, &lt;a href="https://en.opensuse.org/openSUSE:Slowroll"&gt;Leap&lt;/a&gt; or the latest one
&lt;a href="https://en.opensuse.org/openSUSE:Slowroll"&gt;Slowroll&lt;/a&gt;, but Tumbleweed is the one for me.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 06 Oct 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-10-06:/tumbleweed.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>openSUSE</category><category>tumbleweed</category><category>linux</category><category>distribution</category></item><item><title>rpmlint updates (August 2023)</title><link>https://danigm.net/rpmlint-updates-2023-08-30.html</link><description>&lt;p&gt;We are at the end of the summer and this means that this year Google Summer of
code is ending.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/rpmlint-gitg-gsoc-2023.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The recent changes applied now in the main branch include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove usage of &lt;code&gt;pkg_resource&lt;/code&gt; because it's deprecated.&lt;/li&gt;
&lt;li&gt;Fix elf binary check with ELF files with a prefix.&lt;/li&gt;
&lt;li&gt;New check for python packages with multiple .pyc files for different python
   versions.&lt;/li&gt;
&lt;li&gt;Improve the testing framework (merged the work done during the GSoC 2023)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summer of Code 2023 updates&lt;/h2&gt;
&lt;p&gt;The summer of code is ending and the work done by &lt;a href="https://github.com/rpm-software-management/rpmlint/pull/1101"&gt;Afrid was good enough to be merged&lt;/a&gt;,
so I merged it the past week.&lt;/p&gt;
&lt;p&gt;I'm really happy with the work done during the GSoC program, now we've a more
simple way to define tests for rpmlint checks mocking the rpm, so it's not
always needed to build a fake rpm binary for each new test. This will make a
lot easier to create simple tests, so I hope that we can increase the code
coverage using this &lt;a href="https://github.com/rpm-software-management/rpmlint/blob/main/test/README.md"&gt;new framework&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During this time Afrid has extended the &lt;code&gt;FakePkg&lt;/code&gt; class, so it's possible now
to define fake metadata and files with fake tags and attributes. It's not
complete and it's not a simple task to replace all the &lt;code&gt;rpm&lt;/code&gt; binaries used for
tests, because the &lt;code&gt;Pkg&lt;/code&gt; class and &lt;code&gt;RPM&lt;/code&gt; tags is a complex thing, but the
current state allow us to replace a lot of them. Afrid has replaced some of the
tests that uses binaries, but in the following months we can continue working
on this and &lt;a href="https://github.com/rpm-software-management/rpmlint/issues/1105"&gt;replace more&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After this work, we can now start to use more the &lt;code&gt;FakePkg&lt;/code&gt; class in tests,
so another task that we can do is to provide some &lt;a href="https://github.com/rpm-software-management/rpmlint/issues/1104"&gt;common fake pkgs&lt;/a&gt; to use
in different tests and new checks, so now it's possible to create fake packages
with dynamic random data, so we can extend tests with fuzz testing and maybe
this will help to improve the tool reliability.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/gsoc.png" /&gt;
&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I've participated as mentor several times now in the &lt;a href="https://summerofcode.withgoogle.com/"&gt;summer of code&lt;/a&gt;, and
&lt;a href="https://www.outreachy.org/"&gt;outreachy&lt;/a&gt;, and almost always was a good experience. With the &lt;a href="https://www.gnome.org/"&gt;gnome foundation&lt;/a&gt;
in previous programs and this year with &lt;a href="https://www.opensuse.org/"&gt;opensuse&lt;/a&gt;. These two communities
are very open to collaboration and makes the whole process really simple, for
me as mentor, and also for the intern.&lt;/p&gt;
&lt;p&gt;I want to congratulate Afrid, because it was nice to work with him during this
summer, he has done a great work, not just technically, but communicating,
asking and finding his own solutions without requiring a continuous guidance.&lt;/p&gt;
&lt;p&gt;He is very passionate and looks like a nice person, so I hope that he will
continue around the open source, it could be opensuse, rpmlint or any other
community, but this kind of people is what you want to find in any community.&lt;/p&gt;
&lt;p&gt;After many years collaborating with different free software communities, it's
amazing that there are so many great people in every project, of course you can
find toxic communities and people, but in my experience, that's usually just
noise, there are a lot of nice people out there, doing a great work, and I'm
happy that young people like Afrid can be part of the free software movement,
because this is what makes the free software great, the people that is
working on it.&lt;/p&gt;
&lt;p&gt;So Thanks a lot to Google for another summer of code, thanks to SUSE for
letting me, and encourage me, to mentor, and thanks to all the free software
developers that are out there.&lt;/p&gt;
&lt;p&gt;I encourage everyone to participate in this kind of programs, for interns, it's
a good opportunity to learn and to make some money working on free software,
for mentors it's an opportunity to get some help in your project and help
newcomers to be part of the community.&lt;/p&gt;
&lt;p&gt;Have a lot of fun!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 30 Aug 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-08-30:/rpmlint-updates-2023-08-30.html</guid><category>blog</category><category>gnome</category><category>software</category><category>rpmlint</category><category>suse</category><category>gsoc</category></item><item><title>Python in openSUSE Tumbleweed</title><link>https://danigm.net/python-tw.html</link><description>&lt;p&gt;&lt;a href="https://www.opensuse.org/#Tumbleweed"&gt;openSUSE Tumbleweed&lt;/a&gt; is a rolling release distribution, so it's
ideal for developers and users that like to have the bleeding edge
software.&lt;/p&gt;
&lt;p&gt;It's also really "stable" to be a rolling release, from time
to time you can find a broken package because of one package is
updated and another one is not compatible yet, but it's something that
doesn't happen too often thanks to &lt;a href="https://openqa.opensuse.org/group_overview/1"&gt;openqa tests&lt;/a&gt;, so you don't
need to worry about a breaking system.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/python-tw.png" /&gt;
&lt;/p&gt;

&lt;p&gt;You can find the &lt;a href="https://www.python.org/"&gt;Python interpreter&lt;/a&gt; and a lot of &lt;a href="https://pypi.org/"&gt;python modules&lt;/a&gt;
in every Linux distribution, but Tumbleweed does an interesting thing
for Python.&lt;/p&gt;
&lt;h2&gt;Default Python version (python3 -&amp;gt; python-3.11)&lt;/h2&gt;
&lt;p&gt;If you don't worry about the python version, you can just rely on
&lt;code&gt;python3&lt;/code&gt;. In Tumbleweed &lt;code&gt;python3&lt;/code&gt; is not a real package, but the
default python version provides &lt;code&gt;python3&lt;/code&gt;, so depending on when you
install &lt;code&gt;python3&lt;/code&gt; you will get a different package, if you install
it today (August 2023) you'll get &lt;code&gt;python311&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In your system you'll have the &lt;code&gt;/usr/bin/python3&lt;/code&gt; binary that points
to the default python, so you don't need to worry about the current
version, you'll have there the default Python version for the
operating system.&lt;/p&gt;
&lt;p&gt;In addition to the Python interpreter, you can find in the
distribution a lot of python modules, but again you can use the
default version, so, for example, if you want to install &lt;code&gt;poetry&lt;/code&gt;, you
just use &lt;code&gt;zypper install python3-poetry&lt;/code&gt; and that will install
the real package &lt;code&gt;python311-poetry&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Multiple python versions (3.8, 3.9, 3.10, 3.11)&lt;/h2&gt;
&lt;p&gt;Besides the default Python, in Tumbleweed you can also find other
supported Python interpreters. Right now you can find all the Python
versions currently supported by the Python Foundation, from 3.8 to
3.11.&lt;/p&gt;
&lt;p&gt;For Python 3.8 you'll only find the interpreter, because the python
modules are not built anymore, but for all the other versions you can
find almost the same modules.&lt;/p&gt;
&lt;p&gt;All python modules that provide binaries uses the
&lt;code&gt;update-alternatives&lt;/code&gt;, so you can configure in your system the version
that you want to use as default. For example, if you want to use the
&lt;code&gt;3.9&lt;/code&gt; version of &lt;code&gt;poetry&lt;/code&gt;, having installed different versions you can
decide what &lt;code&gt;/usr/bin/poetry&lt;/code&gt; points to:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;zypper&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python311-poetry&lt;span class="w"&gt; &lt;/span&gt;python39-poetry
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;update-alternatives&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;poetry
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;/usr/bin/python3&lt;/code&gt; is a link provided by the default python package,
so you can't modify with &lt;code&gt;update-alternatives&lt;/code&gt;, so if you want to use
a different python version, make sure to do the correct call with the
full name &lt;code&gt;python3.9&lt;/code&gt;, and use the correct shebang in your python
scripts, for example &lt;code&gt;#!/usr/bin/env python3.9&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;What happens when default changes?&lt;/h2&gt;
&lt;p&gt;This way of distributing Python interpreter and modules is useful,
because you don't need to update your software to work with the latest
Python version, if your software requires another version, you can just
install and continue using it, even on a bleeding-edge distribution
like Tumbleweed.&lt;/p&gt;
&lt;p&gt;But this method has some problems. When the default Python interpreter
is changed in the distribution, all packages that depends on &lt;code&gt;python3&lt;/code&gt;
will be updated, and that works correctly. But if you have installed
some python module using the &lt;code&gt;python3&lt;/code&gt; prefix, that package, and all
dependencies, is not updated automatically.&lt;/p&gt;
&lt;p&gt;For example, if you installed &lt;code&gt;python3-poetry&lt;/code&gt; when &lt;code&gt;python3.10&lt;/code&gt; was
the default system, and then the distribution updates the system
Python to &lt;code&gt;python3.11&lt;/code&gt;, you don't get the &lt;code&gt;python311-poetry&lt;/code&gt; package
by default, you'll need to install it again. This could break you
software, because if you use &lt;code&gt;python3&lt;/code&gt; and the dependencies are not
updated, you'll find that some dependencies are not installed after
updating.&lt;/p&gt;
&lt;p&gt;For that reason, when the default python is changed in Tumbleweed, if
you've software that rely on &lt;code&gt;python3&lt;/code&gt; you should make sure to install
dependencies again by hand. And also you can do a cleanup and remove
all old version packages that you don't need anymore.&lt;/p&gt;
&lt;p&gt;If you just want the latest version you can just do all at once with a
simple script like this:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c1"&gt;# up-py-tw.sh&lt;/span&gt;

&lt;span class="nv"&gt;FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nv"&gt;TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-lt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Usage:   up-py-tw.sh FROM TO&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;example: up-py-tw.sh 310 311&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating python packages from &lt;/span&gt;&lt;span class="nv"&gt;$FROM&lt;/span&gt;&lt;span class="s2"&gt; to &lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="nv"&gt;OLDP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;zypper&lt;span class="w"&gt; &lt;/span&gt;-q&lt;span class="w"&gt; &lt;/span&gt;search&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FROM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;-*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;--lines&lt;span class="w"&gt; &lt;/span&gt;+4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;--delimiter&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--fields&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;NEWP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$OLDP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;s/python&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FROM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/python&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TO&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/g&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;

sudo&lt;span class="w"&gt; &lt;/span&gt;zypper&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NEWP&lt;/span&gt;
sudo&lt;span class="w"&gt; &lt;/span&gt;zypper&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$OLDP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should verify what will be installed and what will be removed to
make sure that just the python related packages are removed. It's
possible that other packages depend on a python version that's older
than the system one and that's okay.&lt;/p&gt;
&lt;h2&gt;Beta version (3.12.0b4)&lt;/h2&gt;
&lt;p&gt;In Tumbleweed, right now you can find all the supported Python
versions, but it's not just that. At this moment you can also find the
beta version of the next Python interpreter.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;zypper&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python312
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So if you are adventurous and want to test some new feature in the
next Python release, you can do it with the version provided there.
This version could also be used by openSUSE packagers to test the
packages before the Python version is released so it allow us to
prepare everything for the release and it could be in the distribution
earlier and more tested.&lt;/p&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;p&gt;All this multiple python versions is done at distribution level and
usually there's only one source package that produces the
&lt;code&gt;python39-foo&lt;/code&gt;, &lt;code&gt;python310-foo&lt;/code&gt; and &lt;code&gt;python311-foo&lt;/code&gt;. The source
package is usually called &lt;code&gt;python-foo&lt;/code&gt; and can be found in the
&lt;a href="https://build.opensuse.org/project/show/devel:languages:python"&gt;Python devel project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These packages spec uses the python-rpm-macros to generate all the
versions from one source. If you're a packager you can find more
information on the openSUSE wiki about &lt;a href="https://en.opensuse.org/openSUSE:Packaging_Python"&gt;Python Packaging&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 05 Aug 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-08-05:/python-tw.html</guid><category>blog</category><category>software</category><category>suse</category><category>tumbleweed</category><category>gnome</category></item><item><title>rpmlint updates (July 2023)</title><link>https://danigm.net/rpmlint-updates.html</link><description>&lt;p&gt;I'm spending some time every week working in the &lt;a href="https://github.com/rpm-software-management/rpmlint"&gt;rpmlint&lt;/a&gt; project.
The tool is very stable and the functionality is well defined,
implemented and tested, so there's no crazy development or a lot of
new functionalities, but as in all the software, there are always bugs
to solve and things to improve.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/rpmlint-gitg-20230706.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The recent changes applied now in the main branch include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Update the usage of &lt;code&gt;rpm&lt;/code&gt; to not use old API.&lt;/li&gt;
&lt;li&gt;Fixes for &lt;code&gt;rpmdiff -v&lt;/code&gt;, check for NULL char, special macros in
   comments and spell checking of description in different languages.&lt;/li&gt;
&lt;li&gt;Move all the metadata from &lt;code&gt;setup.py&lt;/code&gt; to &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Releasing rpmlint as pre-commit hook&lt;/li&gt;
&lt;li&gt;Improvements to the PythonCheck in the dependency checking.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summer of Code 2023 updates&lt;/h2&gt;
&lt;p&gt;The first month of the Summer of Code has passed and &lt;a href="https://afridhussain.tech"&gt;Afrid&lt;/a&gt; is
doing a great job there. We've now a &lt;a href="https://github.com/rpm-software-management/rpmlint/pull/1079"&gt;draft Pull Request&lt;/a&gt; with some
initial changes that allow us to mock &lt;code&gt;rpm&lt;/code&gt; packages in tests so it's
easier to create new tests without the need of creating a binary
package.&lt;/p&gt;
&lt;p&gt;The first step done was to extend the existing &lt;code&gt;FakePkg&lt;/code&gt; class to
allow us to define package files and some package metadata.&lt;/p&gt;
&lt;p&gt;Now he's working in replacing all of the &lt;code&gt;test_python.py&lt;/code&gt; tests that
uses binaries &lt;code&gt;rpm&lt;/code&gt; to something that doesn't needed.&lt;/p&gt;
&lt;p&gt;The idea is to replace as much tests as possible to reduce the number
of rpm binaries and after that, provide helper functions, decorators
and classes to make it easy to write tests, writing less code.&lt;/p&gt;
&lt;h2&gt;Roadmap&lt;/h2&gt;
&lt;p&gt;In any software project there's always room for improvements, fixes
and enhancements. If the project is there for enough time, it's even
more critical to modernize the code to reduce the technical debt.&lt;/p&gt;
&lt;p&gt;My plan for 2023 is to improve the tests around rpmlint as much as
possible. First with the GSoC project, making it easier to write more
tests, improving the testing tools that we've. And after the summer,
improving the test coverage.&lt;/p&gt;
&lt;p&gt;There's also a tool that shares some of the ideas with rpmlint,
&lt;a href="https://github.com/rpm-software-management/spec-cleaner"&gt;spec-cleaner&lt;/a&gt;, it's also written in Python, so the next step,
after the tests improvements will be to take a deep look into the code
of these two tools and try to integrate in some way. Maybe it's
possible to refactor the common code into an external module, maybe we
can bring some ideas from spec-cleaner to rpmlint. Not sure yet, but
that'll be my next step.&lt;/p&gt;
&lt;p&gt;Don't forget that this is free software, so you can participate too!
If you find any issue in rpmlint or have an idea to improve it, don't
hesitate and &lt;a href="https://github.com/rpm-software-management/rpmlint/issues"&gt;create a new issue&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 06 Jul 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-07-06:/rpmlint-updates.html</guid><category>blog</category><category>gnome</category><category>software</category><category>rpmlint</category><category>suse</category><category>gsoc</category></item><item><title>rpmlint: Google Summer of Code 2023</title><link>https://danigm.net/gsoc-2023.html</link><description>&lt;p&gt;I'm glad to say that I'll participate again in the &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt;, as
mentor. This year will be a bit different from the previous ones,
because I'm not mentoring a GNOME project but a &lt;a href="https://www.opensuse.org/"&gt;openSUSE&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;I started to work at SUSE the past year and with this new job I get
involved in the openSUSE community and I started to contribute to
&lt;a href="https://github.com/rpm-software-management/rpmlint"&gt;rpmlint&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So this summer I'll be mentoring an intern and we'll work on improving
the testing framework of the &lt;a href="https://github.com/openSUSE/mentoring/issues/189"&gt;rpmlint project&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/rpmlint.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The rpmlint project is a command line tool to check rpm packages, the
correctness of these kind of packages and warn the packagers about
usual problems or good practices. It's widely used in all Linux
distributions based on rpm, mainly SUSE and RedHat.&lt;/p&gt;
&lt;p&gt;It is written in Python and uses pytest for testing the code. Right
now there are a lot of .rpm binary packages, to check different
functionality, but that way of testing makes a bit hard to write new
tests and to maintain with changes. The idea of this GSoC project is
to extend the testing framework of rpmlint to support an easy way
of writting tests that doesn't require a real rpm, something that can
mock what it's in the .rpm binary and try to replace some of the
current binary tests with this new mock.&lt;/p&gt;
&lt;p&gt;The selected intern is &lt;a href="https://afridhussain.tech/post/accepted-into-gsoc/"&gt;Afrid Hussain&lt;/a&gt;. He has done some initial
work in the rpmlint project, solving some minor issues and we're now
preparing the work to be done during the GSoC program. I'm sure that
he will be able to achieve great things during these three months, so
I'm looking forward to start to code and see how far can we go.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 16 May 2023 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2023-05-16:/gsoc-2023.html</guid><category>blog</category><category>gnome</category><category>software</category><category>rpmlint</category><category>suse</category><category>gsoc</category></item><item><title>Hackweek 2023</title><link>https://danigm.net/hackweek22.html</link><description>&lt;p&gt;&lt;center&gt;
    &lt;img src="/pictures/hackweek.png" width="50%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hackweek.opensuse.org/"&gt;Hack Week&lt;/a&gt; is the time SUSE employees experiment, innovate &amp;amp; learn
interruption-free for a whole week! Across teams or alone, but always without
limits.&lt;/p&gt;
&lt;p&gt;This year the Hack Week was this week, the last week of January and for my
first SUSE hack week I decided to work in something funny, &lt;a href="https://hackweek.opensuse.org/22/projects/linux-immersive-learning-system-lils"&gt;LILS&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Linux Immersive Learning System (LILS)&lt;/h2&gt;
&lt;p&gt;I don't think that this is a good name, but don't focus on it. The main idea of
this project is to create some basic machinery to be able to write
"interactive" tutorials or games using the &lt;a href="https://www.inklestudios.com/ink/"&gt;INK language&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is not an original idea, indeed all I've done is something that's
currently working on &lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, and was the main idea behind the dead
project &lt;a href="https://www.hack-computer.com/"&gt;Hack Computer&lt;/a&gt;, you can even take a look to the
&lt;a href="https://flathub.org/apps/details/com.hack_computer.Clubhouse"&gt;Hack app in flathub&lt;/a&gt;. But I wanted to work around this, and create
something simpler, from scratch.&lt;/p&gt;
&lt;p&gt;I wanted to build something simple, with just Python, and make it simple enough
to be able to build other tools on top. The design is simple, an INK parser,
with a simple game runner. In the INK script you can define &lt;em&gt;commands&lt;/em&gt;, to do
something special, and wait for events with &lt;em&gt;listeners&lt;/em&gt;, to wait for an event
in the OS to continue.&lt;/p&gt;
&lt;p&gt;With this basic functionality it's possible to build different user interfaces
for different environments. And the original idea was to make the &lt;em&gt;commands&lt;/em&gt;
and &lt;em&gt;listeners&lt;/em&gt; something extensible with a simple API, but that's something
that I have not done yet, it's all Python functions without extension point.&lt;/p&gt;
&lt;p&gt;The code can be found in &lt;a href="https://github.com/danigm/lils"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The INK parser&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/inky.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The most complex part of this project is the INK language parser. The &lt;a href="https://github.com/inkle/ink"&gt;Ink&lt;/a&gt;
parser is free software and there's a Linux version that you can use to parse
and &lt;strong&gt;compile&lt;/strong&gt; to &lt;em&gt;json&lt;/em&gt;, but I wanted to create my own parser with Python.&lt;/p&gt;
&lt;p&gt;I've spent most of the Hack Week time fighting with the parser and indeed was
the most challenging and fun part, because I've not worked a lot with parsers
and it's not something easy as pie 😛️.&lt;/p&gt;
&lt;p&gt;I remember creating a java compiler long time ago, when I was in the Seville
University, for the Language Processors course. We did that with &lt;a href="https://www.antlr.org/"&gt;ANTLR&lt;/a&gt;, so
starting from that, and looking for a Python lib, I found the &lt;a href="https://github.com/lark-parser/lark"&gt;Lark&lt;/a&gt;
project. So if you like regular expressions, writing a grammar is a lot more
FUN.&lt;/p&gt;
&lt;p&gt;At the end I was able to support some basic INK language with support for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Text&lt;/li&gt;
&lt;li&gt;Tag support&lt;/li&gt;
&lt;li&gt;Options, with suppress text support&lt;/li&gt;
&lt;li&gt;Knots, Stitches and Diverts&lt;/li&gt;
&lt;li&gt;Include other .ink files&lt;/li&gt;
&lt;li&gt;Variable definition and basic operations&lt;/li&gt;
&lt;li&gt;Knots and Stitches automatic visiting count variables&lt;/li&gt;
&lt;li&gt;Conditional options using variables&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It still fails in some cases, the comments and &lt;em&gt;TODO&lt;/em&gt; placed in between text is
not detected correctly and there's a lot of complex stuff that's not supported
yet, but with what's supported right now it's possible to create complex
scripts with loops and complex game graphs, so it's good enough to build games
just with it.&lt;/p&gt;
&lt;h2&gt;GNOME shell extension&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;video src="/pictures/lils.mp4" width="100%" autoplay controls loop /&gt;
&lt;/p&gt;

&lt;p&gt;To integrate with the system I've done a simple &lt;a href="https://github.com/danigm/lils/tree/master/lils%40danigm.net"&gt;GNOME shell extension&lt;/a&gt;.
The extension just shows the text as bubbles and options as buttons, it's
really simple and I've no time to make it something ready to be used, but
I was able to make something usable.&lt;/p&gt;
&lt;p&gt;To be able to run the &lt;em&gt;LILS&lt;/em&gt; python library from &lt;em&gt;gjs&lt;/em&gt; I've created a simple
&lt;em&gt;dbus&lt;/em&gt; service that exposes the basic &lt;em&gt;InkScript&lt;/em&gt; class functionality as a dbus
API.&lt;/p&gt;
&lt;p&gt;I was thinking about being able to change the desktop background, depending of
the value of a &lt;em&gt;background&lt;/em&gt; variable in the script and do something similar to
play music and sounds, so it could be a cool &lt;em&gt;game engine&lt;/em&gt; with some additions.&lt;/p&gt;
&lt;h2&gt;SUSE Hack Week&lt;/h2&gt;
&lt;p&gt;So this Hack week was really fun and I learned a lot. It's really great that
SUSE does things like this, letting us work in different projects for a week,
to learn, to grow or to just explore different paths.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/IxscORgeqOY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen&gt;&lt;/iframe&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 03 Jan 2023 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2023-01-03:/hackweek22.html</guid><category>blog</category><category>gnome</category><category>work</category><category>suse</category><category>ink</category><category>python</category></item><item><title>The end of 2022</title><link>https://danigm.net/2022.html</link><description>&lt;p class="img"&gt;
    &lt;img src="/pictures/2023.png" /&gt;
&lt;/p&gt;

&lt;p&gt;Is the end of 2022 and the beginning of 2023, so it's the right time to look
back and see what great things happened during the year, and also it's the time
to plan some new year resolutions.&lt;/p&gt;
&lt;h2&gt;My contribution to GNOME in 2022&lt;/h2&gt;
&lt;p&gt;I've been focused this year on the &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator"&gt;GNOME Translation Editor&lt;/a&gt;, migrating it
to Gtk4. It's not ready yet, but I hope I will be able to have a working
version soon™.&lt;/p&gt;
&lt;p&gt;It started this summer with one intern from &lt;a href="https://www.outreachy.org/outreachy-may-2022-internship-round/#gnome-migrate-gnome-translation-editor-to-gtk4"&gt;Outreachy&lt;/a&gt;, that did some
initial work, building with the new Gtk4, and after the summer I started to
clean the code and fixing issues, and lately, I'm trying to replace some
deprecations for the next Gtk release.&lt;/p&gt;
&lt;p&gt;so I'm working on the code, modernizing it, and replacing every usage of
&lt;code&gt;GtkDialog&lt;/code&gt; and &lt;code&gt;GtkTreeView&lt;/code&gt;, and trying to follow the &lt;a href="https://developer.gnome.org/hig/"&gt;GNOME HIG&lt;/a&gt; as much
as possible.&lt;/p&gt;
&lt;h3&gt;Live coding Streaming&lt;/h3&gt;
&lt;p&gt;I started the year spending a lot of time working on Gtk on live stream on
&lt;a href="https://www.twitch.tv/abentogil/"&gt;Twitch&lt;/a&gt;, but after the summer I was spending less time... I didn't find the
time or the energy to do it regularly.&lt;/p&gt;
&lt;h2&gt;Changes in the business&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/endless-photo.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;This year was also a year of changes in my work life. After the summer I left
Endless, after three years of working there, to join SUSE.&lt;/p&gt;
&lt;p&gt;I really enjoy my time at &lt;a href="https://www.endlessos.org/"&gt;EndlessOS&lt;/a&gt;, the first years working on the Hack
Computer and the last year working on the Endless Key. I really like the
EndlessOS mission and what I was doing there, with a lot of great people.&lt;/p&gt;
&lt;p&gt;But I was looking for something more in my career path, and I had the
opportunity to join SUSE. Since September, I'm part of the Python packaging
team at SUSE and I've to say that I really love this job. It's a bit different
from what I have been doing before, but the maintainer life is something that I
enjoy, having the opportunity to contribute to a lot of different projects and
debugging and fixing random bugs is one of the most rewarding tasks to do (when
you are able to find the problem).&lt;/p&gt;
&lt;p&gt;Tumbleweed is now my favourite GNU/Linux distribution and the future of
&lt;a href="https://news.opensuse.org/2022/12/22/second-prototype-advances-alp/"&gt;SUSE ALP&lt;/a&gt; looks really promising.&lt;/p&gt;
&lt;h2&gt;Changes in life&lt;/h2&gt;
&lt;p&gt;This year comes also with a lot of changes in my personal life too! At the
beginning of the year I was able to bought a house, so I've now a permanent
residency, after a lot of years of changing from one rent house to another one.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/blackbelt.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;And this year was also the year that I was able to get the kickboxing black
belt, after almost 8 years of practicing. This is the end of a learning path,
and also the beginning of a different one, trying to master this fighting
sport.&lt;/p&gt;
&lt;h2&gt;New year resolutions&lt;/h2&gt;
&lt;p&gt;2022 was great, but we can make 2023 even better, I'm looking always to learn
and improve, so it's good to do some new year resolutions to try to complete
during the next year.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete the Gtranslator migration to gtk4 and GNOME HIG improvements!&lt;/li&gt;
&lt;li&gt;Be more regular with the live coding streams&lt;/li&gt;
&lt;li&gt;Give some love to the &lt;a href="https://www.bassi.io/articles/2022/12/02/on-pygobject/"&gt;PyGObject&lt;/a&gt; project&lt;/li&gt;
&lt;li&gt;Do more serious kickboxing training and loose 10Kg&lt;/li&gt;
&lt;li&gt;Play more chess games&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's all! Happy new year and Have a lot of fun...&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 30 Dec 2022 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2022-12-30:/2022.html</guid><category>blog</category><category>gnome</category><category>work</category><category>2022</category><category>newyear</category></item><item><title>SUSE is my new distribution (new job)</title><link>https://danigm.net/suse.html</link><description>&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://suse.com"&gt;
        &lt;img src="/pictures/Poster-Always-Changing.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This week I've started to work at &lt;a href="https://suse.com/"&gt;SUSE&lt;/a&gt;. I'll be working as Python
Specialist, in the packaging team, so I will go back to work on packaging and
distribution after more than ten years. My first job in 2008 was working on a
Ubuntu based local distribution, &lt;a href="https://en.wikipedia.org/wiki/Guadalinex"&gt;Guadalinex&lt;/a&gt;, so packaging and distribution
work is not something new for me.&lt;/p&gt;
&lt;h2&gt;Python&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; was the first language that I fell in love. I learned to write code
with C and C++, but when I discovered Python, in 2006, I found a really nice
language to be able to create amazing things really fast and with a great
community behind.&lt;/p&gt;
&lt;p&gt;I'm very happy for this new opportunity to be able to collaborate to the Python
distribution in all the SUSE flavours, and also to be able to collaborate in
the creation of one of the most famous and used Linux distributions.&lt;/p&gt;
&lt;h2&gt;Tumbleweed&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://www.opensuse.org/#Tumbleweed"&gt;
        &lt;img src="/pictures/tumbleweed.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;As part of this job change I've also installed &lt;a href="https://www.opensuse.org/#Tumbleweed"&gt;SUSE Tumbleweed&lt;/a&gt; for the
first time. Tumbleweed is a rolling release distribution with the latests
packages. In the past I was using other rolling releases distributions like
Arch, but this one looks more user friendly.&lt;/p&gt;
&lt;p&gt;I've not spent a lot of time here, but from the point of view of a GNOME
developer, I can say that it's a great distribution for development with
updated packages, and it looks "stable". You can choose the desktop to use on
installation and the GNOME desktop is there without any customization that I've
detected, so it looks like it's a good vanilla GNOME desktop distribution.&lt;/p&gt;
&lt;h2&gt;Endless, it's not the end&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://endlessos.org"&gt;
        &lt;img src="/pictures/endless-farewell.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I'm not working for &lt;a href="https://endlessos.org"&gt;EndlessOS&lt;/a&gt; now, but it's not the end. I've been working
here for almost 4 years. At first I worked on the &lt;a href="https://hack-computer.com/"&gt;Hack Computer&lt;/a&gt; and after
that project didn't work, I was working on the &lt;a href="https://www.endlessos.org/key"&gt;Endless Key&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During this time I've also collaborated a bit with the EndlessOS distribution,
and I can say that's a really nice distribution to use, the ostree usage for
the whole filesystem is a great idea, and the amount of content that comes with
the installation is really good.&lt;/p&gt;
&lt;p&gt;The EndlessOS Foundation Goal is to reduce the digital divide, providing
content and tools for offline people, centered on kids. This is a great mission
and in the future, if I find the opportunity to help my local community, I'll
try to use the EndlessOS tools and content to provide good learning content for
kids without online access.&lt;/p&gt;
&lt;p&gt;I was very happy these years at Endless, and I've learned a lot from different
great people. It's incredible the number of talented software engineers that
are related to Endless, and for me it was a real privilege to be able to share
this space and mission for a few years.&lt;/p&gt;
&lt;h2&gt;The future!&lt;/h2&gt;
&lt;p&gt;So there we go, I'm exited for this change, and also sad about leaving a great
project, but life is change and we should go ahead and think about the future!
And my future is green now.&lt;/p&gt;
&lt;p&gt;And if you don't know how to pronounce it, here you've a music video:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/nLdexZlVkAY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 18 Sep 2022 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2022-09-18:/suse.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>suse</category></item><item><title>Berlin Mini GUADEC 2022</title><link>https://danigm.net/berlin-mini-guadec.html</link><description>&lt;h2&gt;The GUADEC is back!&lt;/h2&gt;
&lt;p&gt;This year, the famous GNOME developers meeting event, the &lt;a href="https://events.gnome.org/event/77/"&gt;GUADEC&lt;/a&gt;, gets
back to "normal" after the last year global COVID-19 situation. And when I say
normal, I'm talking about people meeting in one place to share knowledge and to
build a great community around this great software project.&lt;/p&gt;
&lt;p&gt;This year the even was in Guadalajara, Mexico, and that's great, but a bit far
to go from Spain... But thankfully, some of GNOME folks who can't go to Mexico
organized a parallel event to attend remotely in Berlin, Europe, that's the
Berlin Mini GUADEC.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/berlin-mini-guadec/plane.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;I decided to join this people, because there's a direct flight from Málaga, so
it was not a very long travel for me. This was my first big trip after COVID, and
I was a bit afraid, but besides the heat wave, everything was great.&lt;/p&gt;
&lt;h2&gt;My talk&lt;/h2&gt;
&lt;p&gt;The GUADEC event allows a remote attendance and also remote participation, so I
proposed &lt;a href="https://events.gnome.org/event/77/contributions/351/"&gt;a talk&lt;/a&gt; that I finally did from Berlin thanks to the &lt;a href="https://www.c-base.org/"&gt;c-base&lt;/a&gt;
people that build a great setup to give the talk to the local people at the
same time that it was streamed to the main event in Mexico.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/berlin-mini-guadec/gnome-streamers-2022.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;As you may know, I started to do &lt;a href="https://danigm.net/twitch.html"&gt;live coding streaming&lt;/a&gt; this year, and
there are also other &lt;a href="https://wiki.gnome.org/Community/Streamers"&gt;GNOME Developers&lt;/a&gt; doing that, so I wanted to talk
about this new way of sharing and build community, and that was my talk about.&lt;/p&gt;
&lt;p&gt;You can watch my full talk in Youtube:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/wuFTiAcdBXk?start=9346" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2&gt;Endless&lt;/h2&gt;
&lt;p&gt;It's not all party and fun in this event, there's also time to work. We take
advantage of this event and some of the Endless people take the opportunity to
meet together.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/berlin-mini-guadec/endless-family-2.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;We're fully remote and I started to work at Endless in 2019. We had the
opportunity to meet one time in London, but after that, this is the second time
we had the opportunity to share some time together and it was great. Besides
the day to day work, that can be done in remote completely, it's always nice to
have the opportunity to share some time with coworkers to meet the real person.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;My travel was sponsored by the &lt;a href="https://www.gnome.org/foundation/"&gt;GNOME Foundation&lt;/a&gt;, and thanks to the
&lt;a href="https://www.endlessos.org/"&gt;EndlessOS Foundation&lt;/a&gt;, to give me the opportunity to be part of this great
community.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
    &lt;a href="https://gnome.org"&gt;
        &lt;img src="/pictures/sponsored-by-foundation-round.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 22 Jul 2022 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2022-07-22:/berlin-mini-guadec.html</guid><category>blog</category><category>gnome</category><category>guadec</category><category>berlin</category><category>community</category><category>endless</category></item><item><title>Gambito, a chess App in Rust</title><link>https://danigm.net/gambito.html</link><description>&lt;h2&gt;Chess&lt;/h2&gt;
&lt;p&gt;I've been always interested in Chess, but never learned to play it correctly or
even spent some time playing more than a couple of matches with friends. But
during the COVID lockdown I started to watch people &lt;a href="https://www.twitch.tv/gmhikaru"&gt;playing chess&lt;/a&gt;, and
then I realized that the game is even more fun than I expected.&lt;/p&gt;
&lt;p&gt;After that I started to play a bit online and discovered the great online
platform &lt;a href="https://lichess.org/"&gt;Lichess&lt;/a&gt;, that's even &lt;a href="https://github.com/lichess-org"&gt;free software&lt;/a&gt;. I do not play a lot, but
I discovered that I like a lot the game and I watch chess streamers everyday
and I even followed the &lt;a href="https://fide.com/"&gt;professional competition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So if you don't play chess, give it a try, it's a really nice board game, and a
beauty "video game" that you can play online in a complete free software platform
with a lot of community resources to learn, and even if you are a bad player like me,
you can always enjoy the beauty of the chess watching other people playing.&lt;/p&gt;
&lt;h2&gt;Gambito&lt;/h2&gt;
&lt;p&gt;With this new interesting hobby, I installed the chess application that I found
in gnome. &lt;a href="https://gitlab.gnome.org/GNOME/gnome-chess"&gt;GNOME Chess&lt;/a&gt; is a good application, but then I ask myself, why
not rewrite it in Rust? Okay, it's not a rewrite, it's just a new application,
my idea is not to replace GNOME Chess, but to experiment with Gtk4 and Rust,
and that's the reason I started to work on &lt;a href="https://gitlab.gnome.org/danigm/gambito"&gt;Gambito&lt;/a&gt;, that's just a new
Chess game for GNOME, written in Rust with Gtk4.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/gambito-screenshot01.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The first idea was to create a simple app, without widget inheritance or
anything, just draw a board with existing Gtk Widgets, and do the drawing with
CSS and the interaction with drag &amp;amp; drop. And I did that for almost all the
application, but at some point I needed something more specific that I was
unable to do without a new widget. So right now almost everything is done that
way but the marks and arrows, that are custom widgets.&lt;/p&gt;
&lt;p&gt;I'm doing almost all the development in live streaming (in Spanish),
&lt;a href="https://www.twitch.tv/abentogil/"&gt;in my twitch account&lt;/a&gt;, so you can find some of the videos here in my
&lt;a href="https://www.youtube.com/c/danigmx/search?query=gambito"&gt;youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/gambito-screenshot03.png" /&gt;
&lt;/p&gt;

&lt;p&gt;Right now you can use the application to play against Stockfish or to analyse a
match. At the beginning the idea was to create just a chess game, but right now
I'm thinking more about a chess learning application, so I think I'll work more
in analysis tools, tactic training games, and maybe some good content for
beginners, inside the application, like a tutorial and some kind of assistant with
theory.&lt;/p&gt;
&lt;p&gt;And there's a lot of fun things to do, like linking with the Lichess platform,
to be able to watch games in live, play online using the app instead the web
interface, analyze Lichess matches and look for cheaters doing some kind of IA
(yes, there are cheaters using chess engines to win matches in online chess
platforms, I don't know why, but there are people like that).&lt;/p&gt;
&lt;p&gt;So I'm getting a lot of fun from the old game Chess, fun playing, fun watching
an fun writing a Chess game.&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/gambito-logo.png" /&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 09 Jul 2022 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2022-07-09:/gambito.html</guid><category>blog</category><category>gambito</category><category>chess</category><category>gtk4</category><category>gnome</category><category>rust</category><category>twitch</category></item><item><title>GNOME Outreachy 2022</title><link>https://danigm.net/outreachy-2022.html</link><description>&lt;h2&gt;GNOME Translation Editor, Road to Gtk4&lt;/h2&gt;
&lt;p&gt;It's time to move to Gtk4. That could be an easy task for new project or for
small projects without a lot of custom widgets, but &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator"&gt;gtranslator&lt;/a&gt; is old and
the migration will require some time.&lt;/p&gt;
&lt;p&gt;Some time ago I did the &lt;a href="https://danigm.net/gtranslator-resurrection.html"&gt;Gtk2 to Gtk3&lt;/a&gt; migration. It was fun and during the
journey we redesigned a bit the interface, but the internals didn't change a
lot. Now we can do the same, migrate to Gtk4 and also update the User
Interface.&lt;/p&gt;
&lt;p&gt;Thankfully, I'm not alone this time, the GNOME community is there to help. A
couple of months ago, &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/-/commits/master?author=msandova"&gt;Maximiliano&lt;/a&gt; started a series of commits to prepare
the project to the Gtk4 migration, and today starts the Outreachy program and
we've a great intern to work in this. &lt;a href="https://www.outreachy.org/alums/2022-05/"&gt;Afshan Ahmed Khan&lt;/a&gt; will be working
during this summer in the GNOME Translation Editor migration to Gtk4.&lt;/p&gt;
&lt;h2&gt;Outreachy&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt; program provides internship to work in Free and Open Source
Software. This year I've proposed the "Migrate GNOME Translation Editor to Gtk4"
project and we had a lot of applicants. We had some great contributions during
the application phase, and at the end Afshan was selected.&lt;/p&gt;
&lt;p&gt;We've now an initial &lt;a href="https://dev.to/redoca2k/beginning-outreachy-journey-with-gnome-o8j"&gt;intern blog post&lt;/a&gt; and he is working now in the first
step, trying to build the project with Gtk4. It's not a simple task, because
gtranslator uses a lot of inheritance and there's a lot of widgets in the
project.&lt;/p&gt;
&lt;h2&gt;User Interface redesign?&lt;/h2&gt;
&lt;p&gt;Once we've the project working with Gtk4 and libadwaita we can start to think
about user interface improvements, and all the collaboration here is welcome,
so if some designer or translator want to help, don't hesitate to take a look
to the &lt;a href="https://flathub.org/apps/details/org.gnome.Gtranslator"&gt;current interface&lt;/a&gt; and propose some ideas in the &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/-/issues/159"&gt;corresponding task&lt;/a&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 30 May 2022 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2022-05-30:/outreachy-2022.html</guid><category>blog</category><category>gnome</category><category>outreachy</category><category>gtranslator</category><category>gtk4</category></item><item><title>Twitch: GNOME live coding streaming</title><link>https://danigm.net/twitch.html</link><description>&lt;p&gt;This year I've started with something that I wanted to do since the first COVID
lockdown, but never did. So as a first year resolution I decided to start
streaming and I created my Twitch channel &lt;a href="https://www.twitch.tv/abentogil"&gt;Abentogil&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/twitch-loop.png" /&gt;
&lt;/p&gt;

&lt;p&gt;I've been thinking about streaming since lockdown, when a group of Spanish
people created a nice initiative to teach kids how to code and other tech
stuff. I never participated on that initiative, but it was the seed of this.&lt;/p&gt;
&lt;p&gt;This year I've seen other GNOME streamers doing live coding, like &lt;a href="https://twitch.tv/ebassi"&gt;ebassi&lt;/a&gt;
and &lt;a href="https://www.youtube.com/c/GeorgesStavracas"&gt;Georges&lt;/a&gt; and, at the end, I pluck up the courage to start.&lt;/p&gt;
&lt;h2&gt;The plan&lt;/h2&gt;
&lt;p&gt;I've started with one our at the end of my day, so I'm trying to stream from
Monday to Thursday from 20:00 to 21:00 (CET).&lt;/p&gt;
&lt;p&gt;This routing also will help me to spend more time in free software development
regularly, so not just on weekends or holidays, but a bit of work everyday.&lt;/p&gt;
&lt;p&gt;Right now I've started working on my own projects, like &lt;a href="https://gitlab.gnome.org/danigm/timetrack/"&gt;Timetrack&lt;/a&gt; and
&lt;a href="https://gitlab.gnome.org/danigm/loop/"&gt;Loop&lt;/a&gt;. I've fixed some issues that I had with Gtk4 in Timetrack and I've
started to work on the Loop app to add a MIDI keyboard.&lt;/p&gt;
&lt;p&gt;The other day I discovered the &lt;a href="https://gitlab.gnome.org/bertob/app-ideas/-/issues/58"&gt;Music Grid&lt;/a&gt; app idea in the gitlab and it's
related with the MIDI implementation I've been working on, so the next thing
that I'll do on my streams is to create this music grid widget and add it to
the Loop app, to have a nice Music creation App.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/music-grid.png" /&gt;
&lt;/p&gt;

&lt;h2&gt;The language: Live coding in Spanish&lt;/h2&gt;
&lt;p&gt;I've decided to do the streaming mainly in Spanish. The main reason to do that
is because now you can find documentation and a lot of videos in English, but
for people that doesn't master the English language, it's harder to follow this
content and even harder to participate, to ask or say something.&lt;/p&gt;
&lt;p&gt;Spanish is also my main language, and the idea is not just create tutorials or
something like that, this is just for fun, and if I'm able to create a small
community or influence someone, I want to show that the language is not a
unbreakable barrier.&lt;/p&gt;
&lt;p&gt;I want to make this for the Spanish community, but that doesn't mean that for
some streams I cannot talk in English, all depends on the audience, of course,
if a non Spanish speaker comes and ask something, I'll answer in English and
try to do multilingual stream.&lt;/p&gt;
&lt;p&gt;The International English is the language to use in Free Software, but it's
really important to do not convert that in a barrier, because there are a lot
of different communities and people that don't know the language and the first
contact with something new is always better in your main language. Everything
is easier with help from people that's near to your cultural background.&lt;/p&gt;
&lt;h2&gt;The future&lt;/h2&gt;
&lt;p&gt;Right now I'm working on Loop and every stream is similar, live coding on this
Gtk4 music APP, but in the future I'll do different streams, doing different
things on each week day. These are the current ideas that could be a day on my
stream:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Maintenance day: Work on my apps, code review, fixes, releases, and
   development.&lt;/li&gt;
&lt;li&gt;GNOME Love day: Give some love to the GNOME project, look for simple bugs to
   solve in different projects, help with translations, initiatives, and other
   possible one hour task to give some love to the project in general.&lt;/li&gt;
&lt;li&gt;Learning day: Pick some technology and learn by doing, for example, I
   can explore new programming languages writing a simple app, learn about
   Linux writing a driver, learn how to animate with blender, anything new to
   play and discover.&lt;/li&gt;
&lt;li&gt;Newcomers day: Create simple tutorial or introduction to some technology,
   How to write a GNOME Shell extension, how to create a Gtk4 app in python,
   teach to code from zero, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is just a list of ideas, if I discover any other interesting use of this
time and stream, I can do that. The final goal of this is to have fun, and if
someone learns something in the journey, that's even better.&lt;/p&gt;
&lt;p&gt;I'll also upload any interesting stream to &lt;a href="https://www.youtube.com/danigmx"&gt;youtube&lt;/a&gt;, so the good content
could be viewed on demand.&lt;/p&gt;
&lt;p&gt;So if you like this, don't hesitate to view some of the streams and say "Hola":&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="https://twitch.tv/abentogil"&gt;
        &lt;img src="/pictures/twitch.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 22 Jan 2022 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2022-01-22:/twitch.html</guid><category>blog</category><category>gnome</category><category>software</category><category>outreach</category><category>twitch</category><category>live coding</category></item><item><title>Loop: A simple music application</title><link>https://danigm.net/loop.html</link><description>&lt;p&gt;In the last year I've seen some &lt;a href="https://www.twitch.tv/leonbratt"&gt;really good musician&lt;/a&gt; that performs all
the instruments in a song with just a loop machine, recording each instrument
one by one in tracks and looping.&lt;/p&gt;
&lt;p&gt;I was thinking that it should be easy to have a desktop application that does
exactly the same, just some tracks to record some sounds and the playback with
a loop option, and that's what I created during this week.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/loop.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://gitlab.gnome.org/danigm/loop/"&gt;Loop application&lt;/a&gt; is just a simple Gtk4 application that uses gstreamer
to record tracks and then you can play each one at the same with or without
loop option. With that, a good musician could create the base melody of the
song and then sign on top of that. Unfortunately, I'm not a good musician, but
I can use this to play around.&lt;/p&gt;
&lt;p&gt;I've just created the &lt;a href="https://github.com/flathub/flathub/pull/2674"&gt;request on flathub&lt;/a&gt; to add the application, so if
everything is okay it will be available there soon, so more people can play
with this awesome toy.&lt;/p&gt;
&lt;p&gt;Right now it has the basic record, play and loop functionality with just four
tracks, so don't expect to have a professional music app (yet). The recording
and play times are not perfect and there's a delay, that's a known issue, but
I'm planning to fix this issue and add more functionality in the future, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make number of tracks configurable&lt;/li&gt;
&lt;li&gt;Import track from files&lt;/li&gt;
&lt;li&gt;Add a trim slider per track, to be able to adjust the recorder track to loop&lt;/li&gt;
&lt;li&gt;Metronome tick and clock to have a visual reference for recording tracks&lt;/li&gt;
&lt;li&gt;A record button, but export the combination of all tracks and mic to a mp3
   file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that's all. The logo and design is an initial version done by myself, so if
any designer wants to take a look, all contributions are welcome. And of course
any code contribution is also welcome.&lt;/p&gt;
&lt;p&gt;If you use this application and do some good or fun performance, please, ping
me on social networks and let me know.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 11 Dec 2021 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2021-12-11:/loop.html</guid><category>blog</category><category>gnome</category><category>software</category><category>music</category><category>loop</category></item><item><title>Endless Orange Week: Hack content creators platform (2)</title><link>https://danigm.net/hack-content-creators-1.html</link><description>&lt;p&gt;The past Friday was the last day of the &lt;a href="http://danigm.net/hack-content-creators.html"&gt;Endless Orange Week&lt;/a&gt;. It was a nice
and fun experience, and even if I was not able to do as much as I wanted, we
were able to make something that "works" in the Hack project.&lt;/p&gt;
&lt;h2&gt;The Hack Quest editor&lt;/h2&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-1.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The first step to have custom quests on the Hack app was to complete the
&lt;a href="https://www.inklestudios.com/ink/"&gt;Ink language&lt;/a&gt; support. We started to work on this some time ago, but never
completed the functionality.&lt;/p&gt;
&lt;p&gt;I worked on that the first three days, updating the ink library and building
the missing pieces to be able to load quests from random paths. I've
implemented that in a way that the Hack application is able to receive a path
to a &lt;code&gt;.ink&lt;/code&gt; file, and it's able to build and run the quets.&lt;/p&gt;
&lt;p&gt;The Quests are not just the script, but they have some metadata, like title,
subtitle, description, difficulty and the card image to show on the interface.
To solve that I defined a "custom quest bundle format", that's bassically a
folder with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;questId&lt;/li&gt;
&lt;li&gt;quest.jpg&lt;/li&gt;
&lt;li&gt;metadata.json&lt;/li&gt;
&lt;li&gt;quest.ink&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I also added the functionality to import a bundle zip file and export with
the quest information.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-2.png" /&gt;
&lt;/p&gt;

&lt;p&gt;I created some command line options to use this new functionality:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FULL_INK_FILE_PATH&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;import&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PATH_TO_BUNDLE_OR_INK_FILE&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;export&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CUSTOM_QUEST_ID&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;Export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Quest creation interface and the Inky Editor&lt;/h3&gt;
&lt;p&gt;The first idea was to try to provide a full quest creation experience in the
app, but that was too much, so we decided to simplify the way to create quests
and depend on the &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;Inky editor&lt;/a&gt; external tool. Manuel Quiñones took some time
to update the flatpak application with the latests ink version, so we can use
to create custom quests.&lt;/p&gt;
&lt;p&gt;The Inky editor provides help about the language, syntax highlighting and a
simple way to test the script, so it's a nice tool. The main problem with this
tool is that it doesn't provide a way to launch it with a file path so it's
not possible to integrate with the Hack app.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/clubhouse-custom-quests-3.png" /&gt;
&lt;/p&gt;

&lt;p&gt;So at the end, the Quest creation dialog is just a way to define the metadata
and to select the Quest ink files from your filesystem. How the ink script is
created is a decision to make for the content creator.&lt;/p&gt;
&lt;h3&gt;The future&lt;/h3&gt;
&lt;p&gt;We've no time to complete all we wanted to do, and I didn't create a new
release, so this new functionality is still not there. But we'll try to do a
release soon.&lt;/p&gt;
&lt;p&gt;Simon is working on some interface improvements and also on a new tutorial
Quest, so we can introduce the Custom Quest creation tool in the same app.&lt;/p&gt;
&lt;h2&gt;The Character editor&lt;/h2&gt;
&lt;p&gt;The other part of this week planning was the character editor. Joana did a
really nice work designing the application, the initial assets and the user
experience, but I had not too much time to work on the implementation.  So I
spent just one day working on this.&lt;/p&gt;
&lt;p&gt;The main idea was to create a new independent app, and then provide a way to
integrate with the Hack application and the custom Quest creation dialog. And
it'll be a simple application so maybe it could be useful or interesting for
other people, it's a fun way to play around and create random faces.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/avatar-creator-1.png" /&gt;
&lt;/p&gt;

&lt;p&gt;We just created the application &lt;a href="https://github.com/endlessm/avatar-creator/"&gt;Avatar Creator&lt;/a&gt;. I created a simple python
Gtk4 application and worked a bit on the basic functionality. So right now it
loads a list of svg assets and provide the 3x3 grid. You can click on a grid
cell and then choose what basic image should go there.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/avatar-creator-2.png" /&gt;
&lt;/p&gt;

&lt;p&gt;I added the initial set of basic images, created by Joana, to create this funny
robot faces, but the format is simple enough to extend with different "avatar
libraries" in the future.&lt;/p&gt;
&lt;p&gt;Right now it's also possible to export to png, so the app is functional, but it
needs a bit more work.&lt;/p&gt;
&lt;p&gt;My idea is to work a bit more in the following weeks, when I have some time, on
weekends or holidays and at some point, publish it in flathub. And lets see if
there are more developers interested on this app so it can grow.&lt;/p&gt;
&lt;p&gt;The application is simple enough to be a good place for GNOME newcomers and it's
also a fun project to work on. A simple toy app to create faces that could
have some potential, some future ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"Smart" random faces generator&lt;/li&gt;
&lt;li&gt;Configurable grid: Maybe is interesting to make it bigger or smaller to play
   around&lt;/li&gt;
&lt;li&gt;Programmed simple base image manipulations, like rotation, mirror, color&lt;/li&gt;
&lt;li&gt;Animation creation, maybe be able to export to gif&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Endless Orange Week experience&lt;/h2&gt;
&lt;p&gt;This week was a really nice experience, because we were working in a "personal"
chosen project, that we liked and without the day to day meetings, times
schedules and other related work stuff.&lt;/p&gt;
&lt;p&gt;But that was not all. In Endless we've different teams that work mostly
isolated, because we're working on different fields, we've some overlapping,
but we work day to day as small teams, and this week we were all using the same
slack channel to show our progress, and it was nice.&lt;/p&gt;
&lt;p&gt;Maybe now that we're not a big organization with a lot of workers, we can do
something like this more often, it's always good to know more about other
coworkers and to learn something that maybe it's not related with your main
project, but it could be interesting.&lt;/p&gt;
&lt;p&gt;I'm really happy that we did this Endless Orange Week, it's sad that it ended
too soon, I'm waiting to learn from my coworkers what amazing things they do
during this week and I'm looking forward the next year Orange Week!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 15 Nov 2021 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2021-11-15:/hack-content-creators-1.html</guid><category>blog</category><category>hack</category><category>endless</category><category>orangeweek</category><category>work</category><category>gnome</category><category>software</category></item><item><title>Endless Orange Week: Hack content creators platform</title><link>https://danigm.net/hack-content-creators.html</link><description>&lt;p&gt;This week (Nov 8 – 12) I am participating in Endless Orange Week, a program
where the entire &lt;a href="https://www.endlessos.org/"&gt;Endless&lt;/a&gt; team engages in projects designed to grow our
collective learning related to our skills, work and mission.&lt;/p&gt;
&lt;p&gt;We propose a project, that could be anything, and then work during the whole
week, without distraction. I've choosed to work on the &lt;a href="https://www.hack-computer.com/"&gt;Hack project&lt;/a&gt;, that's a
really nice project that needs some love, because since the past year, we have
&lt;a href="https://www.endlessos.org/key"&gt;other priorities&lt;/a&gt;, so there's no time to improve the Hack app.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/clubhouse.png"&gt;
        &lt;img src="/pictures/clubhouse.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The project: Hack content creators platform&lt;/h2&gt;
&lt;p&gt;The Hack application is a "Quest" launcher, and each Quest is an interactive
learning experience, a guided introduction to some technology or topic.&lt;/p&gt;
&lt;p&gt;Quests are just python scripts, with a simple library to expose messages to the
user, ask questions, or wait for desktop events, like launch an application,
focus an application, etc. And all these Quests are inside the application, and
are created by the Hack team and released with a new Hack app flatpak.&lt;/p&gt;
&lt;p&gt;The main idea of the project is to provide a simple Quest editor to allow any
Hack user to create and share their our Quests.&lt;/p&gt;
&lt;p&gt;To have this Hack content creators platform we'll need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To simplify the way we create Quests, instead of a python script, we'll uses
   a Domain Specific Language, called &lt;a href="https://www.inklestudios.com/ink/"&gt;Ink&lt;/a&gt;. We started to work on this, but
   we never ended the support.&lt;/li&gt;
&lt;li&gt;To create the interface to be able to import and export custom Quests, that
   could be zip bundles, with the Ink script and some images.&lt;/li&gt;
&lt;li&gt;To create the interface to write the actual Quests and save or bundle.&lt;/li&gt;
&lt;li&gt;Create some introductory Quest to explain "how to create your own Quests!".&lt;/li&gt;
&lt;li&gt;Create an character editor, to be able to "design" new characters for Quests.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The Quest editor&lt;/h3&gt;
&lt;p&gt;The Quests will be written using the Ink language, and there's &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;something done before&lt;/a&gt;.
The first idea is to just provide a text editor and some helpful information
about the format, and maybe a button to validate. But if there's time we can
use something advanced or even integrate the &lt;a href="https://flathub.org/apps/details/com.inklestudios.Inky"&gt;Inky&lt;/a&gt; editor.&lt;/p&gt;
&lt;h3&gt;The Character editor&lt;/h3&gt;
&lt;p&gt;Each Quest has a main character, and we've five in the Hack app right now, but
it could be great to be able to define new ones for custom Quests. That's the
idea of this part of the project.&lt;/p&gt;
&lt;p&gt;The initial idea is to have a library of character parts to combine, and the
editor will allow the user to combine this parts and maybe change colors, to be
able to create unique characters for your Quests.&lt;/p&gt;
&lt;h3&gt;The Team&lt;/h3&gt;
&lt;p&gt;I'm not working alone in this "side" project during the Endless Orange Week,
Simon Schampijer and Joana Filizola will be working on this too, so this is a
big task but we've a great team. Let's see how far we are able to go during
just one week.&lt;/p&gt;
&lt;h3&gt;The impact&lt;/h3&gt;
&lt;p&gt;This is just a project to try to keep alive more time the Hack application,
without a lot of effort or a whole team behind it. We are not able to put more
content there periodically, so if there's a way to create new content easily
and (maybe in the future) a way to publish, it'll be possible to create a
community around the project.&lt;/p&gt;
&lt;p&gt;And we have also new possibilities, in the near future, we can add some Hack
content to the Endless Key, and using the Ink language, so this editor could
help to bring more content there easily.&lt;/p&gt;
&lt;p&gt;And the final piece, the Character editor, could be an independent application,
a nice simple application that could be used to create your character for your
profile photo, or to generate random character pics.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 08 Nov 2021 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2021-11-08:/hack-content-creators.html</guid><category>blog</category><category>hack</category><category>endless</category><category>orangeweek</category><category>work</category><category>gnome</category><category>software</category></item><item><title>Fractal: Refactoring and the review process</title><link>https://danigm.net/gsoc-2020-1.html</link><description>&lt;p&gt;In this year GSoC, &lt;a href="https://aledomu.github.io/gnome/refactoring-fractal-remove-backend-i/"&gt;Alejandro&lt;/a&gt; is working on Fractal, moving code from the
backend to the client, to try to simplify the code used to communicate with the
matrix.org server and maybe in the future we can replace &lt;code&gt;fractal-matrix-api&lt;/code&gt;
with the &lt;a href="https://matrix.org/sdks/#matrix-rust-sdk"&gt;matrix-rust-sdk&lt;/a&gt;. And then we'll have less code in our project to
maintain.&lt;/p&gt;
&lt;p&gt;This is a great work, something needed in a project with a technological debt
of several years. I created this project to learn Rust, and also I was learning
about the matrix protocol during the project build. And other contributors do
the same. So we've been building one thing on top another for a lot of years.&lt;/p&gt;
&lt;p&gt;In this kind of community driven projects it's the way to go. For some time
we've people interested and developers think about the design and start change
some parts or to write new functionality following a new design pattern. But
voluntary developers motivation change in time and they left the project and
the next one continues the work with a different vision.&lt;/p&gt;
&lt;p&gt;It's not something bad, it's the greatness of the open source. Different people
has different motivations to participate in a free software project, and every
contribution is welcome. I'm the maintainer of the project and I've spent a lot
of time building Fractal, but I don't have the same motivation now to work on
the project, to it's good to have other people working on it so it can continue
alive.&lt;/p&gt;
&lt;p&gt;Alejandro is doing a great work and he's not a 4 months contributor. He's
working on the backend refactoring for 2 years now, step by step and he has
plans for the future.&lt;/p&gt;
&lt;p&gt;Refactoring a big project is always hard, because there's a lot of code
movement and always there's the fear to regressions.&lt;/p&gt;
&lt;p&gt;Rust is a great language and it shines when big code refactoring comes to the
scene. If it compiles, you &lt;strong&gt;know&lt;/strong&gt; that there's no memory errors, dangling
pointers and that kind of problems. If it builds it will work.&lt;/p&gt;
&lt;p&gt;But maybe it will work &lt;em&gt;different&lt;/em&gt;, so the review process is needed to ensure
that the application continues working.&lt;/p&gt;
&lt;p&gt;Automated tests are really useful for big code changes and project refactoring,
because you have a quick picture and some certainty that the project is
working. But we don't have tests in fractal :D, so someone should do that.&lt;/p&gt;
&lt;p&gt;So here I am. &lt;a href="https://gitlab.gnome.org/GNOME/fractal/-/merge_requests/581"&gt;Reviewing large MR&lt;/a&gt;, with a lot of lines. At least gitlab
makes this process a bit easier.&lt;/p&gt;
&lt;p&gt;What I'm trying to do in the review process is to just read the whole diff and
check if there's some problem in the code. And after every change, I run the
app and I do some tests, trying to use the functionality that could be broken
by those new changes.&lt;/p&gt;
&lt;p&gt;This takes a lot of time and it's not something fun to do... But someone has to
do that. And during that process, sometimes I learn something new. Reading code
is an interesting task and try to find bugs in code while reading it, is
something useful. To think about that code, what it does and why.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 30 Jun 2020 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2020-06-30:/gsoc-2020-1.html</guid><category>blog</category><category>gnome</category><category>software</category><category>fractal</category><category>gsoc</category></item><item><title>Fractal: Google Summer of Code 2020</title><link>https://danigm.net/gsoc-2020.html</link><description>&lt;p&gt;I'm glad to say that I'll participate again in the &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt;, as mentor. This
summer we'll try to implement multi-account support in &lt;a href="https://gitlab.gnome.org/GNOME/fractal"&gt;Fractal&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/fractal-gsoc.png" /&gt;
&lt;/p&gt;

&lt;p&gt;The selected student is &lt;a href="https://summerofcode.withgoogle.com/projects/#6726209787920384"&gt;Alejandro Dominguez&lt;/a&gt; (aledomu), that is
collaborating with Fractal since the Seville Hackfest in December 2018, doing
a great work in the backend. Alejandro is young developer with a lot of energy
and ideas, so it's great to have this kind of people working on GNOME.&lt;/p&gt;
&lt;p&gt;I've not spend much time lately developing Fractal, the time and energy is
limited, but I'll try to use this GSoC mentorship to go back to the &lt;strong&gt;active&lt;/strong&gt;
Fractal development. My objective during this summer will be to stabilize,
fix bugs and improve the performance and create a new release at the end of the
GSoC, because we've a lot of new functionality in master, but I didn't spend
the time to do the release.&lt;/p&gt;
&lt;p&gt;The google summer of code is a great opportunity for free software, it give
us a full time working student, during three months, working on free software,
so it's really appreciated in a community where a lot of work is volunteer work.&lt;/p&gt;
&lt;p&gt;There are a total of 14 projects selected for this GSoC round for gnome, you
can take a look to the full list in the &lt;a href="https://summerofcode.withgoogle.com/organizations/5428225724907520/#projects"&gt;GSoC page&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 08 May 2020 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2020-05-08:/gsoc-2020.html</guid><category>blog</category><category>gnome</category><category>software</category><category>fractal</category><category>gsoc</category></item><item><title>End of GNOME Outreachy 2019</title><link>https://danigm.net/outreachy-2019-2.html</link><description>&lt;h2&gt;The Outreachy Program&lt;/h2&gt;
&lt;p&gt;The outreachy program ended the past week and we've done great improvements
during this four months of work. I'm very happy with the result and with the
work of the two interns and also the GNOME co-mentors that make this possible.&lt;/p&gt;
&lt;p&gt;If we're lucky the interns will continue contributing in the future and we can
see the GNOME comunity growing in developers and diversity 🎉.&lt;/p&gt;
&lt;h2&gt;GNOME translation editor (Gtranslator)&lt;/h2&gt;
&lt;video controls width="100%"&gt;
    &lt;source src="/pictures/gtranslator.webm" type="video/webm" /&gt;
    Video showing the new gtranslator search bar
&lt;/video&gt;

&lt;p&gt;&lt;a href="https://priyankasaggu11929.github.io/outreachy.html"&gt;Priyanka Saggu&lt;/a&gt; has been working on the new gtranslator search bar. It's a
replacement for the old search dialog with a new and modern search bar, inspired
in the gnome-builder search.&lt;/p&gt;
&lt;p&gt;This is how it looks in the current gtranslator version and the video is from
gtranslator master, that I'll try to release as 3.36.0 this weekend.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/gtranslator-old-search.png"&gt;
        &lt;img src="/pictures/gtranslator-old-search.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I want to thank to the other co-mentor of this project, Daniel Mustieles, who
has been testing and reviewing this new functionality.&lt;/p&gt;
&lt;h2&gt;Fractal&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://pitag.home.blog/"&gt;Sonja Heinze&lt;/a&gt; has been working on the video player for Fractal, so now
we can see videos inside the fractal message history instead of open it with
an external video player.&lt;/p&gt;
&lt;video controls width="100%"&gt;
    &lt;source src="/pictures/fractal.webm" type="video/webm" /&gt;
    Video showing the new fractal video player
&lt;/video&gt;

&lt;p&gt;This is now in master and will appear in the next release, that I'll try to
publish soon, maybe during this month. I want to fix some performance issues
first.&lt;/p&gt;
&lt;p&gt;Jordan Petridis (alatiera) has done a great work as co-mentor, guiding the
project and helping with the gstreamer.&lt;/p&gt;
&lt;p&gt;I've not presented any project proposal for the next outreachy, I want to take
a break and rest a bit before the Google Summer of Code, when I'll try to get
the multi-account support implemented in Fractal.&lt;/p&gt;
&lt;p&gt;This programs give me a bit of work, reviewing and guiding the intern, but it's
really great to have paid people working on free software, so I'm very happy to
be able to be a mentor in GNOME to help to boost some free software projects
using these resources.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 13 Mar 2020 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2020-03-13:/outreachy-2019-2.html</guid><category>blog</category><category>gnome</category><category>outreachy</category></item><item><title>GNOME Outreachy 2019</title><link>https://danigm.net/outreachy-2019.html</link><description>&lt;h2&gt;The Outreachy Program&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt; program provides internship to work in Free and Open Source
Software. This year I've proposed two projects as part of the GNOME project and
we've two interns working for three months, so we'll have a lot of improvements
in the following months!&lt;/p&gt;
&lt;p&gt;I'll be mentoring these interns, so I will need to spend some time helping them
to work on the existing codebase, but it worth it, if this makes more people to
collaborate in free software development and if this help us to improve some
useful apps.&lt;/p&gt;
&lt;p&gt;These two projects are Fractal and the GNOME translation editor. You can take a
look to the list of &lt;a href="https://www.outreachy.org/alums/"&gt;outreachy interns&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Fractal&lt;/h2&gt;
&lt;p&gt;Fractal is a Matrix.org gtk client, and I've proposed for this year program to
&lt;a href="https://www.outreachy.org/december-2019-to-march-2020-internship-round/communities/gnome/#fractal-implement-video-player-in-message-list"&gt;implement a video player in the message list&lt;/a&gt;. We've a preview for images,
for audio files but nothing for video files.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://pitag.home.blog/"&gt;Sonja Heinze&lt;/a&gt; is the one that will be working on this during the next three
months. She has been working during the past month in some small issues in
Fractal so I'm really sure that she will be able to do great contributions to
the project.&lt;/p&gt;
&lt;p&gt;Jordan Petridis (alatiera) will be helping in this project as a co-mentor, I
don't know a lot about gstreamer, so he'll be really helpful here with the
gstreamer and rust.&lt;/p&gt;
&lt;h2&gt;GNOME translation editor (Gtranslator)&lt;/h2&gt;
&lt;p&gt;GNOME translation editor (gtranslator) is a simple .po editor. I've proposed to
&lt;a href="https://www.outreachy.org/december-2019-to-march-2020-internship-round/communities/gnome/#gtranslator-rework-the-search-and-replace-dialog"&gt;Rework the search and replace dialog&lt;/a&gt;. We've right now a simple
find/replace modal dialog and I want to modernize the interface to integrate
better in the window as a popover.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://priyankasaggu11929.github.io/outreachy.html"&gt;Priyanka Saggu&lt;/a&gt; is the one that will be working on this during the next
three months. She has been working on gtranslator during the past month and she
has done great contributions and improvements during this time.&lt;/p&gt;
&lt;p&gt;Daniel Mustieles is the other co-mentor for this project. He's an experienced
GNOME translator so he will help us a lot with the app user experience design
and testing.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 16 Dec 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-12-16:/outreachy-2019.html</guid><category>blog</category><category>gnome</category><category>outreachy</category></item><item><title>LAS 2019, Barcelona</title><link>https://danigm.net/las-2019.html</link><description>&lt;h2&gt;The event&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://linuxappsummit.org/"&gt;The Linux App Summit&lt;/a&gt; (LAS) is a great event that bring together a lot of
linux application developers, from the bigger communities, it's organized by
GNOME and KDE in collaboration and it's a good place to talk about the Linux
desktop, application distribution and development.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/las-2019.jpg"&gt;
        &lt;img src="/pictures/las-2019.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This year the event was organized in Barcelona, this is not too far from my
home town, Málaga, so I want to be there.&lt;/p&gt;
&lt;p&gt;I sent a talk proposal and was accepted, so I was talking about distributing
services with flatpak and problems related to service deployment in a flatpaked
world.&lt;/p&gt;
&lt;p&gt;Clicking in this image you can find my talk in the event streaming. The sound
is not too good and my accent doesn't help, but there it is :D&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a target="_blank" href="https://youtu.be/4RE8gq0jLhA?t=4770"&gt;
        &lt;img src="/pictures/las-2019-talk.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The event was a really great event, with really good talks, about different
topics, we've some technical talks, some talks about design, talks about
language, about distribution, about the market and economics, and at least two
about "removing" the system tray 😋&lt;/p&gt;
&lt;p&gt;It was really interesting the talk about the &lt;a href="https://conf.linuxappsummit.org/en/LAS2019/public/events/59"&gt;"future" inclusion of payments&lt;/a&gt; in
flathub because I think that this will give a new incentive to people to write
and publish apps in flathub and could be a great step to get donations for
developers.&lt;/p&gt;
&lt;p&gt;Another talk that I liked was the one about the &lt;a href="https://conf.linuxappsummit.org/en/LAS2019/public/events/15"&gt;maintenance of flatpak repositories&lt;/a&gt;,
it's always interesting to know how the things works and this talk give an easy
introduction to ostree, flatpak, repositories and application distribution.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/las-2019-group.jpg"&gt;
        &lt;img src="/pictures/las-2019-group.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Besides the talks, this event is really interesting for the people that bring
together. I've been talking with a lot of people, not too much, because I'm a
shy person, but I've the opportunity to talk a bit with some Fractal
developers, and during a coffee talk with Jordan Petridis, we've time to share
some ideas about a cool new functionality that maybe we can implement in the
near future, thanks to the outreachy program and maybe some help from the
gstreamer people.&lt;/p&gt;
&lt;p&gt;I'm also very happy to be able to spend some time talking with Martín Abente,
about sugar labs, the hack computer and the different ways to teach kids with
free software. Martín is a really nice person and I liked a lot to meet him and
share some thoughts.&lt;/p&gt;
&lt;h2&gt;The city&lt;/h2&gt;
&lt;p&gt;This is not my first time in Barcelona, I was here at the beginning of this
year, but this is a great city and I've no time to visit all the places the
first time.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/las-2019-barcelona.jpg"&gt;
        &lt;img src="/pictures/las-2019-barcelona.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;So I've spent the Thursday afternoon doing some tourism, visiting the "Sagrada
Familia" and the "Montjuïc" fountain.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/las-2019-sagrada.jpg"&gt;
        &lt;img src="/pictures/las-2019-sagrada.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;If you have not been in Barcelona and you have the opportunity to come here,
don't hesitate, it's a really good city, with a great architecture to admire
and really nice culture and people, and here you can find good food to enjoy.&lt;/p&gt;
&lt;h2&gt;Thank you all&lt;/h2&gt;
&lt;p&gt;I was sponsored by the &lt;a href="https://www.gnome.org/foundation/"&gt;GNOME Foundation&lt;/a&gt;, I'm really thankful for this
opportunity, to come here, give a talk and share some time with great people
that makes the awesome Linux and open source community possible.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
    &lt;a href="https://gnome.org"&gt;
        &lt;img src="/pictures/sponsored-by-foundation-round.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I want to thank to my employer &lt;a href="https://endlessos.com/es/"&gt;Endless&lt;/a&gt; because it's really a privilege to
have a job that allows this kind of interactions with the community, and my
team &lt;a href="https://hack-computer.com/"&gt;Hack&lt;/a&gt;, because they I've missed some meetings this week and I was not
very responsive during the week.&lt;/p&gt;
&lt;p&gt;And I want to thank to the LAS organization, because this was a really good
event, good job, you can be very proud.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 14 Nov 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-11-14:/las-2019.html</guid><category>blog</category><category>gnome</category><category>LAS</category><category>endless</category></item><item><title>Andaluh-rs, a lib to transcript Spanish to Andaluh</title><link>https://danigm.net/andaluh.html</link><description>&lt;p&gt;Spain is a big region with a lot of languages, we've the official one for
the whole region, Spanish or Castilian (es-ES), and other officials languages
spoken in other regions, like the Galician (gl-ES) spoken in Galicia,
the Basque (eu-ES), spoken in the Basque Country, the Catalan (ca-ES)
spoken in Catalonia.&lt;/p&gt;
&lt;p&gt;But we've more languages that doesn't have the same official support, the
Valencian, the Aragonese, the Asturian, &lt;a href="https://en.wikipedia.org/wiki/Languages_of_Spain"&gt;and more&lt;/a&gt;. And also we've some
&lt;strong&gt;dialects&lt;/strong&gt; like the &lt;em&gt;Andalusian&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;All of this languages was discredit during the dictatorship period when the
only official language was the Spanish and the others was treated like
vulgar languages or non educated one, and in some cases the language was
&lt;em&gt;prohibited&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Whe the &lt;em&gt;democracy&lt;/em&gt; arrives, some regions spend a lot of resources trying to
recover the language and are supporting it until now with official institutions
and lessons in the official education system. But in other regions the stigma
continued until today.&lt;/p&gt;
&lt;p&gt;That's the case of the &lt;em&gt;Andalusian&lt;/em&gt;, that right now is not considered a language
but a dialect. In any case, this &lt;em&gt;dialect&lt;/em&gt; is treated as a non cultivated
language, spoken by illiterates. We've a lot of Spanish movies and Series where
the character that spoke &lt;em&gt;Andalusian&lt;/em&gt; was the illiterate, from the countryside
or the servant of the family.&lt;/p&gt;
&lt;h2&gt;Be proud of it&lt;/h2&gt;
&lt;p&gt;In Andalusia we've a lot of culture, literature and music done in &lt;em&gt;Andalusian&lt;/em&gt;,
but we don't have a way to write that and many people try to avoid the &lt;em&gt;acent&lt;/em&gt;
and the local words to look more cultured and because there's no a writing
system, we write in Spanish, it's hard to write lyrics, poetry and other
kind of literature. The Andalusian is not only a way to talk, some words are
short and we've contractions and other vowel sounds so if you write in Spanish,
it's not the same as spoken, some information is missed and for example in music
or poetry the metric doesn't match.&lt;/p&gt;
&lt;p&gt;There's a &lt;a href="https://andaluh.es/"&gt;movement&lt;/a&gt; trying to define a writing &lt;strong&gt;Andalusian&lt;/strong&gt; and promoting the
language, trying to make people proud of it and talk and write without complexes.&lt;/p&gt;
&lt;h2&gt;Translator, here comes the code&lt;/h2&gt;
&lt;p&gt;And there's a &lt;a href="https://github.com/andalugeeks/"&gt;group of developers&lt;/a&gt; that are working in some tools to provide
direct translation from Spanish and other tools to ease the &lt;strong&gt;Andalusian&lt;/strong&gt; writing.&lt;/p&gt;
&lt;p&gt;I like to write code and I'm always happy to find new problems to solve, to learn
new languages, tools and to spend some time trying to code something that I've not
done before. So I decided to write a translator from Spanish to Andaluh using rust,
and I've created the &lt;a href="https://github.com/andalugeeks/andaluh-rs"&gt;andaluh-rs&lt;/a&gt; lib.&lt;/p&gt;
&lt;p&gt;The translator is more or less easy, there're some rules that should be applied
from top to bottom that basically replaces some group of letters. There's a
implementation in &lt;a href="https://github.com/andalugeeks/andaluh-py"&gt;python&lt;/a&gt; that uses regular expressions for that. There're
a lot of regular expressions, so I thougth that it could be easy to use a parser,
so I used the &lt;a href="https://github.com/pest-parser/pest"&gt;pest parser&lt;/a&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// supress muted /h/&lt;/span&gt;

&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;h&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;H&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;initial_h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;CH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;inner_ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;inner_h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="n"&gt;inner_ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;hua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ua&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UA&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Ua&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uA&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;hue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ue&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;UE&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Ue&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;noh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="n"&gt;CH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;_&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;SOI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;?&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;initial_h&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inner_ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inner_h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;noh&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I've defined each rule in the pest format, so I've a parser for each rule
and then I can replace the word with the correct replacement.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;h_rule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;H_RULES_EXCEPT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;initial_h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;inner_h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;keep_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;keep_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;güe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hua&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Pair&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Rule&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;keep_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gua&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To simplify the code, I've defined the &lt;code&gt;rule&lt;/code&gt; macro, with the code used in
all rules:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$($t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;pat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;rule&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$($t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$($t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;pat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;replace_exceptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AndaluhParser&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_rule&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$($t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="cp"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;outstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_some&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;outstr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;replace_exceptions_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;outstr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outstr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And because the Spanish and the Andaluh languages uses unicode and rust Strings
can not be iterated by &lt;em&gt;unicode&lt;/em&gt;, I've used &lt;code&gt;unicode_segmentation&lt;/code&gt; crate, and
defined some utility macros to get the real String len and to get slices of that
String.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;UnicodeSegmentation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;graphemes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;chars&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With all this done, we only have to apply all rules, in the correct order,
to the input string so we can get the translated String as output.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;epa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// TODO: escape links&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;h_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;x_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ch_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;gj_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;v_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ll_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;l_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;psico_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;vaf_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;word_ending_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;digraph_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;exception_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;word_interaction_rule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;This code is not the best one, I'm doing a lot of string operations with copies
and clones, I'm sure that anyone with more experience with rust can view a lot
of points where we can optimize this code. At first I thought that the translation
could be done during the parsing, keeping a length to be able to view backward
and forward.&lt;/p&gt;
&lt;p&gt;Maybe it's possible to read char by char, keeping a buffer, and detecting if
we can apply any of the rules with the content in the buffer, but I've based
this lib in the python one, so for me it was easier to translate each regex to
pest regex and then do the same translations in the lib.&lt;/p&gt;
&lt;p&gt;But I still think that there's a better solution for this problem, but some times
it's better to have something that just works instead of a never done best
solution.&lt;/p&gt;
&lt;p&gt;During this process I've learned to use pest and I've been playing a lot with
regular expressions, so it was a fun project.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 06 Jul 2019 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2019-07-06:/andaluh.html</guid><category>blog</category><category>gnome</category><category>software</category><category>andaluh</category><category>language</category></item><item><title>EndlessOS dual boot with Fedora</title><link>https://danigm.net/endlessos-dual-boot.html</link><description>&lt;p&gt;I've a &lt;em&gt;ThinkPad X1 Yoga&lt;/em&gt;, that's basically a &lt;em&gt;ThinkPad X1 Carbon 4th&lt;/em&gt; but
with a touch screen with a pencil that works like a wacom tablet.&lt;/p&gt;
&lt;p&gt;I've this laptop since 2016. The first thing that I did when I received it
was install a GNU/Linux operating system. I'm a GNU/Linux user since the
year 2000 going through a lot of distributions, Debian, Ubuntu, Archlinux, etc.&lt;/p&gt;
&lt;p&gt;When I received this computer I've a customized Archlinux there, and I wanted
to &lt;code&gt;dd&lt;/code&gt; my harddisk and boot, but I was unable to do that. I didn't know
nothing about UEFI and I was unable to boot the Archlinux installer.&lt;/p&gt;
&lt;p&gt;So I decided to go ahead and change my main distribution. I installed Fedora
and almost all the hardware worked so I keep that one and was happy, until
today :P&lt;/p&gt;
&lt;h2&gt;OStree, the new way of distribute GNU/Linux&lt;/h2&gt;
&lt;p&gt;With OStree and flatpak, there's a new way to distribute GNU/Linux, instead of
use directly a package manager and update each package, we can use OStree and
mount the root filesystem as read only and do full OS upgrades without broken
packages and dependencies and so. The operating system go as is and the user
should try hard to break it.&lt;/p&gt;
&lt;p&gt;The other great thing about OStree is that it's like a git repository, so you
can have different branches and a history, so you can easily go back and forward,
it's really easy to test the beta and go back without breaking your system.&lt;/p&gt;
&lt;p&gt;The main problem is that you &lt;em&gt;can't&lt;/em&gt; install anything on your OS, you should
use contained apps like flatpak or install by hand, you can't use &lt;code&gt;apt-get&lt;/code&gt;.
But that's okay for a day to day user, a power user always can &lt;code&gt;unlock&lt;/code&gt; the OS
and use it as a normal GNU/Linux distribution.&lt;/p&gt;
&lt;p&gt;I wanted to try one of these distributions. The logical choice was &lt;a href="https://silverblue.fedoraproject.org/"&gt;Silverblue&lt;/a&gt;
because it's a Fedora and I'm using it for three years now, but there's another
option, &lt;a href="https://endlessos.com/"&gt;EndlessOS&lt;/a&gt; is also OStree based, and &lt;a href="http://danigm.net/endless.html"&gt;I'm working with this OS&lt;/a&gt;,
so I should give a try and use EndlessOS.&lt;/p&gt;
&lt;h2&gt;The EndlessOS install process&lt;/h2&gt;
&lt;p&gt;Like all the new modern GNU/Linux distros, EOS comes with a easy to use installer,
you only need to boot from the USB and click next until it's done...&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/endless-install-2.jpg"&gt;
        &lt;img src="/pictures/eos/endless-install-2.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;But here we've the first problem. I've more than one partition in my disk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/dev/sda1: UEFI&lt;/li&gt;
&lt;li&gt;/dev/sda3: Fedora /&lt;/li&gt;
&lt;li&gt;/dev/sda8: Swap&lt;/li&gt;
&lt;li&gt;/dev/sda4: Fedora /boot&lt;/li&gt;
&lt;li&gt;/dev/sda6: /home&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to keep my Fedora (who knows if something bad happens) and try to use the
same home partition for my new EOS. But the installer only give me the option
to erase all and have a clean system. But that won't stop me.&lt;/p&gt;
&lt;p&gt;Let's go back and instead of reformat I will click on &lt;em&gt;Try Endless OS&lt;/em&gt;:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/EndlessOS-Installation.png"&gt;
        &lt;img src="/pictures/eos/EndlessOS-Installation.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;What we need to do, Robert McQueen gave me some directions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The constraints for booting Endless are 1) you use our grub, and 2) the root
partition is labelled "ostree"&lt;/p&gt;
&lt;p&gt;So if you have an EFI system, you can copy our EFI binaries into the ESP, and
create a new partition for Endless, then dd the endless ostree filesystem into
it&lt;/p&gt;
&lt;p&gt;Then you should be able to boot, if you add a boot entry for the endless grub
to your firmware, or make it the default (by providing the fallback boot64.efi
or whatever it's called), or chain load it from another Linux loader&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Install EOS with other linux (EFI system)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Boot from USB, select try&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch the gnome-disk-utility and prepare a partition. I've not free space,
but I was able resize my Fedora partition and I split in two of the same size,
now I've a new ext4 partition &lt;code&gt;/dev/sda7&lt;/code&gt; with 25GB.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the endless ostree:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su
&lt;span class="c1"&gt;# dd if=/dev/mapper/endless/image3 /dev/sda7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Copy endless grub to EFI. I mounted all partitions in /tmp, the first
partition in &lt;code&gt;/tmp/sda1&lt;/code&gt; and the EOS efi in the &lt;code&gt;/tmp/EOS&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# mkdir /tmp/sda1 /tmp/EOS
# mount /dev/sda1 /tmp/sda1
# mount /dev/mapper/endless-image1 /tmp/EOS
# cp -rf /tmp/EOS/EFI/endless/ /tmp/sda1/EFI
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Add the new boot entry:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# efibootmgr -c -d /dev/sda -p 1 -L EOS -l \\EFI\\endless\\grubx64.efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Set as default boot:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# cp /tmp/EOS/EFI/endless/grubx64.efi /tmp/sda1/EFI/Boot/bootx64.efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Reboot and create my default user. Then I add my home partition to the &lt;code&gt;/etc/fstab&lt;/code&gt;
file:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;UUID=c885e171-1a03-4afb-8519-f9fe26fe92b7 /sysroot/home ext4 defaults 1 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And because the first user in EOS is the shared account, with UID 1000, I've to
change the UID of my user editing the file in &lt;code&gt;/etc/passwd&lt;/code&gt;. Then I rebooted
again and all works. I've all my flatpak apps installed in the user space working.&lt;/p&gt;
&lt;p&gt;So here we're, with a shiny new OS working like a charm:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/eos/screenshot.png"&gt;
        &lt;img src="/pictures/eos/screenshot.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The EFI and efibootmgr (who needs grub to select the OS?)&lt;/h2&gt;
&lt;p&gt;I didn't know much about UEFI and I was very impressed about how easy is to
update this from GNU/Linux. There's a tool called &lt;code&gt;efibootmgr&lt;/code&gt; that does all
the work, and you can mount the partition, that's a FAT32, and put files there.&lt;/p&gt;
&lt;p&gt;In my ThinkPad, I can boot directly to the UEFI boot menu pressing F12 during
the boot, and that menu can be changed using the &lt;code&gt;efibootmgr&lt;/code&gt; so it's not
needed anymore to use the grub2 OS selection interface, I can use the UEFI
menu for that!&lt;/p&gt;
&lt;p&gt;This has some disadvantages, if you remove files from the UEFI partition, you
can break the whole boot, so review all before any change.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 25 May 2019 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2019-05-25:/endlessos-dual-boot.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>fedora</category></item><item><title>Kung-fu Master, Blindfolded debugging</title><link>https://danigm.net/blindfolded.html</link><description>&lt;p&gt;Recently I've been working in the &lt;a href="https://endlessos.com/"&gt;EOS&lt;/a&gt; update. The change is really big
because EOS has some modifications over the upstream code so there are a lot
of commits applied after the last stable upstream commit.&lt;/p&gt;
&lt;p&gt;EOS 3.5 was based on gnome 3.26 and we are updating to use the gnome 3.32 so
all the downstream changes done since the last release should be rebased on top
of the new code and during this process we refactor the code and commits using
new tools and remove what's now in gnome upstream.&lt;/p&gt;
&lt;p&gt;I've been working in the Hack computer custom functionality that's on top of
the EOS desktop and basically I've been rebasing the code in the shell to
do the Flip to Hack, the Clubhouse, a side component and notification override
to propse hack quests and the wobbly windows effects.&lt;/p&gt;
&lt;p&gt;I've been working mainly with gnome shell and updating javascript code to the
new gjs version, but this was a big change and some rare bugs.&lt;/p&gt;
&lt;p&gt;Here comes the blindfolded debugging. I've a development system with a lot of
changes and a functionality in the gnome shell that depends on different
projects, applications and technologies.&lt;/p&gt;
&lt;p&gt;I don't know the code a lot, because I'm not the one that wrote all of this,
I'm working here since February, so I know a bit how things works, but I'm not
the one who knows everything, there are a lot of rare cases that I don't know
about.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/blindfolded/kungfu.gif" /&gt;
&lt;/p&gt;

&lt;p&gt;I've found and fixes several bugs in different projects, that I don't know about
a lot, during this process. How can I do that? If you are a developer that
write code since a few years maybe you've experienced something similar, I'm
calling this the &lt;strong&gt;blindfolded debugging technique&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Start to change code without knowing exactly what you're doing, but with a
small feeling that maybe that line is the problem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This technique is only for experienced programmers, as a kungfu master that
put a blindfold in their eyes to fight against an opponent, the developer that
will be brave enough to try this should have a lot of experience or he will fail.&lt;/p&gt;
&lt;p&gt;You're an experienced developer, but you don't know the software that you're
debugging. It doesn't matter. The same way that in a kungfu fight you don't
know your opponent, but almost every fighter has two arms and two legs, so
more or less you'll know that he'll try to punch you or kick you, you've a
clue. As a programmer, every software has an structure, functions, loops...&lt;/p&gt;
&lt;p&gt;No matters who wrote that or how old that code is, if you're an experienced
programmer you'll feel the code and without knowing exactly why or how, you
will be able to look at one line and says: &lt;em&gt;Here you're little buggy friend&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Maybe I'm only trying to justify my lucky with a story to feel better and
say that I'm not a dumb changing random lines to try to find a bug, but I'm
sure that other developers has this feeling too, that feeling that guides you
to the exact problem but that you're not able to rationalize.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/blindfolded/fight.gif" /&gt;
&lt;/p&gt;

&lt;p&gt;I think that this is the experience, the expertise is your body and your
inner brain doing the work meanwhile you don't need to think about it or
know exactly what you are doing.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 05 May 2019 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2019-05-05:/blindfolded.html</guid><category>blog</category><category>gnome</category><category>software</category><category>debugging</category></item><item><title>I'm a hacker</title><link>https://danigm.net/endless.html</link><description>&lt;h2&gt;I've the strength of the one that fails, trains and returns&lt;/h2&gt;
&lt;p&gt;Some time ago I wrote &lt;a href="http://danigm.net/gnome-gtk-developer.html"&gt;about my interview process&lt;/a&gt; trying to get a job at
GNOME. After this blog post was published in the GNOME planet, I received a lot
of comments from the &lt;em&gt;Great&lt;/em&gt; GNOME community.&lt;/p&gt;
&lt;p&gt;This guided me to take a look to the companies that was looking for GNOME
developers and after some interviews I finally get an offer to work on
&lt;a href="https://endlessos.com/"&gt;Endless&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All the process was online, I've been working from home since 2011 and I want
to continue like this. I'm living in Málaga, the south of Spain and I was
looking for a remote job.&lt;/p&gt;
&lt;p&gt;I've a very nice interview process, talking with developers that I knew about
from their contributions to free software and these interviews weren't
technical, that's a good thing about the free software contribution and
the community, if someone wants to know my technical skills, he only need to
look to my gitlab or github and he will find a lot of code. These interviews
were personal and with some management questions, to know if I'll fit in the
team and the company.&lt;/p&gt;
&lt;p&gt;I did the interview to work directly on the Endless OS, in the desktop team,
but after some interviews I ended in other team, working with the Endless OS
and all GNOME technology, but in the &lt;a href="https://hack-computer.com/"&gt;Hack Computer&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The hack computer&lt;/h2&gt;
&lt;p&gt;The hack computer is an educational project. The main idea is to provide a
fully functional computer for kids to be their first personal computer and also
provide a way to teach kids to &lt;em&gt;hack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The computer is a usual laptop, with an Endless OS running, and with some extra
applications that try to guide kids to explore, modify and finally hack the
computer learning in the process about GNU/Linux, the code and that any part
of your software can be hacked to make it better, an introduction to the
free software and the great world of open source code that you can modify to
learn, play or simply because you can.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/SN7tC4XnGko" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;The way to guide kids to learn is like a video game, with characters that will
appears in your desktop and will guide you with tips and challenges and after
each quest completed the kid will learn something, playing with his computer.&lt;/p&gt;
&lt;p&gt;If you like this and want to collaborate, &lt;a href="https://jobs.lever.co/endless"&gt;we're hiring&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Endless OS&lt;/h2&gt;
&lt;p&gt;The hack computer is built on top of the Endless OS. Endless OS is based on
debian and the desktop is a modified gnome shell, but it's not the usual debian
derivative, it's based on &lt;a href="https://ostree.readthedocs.io/en/latest/"&gt;OSTree&lt;/a&gt;. The main difference is that the root
filesystem is read only and updates are managed with ostree, that's like a git
repository.&lt;/p&gt;
&lt;p&gt;This kind of Operating System is easier to maintain, because the user &lt;em&gt;can't&lt;/em&gt;
modify the base system, so this means that he was unable to &lt;em&gt;break it&lt;/em&gt;. All user
applications are installed via flatpak, so are &lt;em&gt;independent&lt;/em&gt; of the &lt;em&gt;OS&lt;/em&gt;
version and because of flathub you can install latests version of apps without
the need to update the full operating system.&lt;/p&gt;
&lt;p&gt;This is the way that &lt;a href="https://silverblue.fedoraproject.org/"&gt;Fedora SilverBlue&lt;/a&gt; is trying to follow and is a &lt;em&gt;new&lt;/em&gt;
way to build and distribute GNU/Linux.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/hack-mount-tree.png"&gt;
        &lt;img src="/pictures/hack-mount-tree.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;The end of an Era&lt;/h2&gt;
&lt;p&gt;I've been working in &lt;a href="https://wadobo.com"&gt;Wadobo&lt;/a&gt; since 2011. I created that company with two
college friends to try to continue hacking like we were hacking in the Seville
LUG &lt;a href="https://sugus.eii.us.es/"&gt;SUGUS&lt;/a&gt; and earn money from that, and we did it for a long time.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-2.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;We've been working in free software projects and with free software technology,
contributing to the community as much as we can and always trying to free our
work.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-1.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;We created some projects that grow up and follow its own path, like the
agora voting system, that Edulix (Eduardo Robles) converts in &lt;a href="https://nvotes.com/"&gt;nvotes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The self employment was a really good experience. I've been doing was I want
for a long time, taking time to contribute to GNOME and other projects when
I need it, because I was the one deciding what I want to do. But in the other
hand, I've been stuck in the local consultancy market for a long time.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-3.jpg" /&gt;
&lt;/p&gt;

&lt;p&gt;I'm not a business man, I'm a developer and I'm based in Spain, where there
is no money inverted in innovation or we was unable to find that money, so we
were doing django web apps for a living and spending some time in our interests
in the extra time we've. So when I found the possibility to work full time in
an innovative project, I've no choice.&lt;/p&gt;
&lt;p&gt;We'll try to continue with the &lt;strong&gt;Wadobo&lt;/strong&gt; idea, like a group of people
interested in free software and new technologies, maybe this will derive into
a Linux User Group or maybe in the future someone takes the initiative and
build a business around this again.&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;img src="/pictures/wadobo-old-4.jpg" /&gt;
&lt;/p&gt;

&lt;h2&gt;Hacking&lt;/h2&gt;
&lt;p&gt;I'm really happy with this change. Endless OS and the hack computer are really
great projects with a lot of bleeding edge technology and a really great group
of people, and I'm really exited to be able to work with people all around the
world in a project with a global vision.&lt;/p&gt;
&lt;p&gt;I don't want to leave the roots I've here with my Wadobo friends and the local
community and local technology ecosystem. This is also related with the Endless
vision. Spain, and here in the south, in Andalucía, we've a technological
breach that we try to fill with free software.&lt;/p&gt;
&lt;p&gt;I'll continue working with the Seville University, because they give me a lot
and I think it's a talent pool, we only need to guide those students to the
GNOME community or to other free software communities out there, to &lt;em&gt;save&lt;/em&gt;
their souls from the privative software and the dark side.&lt;/p&gt;
&lt;p&gt;I'll continue supporting initiatives like the &lt;a href="http://concursosoftwarelibre.org/"&gt;Free Software Contest&lt;/a&gt;&lt;/p&gt;
&lt;p class="img"&gt;
  &lt;a href="http://concursosoftwarelibre.org/"&gt;
    &lt;img src="http://concursosoftwarelibre.org/1819/files/images/banners/cusl2_500x455.png" /&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;By the way, I'll be talking about rust in the Seville University the next
Tuesday 5th of March 2019, if you're in Seville, come to talk with me :D&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 17 Feb 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-02-17:/endless.html</guid><category>blog</category><category>gnome</category><category>work</category><category>endless</category><category>hack</category></item><item><title>Timetrack app for GNOME</title><link>https://danigm.net/timetrack.html</link><description>&lt;p&gt;This week I started a new small project called &lt;a href="https://flathub.org/apps/details/net.danigm.timetrack"&gt;Timetrack&lt;/a&gt;, you can find
the code in the &lt;a href="https://gitlab.gnome.org/danigm/timetrack"&gt;gnome gitlab&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/timetrack1.png"&gt;
        &lt;img src="/pictures/timetrack1.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This is a simple app to store an activity log in a sqlite database and to
provide useful reports in the future. The main idea is to use this for may day
to day work, so I'll be able to keep track of my working hours and other
activities.&lt;/p&gt;
&lt;h3&gt;The need&lt;/h3&gt;
&lt;p&gt;There's a lot of timetrack applications. There are good web apps and also some
desktop applications. At first, I tried to find a gnome-shell plugin, but I
didn't find any extension that is good for me.&lt;/p&gt;
&lt;p&gt;I've had a &lt;a href="https://github.com/wadobo/django-objs"&gt;custom simple web app&lt;/a&gt; to track my time.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/wadobo-objs.png"&gt;
        &lt;img src="/pictures/wadobo-objs.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I've been using this app for a long time, but I don't like to use web apps for
simple tasks so I want something local.&lt;/p&gt;
&lt;p&gt;So I tried with some gtk desktop applications, but none of the applications
that I've found looks good to me.&lt;/p&gt;
&lt;p&gt;I wanted a simple timetrack app, without any complex stuff, so I thought that it
won't be hard to implement it. So I started with a simple python app based
on the code of &lt;a href="https://gitlab.gnome.org/World/PasswordSafe/"&gt;Password Safe&lt;/a&gt;.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/timetrack2.png"&gt;
        &lt;img src="/pictures/timetrack2.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;So I started to code and in two days I had a simple application that &lt;em&gt;works&lt;/em&gt;.
The applications is now on flathub so it's available for use.&lt;/p&gt;
&lt;h3&gt;The functionality&lt;/h3&gt;
&lt;p&gt;Right now, Timetrack has a limited set of features, but I think I'll improve
the app with new features as soon as I need something. So, the current version
can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Track activity time with a simple button, showing the activity time spent&lt;/li&gt;
&lt;li&gt;List last activities&lt;/li&gt;
&lt;li&gt;Edit / Delete activities&lt;/li&gt;
&lt;li&gt;Simple report by day, week or month&lt;/li&gt;
&lt;li&gt;Report navigation using a calendar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I've plans to add more functionalities in the near future, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Report export to plain text and csv&lt;/li&gt;
&lt;li&gt;Comments for activities&lt;/li&gt;
&lt;li&gt;Tags for activities&lt;/li&gt;
&lt;li&gt;Detailed reports&lt;/li&gt;
&lt;li&gt;Activity Graphs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of this is stored in a sqlite database, if you install the app using flatpak
you can find the database in this path:
&lt;code&gt;~/.var/app/net.danigm.timetrack/data/timetrack.sqlite3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I've &lt;em&gt;done&lt;/em&gt; the icon for this app using the gnome-clocks icon and adding some
colors to it.&lt;/p&gt;
&lt;p&gt;If you find this app useful, don't hesitate and use it. Any feature request or
bug report is welcome. And of course, all is free software, so if you want to
collaborate, go ahead and send me some Merge Request.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 26 Jan 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-01-26:/timetrack.html</guid><category>blog</category><category>gnome</category><category>timetrack</category><category>python</category></item><item><title>GNOME Outreachy mentorship</title><link>https://danigm.net/gnome-outreachy-2018.html</link><description>&lt;p&gt;The &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt; program is a three month internship to work in FOSS. There
are two periods for the outreachy, the first one from December to March and
the other one from May to August. It's similar to the Google Summer Of Code,
but in this case the interns doesn't need to be students.&lt;/p&gt;
&lt;p&gt;I proposed some ideas for interts to work on GNOME, with me as a mentor. I
wrote three proposals this time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extend &lt;a href="https://www.outreachy.org/communities/cfp/gnome/project/extend-fractal-media-viewer-with-video-support-and/"&gt;Fractal&lt;/a&gt; media viewer with video support and explore video
   conference&lt;/li&gt;
&lt;li&gt;Create &lt;a href="https://www.outreachy.org/communities/cfp/gnome/project/create-gtranslator-initial-integration-with-damned/"&gt;Gtranslator&lt;/a&gt; initial integration with Damned Lies&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.outreachy.org/communities/cfp/gnome/project/books-improve-the-epub-support-in-gnome-books/"&gt;Books&lt;/a&gt; : Improve the epub support in gnome-books&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There was people interested in all of three projects, but for the Books app
we don't have any real contribution so there was no real applicants.&lt;/p&gt;
&lt;p&gt;I've two good proposals for Fractal and for Gtranslator, so I approve both and
the Outreachy people approve these two interts. So we get two new devs working
in GNOME for three months as interns.&lt;/p&gt;
&lt;p&gt;This is something great, paid developers working in my proposals is a good
thing, but this implies that I need to do the mentor work for these two interns
during the three months period, so it's more work for me :/&lt;/p&gt;
&lt;p&gt;But I think this is a really important work to do to bring more people to the
free software, so I've less time for hacking, but I think it's good, because
the fresh blood can do the hacking and if, after the Outreachy, one of the
interns  continues collaborating with GNOME, that will be more important for
the GNOME project that some new features in one app.&lt;/p&gt;
&lt;h3&gt;GNOME Translation Editor&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://teja.cetinski.eu/blog"&gt;Teja&lt;/a&gt; is the intern working in gtranslator. She is working in the
&lt;a href="https://l10n.gnome.org/"&gt;Damned Lies&lt;/a&gt; integration.&lt;/p&gt;
&lt;p&gt;Damned Lies is a web application for GNOME translators. This app provides
updated &lt;code&gt;.po&lt;/code&gt; file for each GNOME module and language and translators can
download and update that file using the web interface. That web is able to
do the commit to the original repository with the upload version from
translators.&lt;/p&gt;
&lt;p&gt;The idea is to provide a simple integration with this platform in the
GNOME Translation Editor app, using the web json API to be able to open &lt;code&gt;.po&lt;/code&gt;
files from the web directly without the need to download the file and then
open it.&lt;/p&gt;
&lt;p&gt;The current API of DL is really simple so we can't implement a real integration
without adding more functionality to this API. So this project requires some
work in the DL app too.&lt;/p&gt;
&lt;p&gt;In the future we can improve the integration adding the posibility to upload
the new &lt;code&gt;.po&lt;/code&gt; after saving to DL so translators doesn't need to go to the
web interface and can do all the translation flow using only the Translation
Editor.&lt;/p&gt;
&lt;h3&gt;Fractal&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://mairandom.space/"&gt;Maira&lt;/a&gt; is the intern working in Fractal. They are working in the initial
video preview widget.&lt;/p&gt;
&lt;p&gt;Fractal is a instant messaging app that works over matrix.org. Currently we
support different types of messages, like text, images, audio and files. But
for video we're using the same widget as we're using for files, so you can
download or open, but we've not a preview or inline player.&lt;/p&gt;
&lt;p&gt;The main idea of this project is to provide a simple video player using
gstreamer to play the video inside the Fractal app.&lt;/p&gt;
&lt;p&gt;This is not an easy task, because we're using Rust in Fractal and we need to
deal with bindings and language stuff, but I think it's doable.&lt;/p&gt;
&lt;p&gt;During the internship, Maira is also working fixing some bugs in the audio
player, becuase it uses gstreamer too, so during the code review, Maira
detected some problems and they are fixing it.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 13 Jan 2019 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2019-01-13:/gnome-outreachy-2018.html</guid><category>blog</category><category>gnome</category><category>fractal</category><category>gtranslator</category><category>outreachy</category></item><item><title>Fractal December'18 Hackfest (part 2)</title><link>https://danigm.net/fractal-december-18-hackfest-2.html</link><description>&lt;p&gt;The Friday 14th was the last day of the &lt;a href="https://wiki.gnome.org/Hackfests/FractalDecember2018"&gt;second Fractal Hackfest&lt;/a&gt;. I've not
spend much time writing real code, the Thursday was mainly another hacking day
and I've been able to continue with the &lt;strong&gt;fractal-backend&lt;/strong&gt; creation, but
there's a lot of work to do there.&lt;/p&gt;
&lt;p&gt;But the hackfest was really productive, we've talked about big issues, project
management, some design ideas, new functionalities, the application refactor,
etc.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-seville-hackfest-2.jpg" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h3&gt;GNOME newcomers experience&lt;/h3&gt;
&lt;p&gt;We talked about how to improve the GNOME newcomers experience and how to
improve the main view of Fractal. I think that Tobias will talk more about this,
he was working in some cool design for this and I think we can start to
implement this new views soon.&lt;/p&gt;
&lt;h3&gt;Best practices&lt;/h3&gt;
&lt;p&gt;We've been developing Fractal in a fast way, without spend a lot of time
thinking about the code quality, maintainability and that stuff. Recently we've
set the &lt;strong&gt;rustfmt&lt;/strong&gt; linter in the CI pipeline and we've some tests, but the
Merge Requests process wasn't defined and for example I was pushing directly
to master.&lt;/p&gt;
&lt;p&gt;To improve the quality of Fractal we've started a new wiki page to have a list
of &lt;a href="https://gitlab.gnome.org/GNOME/fractal/wikis/Best-practices-for-Fractal-development"&gt;best practices&lt;/a&gt; to follow. There we'll add some guidances on how we
should write code and the processes to follow to improve Fractal.&lt;/p&gt;
&lt;p&gt;We've decided that we should be more strict with the Merge Request code review
and now, direct push to master is not allowed, all changes will go through the
review process. We should wait at least two days to merge something and have
at least two people that approve the change.&lt;/p&gt;
&lt;p&gt;This will slow down the MR process, but will improve the code quality and
will reduce regressions. Any help is welcome, if you're able to test the MR,
you can leave a comment and other reviewers will have more confident in the
change.&lt;/p&gt;
&lt;p&gt;We're also working in the code quality using the cargo clippy tool. There's a 
Merge Request waiting for review, so we'll have a better rust source code soon.&lt;/p&gt;
&lt;h3&gt;Fractal is now in the GNOME group&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://gitlab.gnome.org/GNOME/fractal/"&gt;Fractal&lt;/a&gt; project was on the &lt;strong&gt;World&lt;/strong&gt; group inside the GNOME gitlab.
Fractal is a GNOME application, the most active developers are GNOME developers
and we try to follow the GNOME Human Interface Guidelines.&lt;/p&gt;
&lt;p&gt;Fractal is one of the first new applications that born just during the gitlab
migration so we go through a new process. At first Fractal was in my personal
gitlab under &lt;strong&gt;/danigm/fractal&lt;/strong&gt; then we move to the World group under
&lt;strong&gt;/World/fractal&lt;/strong&gt; and finally we're in the main GNOME group &lt;strong&gt;/GNOME/fractal&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;New release 4.0.0&lt;/h3&gt;
&lt;p&gt;The last release was the 3.30.0, more than three months has passed since this
release and we've a lot of changes so we want to provide a new stable release.&lt;/p&gt;
&lt;p&gt;We discuss a bit about the &lt;a href="https://gitlab.gnome.org/GNOME/fractal/issues/350"&gt;version number&lt;/a&gt; that we should follow and we
decided that we should do use our own version number system, because we want
to release as much as possible, when we've important changes.&lt;/p&gt;
&lt;p&gt;We're working in the &lt;a href="https://gitlab.gnome.org/GNOME/fractal/issues/396"&gt;4.0.0&lt;/a&gt; release, we're stabilizing and fixing important
bugs before the release and maybe we can have the new release during the next
week.&lt;/p&gt;
&lt;p&gt;So I've spend the last day looking for bugs and preparing the new release.&lt;/p&gt;
&lt;h3&gt;Matrix Live&lt;/h3&gt;
&lt;p&gt;We've a meeting with the people from Matrix.org to talk about Fractal and the
hackfest. You can view the full interview in youtube:&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/SgyLHi8zZXQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2&gt;Friday sponsored lunch&lt;/h2&gt;
&lt;p&gt;We've a sponsored lunch the Friday 14th, the local group &lt;a href="https://www.plan4d.eu"&gt;Plan4D&lt;/a&gt; invite
us to a great lunch in the city center.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.plan4d.eu/"&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/plan4d.jpg"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After that, I goes back to my home and leave the other people there in Seville
doing some tourism, I've to go back to Málaga.&lt;/p&gt;
&lt;p&gt;The hackfest was great and we have done a lot of things. This was the second
Fractal hackfest in 2018, and we meet at the GUADEC too. We've had two GSoC
students and now we've another intern thanks to the outreachy program. There's
a lot of people contributing to Fractal and that's great.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GNOME is a great community&lt;/strong&gt; and I think that Matrix.org and Rust are helping
to this project a lot. The Matrix.org people are supporting us, indeed, Matthew
comes to the first hackfest and I think that the success of Fractal and the
community behind has a lot to thank to the Rust language and to the people
working in the Rust + GNOME integration, Gtk-rs is a great project.&lt;/p&gt;
&lt;p&gt;I want to apologize about the network problem during the hackfest. We've been
working all days thank to Julian network sharing, with eduroam, because we
aren't able to have guest access in the university.&lt;/p&gt;
&lt;p&gt;The university has a strict internet connection filtering, so only a professor
can ask for a guest connection for events and we do the request too late.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 16 Dec 2018 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2018-12-16:/fractal-december-18-hackfest-2.html</guid><category>blog</category><category>gnome</category><category>fractal</category><category>hackfest</category><category>wadobo</category><category>seville</category></item><item><title>Fractal December'18 Hackfest (part 1)</title><link>https://danigm.net/fractal-december-18-hackfest-1.html</link><description>&lt;h2&gt;First two days of work&lt;/h2&gt;
&lt;p&gt;The Tuesday 11th started the &lt;a href="https://wiki.gnome.org/Hackfests/FractalDecember2018"&gt;second Fractal Hackfest&lt;/a&gt;. I've organized this
hackfest in Seville, the city where I studied computer science and here I've a
lot of friends in the University so is a good place to do it here.&lt;/p&gt;
&lt;p&gt;The weather was important too for the hackfest selection, in December
Seville is a good choice because the weather is not too cold, we're having
sunny days.&lt;/p&gt;
&lt;p&gt;The first day was a good day, thinking about some relevant issues and planning
what we want to do. We talked about the work needed for the interface split,
about the E2EE support, new features and the need for a new release.&lt;/p&gt;
&lt;p&gt;We're having some problems with the internet connection, because the University
has a restricted network policy and we ask for the guess internet connection
the Monday, but we're still waiting.&lt;/p&gt;
&lt;p&gt;Meantime we have to thanks to Julian Sparber the hackfest wifi, because
he's using his laptop to stream the eduroam connection.&lt;/p&gt;
&lt;h2&gt;Newcomers&lt;/h2&gt;
&lt;p&gt;The first day we try to promote as a newcomers day, and some people comes.
We've some contributions and I spend some time trying to help people to
introduce to the GNOME community.&lt;/p&gt;
&lt;h2&gt;GNOME Foundation sponsored dinner&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://gnome.org"&gt;GNOME Foundation&lt;/a&gt; payed for a Fractal dev day dinner, so we should
thanks this great dinner to GNOME:&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-seville-hackfest-dinner.jpg" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;We've a good time eating and drinking in the &lt;em&gt;Coco Verde&lt;/em&gt;. We talk about GNOME,
the desktop, matrix.org and other communication tools.&lt;/p&gt;
&lt;h1&gt;Hacking day&lt;/h1&gt;
&lt;p&gt;Today was a hacking day, so we started to work in the stuff that we talk about
yesterday. We've resolved some minor issues and I started with the
&lt;strong&gt;fractal-backend&lt;/strong&gt; crate.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-seville-hackfest-computer.jpg" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;We talked about move all the app data model and logic to the &lt;strong&gt;fractal-backend&lt;/strong&gt;
and leave &lt;strong&gt;fractal-gtk&lt;/strong&gt; only as UI management.&lt;/p&gt;
&lt;p&gt;We talked about the &lt;strong&gt;LMDB&lt;/strong&gt; use to store rooms and messages and we decided
that the best solution should be to use a relational database, because we've
relations and with the key-value thing we'll end creating those relations and
maintaining by hand. In any case, I've this decision in mind and I'm
implementing all this with a trait to hide the storage detail so we can change
easily in the future.&lt;/p&gt;
&lt;p&gt;So today I've spend a lot of time implementing this trait and a first
implementation for the &lt;strong&gt;Room&lt;/strong&gt; struct. I've decided to use &lt;strong&gt;rusqlite&lt;/strong&gt; instead
the &lt;strong&gt;diesel&lt;/strong&gt; orm because I want to keep it simple.&lt;/p&gt;
&lt;p&gt;I want to finish all the database storage and move the AppOp main loop to the
&lt;strong&gt;fractal-backend&lt;/strong&gt; and try to update the &lt;strong&gt;fractal-gtk&lt;/strong&gt; to use the backend
instead the AppOp struct to get the rooms and messages. But maybe is a lot of
work, I don't know if I'll be able to finish this before the end of the
hackfest.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-seville-hackfest-julian.jpg" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;This hackfest is possible because there's a lot of volunteer work and people
helping us. First of all, the Fractal core team that comes &lt;em&gt;Tobias Bernard&lt;/em&gt;,
&lt;em&gt;Julian Sparber&lt;/em&gt; and &lt;em&gt;Alexandre Franke&lt;/em&gt; and of course the &lt;em&gt;GNOME Foundation&lt;/em&gt;.
And also we've to thank &lt;em&gt;Alejandro Domínguez&lt;/em&gt;, a newcomer that is doing a really
good job fixing bugs and cleaning some old code.&lt;/p&gt;
&lt;p&gt;Then I want to thank the &lt;a href="https://sugus.eii.us.es/"&gt;Linux local group, SUGUS&lt;/a&gt; for the help and also
I want to thank to other free software related group &lt;a href="https://www.plan4d.eu"&gt;Plan4D&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.plan4d.eu/"&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/plan4d.jpg"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Plan4D is giving us some help with the place and cookies, fruits, juices and
some tea.&lt;/p&gt;
&lt;p&gt;And finally I want to thank again to my coworkers in &lt;a href="https://wadobo.com"&gt;wadobo&lt;/a&gt; because they
support me to spend a full work week working in gnome and they also spend some
time helping us to organize all the hackfest stuff.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 12 Dec 2018 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2018-12-12:/fractal-december-18-hackfest-1.html</guid><category>blog</category><category>gnome</category><category>fractal</category><category>hackfest</category><category>wadobo</category><category>seville</category></item><item><title>GNOME Gtk Developer</title><link>https://danigm.net/gnome-gtk-developer.html</link><description>&lt;h2&gt;I tried and I failed.&lt;/h2&gt;
&lt;p&gt;This summer, during the GUADEC 2018, the GNOME foundation announces some job
positions. One of that job was for a &lt;a href="https://www.gnome.org/foundation/careers/gtk-core-developer/"&gt;Gtk+ core developer&lt;/a&gt;. I tried to get
that job and after a long period I was rejected.&lt;/p&gt;
&lt;p&gt;The final developer selected for this possition is &lt;a href="https://mail.gnome.org/archives/foundation-list/2018-December/msg00000.html"&gt;Emmanuel Bassi&lt;/a&gt;, a very
active developer in the core of GNOME and the one that's behind the great
&lt;a href="https://www.bassi.io/articles/2018/10/25/the-history-of-gnome/"&gt;The History of GNOME Podcast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To be honest, I really wanted that job. It's a dream job for me, working
fulltime in a free software project, by a foundation, with the great GNOME
technology and community.&lt;/p&gt;
&lt;p&gt;But I've to say that just when I saw the foundation announcement about this
position I thought about ebassi, because as far as I know, he's the best one to
do that job. In any case, I wanted to give a try and go for that job, I didn't
know about other people going for it, so maybe I can do it.&lt;/p&gt;
&lt;h2&gt;Some background&lt;/h2&gt;
&lt;p&gt;I'm working in my &lt;a href="https://wadobo.com"&gt;own little company&lt;/a&gt; since 2010. We're three coworkers
with the same percentage of the company, like a cooperative and we work mainly
as external consultant for bigger companies. We do a lot of work related with
GNU/Linux and free software, but lately we mainly do web apps with python
and react, because that's what our current clients ask for.&lt;/p&gt;
&lt;p&gt;But the first paid project for wadobo was a GNOME project, I started the
company with a small project to improve accessibility in PDF documents, working
directly in evince. And then we worked with Qt, QML and other technologies, but
I wasn't able to get a paid work on GNOME or Gtk+ since that initial work.&lt;/p&gt;
&lt;p&gt;In any case, I continued working in GNOME in my spare time, trying to
contribute, first with &lt;a href="https://gitlab.gnome.org/gnome/libgepub"&gt;libgepub&lt;/a&gt;, trying to bring epub support to evince,
and then to GNOME Books. And the last year I became more active because of
&lt;a href="https://gitlab.gnome.org/World/fractal"&gt;Fractal&lt;/a&gt; and &lt;a href="https://gitlab.gnome.org/gnome/gtranslator"&gt;Gnome Translation Editor (gtranslator)&lt;/a&gt;. And I've been
mentor for the GSoC 2018 and now I've two interns in the Outreachy program.&lt;/p&gt;
&lt;p&gt;I've some time to spend in GNOME, but I'm not making money from that, so now
I'm starting to look for that actively, because I really want to have more time
to spend working with free software.&lt;/p&gt;
&lt;p&gt;So, I talked with my coworkers, to be honest with them, and I told them that
I was going to try to get the Gtk+ core developer position.&lt;/p&gt;
&lt;h2&gt;The process&lt;/h2&gt;
&lt;p&gt;This was a long process, I think that it was long because there was a lot of
people for that position.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Email&lt;/strong&gt;: I sent the initial email in mid July, with a long description
   about me and my work in gnome and free software, with a little hope in my
   heart.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Survey&lt;/strong&gt;: Then I received an email with a link to a survey to complete with
   more information. That was great, because it sounds like I've passed the
   first cut.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Interview&lt;/strong&gt;: At the end of August I received a conglatulations email. My
   resume was positively reviewed and I'll have a personal interview.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That was really nice and I started to think that maybe it was possible after
   all.&lt;/p&gt;
&lt;p&gt;At the mid of September, I've a video conference meeting with Carlos Soriano
   and Matthias Clasen. For me was a great interview, talking about my experience,
   GNOME and Gtk+. Maybe the interview was a disaster and they are just a very
   nice people being nice with a poor developer, but at the end I thought that it
   was well and I was very exited about this.&lt;/p&gt;
&lt;h3&gt;The failure&lt;/h3&gt;
&lt;p&gt;After a long time without knowing anything, I received the email that I was
waiting for. I wasn't selected for the position. The next week, the foundation
announces the new staff member and in that moment I noticed that I've had no
chance to get the job. He's the better candidate and I'm really happy because
this is really good for GNOME.&lt;/p&gt;
&lt;h2&gt;And now what?&lt;/h2&gt;
&lt;p&gt;At the end of the process, I think that this was a great experience for me,
because this forces me to think about my career, what I want to do in the
future and I went through a full selection process, something that I've not done
since 2009.&lt;/p&gt;
&lt;p&gt;I will continue trying to find the way to work in GNOME or something realated
with the GNU/Linux desktop or core technologies.&lt;/p&gt;
&lt;p&gt;I did a lot of web development, I've a lot of experience and I'm really good doing
web with django, but I really want to go back and work with other technologies,
programming in C, the new Rust language and with some low level technologies.&lt;/p&gt;
&lt;p&gt;If someone need help, I'm here and I can work as a contractor. For now I'll
continue working in Wadobo, trying to find clients that requires desktop or
low level work.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 05 Dec 2018 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2018-12-05:/gnome-gtk-developer.html</guid><category>blog</category><category>gnome</category><category>gtk+</category><category>work</category><category>wadobo</category></item><item><title>GNOME Translation Editor 3.30.0</title><link>https://danigm.net/gnome-translation-editor.html</link><description>&lt;p&gt;I'm pleased to announce the new &lt;a href="https://download.gnome.org/sources/gtranslator/3.30/"&gt;&lt;strong&gt;GNOME Translation Editor&lt;/strong&gt;&lt;/a&gt; Release.
This is the new release of the well known &lt;strong&gt;Gtranslator&lt;/strong&gt;. I talked about
the &lt;a href="http://danigm.net/gtranslator-resurrection.html"&gt;&lt;strong&gt;Gtranslator Ressurection&lt;/strong&gt;&lt;/a&gt; some time ago and this is the result:&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator3.30.png"&gt;
        &lt;img src="/pictures/gtranslator3.30.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This new release isn't yet in flathub, but &lt;a href="https://github.com/flathub/org.gnome.Gtranslator/pull/4"&gt;I'm working on it&lt;/a&gt; so we'll
have a flatpak version really soon. Meantime you can test using the gnome
nightly flatpak repo.&lt;/p&gt;
&lt;h2&gt;New release 3.30.0&lt;/h2&gt;
&lt;p&gt;This release doesn't add new functionality. The main change is in the code,
and in the interface.&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator1.png"&gt;
        &lt;img src="/pictures/gtranslator1.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We've removed the toolbar and move the main useful buttons to the headerbar.
We've also removed the statusbar and replaced it with a new widget that shows
the document translation progress.&lt;/p&gt;
&lt;p&gt;The plugin system and the dockable window system has been removed to simplify
the code and make the project more maintenable. The only plugin that is
maintained for now is the translation memory, that's now integrated. I'm
planning to migrate other useful plugins, but that's for the future.&lt;/p&gt;
&lt;p&gt;Other minor changes that we've made are in the message table, we've removed
some columns and now we only show two, the original message and the translated
one and we use colors and text styles to show fuzzy status and untranslated.&lt;/p&gt;
&lt;p&gt;The main work is a full code modernization, now we use meson to build, we've
flatpak integration and this simplify the development because gtranslator know
works by default in Gnome Builder without the need to install development
dependencies.&lt;/p&gt;
&lt;p&gt;There's others minor changes like the new look when you open the app without
any file:&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator-open.png"&gt;
        &lt;img src="/pictures/gtranslator-open.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Or the new language selector that autofill all the profile fields using the
language:&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator-lang.png"&gt;
        &lt;img src="/pictures/gtranslator-lang.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;And for sure we've tried to fix most important bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/issues/1"&gt;Search and replace deletes all fuzzy states&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/issues/5"&gt;Check files before the save&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/issues/19"&gt;msgctxt should make strings different&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/issues/8"&gt;Some headers get line breaks and don't follow the right format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.gnome.org/GNOME/gtranslator/issues?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=closed"&gt;And more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;New name and new Icon&lt;/h2&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator-icon.png"&gt;
        &lt;img src="/pictures/gtranslator-icon.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Following the modern GNOME app names, we've renamed the app from Gtranslator
to &lt;strong&gt;GNOME Translation Editor&lt;/strong&gt;. Internally we'll continue with the gtranslator
name, so the app is gtranslator, but for the final user the name will be
&lt;strong&gt;Translation Editor&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And following the &lt;a href="https://gitlab.gnome.org/GNOME/Initiatives/issues/2"&gt;App Icon Redesign Initiative&lt;/a&gt; we've a new icon that
follows the new &lt;a href="https://developer.gnome.org/hig/stable/icon-design.html.en"&gt;HIG&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Thanks&lt;/h2&gt;
&lt;p&gt;I'm not doing this alone. I became the gtranslator maintainer because Daniel
Mustieles push to have a modern tool for GNOME translators, done with gnome
technology and fully functional.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;GNOME Translation Editor&lt;/strong&gt; is a project done by the GNOME community, there
are other people helping with code, documentation, testing, design ideas and
much more and any help is always welcome. If you're insterested, don't hesitate
and come to the &lt;a href="https://gitlab.gnome.org/GNOME/gtranslator"&gt;gnome gitlab&lt;/a&gt; and collaborate with this great project.&lt;/p&gt;
&lt;p&gt;And maybe it's a bit late, but I've publish a project to the &lt;a href="https://www.outreachy.org/apply/project-selection/"&gt;outreachy.org&lt;/a&gt;,
so maybe someone can work on this as an intern for three months. I'll try to
get more people involved here using following outreachy and maybe GSoC, so if
you're a student, now is the right time to start contributing to be able to be
selected for the next year internship programs.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 03 Nov 2018 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2018-11-03:/gnome-translation-editor.html</guid><category>blog</category><category>gnome</category><category>gtranslator</category></item><item><title>Gtranslator Resurrection</title><link>https://danigm.net/gtranslator-resurrection.html</link><description>&lt;p&gt;The last week I received a telegram message about &lt;a href="https://wiki.gnome.org/Apps/Gtranslator"&gt;Gtranslator&lt;/a&gt;, that was
unmaintained for a long time. GNOME translators uses different tools to
translate .po files, Gtranslator is a tool for translator that is integrated
with the GNOME desktop, but with the time, Gtranslator is getting old and there
are several known bugs that never get fixed.&lt;/p&gt;
&lt;p&gt;So I decided to go ahead and become the maintainer of Gtranslator with the main
idea of update the interface and fix mayor bugs.&lt;/p&gt;
&lt;h2&gt;Why we should care about Gtranslator&lt;/h2&gt;
&lt;p&gt;PO files are plain text files that can be edited with any text editor, but
there're a lot of tools for translator to simplify the edition of .po files,
these way the program will avoid formatting problems and can also provide some
tools to help in the translation.&lt;/p&gt;
&lt;p&gt;There's a lot of tools to edit .po files, so, why we need another application?
why translators can't pick another useful tool if Gtranslator is unmaintained?&lt;/p&gt;
&lt;p&gt;The main reason is the same as we've a text editor or the gnome-builder or other
developer tools, because all users want to use applications integrated in the
desktop, so it always will be better for a GNOME user a native GNOME app to edit
.po files than a Qt one or a webpage.&lt;/p&gt;
&lt;p&gt;The other reason is that we need to simplify the translators life to have better
and more translations and that can only be done if we're developping the tool
that translator will use, because in the future we can integrate Gtranslator
with the gnome gitlab, or with &lt;a href="https://l10n.gnome.org/"&gt;Damned Lies&lt;/a&gt;, to download or upload
translation files.&lt;/p&gt;
&lt;h2&gt;What's the plan&lt;/h2&gt;
&lt;p&gt;Gtranslator has a GNOME 2.0 interface, with toolbar, menus, statusbar and
dockable widgets:&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator1.png"&gt;
        &lt;img src="/pictures/gtranslator1.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;But in the git repo, the main branch was &lt;em&gt;broken&lt;/em&gt;. Someone starts a big
refactor, in 2015, to try to update the interface to look more like a modern
GNOME 3 application but that refactor never ended so the master branch compiles,
but doesn't do anything. There was a lot of widgets that was half ported to a
modern code.&lt;/p&gt;
&lt;p&gt;There's also some &lt;a href="https://wiki.gnome.org/Design/Apps/Translator"&gt;designs&lt;/a&gt; to modernize the interface, but the work wasn't
finished.&lt;/p&gt;
&lt;p&gt;My plan is to continue that work, modernize the UI, remove all &lt;em&gt;deprecated&lt;/em&gt; code
and warnings and then continue the development from there.&lt;/p&gt;
&lt;p&gt;I don't want to spend a lot of time reworking the whole app to have a new one in
two months, I want to have a functional app as soon as possible, and continue
with a continuous development, improving the UI and the functionality needed by
the translator team.&lt;/p&gt;
&lt;p&gt;So the roadmap that I've in mind is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fix the current master state&lt;/li&gt;
&lt;li&gt;Fix the known bugs&lt;/li&gt;
&lt;li&gt;Redesign the interface&lt;/li&gt;
&lt;li&gt;Enhance linking with Damned Lies&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;What I've done in one week&lt;/h2&gt;
&lt;p&gt;I started updating the build system, from autotools to meson build, and then
I've added a flatpak manifest file, so now gnome-builder is able to build
Gtranslator using meson and flatpak and it's easier to develop this way.&lt;/p&gt;
&lt;p&gt;This build tools modernization is great because with the new gitlab we've now
continuous integration, and that means that the gitlab compiles and generates a
flatpak bundle for each commit, making it easier for testers to test new
functionality or Merge Requests, you only need to download the .flatpak and
install locally, no need to build at all.&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator-gitlab.png"&gt;
        &lt;img src="/pictures/gtranslator-gitlab.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Then I started to fix the master branch. There was a &lt;em&gt;project&lt;/em&gt; selector view and
then you go to the translation view. There was only the .ui files and not
working yet, so I reworked that a bit and convert the &lt;em&gt;project&lt;/em&gt; selector to a
&lt;em&gt;file&lt;/em&gt; selector for now and then when you select a file, you've almost the same
old interface, but without the menu, toolbar and statusbar.&lt;/p&gt;
&lt;p style="text-align: center" class="img"&gt;
    &lt;a href="/pictures/gtranslator2.png"&gt;
        &lt;img src="/pictures/gtranslator2.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;I've been moving the toolbar icons to the headerbar so we can have the main
functionality working. We've now a functional application.&lt;/p&gt;
&lt;h2&gt;Plugins&lt;/h2&gt;
&lt;p&gt;Gtranslator has a plugin system and has eight plugins, but that plugins was
disabled some time ago. So I've started to recover that functionality but
instead of as plugins, I've started to move the plugins to the core app code.&lt;/p&gt;
&lt;p&gt;The only plugin ported currently is the translation memory. I'll take a look to
the other plugins and view if it's desirable to reimplement that or remove that
code.&lt;/p&gt;
&lt;h2&gt;What's next&lt;/h2&gt;
&lt;p&gt;All the statusbar functionality is missing right now, I need to find some place
in the new UI to show that.&lt;/p&gt;
&lt;p&gt;I wan't to start as soon as possible to work in a new widget to show messages,
instead of the current table.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;project&lt;/em&gt; selection part is a bit hard because I need to think about what's
a project in this context. Currently Gtranslator is a .po file editor, but if we
change that to manage &lt;em&gt;projects&lt;/em&gt; like a group of .po files, I need to think
about how to store that information and the easier way for translator to use the
interface.&lt;/p&gt;
&lt;p&gt;So if you've time and want to contribute in this project, go ahead, you can ask
in the #gtranslator IRC channel or talk to me directly. Currently there's no
a lot of issues in the gitlab, but as soon as I get a functional version in
gnome-nightly flatpak repo and some translators starts to use it, we'll have a
lot of things to do.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 10 Sep 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-09-10:/gtranslator-resurrection.html</guid><category>blog</category><category>gnome</category><category>gtranslator</category></item><item><title>GIR support in gnome-class</title><link>https://danigm.net/gnome-class-gir.html</link><description>&lt;p&gt;Recently I've been working again in the &lt;a href="http://danigm.net/libgepub-rust.html"&gt;rust port of libgepub&lt;/a&gt;, libgepub
is C code, but in the &lt;a href="https://gitlab.gnome.org/GNOME/libgepub/tree/rust-migration/"&gt;&lt;code&gt;rust-migration&lt;/code&gt; branch&lt;/a&gt; almost all the real
functionality is done with rust and the &lt;code&gt;GepubDoc&lt;/code&gt; class is a &lt;code&gt;GObject&lt;/code&gt; wrapper
around that code.&lt;/p&gt;
&lt;p&gt;For this reason I was thinking about to use &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;&lt;code&gt;gnome-class&lt;/code&gt;&lt;/a&gt; to implement
&lt;code&gt;GepubDoc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Gnome-class is a rust lib to write GObject code in rust that's compatible with
the C binary API so then you can call this new GObject code written with
gnome-class from C. I've worked a little in gnome-class, implementing a
&lt;a href="http://danigm.net/rust-gnome.html"&gt;basic properties support&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;GObject Introspection&lt;/h2&gt;
&lt;p&gt;A great advantage of write GObject code in C is that you can have automatic
bindings using &lt;a href="https://gi.readthedocs.io/en/latest/"&gt;GObject Introspection&lt;/a&gt;. This is great because you only need
to write the C code, write correctly the documentation of the public API and
then you'll get GIR for free, and that means that you can use your lib from
&lt;code&gt;gjs&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt; and other automatic bindings.&lt;/p&gt;
&lt;p&gt;GIR defines a simple XML document to declare the public API and there is the
meta information needed for bindings, to know how to call the lib functions and
how to convert params and also provides memory management information, for
languages with garbage collector and so. These files are places under
&lt;code&gt;/usr/share/gir-1.0/&lt;/code&gt; and it looks like this:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;get_cover&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;c:identifier=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gepub_doc_get_cover&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;return-value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;full&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;cover&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;path&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;retrieve&lt;span class="w"&gt; &lt;/span&gt;with
gepub_doc_get_resource&lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;utf8&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;gchar*&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/return-value&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;parameters&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;instance-parameter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;doc&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;transfer-ownership=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;xml:space=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;preserve&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;#GepubDoc&lt;span class="nt"&gt;&amp;lt;/doc&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Doc&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="na"&gt;c:type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;GepubDoc*&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/instance-parameter&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/parameters&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This xml is &lt;em&gt;compiled&lt;/em&gt; to a binary format to be used from bindings and those
compiled gir files are places under &lt;code&gt;/usr/lib64/girepository-1.0/&lt;/code&gt; with the
&lt;code&gt;.typelib&lt;/code&gt; extension.&lt;/p&gt;
&lt;p&gt;This is great, and the &lt;code&gt;GepubDoc&lt;/code&gt; class is exported as GIR and indeed it's used
from javascript code in the gnome-books application using this. If we want to
migrate libgepub from C to rust, we need to provide this GIR to don't break
the compatibility in other apps. That's done currently in the rust-migration
branch by hand, creating the &lt;code&gt;GepubDoc&lt;/code&gt; in C and calling the rust code from
there.&lt;/p&gt;
&lt;p&gt;With gnome-class it should be possible to write that &lt;code&gt;GepubDoc&lt;/code&gt; code in rust
and have the same ABI, but currently gnome-class doesn't generate GIR, that's
a little problem that I can try to solve using my dev skills.&lt;/p&gt;
&lt;h2&gt;Adding GIR to gnome-class&lt;/h2&gt;
&lt;p&gt;So, libgepub is the excuse to start to implement GIR in gnome-class. There's
an &lt;a href="https://gitlab.gnome.org/federico/gnome-class/issues/8"&gt;issue&lt;/a&gt; in the gitlab with an initial syntax proposal and I started from
that:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[generate_gir(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.gir&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;
&lt;span class="cp"&gt;#[generate_c_header(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.h&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.gir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo.h&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first thing to do is to add a way to tell that we want to generate the GIR
file in the class definition. In this proposal, the GIR tag is before the
&lt;code&gt;gobject_gen&lt;/code&gt; proc-macro, that can't be done, or I don't know how to do that
easily, so I changed to a declaration inside the proc-macro, that's what we're
parsing in gnome-class:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[generate_gir(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Counter.gir&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the code insithe de &lt;code&gt;gobject_gen&lt;/code&gt; I only need to update the parser to
allow this new syntax:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;named&lt;/span&gt;&lt;span class="p"&gt;!{&lt;/span&gt;&lt;span class="nx"&gt;parse_gir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LitStr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;do_parse&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;punct&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                               &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;brackets&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;do_parse&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;generate_gir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parens&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;LitStr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="m m-Double"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="m m-Double"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Synom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;named&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;do_parse&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;gir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;parse_gir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;                                  &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;Ident&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                                        &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;do_parse&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;punct&lt;/span&gt;&lt;span class="p"&gt;!(:)&lt;/span&gt;&lt;span class="w"&gt;                                            &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;superclass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                               &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// FIXME: interfaces&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;superclass&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;                                       &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="nx"&gt;FieldsNamed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;gir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, I'm storing the GIR file name in the ast class so I can check if that
field is &lt;code&gt;None&lt;/code&gt; or &lt;code&gt;Some&lt;/code&gt; and generate the GIR in that case.&lt;/p&gt;
&lt;h2&gt;Generating the XML&lt;/h2&gt;
&lt;p&gt;The parser was the easier part, we've now the hability to define if we want
to generate the GIR file and we're storing that information in the High-level
Internal Representation (hir).&lt;/p&gt;
&lt;p&gt;To generate the XML I've to add a new call before generating the code:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;    let result: Result&amp;lt;proc_macro2::TokenStream&amp;gt; =
&lt;span class="gd"&gt;-        hir::Program::from_ast_program(&amp;amp;ast_program).and_then(|program| Ok(gen::codegen(&amp;amp;program)));&lt;/span&gt;
&lt;span class="gi"&gt;+        hir::Program::from_ast_program(&amp;amp;ast_program)&lt;/span&gt;
&lt;span class="gi"&gt;+            .and_then(|program| {&lt;/span&gt;
&lt;span class="gi"&gt;+                gen::gir::generate(&amp;amp;program)?;&lt;/span&gt;
&lt;span class="gi"&gt;+                Ok(gen::codegen(&amp;amp;program))&lt;/span&gt;
&lt;span class="gi"&gt;+            });&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;    match result {
&lt;span class="w"&gt; &lt;/span&gt;        Ok(tokens) =&amp;gt; {
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://gitlab.gnome.org/danigm/gnome-class/tree/gir/src/gen/gir.rs"&gt;&lt;code&gt;gir&lt;/code&gt;&lt;/a&gt; module generates the XML, iterating over all classes defined in
the program.&lt;/p&gt;
&lt;p&gt;The XML isn't really hard to generate, we've almost all the information so we
can iterate over all the class methods and add to the XML. There's some
information that's not really easy to get so I've let some &lt;em&gt;TODO&lt;/em&gt; in this
initial version, like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find the parent class name (GObject.Object by default)&lt;/li&gt;
&lt;li&gt;Get the library version and shared-lib path (lib#CLASSNAME#1.0.0 by default)&lt;/li&gt;
&lt;li&gt;Get dependencies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So this is not a full featured GIR support, but it's an initial step to get
it, and it &lt;em&gt;works&lt;/em&gt;, at least with simple examples :D&lt;/p&gt;
&lt;h2&gt;Example project&lt;/h2&gt;
&lt;p&gt;To test that this is working correctly I've created a
&lt;a href="https://gitlab.gnome.org/danigm/gnome-class-example/"&gt;simple example project&lt;/a&gt;, that uses gnome-class, generates the gir and
has an small script to call the generated code from python.&lt;/p&gt;
&lt;p&gt;This is the rust code:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;generate_gir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Counter.gir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I've a bash script to compile and generate the typelib file from the xml,
generated by gnome-class:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;+nightly&lt;span class="w"&gt; &lt;/span&gt;build
g-ir-compiler&lt;span class="w"&gt; &lt;/span&gt;Counter.gir&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;Counter-1.0.typelib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And I've written a test in python using &lt;code&gt;gi.repository&lt;/code&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;gi.repository&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is working right now, so we're getting closer to the final goal of having
libgepub written with rust code and have GIR generation.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 01 Sep 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-09-01:/gnome-class-gir.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>gnome-class</category><category>GIR</category></item><item><title>libgepub + rust</title><link>https://danigm.net/libgepub-rust.html</link><description>&lt;p&gt;In 2010 I was working with evince, the gnome PDF document viewer, trying to
add some accessibility to PDF files. That was really hard, not because GTK+ or
ATK technology but because the PDF format itself. The PDF format is really cool
for printing because you know that the piece of paper will look the same as the
PDF doc, and because it's vector it scales and don't loose quality and files
are smaller than image files, but almost all PDF files have not any metadata for
sections, headings, tablets or so, this depends on the creation tool, but it's
really hard to deal with PDF content text, because you don't know event if the
text that you're reading is really in the same order that you read from the
PDF.&lt;/p&gt;
&lt;p&gt;After my fight against the PDF format hell and poppler, I discovered the epub
format that's a really simple format for electronic books. An epub is a zip
with some XML files describing the book index and every chapter is a xhtml and
xhtml is a good format compared to PDF because you can parse easily with any
XML lib and the content is tagged and well structured so you know what's a
heading, what's a paragraph, etc.&lt;/p&gt;
&lt;p&gt;So I started to write a simple C library to read epub files, thinking about
add epub support to evince. That's how &lt;a href="https://gitlab.gnome.org/GNOME/libgepub"&gt;libgepub&lt;/a&gt; was born. I tried to
&lt;a href="https://github.com/danigm/evince/tree/epub"&gt;integrate libgepub in evince&lt;/a&gt;, I've something working, rendering with
webkit, but nothing really useful, because evince needs pages and it's not
easy to split an xhtml file in pages with the same height, because xhtml is
continuous text and it adapts to the page width, so I give up and leave this
branch.&lt;/p&gt;
&lt;h2&gt;gnome-books&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;img src="https://wiki.gnome.org/Apps/Books?action=AttachFile&amp;do=get&amp;target=books-window.png" alt="gnome-books" width="100%"/&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;After some time, I discovered &lt;a href="https://wiki.gnome.org/Apps/Books"&gt;gnome-books&lt;/a&gt;, and the idea of epub support
comes to me again. Books has an initial &lt;em&gt;epub&lt;/em&gt; support, that consists only in
showing in the collection, but when you click on the book, an error message
was shown because there's no epub preview support.&lt;/p&gt;
&lt;p&gt;I've libgepub with GIR support and books was written with gjs so it was easy
for me to add an initial support for epub documents using libgepub and
rendering with webkit.&lt;/p&gt;
&lt;p&gt;So libgepub is used in a gnome app to render epub documents and for that reason
gnome &lt;em&gt;depends&lt;/em&gt; on libgepub now.&lt;/p&gt;
&lt;h2&gt;Rustifying everything&lt;/h2&gt;
&lt;p&gt;In 2017 I discover &lt;a href="https://www.rust-lang.org/"&gt;rust&lt;/a&gt; and fell in love with this language, so I wanted
to write some code with rust and I started porting this epub library and I
ended creating the &lt;a href="https://crates.io/crates/epub"&gt;epub crate&lt;/a&gt;, that's basically the same implementation
but with rust instead of C, the API is really similar.&lt;/p&gt;
&lt;p&gt;After that, I read somewhere that Federico was porting the &lt;a href="https://gitlab.gnome.org/GNOME/librsvg"&gt;librsvg&lt;/a&gt;
code to rust, so I thought that I can do the same with libgepub and replace
almost all the C code with this new rust crate.&lt;/p&gt;
&lt;p&gt;I copied all the code for autotools to build using cargo and I've copied to
the &lt;em&gt;glue&lt;/em&gt; code from librsvg and adapt to my own lib. That worked really well
and I was able to remove the core libgepub C code and replace with the new
rust code.&lt;/p&gt;
&lt;p&gt;But rust is really new and it was not full supported in all distributions, so
release depending on rust will make the release people's live harder. That's
the reason because I decided to leave the C version for now and wait a little
to make the rust migration.&lt;/p&gt;
&lt;p&gt;And here we're, the libgepub has changed a little, some fixes and small changes,
but the main change is that now we're using meson to build instead of autotools,
and it's not easy to integrate a rust+cargo lib in the meson desc. There's a
&lt;a href="https://github.com/mesonbuild/meson/pull/2617"&gt;PR in meson to support this&lt;/a&gt; but it seems that meson devs doesn't like the
idea.&lt;/p&gt;
&lt;p&gt;So yesterday I was playing around with meson to get back the rust code working
in libgepub, and was not easy, but now I've a &lt;a href="https://gitlab.gnome.org/GNOME/libgepub/tree/rust-migration"&gt;working build configuration&lt;/a&gt;
that works. It's a hack with a custom script to build with cargo, but it's
working so I'm really happy.&lt;/p&gt;
&lt;h2&gt;Show me the code&lt;/h2&gt;
&lt;p&gt;To integrate the rust epub crate in the libgepub C lib I needed to write a
simple cargo project with the &lt;em&gt;glue&lt;/em&gt; code that converts the rust types to
glib/c types and expose that in a C lib, and that's the &lt;a href="https://gitlab.gnome.org/GNOME/libgepub/tree/rust-migration/subprojects/libgepub_internals"&gt;libgepub_internals&lt;/a&gt;,
that's full of glue rust+glib code like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;epub_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EpubDoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my_path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_glib_none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EpubDoc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;epub_destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_doc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EpubDoc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;raw_doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, in the &lt;code&gt;gepub-doc.c&lt;/code&gt;, that's the glib object that expose the GIR API,
I added calls to this functions, defining each function heading that'll be
used from the rust static lib at link time:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rust&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;epub_destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_resource_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mdata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_resource_mime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_resource_mime_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_current_mime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_current_with_epub_uris&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nf"&gt;epub_set_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;guint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;guint&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nf"&gt;epub_get_num_pages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;guint&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nf"&gt;epub_get_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;epub_next_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;gboolean&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nf"&gt;epub_prev_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_cover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_resource_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_current_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_current_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_get_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;guint&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nf"&gt;epub_resources_get_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;gchar&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_resources_get_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;gchar&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_resources_get_mime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;gchar&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;epub_resources_get_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;er&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And then calling to this functions:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gboolean&lt;/span&gt;
&lt;span class="nf"&gt;gepub_doc_initable_init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GInitable&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;initable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;GCancellable&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cancellable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="n"&gt;GError&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;GepubDoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GEPUB_DOC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;g_assert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rust_epub_doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;epub_new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;rust_epub_doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;g_set_error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gepub_error_quark&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GEPUB_ERROR_INVALID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                         &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Invalid epub file: %s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make this work, I needed to add the &lt;code&gt;libgepub_internals&lt;/code&gt; dependency to the
libgepub meson.build like this:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gepub_deps = [
  dependency(&amp;#39;gepub_internals&amp;#39;, fallback: [&amp;#39;libgepub_internals&amp;#39;, &amp;#39;libgepub_internals_dep&amp;#39;]),
  dependency(&amp;#39;webkit2gtk-4.0&amp;#39;),
  dependency(&amp;#39;libsoup-2.4&amp;#39;),
  dependency(&amp;#39;glib-2.0&amp;#39;),
  dependency(&amp;#39;gobject-2.0&amp;#39;),
  dependency(&amp;#39;gio-2.0&amp;#39;),
  dependency(&amp;#39;libxml-2.0&amp;#39;),
  dependency(&amp;#39;libarchive&amp;#39;)
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This definition looks for the gepub_internals lib in the libgepub_internals
subproject with this meson.build:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;libgepub_internals&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;rust&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="m m-Double"&gt;3.29.6&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;license&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;GPLv3&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;libgepub_internals_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;meson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_version&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;version_array&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;libgepub_internals_version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;libgepub_internals_major_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;version_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;libgepub_internals_minor_version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;version_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;libgepub_internals_version_micro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;version_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;to_int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;libgepub_internals_prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;cargo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;cargo&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cargo_vendor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;cargo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;vendor&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cargo_script&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;cargo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sh&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;grabber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;grabber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sh&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;cargo_release&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find_program&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sh&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grabber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;cargo_build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;custom_target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;cargo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;build_by_default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;libgepub_internals&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cargo_script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;@&lt;/span&gt;&lt;span class="nx"&gt;CURRENT_SOURCE_DIR&lt;/span&gt;&lt;span class="err"&gt;@&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;@&lt;/span&gt;&lt;span class="nx"&gt;OUTPUT&lt;/span&gt;&lt;span class="err"&gt;@&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nx"&gt;libgepub_internals_lib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;static_library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;gepub_internals&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cargo_build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;cc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;meson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get_compiler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;th&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;threads&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;libdl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find_library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;dl&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;libgepub_internals_dep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;declare_dependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;link_with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;libgepub_internals_lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;th&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;libdl&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cargo_build&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I'm using here a custom_target to build the lib using a custom script that
simply calls to cargo and then copies the result lib to the correct place:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DEBUG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;DEBUG MODE&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--manifest-path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;/Cargo.toml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;/target/debug/libgepub_internals.a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;.a
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;RELEASE MODE&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--manifest-path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;/Cargo.toml&lt;span class="w"&gt; &lt;/span&gt;--release&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;/target/release/libgepub_internals.a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;.a
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I declared the &lt;code&gt;static_library&lt;/code&gt; and the dependency with
&lt;code&gt;declare_dependency&lt;/code&gt;. I need to add &lt;code&gt;threads&lt;/code&gt; and &lt;code&gt;dl&lt;/code&gt; because the epub crate
depends on it and this works!&lt;/p&gt;
&lt;p&gt;I'll need to vendor all dep crates with cargo-vendor for releasing, but I think
that this is working and it's the way to go with libgepub.&lt;/p&gt;
&lt;h2&gt;The future of libgepub + rust&lt;/h2&gt;
&lt;p&gt;Currently, with the libgepub_internals lib, the &lt;code&gt;gepub-doc.c&lt;/code&gt; code is
basically to provide a &lt;code&gt;gobject&lt;/code&gt; and GIR information to be able to work with
epub docs, but the real work is done in Rust. The &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; provides a
simple way to build this &lt;code&gt;gobject&lt;/code&gt; with rust code, but currently it's not
completed and there's no way to generate GIR, but in the future, it could be
cool to remove the &lt;code&gt;gepub-doc.c&lt;/code&gt; code and generate all with &lt;code&gt;gnome-class&lt;/code&gt;.
I can wait until Federico writes the piece of code that I need for this or maybe
I should contribute to &lt;code&gt;gnome-class&lt;/code&gt; to be able to do this.&lt;/p&gt;
&lt;p&gt;Libgepub also provides a widget that inherits from WebkitWebView to render the
book. That widget is written in C to provide GIR data also and we can try to
do the same and use &lt;code&gt;gnome-class&lt;/code&gt; to write this widget.&lt;/p&gt;
&lt;p&gt;But for now, we're really far from this, we need to spend some time improving
&lt;code&gt;gnome-class&lt;/code&gt; to be able to write all the code in &lt;strong&gt;rust&lt;/strong&gt; and expose the
gobject GIR. Meantime we can start to use rust with this &lt;strong&gt;glue&lt;/strong&gt; code, and
that's great, because if you've a gobject library and you want to migrate to
rust, you don't need to migrate all the code at once, you can do the same that
librsvg is doing and migrate function by function and that's really cool.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 09 Aug 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-08-09:/libgepub-rust.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>libgepub</category><category>gnome-books</category><category>epub</category></item><item><title>mdl</title><link>https://danigm.net/mdl.html</link><description>&lt;p&gt;The last month I wrote a blog post about the &lt;a href="http://danigm.net/lmdb.html"&gt;LMDB Cache database&lt;/a&gt; and my
wish to use that in Fractal. To summarize, LMDB is a memory-mapped key-value
database that persist the data to the filesystem. I want to use this in the
Fractal desktop application to replace the current state storage system
(we're using simple json files) and as a side effect we can use this storage
system to share data between threads because currently we're using a big
struct &lt;code&gt;AppOp&lt;/code&gt; shared with &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;AppOp&amp;gt;&amp;gt;&lt;/code&gt; and this cause some problems
because we need to share and lock and update the state there.&lt;/p&gt;
&lt;p&gt;The main goal is to define an app data model with smaller structs and store
this using LMDB, then we can access to the same data querying the LMDB and we
can update the app state storing to the LMDB.&lt;/p&gt;
&lt;p&gt;With this change we don't need to share these structs, we only need to query
to the LMDB to get the data and the work with that, and this should simplify
our code. The other main benefit will be that we'll have this state in the
filesystem by default so when we open the app after close, we'll stay in the
same state.&lt;/p&gt;
&lt;p&gt;Take a look to the &lt;a href="https://gitlab.gnome.org/danigm/mdl/blob/master/examples/gtkapp/src/main.rs"&gt;gtk TODO example app&lt;/a&gt; to view how to use &lt;em&gt;mdl&lt;/em&gt; with
signals in a real gtk app.&lt;/p&gt;
&lt;h2&gt;What is mdl&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://crates.io/crates/mdl"&gt;mdl&lt;/a&gt; is Data model library to share app state between threads and process
and persist the data in the filesystem. Implements a simple way to store
structs instances in a LMDB database and other methods like BTreeMap.&lt;/p&gt;
&lt;p&gt;I started to play with the LMDB rust binding and writing some simple tests.
After some simple tests, I decided to write a simple abstraction to hide the
LMDB internals and to provide a simple data storage and to do that I created
the &lt;strong&gt;mdl&lt;/strong&gt; crate.&lt;/p&gt;
&lt;p&gt;The idea is to be able to define your app model as simple rust structs. LMDB is
a key-value database so every struct instance will have an unique &lt;em&gt;key&lt;/em&gt; to
store in the cache.&lt;/p&gt;
&lt;p&gt;The keys are stored in the cache ordered, so we can use some techniques to
store related objects and to retrieve all objects of a kind, we only need to
build keys correctly, following an scheme. For example, for fractal we can
store rooms, members and messages like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rooms with key "room:roomid", to store all the room information, title,
   topic, icon, unread msgs, etc.&lt;/li&gt;
&lt;li&gt;members with key "member:roomid:userid", to store all member information.&lt;/li&gt;
&lt;li&gt;messages with key "msg:roomid:msgid" to store room messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following this key assignment we can iterate over all rooms by querying all
objects that starts with "room", we can get all members and all messages from
a room.&lt;/p&gt;
&lt;p&gt;This have some inconveniences, because we can't query directly an message by
id if we don't know the roomid. If we need that kind of queries, we need to
think about another key assignment or maybe we should duplicate data. key-value
are simple databases so we don't have the power of relational databases.&lt;/p&gt;
&lt;h2&gt;Internals&lt;/h2&gt;
&lt;p&gt;LMDB is fast and efficient, because it's in memory so using this cache won't
add a lot of overhead, but to make it simple to use I've to add some overhead,
so mdl is easy by default and can be tuned to be really fast.&lt;/p&gt;
&lt;p&gt;This crate has three main modules with traits to implement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;model&lt;/strong&gt;: This contains the &lt;code&gt;Model&lt;/code&gt; trait that should implement every
   struct that we want to make cacheable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;store&lt;/strong&gt;: This contains the &lt;code&gt;Store&lt;/code&gt; trait that's implemented by all the
   cache systems.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;signal&lt;/strong&gt;: This contains the &lt;code&gt;Signaler&lt;/code&gt; trait and two structs that allow
   us to emit/subscribe to "key" signals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And two more modules that implements the current two cache systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;cache&lt;/strong&gt;: LMDB cache that implements the &lt;code&gt;Store&lt;/code&gt; trait.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bcache&lt;/strong&gt;: BTreeMap cache that implements the &lt;code&gt;Store&lt;/code&gt; trait. This is a good
   example of other cache system that can be used, this doesn't persist to the
   filesystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So we've two main concepts here, the &lt;strong&gt;Store&lt;/strong&gt; and the &lt;strong&gt;Model&lt;/strong&gt;. The model
is the plain data and the store is the container of data. We'll be able to add
models to the store or to query the store to get stored models. We store our
models as key-value where the key is a &lt;code&gt;String&lt;/code&gt; and the value is a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt;,
so every model should be serializable.&lt;/p&gt;
&lt;p&gt;This serialization is the bigger overhead added. We need to do this because
we need to be able to store this in the LMDB database. Every request will create
a copy of the object in the database, so we're not using the same data. This can
be tuned to use pointers to the real data, but to do that we'll need to use
&lt;em&gt;unsafe&lt;/em&gt; code and I think that the performance that we'll get with this doesn't
deserve the complexity that this will add.&lt;/p&gt;
&lt;p&gt;By default, the &lt;code&gt;Model&lt;/code&gt; trait has two methods &lt;code&gt;fromb&lt;/code&gt; and &lt;code&gt;tob&lt;/code&gt; to serialize
and deserialize using &lt;a href="https://crates.io/crates/bincode"&gt;bincode&lt;/a&gt;, so any struct that implements the &lt;code&gt;Model&lt;/code&gt;
trait and doesn't reimplement these two methods should implement &lt;code&gt;Serialize&lt;/code&gt;
and &lt;code&gt;Deserialize&lt;/code&gt; from &lt;a href="https://crates.io/crates/serde_derive"&gt;serde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The signal system is an addition to be able to register callbacks to &lt;strong&gt;keys&lt;/strong&gt;
modifications in the &lt;strong&gt;store&lt;/strong&gt;, so we can do something when a new objects is
added, modified or deleted from the store. The signaler is optional and we
should use it in a explicit way.&lt;/p&gt;
&lt;h2&gt;How to use it&lt;/h2&gt;
&lt;p&gt;First of all, you should define your data model, the struct that you want to
be able to store in the database:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(Serialize, Deserialize, Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example we'll define a struct called &lt;strong&gt;A&lt;/strong&gt; with two attributes, &lt;strong&gt;p1&lt;/strong&gt;,
a &lt;code&gt;String&lt;/code&gt;, and &lt;strong&gt;p2&lt;/strong&gt;, an &lt;code&gt;u32&lt;/code&gt;. We derive &lt;code&gt;Serialize&lt;/code&gt; and &lt;code&gt;Deserialize&lt;/code&gt;
because we're using the default &lt;code&gt;fromb&lt;/code&gt; and &lt;code&gt;tob&lt;/code&gt; from the &lt;code&gt;Model&lt;/code&gt; trait.&lt;/p&gt;
&lt;p&gt;Then we need to implement the &lt;code&gt;Model&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}:{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We only reimplement the &lt;code&gt;key&lt;/code&gt; method to build a key for every instance of &lt;code&gt;A&lt;/code&gt;.
In this case our key will be the &lt;code&gt;String&lt;/code&gt; followed by the number, so for example
if we've something like &lt;code&gt;let a = A { p1: "myk", p2: 42 };&lt;/code&gt; the key will be
"myk:42".&lt;/p&gt;
&lt;p&gt;Then, to use this we need to have a &lt;code&gt;Store&lt;/code&gt;, in this example, we'll use the
LMDB store that's the struct &lt;code&gt;Cache&lt;/code&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// initializing the cache. This str will be the fs persistence path&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/tmp/mydb.lmdb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We pass the path to the filesystem where we want to persist the cache as the
first argument, in this example we'll persist to "/tmp/mydb.lmdb". When we
ran the program for the first time a directory will be created there. The next
time, that cache will be used with the information from the previous execution.&lt;/p&gt;
&lt;p&gt;Then, with this &lt;code&gt;cache&lt;/code&gt; object we can instantiate an &lt;code&gt;A&lt;/code&gt; object and store
in the &lt;code&gt;cache&lt;/code&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// create a new *object* and storing in the cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;store&lt;/code&gt; method will serialize the object and store a copy of that in the
cache.&lt;/p&gt;
&lt;p&gt;After the store, we can query for this object from other process, using the
same lmdb path, or from the same process using the cache:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// querying the cache by key and getting a new *instance*&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello:42&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We'll get a copy of the original one.&lt;/p&gt;
&lt;p&gt;This is the full example:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serde_derive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[derive(Serialize, Deserialize, Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}:{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// initializing the cache. This str will be the fs persistence path&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/tmp/mydb.lmdb&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// create a new *object* and storing in the cache&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_ok&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// querying the cache by key and getting a new *instance*&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello:42&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Iterations&lt;/h3&gt;
&lt;p&gt;When we store objects with the same key prefix we can iterate over all of
the objects, because we don't know the full key of all objects.&lt;/p&gt;
&lt;p&gt;Currently there's two ways to iterate over all objects with the same prefix
in a &lt;code&gt;Store&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;all&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the simpler way, calling the &lt;code&gt;all&lt;/code&gt; method we'll receive a &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; so
we've all the objects in a vector.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hellows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hellows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hellow: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This has a little problem, because if we've a lot of objects, this will use a
lot of memory for the vector and we'll be iterating over all objects twice. To
solve this problems, the &lt;code&gt;iter&lt;/code&gt; method was created.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;iter&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;iter&lt;/code&gt; method provides a way to call a closure for every object with this
prefix in the key. This closure should return a &lt;code&gt;Continue(bool)&lt;/code&gt; that will
indicates if we should continue iterating of if we should stop the iteration
here.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hellow: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Continue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using the &lt;code&gt;Continue&lt;/code&gt; we can avoid to iterate over all the objects, for example
if we're searching for one concrete object.&lt;/p&gt;
&lt;p&gt;We're copying every object, but the &lt;code&gt;iter&lt;/code&gt; method is better than the &lt;code&gt;all&lt;/code&gt;,
because if we don't copy or move the object from the closure, this copy only
live in the closure scope, so we'll use less memory and also, we only iterate
one. If we use &lt;code&gt;all&lt;/code&gt;, we'll iterate over all objects with that prefix to build
the vector so if we iterate over that vector another time this will cost more
than the &lt;code&gt;iter&lt;/code&gt; version.&lt;/p&gt;
&lt;h2&gt;Signal system&lt;/h2&gt;
&lt;p&gt;As I said before, the signal system provide us a way to register callbacks
to key modifications. The signal system is independent of the &lt;code&gt;Model&lt;/code&gt; and
&lt;code&gt;Store&lt;/code&gt; and can be used independently:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Signaler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SignalerAsync&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mdl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SignalerAsync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal_loop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// one thread for receive signals&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JoinHandle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_sig&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// waiting for threads to finish&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// one thread for emit signals&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JoinHandle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal:2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal:2:3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// waiting for threads to finish&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ten_millis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ten_millis&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example we're creating a &lt;code&gt;SignalerAsync&lt;/code&gt; that can &lt;code&gt;emit&lt;/code&gt; signal and
we can &lt;code&gt;subscribe&lt;/code&gt; a callback to any signal. The &lt;code&gt;sig.signal_loop();&lt;/code&gt; init the
signal loop thread, that wait for signals and call any subscribed callback when
a signal comes.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_sig&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We subscribe a callback to the signaler. The signaler can be cloned and the list
of callbacks will be the same, if you emit a signal in a clone and subscribe in
other clone, that signal will trigger the callback.&lt;/p&gt;
&lt;p&gt;Then we're emiting some signals:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal:2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;sig2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;signal:2:3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All of this three signals will trigger the previous callback because the
subscription works as a &lt;em&gt;signal starts with&lt;/em&gt;. This allow us to subscribe to
all new room messages insertion if we follow the previous described keys,
subscribing to "msg:roomid" and if we only want to register a callback to
be called only when one message is updated we can subscribe to
"msg:roomid:msgid" and this callback won't be triggered for other messages.&lt;/p&gt;
&lt;p&gt;The callback should be a &lt;code&gt;Box&amp;lt;Fn(signal)&amp;gt;&lt;/code&gt; where signal is the following
struct:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[derive(Clone, Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;SigType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[derive(Clone, Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Signal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;SigType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Currently only &lt;code&gt;Update&lt;/code&gt; and &lt;code&gt;Delete&lt;/code&gt; signal types are supported.&lt;/p&gt;
&lt;h3&gt;Signaler in gtk main loop&lt;/h3&gt;
&lt;p&gt;All the UI operations in a gtk app should be executed in the gtk main loop so
we can't use the &lt;code&gt;SignalerAsync&lt;/code&gt; in a gtk app, because this signaler creates
one thread for the callbacks so all callbacks should implement the &lt;code&gt;Send&lt;/code&gt; trait
and if we want to modify, for example, a &lt;code&gt;gtk::Label&lt;/code&gt; in a callback, that
callback won't implement &lt;code&gt;Send&lt;/code&gt; because &lt;code&gt;gtk::Label&lt;/code&gt; can't be send between
threads safely.&lt;/p&gt;
&lt;p&gt;To solve this problem, I've added the &lt;code&gt;SignalerSync&lt;/code&gt;. That doesn't launch any
threads and where all operations runs in the same thread, even the callback.
This is a problem if one of your callbacks locks the thread, because this will
lock your interface in a gtk app, so any callback in the sync signaler should
be non blocking.&lt;/p&gt;
&lt;p&gt;This signaler should be used in a different way, so we should call from time
to time to the &lt;code&gt;signal_loop_sync&lt;/code&gt; method, that will check for new signals and
will trigger any subscribed callback. This signaler doesn't have a &lt;code&gt;signal_loop&lt;/code&gt;
because we should do the loop in our thread.&lt;/p&gt;
&lt;p&gt;This is an example of how to run the signaler loop inside a gtk app:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SignalerSync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;timeout_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;gtk&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Continue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal_loop_sync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// We can subscribe callbacks using the sig here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example code we're registering a timeout callback, every 50ms this
closure will be called, from the gtk main thread, and the &lt;code&gt;signal_loop_sync&lt;/code&gt;
will check for signals and call the needed callbacks.&lt;/p&gt;
&lt;p&gt;This method returns a &lt;code&gt;bool&lt;/code&gt; that's false when the signaler stops. You can
stop the signaler calling the &lt;code&gt;stop&lt;/code&gt; method.&lt;/p&gt;
&lt;h2&gt;Point of extension&lt;/h2&gt;
&lt;p&gt;I've tried to make this crate generic to be able to extend in the future and
provide other kind of cache that can be used changing little code in the apps
that uses &lt;strong&gt;mdl&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is the main reason to use traits to implement the store, so the first point
of extension is to add more cache systems, we're currently two, the LMDB and
the BTreeMap, but it would be easy to add more key-value storages, like
memcached, &lt;a href="https://crates.io/crates/unqlite"&gt;unqlie&lt;/a&gt;, mongodb, redis, couchdb, etc.&lt;/p&gt;
&lt;p&gt;The signaler is really simple, so maybe we can start to think about new
signalers that uses &lt;code&gt;Futures&lt;/code&gt; and other kind of callbacks registration.&lt;/p&gt;
&lt;p&gt;As I said before, mdl does a copy of the data on every write and on every read,
so it could be cool to explore the implication of these copies in the
performance and try to find methods to reduce this overhead.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 03 Aug 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-08-03:/mdl.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>mdl</category><category>fractal</category></item><item><title>GUADEC 2018</title><link>https://danigm.net/guadec2018.html</link><description>&lt;h2&gt;GUADEC 2018&lt;/h2&gt;
&lt;p&gt;GUADEC is the &lt;strong&gt;GNOME Users And Developers European Conference&lt;/strong&gt;, is an annual
conference that take place in Europe, and this year was in Spain, so I should go.
I've became a foundation member this year and I've two Google Summer of Code students
from GNOME organization working on Fractal, so this year GUADEC was an important
one for me.&lt;/p&gt;
&lt;p&gt;This year &lt;a href="https://2018.guadec.org/"&gt;GUADEC&lt;/a&gt; was in Almería and I was there for the main days. I can't
stay there for the full GUADEC because I'm using my holidays, so I stay in Almería
from Thursday 5th to Sunday 8th and then I continue to Murcia to enjoy my free
time in the beach.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/almeria.jpg"&gt;
        &lt;img src="/pictures/almeria.jpg" alt="almeria" /&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Not my first GUADEC&lt;/h2&gt;
&lt;p&gt;Until the end of 2017 I've not been GNOME foundation member, but I've been
doing small contributions to GNOME since 2010.&lt;/p&gt;
&lt;p&gt;My first GUADEC was the Gran Canaria Desktop Summit, a big event that joined in
one city the GUADEC and Akademy so there was a lot of desktop developers, from
GNOME, KDE and other open source projects. I was there with some friends, I was
working with some GNOME developers, in the &lt;a href="https://en.wikipedia.org/wiki/Guadalinex"&gt;guadalinex&lt;/a&gt; project, the year before
so I started to know the GNOME community.&lt;/p&gt;
&lt;p&gt;The next year I was in the Hague GUADEC. This year I was there as a developer,
I was working in the Evince accessibility support so my employer paid the travel
and all costs.&lt;/p&gt;
&lt;p&gt;After that, I don't have more paid work related to GNOME, and started to work with
Qt, so I started to go to &lt;a href="https://en.wikipedia.org/wiki/Akademy"&gt;Akademy&lt;/a&gt;, but I don't leave the GNOME community,
I was always a GNOME user and was there doing small contributions.&lt;/p&gt;
&lt;p&gt;My last GUADEC was the 2012, in &lt;strong&gt;A Coruña&lt;/strong&gt;, Spain again. Indeed I'm in the
wikipedia GUADEC article photo, from that year, try to find me there.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/guadec-2012.jpg"&gt;
        &lt;img src="/pictures/guadec-2012.jpg" alt="guadec-2012" /&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;Almería&lt;/h2&gt;
&lt;p&gt;This year GNOME was a great event, with good social events. We've a beach party
with a big paella and the famous &lt;em&gt;Ice Cream Death Match&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We've a good time in the Alcazaba of Almería, with a great performance done by
the GNOME crew.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/alcazaba-gnome.jpg"&gt;
        &lt;img src="/pictures/alcazaba-gnome.jpg" alt="alcazaba gnome" /&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;Then we've a flamenco show in a great place with drinks and some food.&lt;/p&gt;
&lt;h2&gt;GNOME&lt;/h2&gt;
&lt;p&gt;As I said before, this is not my first GUADEC, but this one is an important one
for me, because Fractal is becoming important and this year I've been working
with a lot of great people and it was good to meet them in the GUADEC.&lt;/p&gt;
&lt;p&gt;This year I've been in the Madrid Rust hackfest and in the Strasbourg Fractal
hackfest, unfortunately I can't stay there for the working days because there was
interesing BoFs about Rust and other technologies.&lt;/p&gt;
&lt;p&gt;It was great to meet again with Julian and Tobias, and to meet in person other
people that I've been working with, like Carlos Soriano and Alberto Fanjul.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/guadec-2018.jpg"&gt;
        &lt;img src="/pictures/guadec-2018.jpg" alt="guadec 2018 group photo" /&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;The most important thing from this GUADEC, for me, is the growth plan for GNOME,
the new board of directors want to grow the GNOME projects, attracting more
money and more developers.&lt;/p&gt;
&lt;p&gt;The GNOME project starts to loose interest and developers when the mobile app
ecosystem starts to grow, but it seems that now the interest in this great project
is increasing again, thanks to a lot of innovative projects like flatpak,
gnome-builder, librem5, etc and a lot of great changes like the gitlab migration.
The gnome Board of Directors is doing a great work too, increasing the money
spend in hackfest, to make it easy for developers to work in the gnome projects.&lt;/p&gt;
&lt;p&gt;I've no doubt that GNOME will grow during the next year in developers and
importance. I've been around a lot of time, doing a little in my free time, but
I'll try to spend more time in GNOME and I'll try to find a way to get payed
for it :D&lt;/p&gt;
&lt;p&gt;See you in the 2019 GUADEC.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 13 Jul 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-07-13:/guadec2018.html</guid><category>blog</category><category>gnome</category><category>guadec</category><category>almeria</category></item><item><title>LMDB: Cache database in memory</title><link>https://danigm.net/lmdb.html</link><description>&lt;p&gt;Some days ago I was in a meeting talking about the E2E implementation for
Fractal, to know the current implementation state and to talk with other
developers. This meeting was promoted by &lt;a href="https://puri.sm/"&gt;Puri.sm&lt;/a&gt; people, because they
want to use Fractal for the Librem5 phone and they want to have E2E. There's
people working in the E2E and I think we can have this on Fractal at the end
of the year, but this is not what I want to talk about today.&lt;/p&gt;
&lt;p&gt;In this meeting there was Fractal developers but we've also other people,
like the &lt;a href="https://github.com/mujx/nheko"&gt;nheko&lt;/a&gt; developer, mujx (nheko is a Qt matrix client). During the
meeting, mujx ask us about the cache storage that we're using, because for the
E2E is too important to don't lose any key, because that'll be catastrophic,
you won't be able to read room messages. So it's important to have a
transactional database storage for this information. They are using &lt;a href="http://www.lmdb.tech/doc/"&gt;LMDB&lt;/a&gt;,
I didn't know nothing about LMDB so after this meeting I start to about it.&lt;/p&gt;
&lt;h2&gt;LMDB&lt;/h2&gt;
&lt;p&gt;Lightning Memory-Mapped Database Manager (LMDB) is a key-value database, it's
memory mapped so it's fast, and also uses filesystem storage so we've
persistence. This database has transactions so it's safe to read/write from
different threads or process.&lt;/p&gt;
&lt;p&gt;In Fractal we're using a simple json file for cache, but this doesn't support
transactions and if the app crash or if something bad happens, we can lose data.
This method is simple, but is slow and insecure, so using LMDB will improve
Fractal in several ways.&lt;/p&gt;
&lt;p&gt;But LMDB is in memory and in Fractal we've a lot of interface code sharing the
app state, so we're passing the state between threads with copies and complex
data sharing. This can simplify the interface code because using LMDB for the
application global state will make this state accesible from different threads.&lt;/p&gt;
&lt;h2&gt;Testing LMDB&lt;/h2&gt;
&lt;p&gt;Fractal is written in Rust so I want to write some tests before start to use
this on Fractal. There's a simple &lt;a href="https://crates.io/crates/lmdb"&gt;LMDB rust crate&lt;/a&gt;, and I've been writting
an &lt;a href="https://gitlab.gnome.org/danigm/lmdb-rs-tests"&gt;example lib&lt;/a&gt; to test it.&lt;/p&gt;
&lt;p&gt;Basically what I've done is to write a simple trait that you can implement for
simple Rust structs so that struct can be stored and recover from the cache
with a simple method:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nx"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Cacheable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;TESTDB&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;b:{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The struct should be serializable/deserializable with serde because in this
example I'm using &lt;a href="https://crates.io/crates/bincode"&gt;bincode&lt;/a&gt; to convert structs to [u8].&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Cacheable&lt;/code&gt; trait only have two required methods, the db and the key. The
db is the db name to use to store this struct instances and the key is the
key to use when storing a concrete instance.&lt;/p&gt;
&lt;p&gt;With this, we can store in the cache and query from the cache, using the key:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;{}-basic&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;new&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="cp"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="nt"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;is_ok&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;b:1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;assert_eq&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;assert_eq&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;len&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;push&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;One string&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;to_string&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;push&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Second string&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;to_string&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="nt"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;B&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;b:1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;assert_eq&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="nt"&gt;b2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;assert_eq&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="nt"&gt;b2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;len&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;assert_eq&lt;/span&gt;&lt;span class="o"&gt;!(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;b2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;complex&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="cp"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;..&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;One string&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is thread safe, so we can read from the cache from different threads and
we'll always get the last version in the database.&lt;/p&gt;
&lt;p&gt;LMDB is a key-value database, so we don't have relations. This is not a real
problem for us because we can model the relations in the keys, for example, we
can store Room messages with keys like this "message:ROOMID:messageID" and then
we can iterate over all objects with this prefix: "message:ROOMID" that will
give us all room messages. Something like this should work:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="o"&gt;!(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message:{}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;iter&lt;/span&gt;&lt;span class="o"&gt;(&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nt"&gt;m&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fetched&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;database,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;we&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;here&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;Continue(true)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;LMDB in Fractal data model&lt;/h2&gt;
&lt;p&gt;We're thinking about moving the Fractal data model from the AppOp struct to
a new crate, independent of the UI, to simplify the UI code and to be able
to use the same data model from different UIs (we wan't to split fractal in
two different apps), &lt;a href="https://blogs.gnome.org/jsparber/2018/06/17/refactor-backend-and-ui/"&gt;Julian wrote about this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I think that we can use the LMDB cache to store this new app state that we
want to have and this will simplify a lot our code, because we will share the
same state and this state will be persisted in filesystem.&lt;/p&gt;
&lt;p&gt;I'll start to write a new crate for Fractal to start to move all the app state
to this new crate. I think I can write a generic tool to simplify the LMDB use,
maybe I'll publish another crate in crates.io and use that in Fractal, but I
need to think a little more about the pattern to follow.&lt;/p&gt;
&lt;p&gt;I write a lot of web code in my day to day work, and I've been working with
react+redux. This LMDB cache thing in Fractal reminds me a lot to the redux
store and I want to follow a similar pattern so we can have only an app state
and only a way to update this state.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 30 Jun 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-06-30:/lmdb.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>programming</category><category>lmdb</category><category>cache</category><category>fractal</category></item><item><title>Stickers in Riot</title><link>https://danigm.net/stickers-in-riot.html</link><description>&lt;p&gt;Yesterday I read a &lt;a href="https://medium.com/@RiotChat/stickers-are-here-introducing-riot-im-0-15-for-web-desktop-284c32b93acc"&gt;blog post&lt;/a&gt; about the new Riot.im Stickers. This is
not a matrix.org feature, it's implemented as a widget, when you send an
sticker you're sending a new event with the type "m.sticker", which is
similar to the "m.image" event.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/stickers.gif" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;The matrix.org protocol is flexible so this is a good example of how to add
new features to the clients that uses matrix without the need to change the
protocol.&lt;/p&gt;
&lt;p&gt;This is not a core feature because you can send images, but I think this is
great and add a simple way to show reactions for the users, so as I was
reading I thought that we can add this to &lt;a href="https://wiki.gnome.org/Apps/Fractal"&gt;Fractal&lt;/a&gt;, so I started to
read how we can add support for this.&lt;/p&gt;
&lt;h2&gt;Reading the doc&lt;/h2&gt;
&lt;p&gt;The first thing to implement a feature is to read the specifications or the
technical documentation so we can know what is needed... But there's no
&lt;a href="https://github.com/matrix-org/matrix-doc/issues/1236"&gt;documentation yet about Stickers or widgets yet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is a problem because we can't implement a feature if we don't know
what we should do. But free software give us a great opportunity when this
happens, we've the &lt;a href="https://github.com/vector-im/riot-web"&gt;Riot&lt;/a&gt; source code so we can look at the code and
learn what they are doing.&lt;/p&gt;
&lt;h2&gt;Reading the code&lt;/h2&gt;
&lt;p&gt;Riot web is a javascript application that uses AJAX to communicate with
different server APIs so the first thing that I did to start to understand
the stickers thing was to open the firefox debugger and view how riot is
communicating with the server.&lt;/p&gt;
&lt;p&gt;From here I've learned that for stickers riot is asking to the
scalar.vector.im server. But I don't understand the whole thing with the
requests because riot does a lot of request to different APIs and I can't
isolate the stickers thing easily.&lt;/p&gt;
&lt;p&gt;To fill my understanding gap I go to the &lt;a href="https://github.com/matrix-org/matrix-js-sdk"&gt;matrix-js-sdk&lt;/a&gt; and
&lt;a href="https://github.com/matrix-org/matrix-react-sdk"&gt;matrix-react-sdk&lt;/a&gt; and I did a quick grep to the source code looking for
the API calls that I've view in firefox. With this I can understand the
full stickers process.&lt;/p&gt;
&lt;h2&gt;Writing an example&lt;/h2&gt;
&lt;p&gt;To say that I know how this is working, it's not enough the code reading.
To make sure that I've understood the whole process I need to write a
simple program that does all the process and then I can say that I
understand this.&lt;/p&gt;
&lt;p&gt;So I started to write a &lt;a href="https://github.com/danigm/matrix-stickers-example"&gt;simple python script&lt;/a&gt; using requests. This
simple script does the request to the server and list all the stickers json
so I can say that I'm able to communicate with the API.&lt;/p&gt;
&lt;h2&gt;Stickers in Fractal&lt;/h2&gt;
&lt;p&gt;After this small research I'm able to implement an initial sticker support
for Fractal. I'll try to add a simple way to show and use stickers and a
way to render stickers in the messages history.&lt;/p&gt;
&lt;p&gt;If there's no secret problems we'll have a basic stickers support in
Fractal soon.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 19 May 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-05-19:/stickers-in-riot.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>programming</category><category>fractal</category></item><item><title>Fractal Hackfest, Strasbourg (day 2)</title><link>https://danigm.net/fractal-hackfest2.html</link><description>&lt;p&gt;The second day of Fractal hackfest was really productive, we talk about a
lot of topics and takes some important decisions.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-hackfest2.png" width="100%"/&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;h2&gt;E2E Encryption&lt;/h2&gt;
&lt;p&gt;The encryption is a needed feature but encryption is hard to do in rooms.
Matrix uses public-key cryptography, for rooms they are using &lt;a href="https://git.matrix.org/git/olm/about/docs/megolm.rst"&gt;Megolm&lt;/a&gt;,
that's a protocol to exchange encrypted messages with more than one and
share that message keys in a one-to-one secure communication.&lt;/p&gt;
&lt;p&gt;I don't know a lot about this E2E because for me it's more important to
have the client working with a basic functionality before the encryption.
So you should read the official doc because maybe this that I'm writing
here is completely wrong.&lt;/p&gt;
&lt;p&gt;To do all this E2E key sharing, client side encryption and communication,
Riot has three different implementations of the &lt;em&gt;same&lt;/em&gt; lib, so they have
this code in the JavaScript SDK, the same ported to iOS version in
ObjectiveC and the same ported to Android in Java. Below this lib there's
the libolm that does the real encryption.&lt;/p&gt;
&lt;p&gt;For the future it should be a good solution to have only one lib that does
the encryption thing, so we need to push in that direction and maybe
matrix.org and Purism can pay for that work to be done.&lt;/p&gt;
&lt;p&gt;From Fractal, we've two options or wait until we've the official E2E
C/C++-lib or something, or try to port the iOS lib to Rust or C to use in
our codebase. I think that the best solution is the first one, in any case,
we'll need to wait some time to view E2E in Fractal.&lt;/p&gt;
&lt;h2&gt;Calls&lt;/h2&gt;
&lt;p&gt;Calls are easy compared to the Encryption thing, the &lt;a href="https://matrix.org/docs/spec/client_server/r0.3.0.html#voice-over-ip"&gt;protocol is well documented&lt;/a&gt;
and it's really simple. The hard part here is that the call is implemented
using the webRTC and that is a web protocol... But it seems that there's
something done in this case with GStreamer working with webRTC.&lt;/p&gt;
&lt;h2&gt;Multiple accounts&lt;/h2&gt;
&lt;p&gt;We was talking yesterday about the multiple accounts problem, if we want to
support and in that case what solution we should take.&lt;/p&gt;
&lt;p&gt;We've two possible solutions, one is to support multiple accounts at the
same time and a way to change between accounts, and the other one is to
open a window for each account.&lt;/p&gt;
&lt;p&gt;At the end we think that the best solution could be to open a separated
window for each account so if you've multiple accounts, at first you should
choose what account you want to open and then from the menu you can open a
new &lt;em&gt;window&lt;/em&gt; and go to the account selection menu again.&lt;/p&gt;
&lt;p&gt;We need to work in the design of this feature and it's not confirmed but I
think that this was the best solution, because it's simple and powerful.&lt;/p&gt;
&lt;h2&gt;Communities&lt;/h2&gt;
&lt;p&gt;Communities are something really new in the Matrix.org protocol and it's
not well documented yet and there's some functionality that is not
implemented so we decide to wait until this functionality is more mature to
view how we can integrate this in Fractal.&lt;/p&gt;
&lt;p&gt;Communities today are a group of rooms and a group of people and a full
html description to show in the community &lt;em&gt;page&lt;/em&gt;. There's other features
like show a &lt;em&gt;label&lt;/em&gt; for each member of the community or group, so I think
these features are cool. We'll need to support some parts of the
communities protocol soon.&lt;/p&gt;
&lt;h2&gt;Google Summer of Code&lt;/h2&gt;
&lt;p&gt;&lt;center&gt;
    &lt;p class="img"&gt;
    &lt;img src="/pictures/fractal-hackfest1.png" width="100%" /&gt;
    &lt;/p&gt;
&lt;/center&gt;&lt;/p&gt;
&lt;p&gt;As I said this year we've two students working on Fractal thanks to Google,
as part of the &lt;a href="https://summerofcode.withgoogle.com/organizations/5900447454330880/"&gt;GNOME organization&lt;/a&gt;, and both students comes to the
Hackfest so thank you Julian and Eisha for coming and for the work done
before the GSoC and for sure for the work you'll be doing during the
summer.&lt;/p&gt;
&lt;p&gt;We're talking about how we'll be organizing, I'm the mentor of both but
we'll have the help from Tobias Bernard and from Alexandre Franke so we'll
have a summer hacking group to improve Fractal a lot.&lt;/p&gt;
&lt;p&gt;We'll have a weekly meeting to talk about what we're doing and what to do
in the next week.&lt;/p&gt;
&lt;p&gt;For this first week we'll start with two needed features. Julian will be
working in the user preference dialog and Eisha will start to work in the
internationalization (i18n) because it's not easy to use gettext in rust
and we want to translate the app to make it more accessible for everyone in
the world.&lt;/p&gt;
&lt;h2&gt;Hacking a bit&lt;/h2&gt;
&lt;p&gt;In the meantime, between functionality discussion I was working in a way to
use Fractal without SecretService, so if you're using Fractal outside GNOME
or KDE you can configure it to store password and token in a plain text.
We shouldn't store passwords in a clear text file, but I think that this
will simplify the day for many people that wants to use Fractal but don't
want to write the user and password every time.&lt;/p&gt;
&lt;p&gt;This is not finished yet, but we'll have this very soon, and with this it's
possible to implement other password &amp;amp; token storage services and make it
configurable, so maybe in the future someone implements the storage for
MacOS or something.&lt;/p&gt;
&lt;h2&gt;Holidays&lt;/h2&gt;
&lt;p&gt;This was my last day in the hackfest, I've the travel back to Spain the
Sunday but I'll do some tourism here so I need to leave the people, they
will continue working the Saturday and the Sunday.&lt;/p&gt;
&lt;p&gt;This have been the first Fractal hackfest and it was a great experience, to
meet other people working on it and to talk about the future of the
application. It's really cool that with less than a year project we've now
a big community, so thank you all form coming and see you on GUADEC.&lt;/p&gt;
&lt;p&gt;There's a lot of work to do, but we're lucky because we're two students
working in Fractal this summer and the people from &lt;a href="https://matrix.org/blog/2018/05/11/this-week-in-matrix-2018-05-11/"&gt;Matrix.org&lt;/a&gt; and
&lt;a href="https://puri.sm/posts/librem5-progress-report-11/"&gt;Purism&lt;/a&gt; are working with us, so thank you all.&lt;/p&gt;
&lt;p&gt;I want to thank again the GNOME foundation and GNOME people for make this
possible and to my company &lt;a href="https://wadobo.com"&gt;Wadobo&lt;/a&gt;, for let me spend some time working
on this great project.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;a href="https://wadobo.com"&gt;
        &lt;img src="/pictures/wadobo-mini.png" /&gt;
    &lt;/a&gt;
&lt;/center&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 12 May 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-05-12:/fractal-hackfest2.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>programming</category><category>fractal</category><category>wadobo</category></item><item><title>Fractal Hackfest, Strasbourg (day 1)</title><link>https://danigm.net/fractal-hackfest1.html</link><description>&lt;p&gt;Yesterday was the first day in the first &lt;a href="https://wiki.gnome.org/Hackfests/Fractal2018"&gt;Fractal Hackfest&lt;/a&gt;. I'll try to
write an small blog post every day to share the development with the world.&lt;/p&gt;
&lt;p&gt;My travel to Strasbourg was not an easy travel because I've to take two
flights to get here from Málaga so a long day travelling.&lt;/p&gt;
&lt;p&gt;I met with Mathew from Matrix.org at the London airport because we took the
same flight to here and it was really cool to meet him in person and we
talk a little about the current Matrix situation.&lt;/p&gt;
&lt;p&gt;I've met the other Fractal people and collaborators at the event, and it's
great that people from Purism, Matrix, Gnome and the two GSoC students come
here to work together in this great application.&lt;/p&gt;
&lt;h2&gt;Barbecue and Banquet&lt;/h2&gt;
&lt;p&gt;We've spend almost all the day talking about the different uses cases for
the messaging problem and Tobias has come with a proposal for split the
current application in two because the use case is totally different.&lt;/p&gt;
&lt;p&gt;We've the first case when you use the app to talk to family, friends and
small groups of people where all conversations are private and you want to
read almost every message there, we call that situation the "Barbecue".&lt;/p&gt;
&lt;p&gt;The second case is the one where you use the messaging app to talk in a
public or private room with a lot of people, where you are receiving a lot
of messages but you don't want to follow the full conversation you'll talk
with someone or read a topic conversation, we call this one the "Banquet".&lt;/p&gt;
&lt;p&gt;Currently Matrix clients are more oriented to the Banquet use case so
there's a lot of people and communities using it for this. The idea behind
this split is to provide two apps to the user to make both cases possible.&lt;/p&gt;
&lt;p&gt;We need to work on this idea but it seems that is the correct way to go.&lt;/p&gt;
&lt;h2&gt;Initial Syn speed up&lt;/h2&gt;
&lt;p&gt;At the afternoon. We've reviewing the current initial sync filter and
detect some points to speedup.&lt;/p&gt;
&lt;p&gt;I changed the filter and the initial sync goes a lot faster. I've removed
the member events from the initial sync so there's a lot of less
information to retrieve from the server.&lt;/p&gt;
&lt;p&gt;This little change breaks the one to one room name and default avatars
because that name is calculated using the members in the room so I need to
fix that making the name calculation a backend process. So now if a room
has no name, We'll ask for the room member list and when we've that we'll
calculate the room name with the same algorithm, if there're only two
people, we'll use the other person username, if there's three people we'll
use "one and another" and if there're more we'll use "one and others".&lt;/p&gt;
&lt;h2&gt;Gnome dinner&lt;/h2&gt;
&lt;p&gt;We've a good dinner sponsored by the gnome foundation. Thank you so much.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 11 May 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-05-11:/fractal-hackfest1.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>programming</category><category>fractal</category><category>wadobo</category></item><item><title>GNOME 💙 Rust Hackfest in Madrid</title><link>https://danigm.net/rust-gnome.html</link><description>&lt;p&gt;The last week was the &lt;a href="https://wiki.gnome.org/Hackfests/Rust2018#Reports"&gt;GNOME 💙 Rust hackfest&lt;/a&gt; in Madrid. I was there,
only for the first two days, but was a great experience to meet the people
working with Rust in GNOME a great community with a lot of talented people.&lt;/p&gt;
&lt;p&gt;The event was in the &lt;a href="https://www.openshine.com/"&gt;OpenShine&lt;/a&gt; office, that was a great place and the
OpenShine people was very friendly too so thank you very much to OpenShine
for support this kind of events.&lt;/p&gt;
&lt;h2&gt;What I did during the Hackfest&lt;/h2&gt;
&lt;p&gt;I arrive at 10:30, more or less, and there are some people there, but two
or three comes after the lunch, so the first morning we started to work,
each one in their project.&lt;/p&gt;
&lt;p&gt;I've some patches for &lt;a href="https://gitlab.gnome.org/World/fractal"&gt;Fractal&lt;/a&gt; to review and I was working on the glade
file splitting. After that I downloaded the &lt;a href="https://gitlab.gnome.org/federico/gnome-class"&gt;gnome-class&lt;/a&gt; code and
started to read and try to understand the code because I want to help in
the gnome-class development during the Hackfest.&lt;/p&gt;
&lt;p&gt;After the lunch, the missing people from the morning was there so we did an
official "Hackfest presentation" everyone did a little presentation about
his work and what want to do during the event.&lt;/p&gt;
&lt;p&gt;Gnome-class was the main project to join GNOME and Rust, and it's still in
a early alpha stage so Federico give us a little talk about what's
gnome-class and its parts.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/madrid-whiteboard.jpg"&gt;
        &lt;img src="/pictures/madrid-whiteboard.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Gnome-class&lt;/h2&gt;
&lt;p&gt;Gnome-class is basically a &lt;em&gt;compiler&lt;/em&gt; that translate custom syntax to
&lt;em&gt;Gobject&lt;/em&gt; binary compatible Rust code. Using the &lt;a href="https://doc.rust-lang.org/unstable-book/language-features/proc-macro.html"&gt;proc-macro&lt;/a&gt;,
gnome-class parses a &lt;em&gt;Gobject&lt;/em&gt; like declaration and creates all the Rust
code needed to use the &lt;em&gt;Glib&lt;/em&gt; so we can have binary code that can be called
from &lt;em&gt;C&lt;/em&gt; or from &lt;em&gt;Rust&lt;/em&gt;. With this we can do Object Oriented programming in
Rust using the &lt;em&gt;Gobject&lt;/em&gt; library and types.&lt;/p&gt;
&lt;p&gt;So we've &lt;a href="https://federico.pages.gitlab.gnome.org/gnome-class/"&gt;three parts in gnome-class&lt;/a&gt;, the parser, the High-level
Internal Representation (HIR) and the code generation.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nl"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;Counter has value: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;assert_eq&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;Counter has value: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is Rust code with gnome-class, here we're creating a new &lt;em&gt;Class&lt;/em&gt;
called &lt;code&gt;Counter&lt;/code&gt; with two public methods, then we've a test that use this.
Behind this code, gnome-class generates a lot of ugly code with pointers
and so to make all of this C-Compatible and generate all the needed binary
using the &lt;em&gt;GObject&lt;/em&gt; data scheme.&lt;/p&gt;
&lt;h2&gt;My work in gnome-class&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://developer.gnome.org/gobject/stable/gobject-properties.html"&gt;Properties&lt;/a&gt; declaration was not supported in gnome-class so took that
&lt;a href="https://gitlab.gnome.org/federico/gnome-class/issues/2"&gt;task&lt;/a&gt;. There was a &lt;a href="https://gitlab.gnome.org/federico/gnome-class/blob/master/gobject-notes/syntax.md"&gt;proposed syntax&lt;/a&gt; and I started to work in the
parser to try to support that syntax and convert all the relevant
information into a Rust struct in the HIR tree.&lt;/p&gt;
&lt;p&gt;To parse that I needed to learn &lt;a href="https://crates.io/crates/syn"&gt;syn&lt;/a&gt; that's a parser based in
&lt;a href="https://crates.io/crates/nom"&gt;nom&lt;/a&gt;. That was not easy, but there's a lot of code in gnome-class so I
can read and learn from that and at the end of the day I had a working
properties parser.&lt;/p&gt;
&lt;p&gt;The second day I continue with my work and started to generate code. Here I
have more problems because the code generated is too low level and I didn't
now much about the &lt;em&gt;GObject&lt;/em&gt; internals so I was playing around types
conversions.&lt;/p&gt;
&lt;p&gt;I've to go just after the lunch, but during the back to home train trip I
was able to create a &lt;a href="https://gitlab.gnome.org/federico/gnome-class/merge_requests/9"&gt;Merge Request&lt;/a&gt; with all the work I've done.&lt;/p&gt;
&lt;p&gt;I've work to do during the week so I can't continue working on properties
support in gnome-class. But this week I've more time and I've been working
to complete the code generation, so now we've this test working:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#![feature(proc_macro)]&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;glib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;gobject_gen&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassWithProps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassWithProps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyProp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Prop2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_priv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[test]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test_props&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ClassWithProps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassWithProps&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property_prop2&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_prop2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property_prop2&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_property_myprop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_property_myprop&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;My first GNOME hackfest&lt;/h2&gt;
&lt;p&gt;This was my first GNOME hackfest. I've been in different GUADECs and other
events with GNOME devs, but this was the first time that I travel to work
on a specific &lt;em&gt;project&lt;/em&gt; and not just to meet the people and view talks from
the distance.&lt;/p&gt;
&lt;p&gt;It was a great experience. Rust is really new in the desktop development,
but there's a lot of people working so it's great.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/madrid-food.jpg"&gt;
        &lt;img src="/pictures/madrid-food.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;The next milestone is the &lt;a href="https://wiki.gnome.org/Hackfests/Fractal2018"&gt;Fractal Hackfest&lt;/a&gt;, we'll be in Strasbourg
four days working.&lt;/p&gt;
&lt;p&gt;I want to thank all the great GNOME community that makes collaboration
so easy, it's a great community.&lt;/p&gt;
&lt;p&gt;Currently all of my work on this is voluntary so I need to thank my
coworkers at &lt;a href="https://wadobo.com"&gt;Wadobo&lt;/a&gt;, because I'm spending some work time in this. I
can do this because my company is great.&lt;/p&gt;
&lt;p&gt;&lt;center&gt;
    &lt;a href="https://wadobo.com"&gt;
        &lt;img src="/pictures/wadobo-mini.png" /&gt;
    &lt;/a&gt;
&lt;/center&gt;&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 26 Apr 2018 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2018-04-26:/rust-gnome.html</guid><category>blog</category><category>gnome</category><category>rust</category><category>programming</category><category>gnome-class</category><category>wadobo</category></item><item><title>Rust: Rust+C (parte 2), Llamando código C desde Rust</title><link>https://danigm.net/rust-ffi2.html</link><description>&lt;p&gt;En el &lt;a href="http://danigm.net/rust-ffi1.html"&gt;artículo anterior&lt;/a&gt; hablamos sobre la integración de Rust con C,
sobre cómo llamar a código Rust desde C. Este artículo es la segunda parte
sobre integración de Rust con C, donde veremos cómo hacer la operación
inversa, llamar código C desde Rust.&lt;/p&gt;
&lt;p&gt;Esto puede ser muy útil si tenemos librerías de terceros que tenemos que
usar, así podemos hacer un wrapper en Rust fácilmente. En cuanto a
rendimiento no es muy útil, ya que en Rust se puede escribir código tan
eficiente o más que en C.&lt;/p&gt;
&lt;h2&gt;Llamando a código C desde Rust&lt;/h2&gt;
&lt;p&gt;Supongamos que tenemos una función en C, que queremos llamar desde nuestro
código en Rust:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En el &lt;a href="http://danigm.net/rust-ffi1.html"&gt;primer artículo&lt;/a&gt; se habla sobre cómo pasar tipos de datos más
complejos, de momento, para este ejemplo tenemos tipos básicos, como un
puntero a char y un int, que se traducen en Rust como &lt;strong&gt;*const u8&lt;/strong&gt; y &lt;strong&gt;i32&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Esta función la podemos llamar desde nuestro código Rust de la siguiente
manera:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[link(name = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cffi&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Salida desde C&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lo primero a resaltar de este código Rust es el atributo "link". Esto le
dice al compilador de Rust que tiene que enlazar con la biblioteca libcffi.
La otra cosa que hay que tener en cuenta es el uso de unsafe. Cuando
llamamos a una función en C, siempre tendremos que usar usanfe, porque ese
código no está controlado por el compilador Rust y por tanto no podemos
considerarlo seguro.&lt;/p&gt;
&lt;p&gt;Si queremos limitar el uso de unsafe, la práctica recomendada es la
creación de una interfaz segura:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;libc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[link(name = &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cffi&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;safe_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Salida desde C&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;safe_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Safe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para este ejemplo podemos convertir la cadena a una cadena de C, terminada
en \0, además de ocultar la función no segura.&lt;/p&gt;
&lt;h2&gt;Compilando código C con Cargo&lt;/h2&gt;
&lt;p&gt;Para compilar código C utilizando Cargo se puede utilizar el &lt;a href="https://crates.io/crates/gcc"&gt;crate gcc&lt;/a&gt;,
que ofrece una interfaz Rust para llamar a gcc, en combinación con el
script de compilación &lt;a href="http://doc.crates.io/build-script.html"&gt;build.rs&lt;/a&gt;, que es llamado por cargo por defecto antes
de compilar.&lt;/p&gt;
&lt;p&gt;Por ejemplo, si tenemos un fichero 'lib.c' y queremos que se compile cuando
ejecutamos &lt;strong&gt;cargo build&lt;/strong&gt;, sólo tenemos que añadir lo siguiente a los ficheros
build.rs y Cargo.toml:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# Cargo.tolm
...
[build-dependencies]
gcc = &amp;quot;0.3&amp;quot;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// build.rs&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;gcc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;compile_library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;libcffi.a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;src/lib.c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Todo el código de ejemplo se puede encontrar en &lt;a href="https://github.com/danigm/rust-ffi"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Integración con otros lenguajes&lt;/h2&gt;
&lt;p&gt;Esta integración con C tan sencilla por parte de Rust nos permite utilizar
el gran catálogo de bibliotecas que hay en C. Pero además de esto, dado que
C es el lenguaje común entre casi todos los lenguajes modernos, podemos
llamar a código Rust fácilmente desde casi cualquier lenguaje, simplemente
creando una interfaz C y compilando a una biblioteca en formato C.&lt;/p&gt;
&lt;p&gt;Hay un &lt;a href="https://github.com/alexcrichton/rust-ffi-examples"&gt;repositorio en github&lt;/a&gt; donde se pueden encontrar una serie de
ejemplos sencillos de integración de Rust con Python, Perl, Ruby, Haskell,
etc.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 30 Apr 2017 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2017-04-30:/rust-ffi2.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>ffi</category><category>C</category></item><item><title>Rust: Rust+C (parte 1), Llamando código Rust desde C</title><link>https://danigm.net/rust-ffi1.html</link><description>&lt;p&gt;Rust es un lenguaje cuyo objetivo principal es sustituir o reemplazar
código escrito en C o C++ con código más seguro e igual de eficiente a
nivel de rendimiento.&lt;/p&gt;
&lt;p&gt;Sin embargo, no es fácil tomar la decisión de migrar todo un proyecto
escrito en C/C++ a Rust, de la noche a la mañana. En proyectos pequeños o
con poca actividad, quizás sí sea fácil hacer una reescritura completa,
pero en la mayoría de proyectos no es viable.&lt;/p&gt;
&lt;p&gt;Sin embargo con Rust se puede hacer una migración incremental, implementar
la nueva funcionalidad en Rust, o implementar tan sólo las partes que
requieran una seguridad extra en la gestión de memoria, y esto es posible
gracias a que Rust se puede integrar muy fácilmente con C y C++ con el
llamado &lt;a href="https://doc.rust-lang.org/book/ffi.html"&gt;&lt;strong&gt;ffi&lt;/strong&gt; o &lt;strong&gt;Foreign Function Interface&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Llamando a código Rust desde C&lt;/h2&gt;
&lt;p&gt;Empecemos por lo más sencillo. Supongamos que tenemos una base de código en
C, y queremos comenzar una migración, reimplementando algunas partes, o
alguna biblioteca interna con Rust. Esto es realmente sencillo siempre y
cuando las funciones Rust sean independientes, ya que se pueden llamar
directamente.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;//lib.rs&lt;/span&gt;

&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sumando dentro de rust {} + {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para poder acceder desde C a estas funciones debemos añadir algunos
detalles, como el atributo &lt;em&gt;"#[no_mangle]"&lt;/em&gt;, y el modificador &lt;em&gt;extern&lt;/em&gt; en
la definición de la función.&lt;/p&gt;
&lt;p&gt;Supongamos ahora que tenemos un código en C donde queremos hacer uso de
esta función definida en Rust:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// example1.c&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d + %d = %d&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como vemos, declaramos la función, &lt;em&gt;suma&lt;/em&gt; en el código C, pero no añadimos
la implementación, ya que usaremos la implementación Rust.&lt;/p&gt;
&lt;p&gt;Para poder compilar este código C, tenemos que tener el código Rust
compilado en forma de &lt;a href="https://doc.rust-lang.org/reference.html#linkage"&gt;biblioteca compatible&lt;/a&gt; con C, podemos hacerlo como
staticlib (.a) o como cdylib (.so).&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;rustc&lt;span class="w"&gt; &lt;/span&gt;--crate-type&lt;span class="w"&gt; &lt;/span&gt;staticlib&lt;span class="w"&gt; &lt;/span&gt;lib.rs&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;librust.a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con esto tenemos el fichero .a compilado con la implementación de la
función suma, ahora tan sólo tenemos que compilar nuestro fichero C para
que haga uso de esta implementación:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-Wl,--gc-sections&lt;span class="w"&gt; &lt;/span&gt;-lpthread&lt;span class="w"&gt; &lt;/span&gt;example1.c&lt;span class="w"&gt; &lt;/span&gt;librust.a&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;example1
$&lt;span class="w"&gt; &lt;/span&gt;./example1

sumando&lt;span class="w"&gt; &lt;/span&gt;dentro&lt;span class="w"&gt; &lt;/span&gt;de&lt;span class="w"&gt; &lt;/span&gt;rust&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Devolución de tipos más complejos, structs&lt;/h3&gt;
&lt;p&gt;Trabajar con enteros es muy &lt;em&gt;sencillo&lt;/em&gt;, ya que tenemos compatibilidad de
tipos, i32 e int. Sin embargo normalmente tendremos otros tipos más
complejos que querremos pasar a nuestras funciones Rust, o que querremos
devolver.&lt;/p&gt;
&lt;p&gt;En Rust se pueden definir estructuras compatibles con C añadiendo un
atributo, al igual que en las definiciones de funciones, pero en este caso
sería &lt;em&gt;"#[repr(C)]"&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cadenarust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dato_crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_utf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_raw_parts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;, desde Rust&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dato&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cadenarust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;v&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dato_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dato&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cadena: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;cadenarust&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;vec: {:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dato_destruir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Dato&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo definimos una estructura, &lt;strong&gt;Dato&lt;/strong&gt;, que tiene varios
campos, algunos compatibles con C, &lt;strong&gt;n&lt;/strong&gt; y &lt;strong&gt;cadenac&lt;/strong&gt;, y otros que no,
&lt;strong&gt;cadenarust&lt;/strong&gt; y &lt;strong&gt;vec&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Además definimos una serie de funciones que nos permitirán trabajar con
esta estructura desde C, para la creación &lt;strong&gt;dato_crear&lt;/strong&gt;, para acceder a
elementos Rust del dato &lt;strong&gt;dato_print&lt;/strong&gt; y para liberar la memoria
&lt;strong&gt;dato_destruir&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Hay que tener en cuenta que para poder trabajar en C con esta estructura,
en la creación del dato no devolvemos el dato creado, sino un puntero a
este &lt;strong&gt;*mut Dato&lt;/strong&gt; y además, para evitar que Rust elimine la memoria
asociada a esta estructura y podamos acceder desde C, la metemos en un
&lt;strong&gt;Box&lt;/strong&gt; y lo convertimos a puntero &lt;strong&gt;into_raw&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;El meter el dato en un &lt;a href="https://doc.rust-lang.org/std/boxed/"&gt;&lt;strong&gt;Box&lt;/strong&gt;&lt;/a&gt;, lo que hacemos es alojar esta memoria
en el &lt;em&gt;heap&lt;/em&gt; en lugar de en el &lt;em&gt;stack&lt;/em&gt;. Luego, usando el
&lt;a href="https://doc.rust-lang.org/std/boxed/struct.Box.html#method.into_raw"&gt;&lt;strong&gt;into_raw&lt;/strong&gt;&lt;/a&gt;, Rust se olvida de esta memoria y nos devuelve un
puntero, así que a partir de ahora, nosotros seremos responsables de esta
memoria y tenemos que tener especial cuidado, porque podremos tener &lt;em&gt;memory
leaks&lt;/em&gt; si no liberamos esto.&lt;/p&gt;
&lt;p&gt;Para liberar esta memoria que ahora gestionamos manualmente desde Rust,
podemos utilizar la operación inversa al &lt;strong&gt;into_raw&lt;/strong&gt;, que es el
&lt;strong&gt;from_raw&lt;/strong&gt;, que hace justamente lo contrario, recibe un puntero y nos
devuelve un &lt;strong&gt;Box&lt;/strong&gt;, y cuando Rust elimine esta variable, la memoria se
liberará, de ahí el uso de esta función en &lt;strong&gt;dato_destruir&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A parte de la creación y destrucción usando &lt;strong&gt;Box&lt;/strong&gt;, también se define una
función intermedia en Rust, que hace uso de esta estructura en código Rust,
en este caso, para imprimir la cadena y el vector.&lt;/p&gt;
&lt;p&gt;Este código está englobado dentro de un bloque &lt;strong&gt;unsafe&lt;/strong&gt;, porque cada vez
que dereferenciamos un puntero, el código es inseguro, y debemos marcarlo
como tal. El código es inseguro, porque el compilador no puede asegurar que
ese puntero que recibimos apunte realmente a memoria válida, y en esas
partes dentro de &lt;strong&gt;unsafe&lt;/strong&gt; es donde podríamos encontrarnos los problemas
de &lt;strong&gt;segmentation fault&lt;/strong&gt; y demás.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// example2.c&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dato_crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dato_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dato_destruir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cadena&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Esto es una cadena C&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dato_crear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cadena&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cadena&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dato: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cadenac&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dato_print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;dato_destruir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dato&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Desde C es trivial usar esta estructura y estas nuevas funciones que nos
hemos definido. Tan sólo tendríamos que definir una estructura similar en
código C y definir las cabeceras de las funciones. Desde C podemos acceder
a los parámetros de la estructura compatibles.&lt;/p&gt;
&lt;p&gt;Un detalle interesante es que en C no definimos todos los parámetros de la
estructura original de Rust, ya que no vamos a acceder a la cadena Rust ni
al vector, esto funciona porque hemos definido los parámetros compatibles
primero y por tanto al acceder a la memoria es completamente compatible la
estructura Rust y la estructura C.&lt;/p&gt;
&lt;p&gt;Para la interoperabilidad entre C y Rust, existe un &lt;a href="https://doc.rust-lang.org/libc/x86_64-unknown-linux-gnu/libc/#types"&gt;crate llamado libc&lt;/a&gt;,
que define una serie de tipos que se pueden usar en Rust cuando se hace una
interfaz hacia C. En los ejemplos no he utilizado el crate libc, pero
sería recomendable si queremos mantener un código compatible con el mayor
número de plataformas.&lt;/p&gt;
&lt;p&gt;Todo el código de ejemplo se puede encontrar en &lt;a href="https://github.com/danigm/rust-ffi"&gt;github&lt;/a&gt;, con un
Makefile para poder compilarlo fácilmente.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 22 Apr 2017 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2017-04-22:/rust-ffi1.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>ffi</category><category>C</category></item><item><title>Rust: Concurrencia</title><link>https://danigm.net/rust-thread.html</link><description>&lt;p&gt;La programación concurrente es algo básico a día de hoy para poder sacar el
máximo rendimiento a los ordenadores modernos con múltiples cores. Sin
embargo es también de lo más complejo programar cualquier cosa compartiendo
memoria, hay que tener mucho cuidado y añadir semáforos y gestionar
manualmente el acceso a memoria compartida, cualquier despiste puede ser un
gran problema.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://doc.rust-lang.org/book/concurrency.html"&gt;Rust facilita la programación concurrente&lt;/a&gt; con las comprobaciones que se
hacen en tiempo de compilación y con la gestión de memoria que realiza, el
sistema de propiedad de la memoria que implementa Rust nos asegura que no
ocurrirán "data race" y esto es válido también para la programación
concurrente, por lo que una vez compilado tenemos la certeza de que la
gestión de la memoria compartida es correcta y que no habrá ningún
"segmentation fault" porque un hilo se ejecute antes que otro y elimine la
memoria compartida, etc.&lt;/p&gt;
&lt;h1&gt;Hilos&lt;/h1&gt;
&lt;p&gt;Empecemos con un ejemplo muy básico con el uso de &lt;a href="https://doc.rust-lang.org/book/concurrency.html#threads"&gt;hilos en Rust&lt;/a&gt; y vayamos
viendo el tratamiento de las variables compartidas según lo complicamos.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from a thread!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Athread%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20thread%3A%3Aspawn(%7C%7C%20%7B%0A%20%20%20%20%20%20%20%20println!(%22Hello%20from%20a%20thread!%22)%3B%0A%20%20%20%20%7D)%3B%0A%7D%0A%20&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo básico creamos un hilo con &lt;strong&gt;thread::spawn&lt;/strong&gt;, que recibe un
&lt;em&gt;closure&lt;/em&gt; y se lanza justo al definirlo. Si ejecutamos este ejemplo no
saldrá nada por pantalla, ya que el proceso inicial termina antes de que el
hilo llegue a ejecutarse e imprimir. Para esperar a que un hilo termine se
puede utilizar el método &lt;strong&gt;join&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from a thread!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Athread%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20child%20%3D%20thread%3A%3Aspawn(%7C%7C%20%7B%0A%20%20%20%20%20%20%20%20println!(%22Hello%20from%20a%20thread!%22)%3B%0A%20%20%20%20%7D)%3B%0A%20%20%20%20let%20_%20%3D%20child.join()%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Podemos lanzar varios hilos dentro de un bucle:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from a thread! {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Athread%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20childs%20%3D%20vec!%5B%5D%3B%0A%0A%20%20%20%20for%20i%20in%200..10%20%7B%0A%20%20%20%20%20%20%20%20let%20child%20%3D%20thread%3A%3Aspawn(move%20%7C%7C%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20println!(%22Hello%20from%20a%20thread!%20%7B%7D%22%2C%20i)%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20childs.push(child)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20for%20c%20in%20childs%20%7B%0A%20%20%20%20%20%20%20%20let%20_%20%3D%20c.join()%3B%0A%20%20%20%20%7D%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo ya hay varias cosas que hay que explicar, porque empezamos
a &lt;em&gt;compartir&lt;/em&gt; memoria. Creamos un &lt;em&gt;Vec&lt;/em&gt; donde metemos todos los hilos para
luego poder hacer un join y esperar a que todos terminen. Dentro del hilo
imprimimos por pantalla el índice de la iteración.&lt;/p&gt;
&lt;p&gt;Hemos tenido que añadir &lt;strong&gt;move&lt;/strong&gt; en el closure del hilo, ya que si no lo
usamos, el compilador se quejará de que el closure puede vivir más allá de
&lt;strong&gt;i&lt;/strong&gt;. Al poner el &lt;strong&gt;move&lt;/strong&gt; lo que hacemos es que en lugar de &lt;em&gt;borrow&lt;/em&gt; se
hace &lt;em&gt;move&lt;/em&gt; de las variables utilizadas dentro del &lt;em&gt;closure&lt;/em&gt;, y en este
caso nos permite utilizar &lt;strong&gt;i&lt;/strong&gt; dentro del hilo.&lt;/p&gt;
&lt;p&gt;Al ser &lt;strong&gt;i&lt;/strong&gt; un entero, el &lt;strong&gt;move&lt;/strong&gt; nos vale perfectamente, porque se copia
la memoria, y podríamos acceder al valor de &lt;strong&gt;i&lt;/strong&gt; después de lanzar el hilo
sin problemas. Sin embargo si queremos compartir un &lt;strong&gt;String&lt;/strong&gt;, no sería
posible ya que para el siguiente hilo la cadena se ha movido.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Shared string&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello from a thread! {} - {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;error&lt;span class="o"&gt;[&lt;/span&gt;E0382&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;capture&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;moved&lt;span class="w"&gt; &lt;/span&gt;value:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;shared&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;--&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;src/main.rs:9:54
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nb"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;thread::spawn&lt;span class="o"&gt;(&lt;/span&gt;move&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                                   &lt;/span&gt;-------&lt;span class="w"&gt; &lt;/span&gt;value&lt;span class="w"&gt; &lt;/span&gt;moved&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;into&lt;span class="w"&gt; &lt;/span&gt;closure&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;here
&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;println!&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hello from a thread! {} - {}&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;shared,&lt;span class="w"&gt; &lt;/span&gt;i&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                                                      &lt;/span&gt;^^^^^^&lt;span class="w"&gt; &lt;/span&gt;value&lt;span class="w"&gt; &lt;/span&gt;captured&lt;span class="w"&gt; &lt;/span&gt;here&lt;span class="w"&gt; &lt;/span&gt;after&lt;span class="w"&gt; &lt;/span&gt;move
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;note:&lt;span class="w"&gt; &lt;/span&gt;move&lt;span class="w"&gt; &lt;/span&gt;occurs&lt;span class="w"&gt; &lt;/span&gt;because&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;shared&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;std::string::String&lt;span class="sb"&gt;`&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;which&lt;span class="w"&gt; &lt;/span&gt;does&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;implement&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;Copy&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;trait
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto se puede solucionar clonando la cadena antes, y en este caso, no
compartiremos memoria, sino que estamos usando una variable diferente para
cada hilo.&lt;/p&gt;
&lt;p&gt;Si queremos compartir realmente una referencia a memoria entre hilos
tenemos que usar los tipos &lt;strong&gt;Arc&lt;/strong&gt; y &lt;strong&gt;Mutex&lt;/strong&gt; en combinación.&lt;/p&gt;
&lt;h2&gt;Arc / Mutex&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;In thread {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Thread &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Output:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Athread%3B%0Ause%20std%3A%3Async%3A%3A%7BArc%2C%20Mutex%7D%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20childs%20%3D%20vec!%5B%5D%3B%0A%20%20%20%20let%20shared%20%3D%20Arc%3A%3Anew(Mutex%3A%3Anew(String%3A%3Afrom(%22%22)))%3B%0A%0A%20%20%20%20for%20i%20in%200..10%20%7B%0A%20%20%20%20%20%20%20%20let%20s%20%3D%20shared.clone()%3B%0A%20%20%20%20%20%20%20%20let%20child%20%3D%20thread%3A%3Aspawn(move%20%7C%7C%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20println!(%22In%20thread%20%7B%7D%22%2C%20i)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20out%20%3D%20String%3A%3Afrom(%22Thread%20%22)%20%2B%20%26i.to_string()%20%2B%20%22%5Cn%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20s.lock().unwrap().push_str(%26out)%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20childs.push(child)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20for%20c%20in%20childs%20%7B%0A%20%20%20%20%20%20%20%20let%20_%20%3D%20c.join()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20println!(%22%5CnOutput%3A%5Cn%7B%7D%22%2C%20*(shared.lock().unwrap()))%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo definimos la cadena dentro de un &lt;strong&gt;Mutex&lt;/strong&gt; y este dentro de
un &lt;strong&gt;Arc&lt;/strong&gt;, así podemos compartir realmente la memoria entre hilos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Arc&lt;/strong&gt; es un contador de referencias que se puede compartir entre hilos,
por lo tanto, el &lt;strong&gt;clone&lt;/strong&gt; no copia la memoria, sino que crea una nueva
referencia.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mutex&lt;/strong&gt; implementa el bloqueo asociado a la variable en concreto, por lo
tanto para acceder a esta variable es necesario llamar al método &lt;strong&gt;lock&lt;/strong&gt;,
que nos asegura que podemos leer o modificar esta variable sin que haya
condiciones de carrera entre hilos.&lt;/p&gt;
&lt;p&gt;A diferencia de otros lenguajes, el &lt;strong&gt;Mutex&lt;/strong&gt; asociado a los datos hace más
simple el acceso y nos asegura que no hay condiciones de carrera, ya que si
no utilizamos estos tipos e intentamos compartir memoria entre hilos el
compilador se quejará.&lt;/p&gt;
&lt;h1&gt;Canales&lt;/h1&gt;
&lt;p&gt;Además de compartir variables con &lt;strong&gt;Arc/Mutex&lt;/strong&gt;, hay otra forma de
comunicar diferentes hilos de forma relativamente sencilla, usando canales.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;In thread {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Thread &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Output:&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;try_recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Athread%3B%0Ause%20std%3A%3Async%3A%3Ampsc%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20(tx%2C%20rx)%20%3D%20mpsc%3A%3Achannel()%3B%0A%20%20%20%20let%20mut%20childs%20%3D%20vec!%5B%5D%3B%0A%0A%20%20%20%20for%20i%20in%200..10%20%7B%0A%20%20%20%20%20%20%20%20let%20tx%20%3D%20tx.clone()%3B%0A%20%20%20%20%20%20%20%20let%20child%20%3D%20thread%3A%3Aspawn(move%20%7C%7C%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20println!(%22In%20thread%20%7B%7D%22%2C%20i)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20out%20%3D%20String%3A%3Afrom(%22Thread%20%22)%20%2B%20%26i.to_string()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20tx.send(out).unwrap()%3B%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20childs.push(child)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20for%20c%20in%20childs%20%7B%0A%20%20%20%20%20%20%20%20let%20_%20%3D%20c.join()%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20println!(%22%5CnOutput%3A%22)%3B%0A%20%20%20%20loop%20%7B%0A%20%20%20%20%20%20%20%20match%20rx.try_recv()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Ok(x)%20%3D%3E%20println!(%22%7B%7D%22%2C%20x)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20Err(_)%20%3D%3E%20break%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Con &lt;strong&gt;channel&lt;/strong&gt; creamos un transmisor, &lt;strong&gt;tx&lt;/strong&gt;, y un receptor, &lt;strong&gt;rx&lt;/strong&gt;, en
cada hilo, clonamos el transmisor y escribimos ahí nuestra salida, en el
&lt;strong&gt;send&lt;/strong&gt; podemos enviar cualquier tipo de dato según se cree el channel, no
se pueden enviar diferentes tipos de datos por el mismo canal.&lt;/p&gt;
&lt;p&gt;Usando el receptor se puede leer del canal, en este ejemplo leemos cuando
todos los hilos han terminado, pero el método &lt;strong&gt;recv&lt;/strong&gt; se puede usar en
cualquier momento y bloqueará la ejecución hasta que se envíe algo por el
canal.&lt;/p&gt;
&lt;h1&gt;Bibliotecas externas&lt;/h1&gt;
&lt;p&gt;Además de usar los threads básicos de Rust, existen otras muchas
bibliotecas que nos ofrecen otras formas de hacer programación concurrente,
aquí pongo algunos enlaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/aturon/crossbeam"&gt;Crossbeam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nikomatsakis/rayon"&gt;Rayon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rustcc/coroutine-rs"&gt;Coroutine-rs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/zonyitoo/coio-rs"&gt;Coiro-rs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tokio.rs/docs/getting-started/futures/"&gt;Futures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 08 Apr 2017 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2017-04-08:/rust-thread.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>threads</category></item><item><title>Rust: Macros</title><link>https://danigm.net/rust-macros.html</link><description>&lt;p&gt;Rust tiene un sistema de macros muy potente que hacen que el lenguaje sea
mucho más dinámico y permite reutilizar mucho código.&lt;/p&gt;
&lt;p&gt;Una macro no es más que una "función" que define cómo se generará código,
todas las macros se ejecutarán en una primera fase de la compilación,
generando el código final Rust que se compilará realmente. Una macro no se
traduce directamente a código máquina, sino que se expande en código fuente
que luego se compila a código máquina.&lt;/p&gt;
&lt;p&gt;Si vienes de C, habrás utilizado macros para definir funciones con un
número de argumentos variables y para eso mismo se pueden usar en Rust,
además de para muchos otros casos de uso.&lt;/p&gt;
&lt;h1&gt;Sintaxis&lt;/h1&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hola!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Si has hecho un hola mundo en Rust, ya has usado una macro. El signo de
exclamación que se puede ver tras &lt;em&gt;println&lt;/em&gt; detona que no es una función
cualquiera, sino que es una macro. Gracias a esta sintaxis podemos
diferenciar fácilmente lo que es una macro de lo que es una función
cualquiera.&lt;/p&gt;
&lt;h1&gt;Definición de macros&lt;/h1&gt;
&lt;p&gt;Una macro se define con la palabra clave &lt;strong&gt;macro_rules!&lt;/strong&gt; y contiene una
sintaxis diferente al código normal de Rust.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imprimir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="fm"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;imprimir&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mundo!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; hola, mundo!,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esta macro lo único que hace es imprimir todos los parámetros que recibe,
separados por comas.&lt;/p&gt;
&lt;p&gt;No es muy fácil de entender a primera vista, pero la definición de una
macro se puede dividir en tres partes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Definición&lt;/li&gt;
&lt;li&gt;Matching / Parámetros&lt;/li&gt;
&lt;li&gt;Expansión&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Definición&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imprimir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí decimos que vamos a definir una macro llamada imprimir, nada más, así
se comienza la definición de una macro.&lt;/p&gt;
&lt;h2&gt;Matching / Parámetros&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí definimos los parámetros que recibe la macro. Es similar a un match,
por lo que se pueden definir varios match diferentes, por ejemplo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mimacro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo, se define una macro que puede recibir 0, 1 o 2 parámetros,
y se definiría una expansión diferente para cada uno, en este caso he
omitido la expansión, porque ahora mismo no es relevante.&lt;/p&gt;
&lt;p&gt;Si entramos en la definición de cada match, vemos que la definición de los
parámetros de la macro es algo parecida a la definición de los parámetros
de una función, se define un nombre &lt;strong&gt;$x&lt;/strong&gt; y tras los dos puntos se define
un tipo &lt;strong&gt;expr&lt;/strong&gt;. Hay una serie de tipos definidos que se pueden usar en
las macros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;item&lt;/li&gt;
&lt;li&gt;block&lt;/li&gt;
&lt;li&gt;stmt&lt;/li&gt;
&lt;li&gt;pat&lt;/li&gt;
&lt;li&gt;expr&lt;/li&gt;
&lt;li&gt;ty&lt;/li&gt;
&lt;li&gt;ident&lt;/li&gt;
&lt;li&gt;path&lt;/li&gt;
&lt;li&gt;tt&lt;/li&gt;
&lt;li&gt;meta&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hay más información sobre esto en la &lt;a href="https://doc.rust-lang.org/reference.html#macro-by-example"&gt;documentación de Rust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;De momento nosotros hemos usado &lt;strong&gt;expr&lt;/strong&gt; en nuestro ejemplo, que define una
expresión, y esto es válido para recibir variables.&lt;/p&gt;
&lt;p&gt;También es posible definir un número indeterminado de argumentos, osea,
repetición de argumentos, con la expresión:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con eso podemos decir que esperamos de 0 a n parámetros, por ejemplo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// de 0 a n expresiones&lt;/span&gt;
&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// de 0 a n pares de expresiones&lt;/span&gt;
&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// de 1 a n expresiones&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para más detalle sobre la repetición en macros, se puede consultar la
&lt;a href="https://doc.rust-lang.org/book/macros.html#repetition"&gt;sección correspondiente&lt;/a&gt; del libro de rust.&lt;/p&gt;
&lt;h2&gt;Expansión&lt;/h2&gt;
&lt;p&gt;Después de definir los parámetros de nuestra macro, lo que realmente nos
interesa es definir la expansión, que es en lo que se va a traducir esa
llamada.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mimacro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;sin parámetros&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;un parámetro: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dos parámetros: {}, {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;mimacro&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// sin parámetros&lt;/span&gt;
&lt;span class="n"&gt;mimacro&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// un parámetro: 1&lt;/span&gt;
&lt;span class="n"&gt;mimacro&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// dos parámetros: 1, hola&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este simple ejemplo se puede ver que entre las llaves escribimos código
Rust directamente, la llamada a la macro se transformará en el código
contenido entre las llaves, dependiendo del matching de los parámetros. Lo
único extraño en este ejemplo es el uso de &lt;strong&gt;$x&lt;/strong&gt; y &lt;strong&gt;$y&lt;/strong&gt;, que son los
parámetros de la macro y que se pueden usar de esta manera en la definición
de la expansión.&lt;/p&gt;
&lt;p&gt;Volvamos al ejemplo inicial ahora:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imprimir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="fm"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;imprimir&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mundo!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; hola, mundo!,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí la expansión es más compleja, en este caso, la llamada se expandirá a
lo siguiente:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mundo!, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Las llaves y el &lt;strong&gt;println&lt;/strong&gt; son directos, ahí no hay nada extraño, pero las
otras dos líneas se expanden a partir de la repetición de parámetros
definida con &lt;strong&gt;$(...)*&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Se utiliza una sintáxis similar en la expansión, para iterar sobre todos
los parámetros de entrada:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;$(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}, &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto hace que se repita lo que ha entre los paréntesis tantas veces como
parámetros haya, además &lt;strong&gt;$x&lt;/strong&gt; tendrá el valor del parámetro
correspondiente a cada iteración.&lt;/p&gt;
&lt;h1&gt;Ámbito de las macros, importación y exportación&lt;/h1&gt;
&lt;p&gt;Las macros se expanden al principio de la compilación, por lo tanto no se
ha aplicado la resolución de nombres, las importaciones y demás, así que la
importación de módulos funciona un poco diferente para las macros.&lt;/p&gt;
&lt;p&gt;Una macro es visible justo después de su definición en el mismo módulo
donde se define y en todos los módulos hijos de este.&lt;/p&gt;
&lt;p&gt;También se puede ampliar esta visiblidad usando el atributo &lt;strong&gt;macro_use&lt;/strong&gt;,
con el que podemos hacer visible una macro para el módulo padre.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;mimodulo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En el &lt;a href="https://doc.rust-lang.org/book/macros.html#scoping-and-macro-importexport"&gt;libro&lt;/a&gt; se puede ver un ejemplo de código con la visibilidad de
las macros.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Visible here: `m1`.&lt;/span&gt;

&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;foo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Visible here: `m1`.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[macro_export]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Visible here: `m1`, `m2`.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Visible here: `m1`.&lt;/span&gt;

&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Visible here: `m1`, `m3`.&lt;/span&gt;

&lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Visible here: `m1`, `m3`.&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Visible here: `m1`, `m3`, `m4`.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Visible here: `m1`, `m3`, `m4`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Cuando esta biblioteca se carga con&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testlib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sólo se importará la macro &lt;strong&gt;m2&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;Depuración de macros&lt;/h1&gt;
&lt;p&gt;Las macros se traducen a código Rust, por lo tanto, podemos encontrarnos
con problemas de código no esperados, si tenemos un error en una macro.
Para encontrar estos problemas, se puede usar la opción del compilador
&lt;strong&gt;rustc --pretty expanded&lt;/strong&gt; para ver cómo queda el código con las macros
expandidas.&lt;/p&gt;
&lt;h1&gt;Ejemplo de macro&lt;/h1&gt;
&lt;p&gt;En python existen los decoradores, que no son más que funciones que reciben
como parámetro una función y devuelven otra función como salida. Esto se
puede usar para modificar el comportamiento de las funciones, añadiendo
código que se ejecute antes, como comprobaciones de los parámetros,
permisos, etc y es bastante útil para extender el comportamiento de
cualquier función de manera fácil.&lt;/p&gt;
&lt;p&gt;Podemos usar las macros para definirnos un &lt;em&gt;decorador&lt;/em&gt; en Rust, que añada
por ejemplo un mensaje de depuración para saber cuánto tiempo ha tardado
esa llamada.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="fm"&gt;macro_rules!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ident&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;ty&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Llamando a la función...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cp"&gt;$($x&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Finalizado&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msecs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_secs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subsec_nanos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Duración: {} ms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msecs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Salida:&lt;/span&gt;
&lt;span class="c1"&gt;// Llamando a la función...&lt;/span&gt;
&lt;span class="c1"&gt;// Finalizado&lt;/span&gt;
&lt;span class="c1"&gt;// Duración: 685 ms&lt;/span&gt;
&lt;span class="c1"&gt;// 102334155&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo, se recibe un primer parámetro, que es de tipo
identificador, que será el nombre de la función a &lt;em&gt;decorar&lt;/em&gt;, y luego un
número indefinido de pares, identificador, :, tipo, de tal forma que
definamos los parámetros que recibe esa función.&lt;/p&gt;
&lt;p&gt;Luego la macro genera un closure, con esos mismos parámetros, y llama a la
función, parándole todos los parámetros recibidos, se calcula el tiempo que
pasa durante la llamada a la función y finalmente devuelve la respuesta de
esta.&lt;/p&gt;
&lt;p&gt;Con este ejemplo se puede ver el uso de diferentes tipos de parámetros para
las macros, como los identificadores o los tipos, además de generar código
que se puede asignar a una variable, en este caso se genera un closure.&lt;/p&gt;
&lt;h1&gt;Conclusiones&lt;/h1&gt;
&lt;p&gt;Las macros son muy potentes, pero no hay que olvidar que complican la
lectura del código y también la depuración del mismo, pudiendo esconder
errores, así que se deben usar con moderación y sólo cuando lo que queremos
hacer no se pueda generalizar con funciones normales, ya que en la mayoría
de los casos será mucho más fácil de depurar si hay algún comportamiento
extraño y además, será mucho más fácil de entender el código.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 01 Apr 2017 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2017-04-01:/rust-macros.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>macros</category></item><item><title>Rust: Implementación de estructuras complejas (Grafo)</title><link>https://danigm.net/rust-graph.html</link><description>&lt;p&gt;Con el cambio de paradigma que supone la gestión de memoria de Rust, una de
las cosas que pueden resultar más difíciles al principio es la definición
de estructuras de datos "complejas", con el concepto de propiedad de
memoria y referencias, definir cosas como una lista enlazada no es tan
"sencillo" como en C.&lt;/p&gt;
&lt;p&gt;Por supuesto esto no es sencillo porque definir este tipo de estructuras de
forma segura es muy complejo, en C es muy fácil definir lo básico, con
punteros, pero también es muy fácil que una lista enlazada apunte a un nodo
eliminado, etc.&lt;/p&gt;
&lt;p&gt;Voy a explicar diferentes aproximaciones para implementar una estructura
cíclica en Rust, en este caso, vamos a definir un grafo.&lt;/p&gt;
&lt;p&gt;He creado un &lt;a href="https://github.com/danigm/rust-graph-example"&gt;repositorio en github&lt;/a&gt; con el código para que se pueda
estudiar. En este artículo pondré partes del código para mostrar lo básico
de la implementación, pero sobretodo me centraré en explicar la teoría
detrás de cada solución.&lt;/p&gt;
&lt;h2&gt;Problema&lt;/h2&gt;
&lt;p&gt;Queremos implementar una estructura de datos sencilla para manejar grafos
dirigidos.&lt;/p&gt;
&lt;p&gt;Un grafo no es más que una lista de vértices conectados entre sí. Cada nodo
tiene un valor, y una lista de nodos a los que apunta.&lt;/p&gt;
&lt;p&gt;Podemos pensar en una primera implementación donde definamos cada nodo, con
su valor y que tenga una lista de nodos hijos.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pero dada la gestión de memoria que se hace en Rust, esta estructura no nos
valdría de mucho, ya que tendríamos que tener una copia diferente de un
nodo para cada referencia, añadimos un nodo a otro, y luego intentamos
usarlo, no podremos, porque será el nodo padre el que tenga la propiedad de
sus hijos.&lt;/p&gt;
&lt;p&gt;Con esta solución en realidad cada nodo es independiente, no se reutilizan,
por lo que deja de ser útil para nuestro caso.&lt;/p&gt;
&lt;p&gt;Lo primero que se nos ocurre para solucionar este problema es usar
referencias:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pero esto no compila, al usar referencias el compilador nos pide que
definamos el lifetime de estas referencias, y al ser una estructura
recursiva, se complica mucho el tema, los nodos se deben almacenar en
alguna parte y ser referenciados entre sí, además, dado que en rust no es
compatible tener referencias no mutables a la vez que una referencia
mutable, no podríamos modificar estos nodos hijos por la referencia.&lt;/p&gt;
&lt;h2&gt;Usando punteros, unsafe&lt;/h2&gt;
&lt;p&gt;Una primera solución que se nos puede ocurrir es tirar directamente de
punteros tipo C. Rust nos da la posibilidad de acceder a la memoria como en
C, con punteros, de esta forma nos podemos saltar las limitaciones del
compilador de Rust, pero esto implica que también perdemos la gestión de
memoria, por lo que tendremos que controlar nosotros la memoria y perdemos
la seguridad que nos proporciona el compilador.&lt;/p&gt;
&lt;p&gt;El uso de punteros en Rust nos obliga a usar el calificador &lt;strong&gt;unsafe&lt;/strong&gt;,
para poder diferenciar de forma rápida el código seguro, donde la gestión
de memoria se comprueba en tiempo de compilación, del código inseguro, que
es código donde la memoria se gestiona de manera manual.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El tipo de dato &lt;a href="https://doc.rust-lang.org/std/boxed/struct.Box.html"&gt;&lt;strong&gt;Box&lt;/strong&gt;&lt;/a&gt; nos permite convertir a puntero o desde
puntero de forma sencilla con los métodos &lt;strong&gt;into_raw&lt;/strong&gt; y &lt;strong&gt;from_raw&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;pointer&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Y podemos acceder al valor de un puntero utilizando el operador * para
deferenciar el puntero.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con &lt;strong&gt;into_raw&lt;/strong&gt; Rust deja la gestión de la memoria en nuestras manos, por
lo que para evitar memory leaks tenemos que destruir esa memoria en algún
momento, y para ello podemos usar el &lt;strong&gt;from_raw&lt;/strong&gt; que hace la operación
inversa y devuelve a Rust la gestión de esa memoria.&lt;/p&gt;
&lt;h2&gt;Usando referencias, Rc&amp;lt;RefCell&amp;lt;Node&amp;gt;&amp;gt;, Arc&amp;lt;Mutex&amp;lt;Node&amp;gt;&amp;gt;&lt;/h2&gt;
&lt;p&gt;El uso de punteros es algo de lo que queremos huir cuando usamos Rust, ya
que es código &lt;em&gt;menos seguro&lt;/em&gt;. Por eso debemos dejar el uso de punteros sólo
para momentos en los que necesitemos eficiencia a nivel de memoria o
velocidad y sepamos exactamente lo que estamos haciendo.&lt;/p&gt;
&lt;p&gt;En Rust hay una estructura que nos ofrece la posibilidad de implementar
algo &lt;em&gt;similar&lt;/em&gt; a los punteros, el &lt;a href="https://doc.rust-lang.org/std/rc/"&gt;contador de referencias&lt;/a&gt;. El patrón
básico para permitir modificaciones de elementos interiores, es la
composición &lt;strong&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNodeRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Rc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GraphNodeRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;De esta forma podemos hacer un uso exactamente igual al de los punteros,
pero con la seguridad de que no tendremos problemas de seguridad de
memoria.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNodeRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNodeRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rnode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow_mut&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;rnode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En lugar de usar * para deferenciar los punteros, en este caso usamos
&lt;strong&gt;borrow&lt;/strong&gt; y &lt;strong&gt;borrow_mut&lt;/strong&gt; para obetener una referencia. Con el método
&lt;strong&gt;clone&lt;/strong&gt;, el tipo &lt;strong&gt;Rc&lt;/strong&gt; crea una referencia nueva, no duplica la
información en sí, y cuando se queda sin referencias es cuando se elimina
el contenido.&lt;/p&gt;
&lt;p&gt;Esta solución nos permite hacer algo muy parecido a lo que hacemos con
punteros, pero sin preocuparnos de tener que eliminar la memoria o de que
hay overflow o lo que sea.&lt;/p&gt;
&lt;p&gt;Sin embargo, esto no es la panacea, hay un problema si se generan ciclos,
ya que las referencias cíclicas no se eliminarán nunca, no es algo muy
grave, pero hay que tenerlo en cuenta, aunque ya hay alguien que ha
implementado un &lt;a href="https://github.com/cmr/rust-cc"&gt;recolector de basura&lt;/a&gt; para estos casos.&lt;/p&gt;
&lt;p&gt;De forma similar, en caso de querer que sea &lt;strong&gt;thread safe&lt;/strong&gt;, se puede usar
&lt;strong&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Usando una estructura básica e identificadores de nodos, Vec, HashMap&lt;/h2&gt;
&lt;p&gt;Otra posible aproximación puede ser usar una estructura básica de Rust,
como un Vec o un HashMap, para almacenar todos los elementos, y luego
definir las referencias de los nodos usando índices a esta estructura.&lt;/p&gt;
&lt;p&gt;Por ejemplo podríamos definir un vector con todos los nodos de nuestro
grafo, y cada nodo define sus hijos como índices en ese vector, números
enteros.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Graph&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En el código de ejemplo he usado HashMap en lugar de Vec, porque si por
ejemplo queremos poder eliminar un nodo de forma fácil, en un Vec
tendríamos que recorrer todo el vector y cambiar los indices de todos los
nodos con cada cambio.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Graph&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// índice del siguiente nodo que se añada&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphNode&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con esta implementación, para nosotros los nodos serán enteros, y nos
podemos definir los métodos que hagan uso de estos índices.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_child&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphNode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_mut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;childs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;De esta forma, todo el código será seguro y además no utilizamos
referencias, simplemente nos estamos implementando nuestros propios
&lt;em&gt;punteros&lt;/em&gt;. Aquí tenemos el compilador que comprueba la seguridad de la
memoria, pero si no manejamos correctamente los índices enteros, podemos
tener algún que otro &lt;strong&gt;panic&lt;/strong&gt;, aunque siempre es mejor un &lt;strong&gt;panic&lt;/strong&gt; que un
&lt;strong&gt;segmentation fault&lt;/strong&gt;, un &lt;strong&gt;painc&lt;/strong&gt; es algo controlable y no da los mismos
problemas que podría dar un &lt;em&gt;overflow&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusiones&lt;/h2&gt;
&lt;p&gt;Este ejemplo nos sirve para conocer diferentes formas de resolver un
problema, con las herramientas que nos da Rust, pero también nos muestra
que no sólo hay una solución correcta a un problema, se puede pensar de
manera diferente e implementar.&lt;/p&gt;
&lt;p&gt;Para mi, en principio la manera más &lt;em&gt;natural&lt;/em&gt; es la de &lt;strong&gt;Rc&amp;lt;RefCell&amp;gt;&amp;gt;&lt;/strong&gt;,
viniendo de usar C y C++ y pensando en no usar punteros, pero después de
investigar, veo que la opción de usar el &lt;strong&gt;HashMap&lt;/strong&gt; no me parece ninguna
locura, y se me ocurren otras formas de almacenar un grafo en memoria.&lt;/p&gt;
&lt;p&gt;Por supuesto no soy un experto en este tipo de implementaciones y quizás
esté haciendo alguna locura, si ese es el caso, no dudes en comentar y
corregir cualquier gazapo.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 25 Mar 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-03-25:/rust-graph.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>graph</category></item><item><title>Rust: Documentación</title><link>https://danigm.net/rust-doc.html</link><description>&lt;p&gt;He hablado en este blog sobre casi todas las partes importantes de Rust, he
puesto muchos ejemplos de código y con esta información, cualquiera podría
empezar a escribir código que funcione. Pero a la hora de hacer algo de
verdad, de escribir una biblioteca o un programa que pueda ser usado por
otra persona o mantenido en un futuro es imprescindible la documentación y
por supuesto los tests unitarios.&lt;/p&gt;
&lt;p&gt;Podemos escribir código sin documentación y sin tests, pero mantener ese
código es mucho más difícil y que otra persona lo use también, ya que si no
está debidamente documentado tendrá que irse al código y entender qué es lo
que hace cada función.&lt;/p&gt;
&lt;p&gt;Rust ofrece por defecto una forma de documentar y de implementar tests
bastante simple, además, la norma de un buen código Rust requiere que todo
método público esté documentado, por lo que si seguimos esta norma,
tendremos un código más mantenible. El tener la documentación y los tests
tan bien definidos desde el inicio ha provocado que la mayoría de las
bibliotecas existentes a día de hoy estén bien documentadas y tengan una
serie de tests definidos, y todo ello va junto con el código fuente
siempre.&lt;/p&gt;
&lt;p&gt;La documentación en Rust se genera a partir de comentarios en el código,
comparado con python, sería algo similar a los docstrings. Se escribe en
formato Markdown y con herramientas como cargo se pueden generar la
documentación en html fácilmente.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/documentation.html"&gt;Documentando&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Los comentarios de documentación en Rust no son iguales que los comentarios
normales de código. Los comentarios normales son similares a los
comentarios en C, pero se definen otros comentarios definidos con &lt;strong&gt;///&lt;/strong&gt; y
con &lt;strong&gt;//!&lt;/strong&gt;, que sí son documentación.&lt;/p&gt;
&lt;p&gt;La diferencia entre &lt;strong&gt;//!&lt;/strong&gt; y &lt;strong&gt;///&lt;/strong&gt; es que el primero se documenta el
elemento que lo engloba, mientras que el segundo documenta el elemento que
viene justo después. Normalmente se usa el primero para documentar módulos,
ya que se suele escribir ese comentario al principio del fichero, y las
estructuras y métodos se documentan con &lt;strong&gt;///&lt;/strong&gt; poniendo la documentación
justo antes de la implementación.&lt;/p&gt;
&lt;h3&gt;Generando la documentación con cargo&lt;/h3&gt;
&lt;p&gt;Con &lt;strong&gt;cargo&lt;/strong&gt; se puede generar la documentación muy fácilmente, simplemente
hay que lanzar el comando &lt;strong&gt;cargo doc&lt;/strong&gt; y esto generará toda la
documentación en HTML en el directorio &lt;strong&gt;target/doc&lt;/strong&gt;&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;doc
$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;target/doc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Documentación de módulos&lt;/h3&gt;
&lt;p&gt;Si tenemos un módulo definido en un fichero, se puede documentar tal que
así:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// Módulo de ejemplo para explicar cómo funciona la documentación&lt;/span&gt;
&lt;span class="sd"&gt;/// en Rust.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;ejemplo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sin embargo, normalmente los módulos se definen en ficheros independientes
y la documentación se suele poner al principio de cada módulo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;//! Módulo de ejemplo para explicar cómo funciona la documentación&lt;/span&gt;
&lt;span class="sd"&gt;//! en Rust.&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;funcion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Secciones en la documentación&lt;/h3&gt;
&lt;p&gt;En la documentación se pueden definir diferentes secciones, para separar la
documentación y que se muestre de manera diferente. Estas secciones se
definen como encabezados Markdown (&lt;strong&gt;# Examples&lt;/strong&gt;), y lo que viene debajo
pertenece a esa sección.&lt;/p&gt;
&lt;p&gt;Estas son las secciones especiales que se definen en Rust:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Panics&lt;/strong&gt;, si pueden ocurrir errores que no son recuperables, osea, que
   terminan la ejecución.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Errors&lt;/strong&gt;, cuando se devuelve un &lt;em&gt;Result&lt;/em&gt;, es conveniente documentar
   qué tipos de errores se pueden devolver y cuando.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Safety&lt;/strong&gt;, esto es más raro de encontrar, pero si una función es
   &lt;em&gt;unsafe&lt;/em&gt; es conveniente explicar el porqué.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;, esto es lo más común y recomendable en todo método. Aquí
   se pueden definir ejemplos de código, que además funcionarán como tests
   unitarios.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No es obligatorio, pero sí recomendable el rellenar cada una de estas
secciones, siempre y cuando tenga sentido, en la documentación de tus
métodos, ya que facilitará la tarea a futuros usuarios.&lt;/p&gt;
&lt;h2&gt;Tests en la documentación&lt;/h2&gt;
&lt;p&gt;Como hemos visto, la sección &lt;strong&gt;Examples&lt;/strong&gt; sirve para definir ejemplos de
código que se verán en la documentación, bien formateados, pero que además
sirven como tests unitarios.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// Comprueba si un número es mayor que 3&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// Se devuelve verdadero si *x* es mayor que 3,&lt;/span&gt;
&lt;span class="sd"&gt;/// en otro caso se deuvelve falso.&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// # Examples&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// Ejemplo básico&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="sd"&gt;/// use geometry::mayor3;&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(mayor3(2), false);&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(mayor3(3), false);&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(mayor3(4), true);&lt;/span&gt;
&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// Más ejemplos&lt;/span&gt;
&lt;span class="sd"&gt;///&lt;/span&gt;
&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="sd"&gt;/// use geometry::mayor3;&lt;/span&gt;
&lt;span class="sd"&gt;/// let mut n = 1;&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(mayor3(n), false);&lt;/span&gt;
&lt;span class="sd"&gt;/// while !mayor3(n) {&lt;/span&gt;
&lt;span class="sd"&gt;///     n += 1;&lt;/span&gt;
&lt;span class="sd"&gt;/// }&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(n, 4);&lt;/span&gt;
&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mayor3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se puede ver cómo se documenta una función, con un par de
ejemplos.&lt;/p&gt;
&lt;p&gt;Podemos ver cómo quedaría esta documentación en el HTML generado:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/rust-doc-1.png" /&gt;
&lt;/p&gt;

&lt;h3&gt;Ejecutando los tests con cargo&lt;/h3&gt;
&lt;p&gt;Como he comentado anteriormente, los ejemplos de código definidos en la
documentación también hacen la función de tests unitarios. Para ejecutar
los tests tan sólo hay que usar la herramienta &lt;strong&gt;cargo test&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Finished&lt;span class="w"&gt; &lt;/span&gt;debug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;unoptimized&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;debuginfo&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.0&lt;span class="w"&gt; &lt;/span&gt;secs
&lt;span class="w"&gt;     &lt;/span&gt;Running&lt;span class="w"&gt; &lt;/span&gt;target/debug/deps/geometry-d942cf2b29083ab0

running&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tests

&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;result:&lt;span class="w"&gt; &lt;/span&gt;ok.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;passed&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;failed&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ignored&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;measured

&lt;span class="w"&gt;   &lt;/span&gt;Doc-tests&lt;span class="w"&gt; &lt;/span&gt;geometry

running&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;tests
&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mayor3_0&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;ok
&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;mayor3_1&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;ok

&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;result:&lt;span class="w"&gt; &lt;/span&gt;ok.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;passed&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;failed&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ignored&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;measured
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Si eres buen observador, habrás visto que en los tests se mete la
importación del módulo en concreto, &lt;strong&gt;use geometry::mayor3&lt;/strong&gt;, esto es así
porque para ejecutar los tests de la documentación, lo que hace cargo es
crear un nuevo fichero rust con ese código, y lo mete todo dentro de un
&lt;strong&gt;fn main&lt;/strong&gt;, si no está definido. Por lo tanto, todo el código que se
escriba en un test ha de estar como si estuviera en un fichero
independiente.&lt;/p&gt;
&lt;p&gt;En ocasiones no queremos mostrar en la documentación todas las
importaciones, o definiciones, sólo la parte importante, pero si hacemos
eso, los tests no funcionarán. Para esos casos, se puede comenzar cada
línea de código a ocultar en la documentación con &lt;em&gt;#&lt;/em&gt;, de tal forma que se
ejecutará en los tests, pero no aparecerá en la documentación, por ejemplo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="sd"&gt;/// # use geometry::mayor3;&lt;/span&gt;
&lt;span class="sd"&gt;/// let mut n = 1;&lt;/span&gt;
&lt;span class="sd"&gt;/// assert_eq!(mayor3(n), false);&lt;/span&gt;
&lt;span class="sd"&gt;/// # while !mayor3(n) {&lt;/span&gt;
&lt;span class="sd"&gt;/// #     n += 1;&lt;/span&gt;
&lt;span class="sd"&gt;/// # }&lt;/span&gt;
&lt;span class="sd"&gt;/// # assert_eq!(n, 4);&lt;/span&gt;
&lt;span class="sd"&gt;/// ```&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mayor3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con esta documentación, el test seguiría siendo el mismo, pero sólo se
muestra en la documentación generada lo que no está "&lt;em&gt;comentado&lt;/em&gt;", quedando
tal que así:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/rust-doc-2.png" /&gt;
&lt;/p&gt;

&lt;h2&gt;Extra: Esconder la documentación en vim&lt;/h2&gt;
&lt;p&gt;Con la documentación y los tests incluidos, los ficheros de código se
vuelven muy grandes rápidamente y navegar por ellos se vuelve un poco
complejo.&lt;/p&gt;
&lt;p&gt;Creo que viene muy bien que la documentación y el código estén en el mismo
fichero, y juntos, ya que si se cambia el código no nos olvidaremos de
cambiar la documentación y por tanto es mucho más fácil mantener esta
documentación consistente. Además para cualquiera que lea el código, y no
sea un desarrollador avanzado, le vendrá muy bien esa documentación.&lt;/p&gt;
&lt;p&gt;Sin embargo, cuando ya conoces un código y estás modificando un fichero
cualquiera, tener que navegar por todo el fichero con tantos comentarios,
es un poco engorroso, normalmente quieres ocultar esos comentarios para
centrarte en el código.&lt;/p&gt;
&lt;p&gt;Para ello tengo definido en el vim una función para que agrupe los
comentarios con &lt;strong&gt;fold&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;foldmethod&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;expr
&lt;span class="k"&gt;setlocal&lt;/span&gt; &lt;span class="nb"&gt;foldexpr&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;GetRustFold&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; IndentLevel&lt;span class="p"&gt;(&lt;/span&gt;lnum&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; indent&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt; / &amp;amp;&lt;span class="nb"&gt;shiftwidth&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; GetRustFold&lt;span class="p"&gt;(&lt;/span&gt;lnum&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; getline&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=~&lt;/span&gt;? &lt;span class="s1"&gt;&amp;#39;\v^\s*$&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;-1&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; this_indent &lt;span class="p"&gt;=&lt;/span&gt; IndentLevel&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; getline&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=~&lt;/span&gt;? &lt;span class="s1"&gt;&amp;#39;^\s*///.*$&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; this_indent &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;endif&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; this_indent
    &lt;span class="k"&gt;endif&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; getline&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:lnum&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=~&lt;/span&gt;? &lt;span class="s1"&gt;&amp;#39;^\s*//!.*$&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; this_indent &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;
        &lt;span class="k"&gt;endif&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; this_indent
    &lt;span class="k"&gt;endif&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Por ejemplo, si abro el fichero de &lt;strong&gt;string.rs&lt;/strong&gt;:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;img src="/pictures/rust-doc-3.png" /&gt;
&lt;/p&gt;

&lt;p&gt;Y puedo desplegar o contraer los comentarios a mi gusto con &lt;strong&gt;za&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusiones&lt;/h2&gt;
&lt;p&gt;Hay muchas cosas sobre documentación en Rust que no he comentado por aquí y
que se pueden encontrar en la documentación oficial. Lo que he contado es
lo básico y la forma más sencilla de empezar a documentar y a probar el
código.&lt;/p&gt;
&lt;p&gt;Como ejemplo de documentación más completa, se puede mirar cualquier
&lt;em&gt;crate&lt;/em&gt; de Rust, en &lt;a href="https://github.com"&gt;github&lt;/a&gt; hay mucho código Rust, que está documentado
de esta manera. Por ejemplo la &lt;a href="https://github.com/danigm/epub-rs/blob/master/src/doc.rs"&gt;biblioteca para leer epubs&lt;/a&gt; que yo mismo
he implementado define la documentación y los tests de esta forma.&lt;/p&gt;
&lt;p&gt;Y como resultado de la documentación, pues se puede mirar la
&lt;a href="https://doc.rust-lang.org/std/"&gt;documentación de std de &lt;em&gt;Rust&lt;/em&gt;&lt;/a&gt;, por ejemplo, se puede mirar el
&lt;a href="https://github.com/rust-lang/rust/blob/master/src/libcollections/string.rs"&gt;código de String&lt;/a&gt; y comparar con la &lt;a href="https://doc.rust-lang.org/std/string/struct.String.html"&gt;documentación html&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 18 Mar 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-03-18:/rust-doc.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Rust: Pattern Matching</title><link>https://danigm.net/rust-match.html</link><description>&lt;p&gt;En Rust se utiliza mucho la &lt;em&gt;búsqueda de patrones&lt;/em&gt;, más conocida como
&lt;strong&gt;pattern matching&lt;/strong&gt;. Es una estructura lógica en el código que permite
hacer varias cosas diferentes de una forma muy sencilla. Se puede usar por
ejemplo para hacer algo similar al &lt;strong&gt;switch&lt;/strong&gt; de lenguajes como &lt;strong&gt;C/C++&lt;/strong&gt;,
pero también se puede usar para asignaciones complejas, descomposición de
estructuras comprobación de errores, etc.&lt;/p&gt;
&lt;p&gt;Con el &lt;strong&gt;pattern matching&lt;/strong&gt; lo que se hace, básicamente, es definir
condiciones o asignaciones en función de un patrón. Se podría decir que es
algo similar a las expresiones regulares, pero más simple, y aplicado a la
escritura de código.&lt;/p&gt;
&lt;p&gt;En este artículo definiré el uso principal en Rust, que es el uso dentro de
los &lt;strong&gt;match&lt;/strong&gt;, y también otros usos, como la asignación o la asignación
condicional.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/match.html"&gt;Match&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Match&lt;/em&gt; es una expresión condicional en &lt;em&gt;Rust&lt;/em&gt;. Se aplica sobre una
variable y se definen una serie de patrones, y sólo se ejecuta el código
correspondiente al patrón que concuerde con la variable.&lt;/p&gt;
&lt;p&gt;El uso principal que se le puede dar a &lt;em&gt;match&lt;/em&gt; es el de condición múltiple,
tenemos una estructura &lt;em&gt;if/else if/else if&lt;/em&gt;, que podemos simplificar con
una sola expresión.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uno&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tres&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cuatro&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cinco&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;gt; 5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20main()%20%7B%0A%20%20%20%20let%20x%20%3D%205%3B%0A%20%20%20%20match%20x%20%7B%0A%20%20%20%20%20%20%20%201%20%3D%3E%20println!(%22uno%22)%2C%0A%20%20%20%20%20%20%20%202%20%3D%3E%20println!(%22dos%22)%2C%0A%20%20%20%20%20%20%20%203%20%3D%3E%20println!(%22tres%22)%2C%0A%20%20%20%20%20%20%20%204%20%3D%3E%20println!(%22cuatro%22)%2C%0A%20%20%20%20%20%20%20%205%20%3D%3E%20println!(%22cinco%22)%2C%0A%20%20%20%20%20%20%20%20_%20%3D%3E%20println!(%22%3E%205%22)%2C%0A%20%20%20%20%7D%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Con este match, tenemos la condición múltiple, comprobamos un entero y
según el que sea se imprime ese número en texto.&lt;/p&gt;
&lt;p&gt;Como se puede ver en el ejemplo, se usa el operador &lt;em&gt;=&amp;gt;&lt;/em&gt; para diferenciar
el patrón y lo que se ejecuta si se cumple. Lo que se ejecuta no tiene por
qué ser una sola línea, se pueden ejecutar varias sentencias englobándolo
en unas llaves.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uno&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tres&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cuatro&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cinco&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;el valor es {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;gt; 5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El match también es muy usado para asignaciones, devuelve lo que se
devuelva dentro de las condiciones, por lo tanto se puede usar en una
asignación let.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uno&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tres&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cuatro&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;detro del match&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cinco&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;gt; 5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20main()%20%7B%0A%20%20%20%20let%20x%20%3D%205%3B%0A%20%20%20%20let%20number%20%3D%20match%20x%20%7B%0A%20%20%20%20%20%20%20%201%20%3D%3E%20%22uno%22%2C%0A%20%20%20%20%20%20%20%202%20%3D%3E%20%22dos%22%2C%0A%20%20%20%20%20%20%203%20%3D%3E%20%22tres%22%2C%0A%20%20%20%20%20%20%204%20%3D%3E%20%22cuatro%22%2C%0A%20%20%20%20%20%20%205%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20println!(%22detro%20del%20match%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%22cinco%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20_%20%3D%3E%20%22%3E%205%22%2C%0A%20%20%20%20%7D%3B%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20number)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Además de patrones simples de enteros o cadenas, en el match se pueden usar
&lt;em&gt;Enums&lt;/em&gt;, estructuras y otras composiciones que lo hacen bastante más
potente, veamoslo con más detalle en el apartado de &lt;em&gt;Patrones&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Hay que tener en cuenta que los patrones han de ser completos, es decir,
han de cubrir todas las posibilidades de la variable sobre la que se hace
&lt;em&gt;match&lt;/em&gt;. Otra cosa importante es que se ejecutan de arriba hacia abajo, por
lo que la definición ha de ser de más concreto a más genérico siempre, ya
que si no, el compilador se quejará porque existen patrones que nunca se
alcanzarán.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/patterns.html"&gt;Patrones&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Como hemos visto con el &lt;em&gt;match&lt;/em&gt;, los patrones se pueden definir con
literales directamente, y el caso de &lt;em&gt;_&lt;/em&gt;, que se explica más adelante.&lt;/p&gt;
&lt;p&gt;Además de la comprobación con literales, los patrones pueden &lt;em&gt;definir&lt;/em&gt;
nuevas variables, que se pueden usar dentro del &lt;em&gt;match&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;El valor de x es {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este caso, al no poner un literal en la parte izquierda de la expresión,
en el patrón, se hace el matching y se asigna el valor de &lt;em&gt;x&lt;/em&gt; a &lt;em&gt;n&lt;/em&gt;. Hay
que tener cuidado con esto, porque es lo mismo que una asignación con
&lt;em&gt;let&lt;/em&gt;, en el caso de que el tipo implemente &lt;em&gt;Copy&lt;/em&gt; se hará una copia, en
otro caso se hará un &lt;em&gt;move&lt;/em&gt;. Para modificar estos comportamientos se pueden
usar &lt;em&gt;ref&lt;/em&gt; y &lt;em&gt;ref mut&lt;/em&gt;, pero eso lo veremos más adelante.&lt;/p&gt;
&lt;h3&gt;Múltiples patrones&lt;/h3&gt;
&lt;p&gt;Se pueden definir múltiples patrones que ejecuten la misma secuencia, esto
podría verse como algo similar a lo que se hace en los &lt;em&gt;switch&lt;/em&gt; cuando se
deja un case vacío, que sabes que se ejecutará lo mismo para este y para el
siguiente.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;uno o dos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;otro número&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Se utiliza el operador &lt;strong&gt;|&lt;/strong&gt; para definir patrones múltiples. Se intenta
hacer matching con la primera parte del &lt;strong&gt;|&lt;/strong&gt; y si no, se intenta con la
segunda, si alguno de los dos patrones concuerdan con el valor, se ejecuta
la sentencia.&lt;/p&gt;
&lt;h3&gt;Descomposición&lt;/h3&gt;
&lt;p&gt;El pattern matching es muy útil cuando estamos usando estructuras más o
menos complejas o enums, ya que permite descomponer el valor de forma fácil
y acceder a componentes de estas estructuras de forma directa.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte imaginaria es 0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{},{}i&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20main()%20%7B%0A%20%20%20%20struct%20Complex%20%7B%0A%20%20%20%20%20%20%20%20real%3A%20i32%2C%0A%20%20%20%20%20%20%20%20img%3A%20i32%2C%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20let%20x%20%3D%20Complex%7Breal%3A%205%2C%20img%3A%203%7D%3B%0A%20%20%20%20match%20x%20%7B%0A%20%20%20%20%20%20%20%20Complex%7Breal%3A%20_%2C%20img%3A%200%7D%20%3D%3E%20println!(%22parte%20imaginaria%20es%200%22)%2C%0A%20%20%20%20%20%20%20%20Complex%7Breal%3A%20r%2C%20img%3A%20i%7D%20%3D%3E%20println!(%22%7B%7D%2C%7B%7Di%22%2C%20r%2C%20i)%2C%0A%20%20%20%20%7D%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se define una estructura compleja, con dos valores enteros,
y en el match se puede ver cómo se descompone, pudiendo acceder de forma
rápida y sencilla a los valores correspondientes. En el primer patrón se
ignora la parte real y se obliga a que la parte imaginaria sea 0, y en el
segundo patrón entraría cualquier otra cosa, y tenemos acceso a &lt;em&gt;r&lt;/em&gt; e &lt;em&gt;i&lt;/em&gt;
con los valores en concreto del valor de &lt;em&gt;x&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La descomposición se puede usar para gestión de errores con los enums
&lt;em&gt;Option&lt;/em&gt; y &lt;em&gt;Result&lt;/em&gt;, teniendo expresiones del tipo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;valor {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;no existe&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;somecall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;resultado {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ha ocurrido un error&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Ignorando variables o componentes&lt;/h3&gt;
&lt;p&gt;En los ejemplos anteriores ya hemos ignorado algunas variables, que en un
caso concreto no nos interesan dentro del match, para ello se usa el
operador &lt;strong&gt;_&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En otras ocasiones, dentro de una descomposición, por ejemplo, queremos
ignorar todos los elementos de este, o una parte y para eso existe el
operador &lt;strong&gt;..&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte imaginaria es 0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Cualquier complejo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El operador &lt;strong&gt;..&lt;/strong&gt; se puede usar como en el ejemplo, para ignorar todo, o
para ignorar sólo parte, si tuviéramos una estructura más compleja, con 5
variables, por ejemplo, y sólo nos interesa una:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;SuperComplex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SuperComplex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;real1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;real2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;SuperComplex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;img1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte imaginaria 1 es 0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;SuperComplex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Cualquier complejo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Referencias (ref, ref mut)&lt;/h3&gt;
&lt;p&gt;Cuando se definen nuevos nombres en el match, se crean nuevas variables, de
forma similar a cuando se hace un let, y por lo tanto, entra en juego la
gestión de memoria. Por defecto se hace un &lt;em&gt;move&lt;/em&gt;, pero habrá ocasiones en
las que no queramos eso, sino que queramos una referencia, para evitar que
la variable se destruya tras el match. Para eso se pueden usar las palabras
clave &lt;strong&gt;ref&lt;/strong&gt; y &lt;strong&gt;ref mut&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte imaginaria es 0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Cualquier complejo {}, {}i&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte real: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo definimos el patrón &lt;em&gt;ref a&lt;/em&gt;, por lo tanto, &lt;em&gt;a&lt;/em&gt; es del tipo
&lt;em&gt;&amp;amp;Complex&lt;/em&gt; y al ser una referencia, se puede usar &lt;em&gt;x&lt;/em&gt; después del match sin
problemas. Si eliminamos el &lt;em&gt;ref&lt;/em&gt;, el compilador nos daría un error, ya que
en el match se movería el valor de &lt;em&gt;x&lt;/em&gt; a &lt;em&gt;a&lt;/em&gt; y por tanto ya no se podría
usar &lt;em&gt;x&lt;/em&gt; después del match.&lt;/p&gt;
&lt;h3&gt;Rangos (Ranges)&lt;/h3&gt;
&lt;p&gt;Con el uso de literales enteros y caracteres existe una definición que
permite definir de forma simple un rango de valores, para ello se usa el
operador &lt;strong&gt;...&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;entre uno y diez&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mayor que diez&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;minúscula&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;Z&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mayúscula&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;otra cosa&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Enlaces (Bindings)&lt;/h3&gt;
&lt;p&gt;Se pueden asignar variables a patrones, no sólo como hemos visto en la
descomposición, sino de manera global, ya sea a patrones literales, o al
global de una descomposición, y para ello se usa el operador &lt;strong&gt;@&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{} es menor de 10&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mayor de 10&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte imaginaria es 0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Cualquier complejo {}, {}i&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte real: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hay que tener en cuenta que si se usan múltiples condiciones con &lt;strong&gt;|&lt;/strong&gt;, el
binding se aplica a una parte, no al conjunto:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}: uno o dos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;otro número&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Condicionales (Guards)&lt;/h3&gt;
&lt;p&gt;En los patrones también se pueden definir condicionantes, de tal forma que
sólo se ejecute la sentencia correspondiente si se aplica el match y además
si se cumple cierta condición.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}: es menor que 5&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;otro número&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Los condicionales se definen con &lt;strong&gt;if&lt;/strong&gt; y detrás la condición que se quiera
comprobar, además se pueden usar las variables que defina el patrón para la
condición, por lo que nos proporcionan una gran potencia a la hora de
definir patrones.&lt;/p&gt;
&lt;p&gt;En las condiciones múltiples con &lt;strong&gt;|&lt;/strong&gt; el &lt;strong&gt;if&lt;/strong&gt; se aplica sobre las dos
partes de la condición, por lo tanto no se pueden definir varios &lt;strong&gt;if&lt;/strong&gt; en
un mismo patrón.&lt;/p&gt;
&lt;h2&gt;Otros usos de los patrones&lt;/h2&gt;
&lt;p&gt;Además de para el &lt;strong&gt;match&lt;/strong&gt;, los patrones se usan en Rust en diferentes
partes.&lt;/p&gt;
&lt;h3&gt;&lt;a href="https://doc.rust-lang.org/book/if-let.html"&gt;If let&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;En muchas ocasiones, nos encontramos con variables que son del tipo
&lt;em&gt;Option&lt;/em&gt; o &lt;em&gt;Result&lt;/em&gt; y queremos hacer algo, sólo si tienen un valor, por
ejemplo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_some&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para simplificar este caso existe el &lt;strong&gt;if let&lt;/strong&gt; que unifica la asignación y
el condicional en una sola línea, teniendo algo que sólo se ejecuta si el
patrón se aplica correctamente:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;&lt;a href="https://doc.rust-lang.org/book/variable-bindings.html#patterns"&gt;Asignación&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Los patrones también se pueden usar directamente en las asignaciones con
&lt;em&gt;let&lt;/em&gt;. Esto es realmente útil cuando lo combinamos con una descomposición
de una lista o una estructura:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Complex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Complex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;parte real: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como se puede ver, el pattern matching es algo muy utilizado en Rust y
bastante potente, con lo que se puede escribir código simple que haga cosas
increíbles.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 11 Mar 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-03-11:/rust-match.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Rust: Tipos nulos (Option) y gestión de errores (Result)</title><link>https://danigm.net/rust-option-result.html</link><description>&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/std/option/index.html"&gt;Option&lt;/a&gt;, Tipos nulos&lt;/h2&gt;
&lt;p&gt;En rust no existe el tipo especial &lt;em&gt;null&lt;/em&gt;, como en C/C++, y al ser
fuertemente tipado, no se puede asignar algo de diferente tipo a una
variable, por lo tanto no es posible tener variables declaradas de un tipo,
por ejemplo &lt;em&gt;File&lt;/em&gt; y que valga &lt;em&gt;null&lt;/em&gt; si no está inicializado o algo así,
ni tampoco se puede devolver &lt;em&gt;null&lt;/em&gt; o algo así, como se haría en C++, en
una función que declara como valor de retorno un tipo, y por alguna razón
no tiene sentido para una entrada determinada.&lt;/p&gt;
&lt;p&gt;Lo que se usa en rust para solucionar este tipo de problemas y poder
asignar valores nulos a variables o en devoluciones es el &lt;a href="https://doc.rust-lang.org/std/option/enum.Option.html"&gt;&lt;em&gt;enum
Option&lt;/em&gt;&lt;/a&gt;, que se define como:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;None&lt;/em&gt; sería el tipo &lt;em&gt;nulo&lt;/em&gt; en rust, y &lt;em&gt;Some(T)&lt;/em&gt; sería cuando tenemos un
valor. Por lo tanto, si queremos declarar una variable que en principio
pueda ser nula, la declararemos como &lt;em&gt;Option&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;correo para {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{} no tiene correo asignado&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm@wadobo.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=struct%20User%3C%27a%3E%20%7B%0A%20%20%20%20username%3A%20%26%27a%20str%2C%0A%20%20%20%20email%3A%20Option%3C%26%27a%20str%3E%2C%0A%7D%0A%0Afn%20send_email(u%3A%20%26User)%20%7B%0A%20%20%20%20match%20u.email%20%7B%0A%20%20%20%20%20%20%20%20Some(email)%20%3D%3E%20println!(%22correo%20para%20%7B%7D%22%2C%20email)%2C%0A%20%20%20%20%20%20%20%20None%20%3D%3E%20println!(%22%7B%7D%20no%20tiene%20correo%20asignado%22%2C%20u.username)%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20u%20%3D%20User%7B%20username%3A%20%22danigm%22%2C%20email%3A%20None%20%7D%3B%0A%20%20%20%20send_email(%26u)%3B%0A%0A%20%20%20%20u.email%20%3D%20Some(%22danigm%40wadobo.com%22)%3B%0A%20%20%20%20send_email(%26u)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo, declaramos una estructura con dos atributos, el nombre de
usuario que es de tipo &lt;em&gt;&amp;amp;str&lt;/em&gt; y el email, que es de tipo &lt;em&gt;Option&amp;lt;&amp;amp;str&amp;gt;&lt;/em&gt;,
para poder tener usuarios que no tengan email asociado.&lt;/p&gt;
&lt;p&gt;En la función &lt;em&gt;send_email&lt;/em&gt; se utiliza el &lt;a href="https://doc.rust-lang.org/book/match.html"&gt;&lt;em&gt;match&lt;/em&gt;&lt;/a&gt; para diferenciar si
el valor es &lt;em&gt;None&lt;/em&gt; o si tiene una cadena asociada y se actúa en
consecuencia.&lt;/p&gt;
&lt;p&gt;Además de poder diferenciar el tipo &lt;em&gt;Option&lt;/em&gt; con &lt;em&gt;patter matching&lt;/em&gt;, también
dispone de algunos métodos que se pueden llamar para ver si tiene un valor
o no:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_some&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;email definido: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;email no definido&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;email: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;no definido&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se usan los métodos &lt;em&gt;is_some&lt;/em&gt; e &lt;em&gt;is_none&lt;/em&gt;, que te devuelven
un &lt;em&gt;bool&lt;/em&gt; si el tipo es lo que preguntamos, y también se usan el &lt;em&gt;unwrap&lt;/em&gt;,
que lo que hace es devolver el valor dentro del &lt;em&gt;Some&lt;/em&gt;, por lo que daría un
&lt;em&gt;panic&lt;/em&gt; si el &lt;em&gt;Option&lt;/em&gt; es &lt;em&gt;None&lt;/em&gt;. Y por último también se usa el
&lt;em&gt;unwrap_or&lt;/em&gt;, que es similar al &lt;em&gt;unwrap&lt;/em&gt;, pero que no fallaría en caso de
ser &lt;em&gt;None&lt;/em&gt;, sino que devolvería el valor definido.&lt;/p&gt;
&lt;p&gt;En la &lt;a href="https://doc.rust-lang.org/std/option/enum.Option.html"&gt;documentación de &lt;em&gt;Option&lt;/em&gt;&lt;/a&gt; vienen todos los métodos y es
recomendable echarle un vistazo porque hay muchos que son muy interesantes.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/std/result/index.html"&gt;Result&lt;/a&gt;, Gestión de errores&lt;/h2&gt;
&lt;p&gt;En rust no existen excepciones, como en python y otros lenguajes, para
gestionar los errores, ni tampoco se hace como C, que realmente no tiene
gestión de errores alguna, sino que se usa el valor de retorno para indicar
errores, devolviendo números negativos, por ejemplo, o 0, o algo similar.&lt;/p&gt;
&lt;p&gt;En rust la gestión de errores se hace usando el tipo de retorno, pero no
devolviendo un valor determinado, sino devolviendo un tipo &lt;em&gt;Result&lt;/em&gt;, que te
&lt;em&gt;obliga&lt;/em&gt; a comprobar si ha funcionado bien antes de poder usar el valor
devuelto, evitando así problemas de uso de variables no inicializadas y
demás.&lt;/p&gt;
&lt;p&gt;El tipo &lt;em&gt;Result&lt;/em&gt; es muy similar al &lt;em&gt;Option&lt;/em&gt;, que hemos visto anteriormente,
la única diferencia es que el &lt;em&gt;Result&lt;/em&gt; se define con dos tipos genéricos,
el de la respuesta y el del error, para poder especificar el tipo de error:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Es un simple &lt;em&gt;enum&lt;/em&gt;, por lo tanto un &lt;em&gt;Result&lt;/em&gt; puede ser o un &lt;em&gt;Ok(T)&lt;/em&gt; o un
&lt;em&gt;Err(E)&lt;/em&gt;&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;nth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;@newdomain.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;email no definido&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Este es el nuevo email: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Error: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm@wadobo.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Nuevo email: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(dead_code)%5D%0A%23%5Ballow(unused_variables)%5D%0A%0Astruct%20User%3C%27a%3E%20%7B%0A%20%20%20%20username%3A%20%26%27a%20str%2C%0A%20%20%20%20email%3A%20Option%3C%26%27a%20str%3E%2C%0A%7D%0A%0Afn%20transform_email(u%3A%20%26User)%20-%3E%20Result%3CString%2C%20String%3E%20%7B%0A%20%20%20%20match%20u.email%20%7B%0A%20%20%20%20%20%20%20%20Some(email)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20s%20%3D%20email.split(%27%40%27).nth(0).unwrap()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Ok(String%3A%3Afrom(s)%20%2B%20%22%40newdomain.com%22)%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20None%20%3D%3E%20Err(String%3A%3Afrom(%22email%20no%20definido%22))%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20u%20%3D%20User%7B%20username%3A%20%22danigm%22%2C%20email%3A%20None%20%7D%3B%0A%0A%20%20%20%20let%20ret%20%3D%20transform_email(%26u)%3B%0A%20%20%20%20match%20ret%20%7B%0A%20%20%20%20%20%20%20%20Ok(email)%20%3D%3E%20println!(%22Este%20es%20el%20nuevo%20email%3A%20%7B%7D%22%2C%20email)%2C%0A%20%20%20%20%20%20%20%20Err(error)%20%3D%3E%20println!(%22Error%3A%20%7B%7D%22%2C%20error)%0A%20%20%20%20%7D%0A%0A%20%20%20%20u.email%20%3D%20Some(%22danigm%40wadobo.com%22)%3B%0A%20%20%20%20if%20let%20Ok(email)%20%3D%20transform_email(%26u)%20%7B%0A%20%20%20%20%20%20%20%20println!(%22Nuevo%20email%3A%20%7B%7D%22%2C%20email)%3B%0A%20%20%20%20%7D%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se define la función &lt;em&gt;transform_email&lt;/em&gt;, que devuelve un
&lt;em&gt;Result&lt;/em&gt; con el tipo &lt;em&gt;String&lt;/em&gt; para el &lt;em&gt;Ok&lt;/em&gt; y también para el &lt;em&gt;Err&lt;/em&gt;. En este
caso he usado este tipo para los dos posibles valores, pero normalmente el
tipo de error implementa el &lt;a href="https://doc.rust-lang.org/std/error/trait.Error.html"&gt;&lt;em&gt;trait Error&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;En la función lo único que hacemos es mirar si está definido, haciendo un
&lt;em&gt;match&lt;/em&gt; al &lt;em&gt;email&lt;/em&gt; y en caso de estar definido devolvemos &lt;em&gt;Ok(...)&lt;/em&gt; con la
cadena transformada, y en el caso de error devolvemos &lt;em&gt;Err(...)&lt;/em&gt; con un
mensaje de error.&lt;/p&gt;
&lt;p&gt;Luego a la hora de usarlo, al ser el valor devuelto de tipo &lt;em&gt;Result&lt;/em&gt; y no
de tipo &lt;em&gt;String&lt;/em&gt;, nos obliga a comprobar si la llamada ha sido correcta
antes de poder usar el valor de retorno real. Por lo tanto hay que hacer un
&lt;em&gt;pattern matching&lt;/em&gt; y actuar en consecuencia si es un error o si es un valor
correcto.&lt;/p&gt;
&lt;p&gt;Al igual que el &lt;em&gt;Option&lt;/em&gt;, el tipo &lt;em&gt;Result&lt;/em&gt; tiene métodos similares
definidos, como el &lt;em&gt;is_ok&lt;/em&gt;, &lt;em&gt;is_err&lt;/em&gt;, &lt;em&gt;unwrap&lt;/em&gt;, &lt;em&gt;unwrap_or&lt;/em&gt;, etc.&lt;/p&gt;
&lt;h2&gt;Propagación de errores&lt;/h2&gt;
&lt;p&gt;Esta forma de gestionar errores es muy simple, pero al obligarte a
comprobar el tipo de respuesta de cada llamada que devuelve un &lt;em&gt;Result&lt;/em&gt;,
hace que se introduzca mucho código de comprobación de errores en todas las
funciones, y normalmente lo que queremos es que si va bien continuamos y si
va mal, devolvemos un error, osea, propagamos el error hacia arriba, como
se haría en python con un &lt;em&gt;raise&lt;/em&gt;, como funcionan las excepciones.&lt;/p&gt;
&lt;p&gt;Para eso existe la macro &lt;a href="https://doc.rust-lang.org/std/macro.try.html"&gt;&lt;em&gt;"try!"&lt;/em&gt;&lt;/a&gt; en &lt;em&gt;Rust&lt;/em&gt; que simplifica el código, y
recientemente también han añadido el nuevo operador &lt;em&gt;?&lt;/em&gt; que hace lo mismo
que la macro &lt;em&gt;try!&lt;/em&gt;, pero a nivel de compilador, por lo que es recomendable
usar este último. Sin embargo voy a mostrar código con las dos
posibilidades, porque supongo que aún habrá mucho código rust por ahí que
usa la macro &lt;em&gt;try!&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Iter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;nth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;@newdomain.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;email no definido&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;transform_all_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{} new email: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user2@wadobo.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_all_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Error: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;danigm@wadobo.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_all_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Error: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=use%20std%3A%3Aslice%3A%3AIter%3B%0A%0Astruct%20User%3C%27a%3E%20%7B%0A%20%20%20%20username%3A%20%26%27a%20str%2C%0A%20%20%20%20email%3A%20Option%3C%26%27a%20str%3E%2C%0A%7D%0A%0Afn%20transform_email(u%3A%20%26User)%20-%3E%20Result%3CString%2C%20String%3E%20%7B%0A%20%20%20%20match%20u.email%20%7B%0A%20%20%20%20%20%20%20%20Some(email)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20s%20%3D%20email.split(%27%40%27).nth(0).unwrap()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Ok(String%3A%3Afrom(s)%20%2B%20%22%40newdomain.com%22)%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20None%20%3D%3E%20Err(String%3A%3Afrom(%22email%20no%20definido%22))%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20transform_all_emails(users%3A%20Iter%3C%26User%3E)%20-%3E%20Result%3C()%2C%20String%3E%20%7B%0A%20%20%20%20for%20u%20in%20users%20%7B%0A%20%20%20%20%20%20%20%20let%20new%20%3D%20transform_email(u)%3F%3B%0A%20%20%20%20%20%20%20%20println!(%22%7B%7D%20new%20email%3A%20%7B%7D%22%2C%20u.username%2C%20new)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20Ok(())%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20u%20%3D%20User%7B%20username%3A%20%22danigm%22%2C%20email%3A%20None%20%7D%3B%0A%20%20%20%20let%20u2%20%3D%20User%7B%20username%3A%20%22user2%22%2C%20email%3A%20Some(%22user2%40wadobo.com%22)%20%7D%3B%0A%0A%20%20%20%20if%20let%20Err(e)%20%3D%20transform_all_emails(vec!%5B%26u%2C%20%26u2%5D.iter())%20%7B%0A%20%20%20%20%20%20%20%20println!(%22Error%3A%20%7B%7D%22%2C%20e)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20u.email%20%3D%20Some(%22danigm%40wadobo.com%22)%3B%0A%20%20%20%20if%20let%20Err(e)%20%3D%20transform_all_emails(vec!%5B%26u%2C%20%26u2%5D.iter())%20%7B%0A%20%20%20%20%20%20%20%20println!(%22Error%3A%20%7B%7D%22%2C%20e)%3B%0A%20%20%20%20%7D%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo, además de lo anterior, he definido otra función que
transforma todos los emails de una lista de usuarios y devuelve un &lt;em&gt;Result&lt;/em&gt;
con la lista vacía si todo ha ido bien, o con un mensaje de error si algo
ha fallado. Dentro de esta función no hay un &lt;em&gt;return Err&lt;/em&gt; por ninguna
parte, sin embargo se hace en la línea:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El operador &lt;em&gt;?&lt;/em&gt; lo que hace es básicamente un &lt;em&gt;match&lt;/em&gt; de la respuesta, si
es &lt;em&gt;Ok(t)&lt;/em&gt;, devuelve &lt;em&gt;t&lt;/em&gt;, si es un &lt;em&gt;Err(e)&lt;/em&gt;, hace un &lt;em&gt;return Err(e)&lt;/em&gt;, por
lo que el error se propaga hacia arriba, y el código que hay detrás puede
suponer que el valor de &lt;em&gt;new&lt;/em&gt; es un &lt;em&gt;String&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Como he comentado antes, el operador &lt;em&gt;?&lt;/em&gt; es relativamente nuevo, el mismo
código usando la macro &lt;em&gt;try!&lt;/em&gt; sería:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;try&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transform_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El operador &lt;em&gt;?&lt;/em&gt; sólo se puede usar dentro de funciones de devuelvan un
&lt;em&gt;Result&lt;/em&gt; y que tengan como tipo de error el mismo o compatible con las
funciones que lo usan, ya que se va a hacer un &lt;em&gt;return&lt;/em&gt; directamente del
error devuelto y por tanto esos tipos tienen que coincidir.&lt;/p&gt;
&lt;h3&gt;Propagación de errores con Option&lt;/h3&gt;
&lt;p&gt;El operador &lt;em&gt;?&lt;/em&gt; sólo vale para el tipo &lt;em&gt;Result&lt;/em&gt;, sin embargo, el tipo
&lt;em&gt;Option&lt;/em&gt; es muy similar y es muy típico que en una función o método sólo se
pueda continuar si el &lt;em&gt;Option&lt;/em&gt; tiene valor, es decir, si no es &lt;em&gt;None&lt;/em&gt;, por
lo tanto, puede ser interesante poder propagar los errores de forma
sencilla sin tener que hacer el &lt;em&gt;match&lt;/em&gt; y el &lt;em&gt;return&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para eso se puede utilizar el método &lt;em&gt;ok_or&lt;/em&gt; del tipo &lt;em&gt;Option&lt;/em&gt;, que lo que
hace es devolverte un &lt;em&gt;Result&lt;/em&gt; con el valor si es &lt;em&gt;Some(t)&lt;/em&gt; y en caso de
ser &lt;em&gt;None&lt;/em&gt; te devolverá &lt;em&gt;Err(e)&lt;/em&gt;, siendo &lt;em&gt;e&lt;/em&gt; la variable que se pasa como
único argumento al método.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;print_all_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Iter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot; sin email&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;print_all_emails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;u2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Error: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 04 Mar 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-03-04:/rust-option-result.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Rust: Funciones y closures</title><link>https://danigm.net/rust-funcs.html</link><description>&lt;p&gt;En Rust se pueden definir &lt;a href="https://doc.rust-lang.org/book/functions.html"&gt;funciones&lt;/a&gt;, a nivel global, como parte de una
implementación de una estructura o como parte de una interfaz o &lt;em&gt;trait&lt;/em&gt;,
además, se pueden pasar como parámetros a otras funciones, se puede decir
que una función también define un nuevo tipo.&lt;/p&gt;
&lt;p&gt;La estructura de una definición simple es la siguiente:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;nombre_funcion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// cuerpo de la función&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Se usa la palabra clave "&lt;em&gt;fn&lt;/em&gt;", después va el nombre de la función, que
normalmente se usa notación en minúsculas y con separando palabras con
guión bajo, el llamado "&lt;em&gt;snake_case&lt;/em&gt;". Entre paréntesis van todos los
argumentos, separados por coma. Después si la función devuelve algo, va el
operador "&lt;em&gt;-&amp;gt;&lt;/em&gt;" y luego se define el tipo de retorno.&lt;/p&gt;
&lt;p&gt;Tanto la lista de argumentos como el retorno son opcionales, pudiendo
definir funciones que no reciben argumentos y no devuelven nada:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;nombre_funcion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// cuerpo&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Las funciones se pueden definir dentro de cualquier &lt;em&gt;scope&lt;/em&gt; y serán
visibles sólo durante ese &lt;em&gt;scope&lt;/em&gt;, por tanto en &lt;em&gt;Rust&lt;/em&gt; se pueden definir
funciones a nivel global, dentro de una función, o dentro de otro &lt;em&gt;scope&lt;/em&gt;,
cualquiera. En ese sentido es muy similar a como se pueden definir las
funciones en Python.&lt;/p&gt;
&lt;h2&gt;Argumentos&lt;/h2&gt;
&lt;p&gt;La definición de argumentos en las funciones en Rust no difiere mucho de
otros lenguajes, como C o C++. Se definen como pares,
&lt;strong&gt;identificador: tipo&lt;/strong&gt;. El &lt;em&gt;identificador&lt;/em&gt; es el nombre de la variable, y
como Rust es fuertemente tipado, hay que definir el tipo de todo argumento.
El tipo puede llevar modificadores &lt;em&gt;&amp;amp;&lt;/em&gt; o &lt;em&gt;&amp;amp;mut&lt;/em&gt; para modificar la
forma en la que se pasan esas funciones, y el identificador puede llevar el
modificador &lt;em&gt;mut&lt;/em&gt;, que sería similar al funcionamiento en una asignación
&lt;em&gt;let&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;add_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se ve cómo se pasa un vector como parámetro, y con el
modificador &lt;em&gt;mut&lt;/em&gt; es editable dentro de la función, al no llevar
modificadores el tipo, el valor se mueve, por lo que en este ejemplo, &lt;em&gt;v&lt;/em&gt;
no se puede usar después de la llamada a la función, ya que el propietario
de la memoria pasa a la variable &lt;em&gt;a&lt;/em&gt; de la función, y luego al devolverse,
se pasa a la variable &lt;em&gt;v2&lt;/em&gt;. Si no devolviéramos nada en la función, el
vector se liberaría al finalizar la llamada a la función.&lt;/p&gt;
&lt;p&gt;El compilador da bastante información en caso de que intentáramos usar &lt;em&gt;v&lt;/em&gt;
después de la llamada a la función:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;error&lt;span class="o"&gt;[&lt;/span&gt;E0382&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;use&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;moved&lt;span class="w"&gt; &lt;/span&gt;value:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;v&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;--&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;src/main.rs:9:27
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="nb"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;add_element&lt;span class="o"&gt;(&lt;/span&gt;v&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;value&lt;span class="w"&gt; &lt;/span&gt;moved&lt;span class="w"&gt; &lt;/span&gt;here
&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;println!&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;{:?} {:?}&amp;quot;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;v,&lt;span class="w"&gt; &lt;/span&gt;v2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;^&lt;span class="w"&gt; &lt;/span&gt;value&lt;span class="w"&gt; &lt;/span&gt;used&lt;span class="w"&gt; &lt;/span&gt;here&lt;span class="w"&gt; &lt;/span&gt;after&lt;span class="w"&gt; &lt;/span&gt;move
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;note:&lt;span class="w"&gt; &lt;/span&gt;move&lt;span class="w"&gt; &lt;/span&gt;occurs&lt;span class="w"&gt; &lt;/span&gt;because&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;v&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;std::vec::Vec&amp;lt;i32&amp;gt;&lt;span class="sb"&gt;`&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;which&lt;span class="w"&gt; &lt;/span&gt;does&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;implement&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;Copy&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;trait
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para poder seguir usando &lt;em&gt;v&lt;/em&gt; lo suyo es pasar el argumento como una
referencia, para hacer un &lt;em&gt;borrow&lt;/em&gt; en lugar de un &lt;em&gt;move&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;add_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;add_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí se pasa una referencia &lt;em&gt;&amp;amp;&lt;/em&gt; editable &lt;em&gt;mut&lt;/em&gt;, por lo que se hace un
&lt;em&gt;borrow&lt;/em&gt; de la memoria, durante la llamada, y por tanto, al terminar la
llamada, se puede volver a usar &lt;em&gt;v&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Devolución&lt;/h2&gt;
&lt;p&gt;El tipo de la devolución de una función, como he explicado antes, se define
con "&lt;em&gt;-&amp;gt;&lt;/em&gt;" y a diferencia de los argumentos, no es necesario especificar
un identificador, sólo el tipo.&lt;/p&gt;
&lt;p&gt;En una función en Rust, la última línea, si no termina en "&lt;em&gt;;&lt;/em&gt;" es lo que
se devuelve, aunque también se puede hacer un &lt;em&gt;return&lt;/em&gt; explícito, para
que quede más claro o para los &lt;em&gt;early returns&lt;/em&gt;, por ejemplo, estas dos
definiciones son similares:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;f1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;f2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En Rust sólo es posible devolver un elemento, aunque se puede simular la
devolución múltiple devolviendo una tupla y haciendo la asignación con
&lt;em&gt;patter matching&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;dos_ultimos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dos_ultimos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{} {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El tipo de devolución, al igual que los argumentos, se &lt;em&gt;mueven&lt;/em&gt; por
defecto, pero se puede devolver una referencia, &lt;em&gt;&amp;amp;&lt;/em&gt;, o una referencia
mutable &lt;em&gt;&amp;amp;mut&lt;/em&gt;, para que sea un &lt;em&gt;borrow&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;addel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Tipos genéricos y &lt;em&gt;traits&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Las funciones también pueden recibir tipos genéricos, para poder definir
funciones que valgan para diferentes tipos:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fn_generica&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// definición&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_generica&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En esta función de ejemplo se definen dos tipos genéricos, &lt;em&gt;T&lt;/em&gt; y &lt;em&gt;K&lt;/em&gt;, y se
ve el uso en los argumentos, &lt;em&gt;x&lt;/em&gt; e &lt;em&gt;y&lt;/em&gt; son de tipo &lt;em&gt;T&lt;/em&gt; y &lt;em&gt;z&lt;/em&gt; y el valor de
retorno son de tipo &lt;em&gt;K&lt;/em&gt;. Esta función acepta cualquier tipo para &lt;em&gt;T&lt;/em&gt; y &lt;em&gt;K&lt;/em&gt;,
en el ejemplo se hace la llamada con &lt;em&gt;T = i32&lt;/em&gt; y &lt;em&gt;K = Vec&amp;lt;i32&amp;gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Así tal cual, no se puede hacer gran cosa con sólo tipos completamente
genéricos, se pueden crear estructuras con estos tipos y poco más, porque
al ser completamente genéricos no se puede acceder a ningún atributo o
método de estos tipos.&lt;/p&gt;
&lt;p&gt;Para un uso más específico se pueden usar los &lt;em&gt;traits&lt;/em&gt;, de forma similar a
los tipos genéricos, para poder definir funciones genéricas que hagan uso
de esas interfaces:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mayor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ord&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Less&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mayor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;También existe una sintaxis más clara, para cuando hay muchos tipos
genéricos, no tener que especificar todos los tipos entre el nombre de la
función y la lista de argumentos, sólo los nombres de los tipos. Para esto
se usa la palabra clave &lt;em&gt;where&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mayor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// cuerpo de la función&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En esta cabecera de ejemplo se definen cuatro tipos genéricos, el primero
tiene que implementar &lt;em&gt;Ord&lt;/em&gt;, el segundo &lt;em&gt;Iterator&lt;/em&gt;, el tercero &lt;em&gt;Clone&lt;/em&gt; y
&lt;em&gt;Debug&lt;/em&gt; y el cuarto &lt;em&gt;Default&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Lifetimes&lt;/h2&gt;
&lt;p&gt;Además de los tipos genéricos, dentro del mayor/menor, &lt;em&gt;&amp;lt;&amp;gt;&lt;/em&gt;, puede ir
información relativa a los tiempos de vida. El ejemplo típico es una
función que recibe dos referencias y devuelve una referencia, todo del
mismo tipo, el compilador no tiene información suficiente para saber con
qué variable se relaciona la referencia devuelta, por lo que hay que anotar
la función, el mismo compilador te dirá cuando no sea capaz de inferir los
lifetimes:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;skip_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim_left_matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skip_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ho&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;error&lt;span class="o"&gt;[&lt;/span&gt;E0106&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;missing&lt;span class="w"&gt; &lt;/span&gt;lifetime&lt;span class="w"&gt; &lt;/span&gt;specifier
&lt;span class="w"&gt; &lt;/span&gt;--&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;src/main.rs:2:41
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;fn&lt;span class="w"&gt; &lt;/span&gt;skip_prefix&lt;span class="o"&gt;(&lt;/span&gt;x:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;str,&lt;span class="w"&gt; &lt;/span&gt;y:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;str&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;str&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                                         &lt;/span&gt;^&lt;span class="w"&gt; &lt;/span&gt;expected&lt;span class="w"&gt; &lt;/span&gt;lifetime&lt;span class="w"&gt; &lt;/span&gt;parameter
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;help:&lt;span class="w"&gt; &lt;/span&gt;this&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;contains&lt;span class="w"&gt; &lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;borrowed&lt;span class="w"&gt; &lt;/span&gt;value,&lt;span class="w"&gt; &lt;/span&gt;but&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;signature&lt;span class="w"&gt; &lt;/span&gt;does&lt;span class="w"&gt; &lt;/span&gt;not&lt;span class="w"&gt; &lt;/span&gt;say&lt;span class="w"&gt; &lt;/span&gt;whether&lt;span class="w"&gt; &lt;/span&gt;it&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;borrowed&lt;span class="w"&gt; &lt;/span&gt;from&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;x&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;or&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;y&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Así que es necesario añadir el lifetime:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;skip_prefix&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim_left_matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skip_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ho&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Los lifetimes se definen con letras en minúsculas y con un apóstrofe, en
este ejemplo se define el lifetime &lt;em&gt;'a&lt;/em&gt;, pero se pueden definir tantos
lifetimes como sean necesarios. En este caso, como devolvemos una subcadena
de &lt;em&gt;x&lt;/em&gt;, pues tiene que coincidir el &lt;em&gt;lifetime&lt;/em&gt; de estos dos, si intentamos
definir el lifetime con &lt;em&gt;y&lt;/em&gt; en lugar de con &lt;em&gt;x&lt;/em&gt;, el compilador se nos
quejará:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;skip_prefix&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim_left_matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;error&lt;span class="o"&gt;[&lt;/span&gt;E0495&lt;span class="o"&gt;]&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;cannot&lt;span class="w"&gt; &lt;/span&gt;infer&lt;span class="w"&gt; &lt;/span&gt;an&lt;span class="w"&gt; &lt;/span&gt;appropriate&lt;span class="w"&gt; &lt;/span&gt;lifetime&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;autoref&lt;span class="w"&gt; &lt;/span&gt;due&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;conflicting&lt;span class="w"&gt; &lt;/span&gt;requirements
&lt;span class="w"&gt; &lt;/span&gt;--&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;src/main.rs:3:18
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;x.trim_left_matches&lt;span class="o"&gt;(&lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;^^^^^^^^^^^^^^^^^
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
help:&lt;span class="w"&gt; &lt;/span&gt;consider&lt;span class="w"&gt; &lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;an&lt;span class="w"&gt; &lt;/span&gt;explicit&lt;span class="w"&gt; &lt;/span&gt;lifetime&lt;span class="w"&gt; &lt;/span&gt;parameter&lt;span class="w"&gt; &lt;/span&gt;as&lt;span class="w"&gt; &lt;/span&gt;shown:&lt;span class="w"&gt; &lt;/span&gt;fn&lt;span class="w"&gt; &lt;/span&gt;skip_prefix&amp;lt;&lt;span class="s1"&gt;&amp;#39;a&amp;gt;(x: &amp;amp;&amp;#39;&lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;str,&lt;span class="w"&gt; &lt;/span&gt;y:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a str) -&amp;gt; &amp;amp;&amp;#39;&lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;str
&lt;span class="w"&gt; &lt;/span&gt;--&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;src/main.rs:2:5
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;fn&lt;span class="w"&gt; &lt;/span&gt;skip_prefix&amp;lt;&lt;span class="s1"&gt;&amp;#39;a&amp;gt;(x: &amp;amp;str, y: &amp;amp;&amp;#39;&lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;str&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;a&lt;span class="w"&gt; &lt;/span&gt;str&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;_____^&lt;span class="w"&gt; &lt;/span&gt;starting&lt;span class="w"&gt; &lt;/span&gt;here...
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;x.trim_left_matches&lt;span class="o"&gt;(&lt;/span&gt;y&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;_____^&lt;span class="w"&gt; &lt;/span&gt;...ending&lt;span class="w"&gt; &lt;/span&gt;here
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como se puede ver en el mensaje de error, el compilador es bastante
inteligente en este caso y nos da incluso una definición que sería válida
para nuestro caso.&lt;/p&gt;
&lt;h1&gt;&lt;a href="https://doc.rust-lang.org/book/closures.html"&gt;Closures&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Se pueden definir funciones que reciban una función como parámetro, estas
funciones se llaman &lt;em&gt;closures&lt;/em&gt; y se definen de forma similar a los tipos
genéricos y los &lt;em&gt;traits&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo hay dos cosas claves que no he explicado hasta ahora, el
primero es el tipo &lt;em&gt;F&lt;/em&gt;, que se define como &lt;em&gt;Fn(T) -&amp;gt; K&lt;/em&gt;, con esta sintaxis
definimos que &lt;em&gt;F&lt;/em&gt; tiene que ser una función o &lt;em&gt;closure&lt;/em&gt; que reciba un
parámetro de tipo &lt;em&gt;T&lt;/em&gt; y devuelva un tipo &lt;em&gt;K&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La segunda sintaxis extraña está dentro de la llamada a &lt;em&gt;apply&lt;/em&gt;, como
primer argumento debe recibir la función de tipo &lt;em&gt;F&lt;/em&gt; y le pasamos &lt;em&gt;|x: i32|
x + 1&lt;/em&gt;, que en realidad es esa definición.&lt;/p&gt;
&lt;p&gt;Un &lt;em&gt;closure&lt;/em&gt; se define con las barras verticales, para definir los
argumentos y sus tipos, y después se define el cuerpo de la función,
pudiendo obviar los corchetes cuando es una definición muy simple, como en
el ejemplo.&lt;/p&gt;
&lt;p&gt;También se puede asignar un &lt;em&gt;closure&lt;/em&gt; a una variable para luego pasarlo en
la llamada:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este caso, es lo mismo que definir la función de forma normal y luego
pasarla por parámetro:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Por lo que asignar &lt;em&gt;closures&lt;/em&gt; a variables tiene poco sentido, en realidad
son útiles cuando se definen directamente en la llamada, para no tener que
definir una función con nombre para algo que sólo se llamará una vez.&lt;/p&gt;
&lt;h2&gt;Move en closures&lt;/h2&gt;
&lt;p&gt;Cuando se define un &lt;em&gt;closure&lt;/em&gt; se pueden usar variables que estén en el
ámbito, y por defecto se cogen como &lt;em&gt;borrow&lt;/em&gt;, por lo que el &lt;em&gt;closure&lt;/em&gt;
estará ligado a las variables que use.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;plus_num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Este código, sacado de la doc de Rust, no compila, porque se intenta hacer
una referencia mutable en la asignación de &lt;em&gt;y&lt;/em&gt;, cuando ya existe una
referencia a &lt;em&gt;num&lt;/em&gt; dentro del &lt;em&gt;closure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para evitar este problema se usa el &lt;em&gt;move&lt;/em&gt;, que funciona igual que el paso
de argumentos sin modificadores, es decir, para los tipos que implementen
el &lt;em&gt;trait&lt;/em&gt; copy se copiará el valor, para los demás, se hará &lt;em&gt;move&lt;/em&gt; de la
propiedad de la memoria.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;plus_num&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Un caso típico de &lt;em&gt;move&lt;/em&gt; en &lt;em&gt;closure&lt;/em&gt; es cuando se lanza un hilo:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JoinHandle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hilo {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se lanzan 9 hilos, la variable &lt;em&gt;i&lt;/em&gt; se usa dentro del
&lt;em&gt;closure&lt;/em&gt;, que al definirse con &lt;em&gt;move&lt;/em&gt; será una copia, ya que es un &lt;em&gt;i32&lt;/em&gt; y
este tipo implementa &lt;em&gt;Copy&lt;/em&gt;, si no se pone el &lt;em&gt;move&lt;/em&gt;, el compilador se
quejará, ya que la variable &lt;em&gt;i&lt;/em&gt; sólo existe en el scope del bucle, y el
otro hilo puede existir más allá del bucle.&lt;/p&gt;
&lt;h2&gt;Devolución de closures&lt;/h2&gt;
&lt;p&gt;También se pueden &lt;a href="https://doc.rust-lang.org/book/closures.html#returning-closures"&gt;devolver closures&lt;/a&gt;, pero no es algo trivial, hay que
encapsularlas en un &lt;em&gt;Box&lt;/em&gt; para que se pueda devolver y para evitar los
problemas con la gestión de la memoria de Rust.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 25 Feb 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-02-25:/rust-funcs.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Rust: Structs y Traits</title><link>https://danigm.net/rust-traits.html</link><description>&lt;p&gt;Rust ofrece por defecto los tipos de datos básicos que ofrece cualquier
lenguaje de programación, pero al igual que en otros lenguajes, se pueden
definir tipos propios más complejos con &lt;em&gt;struct&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Rust no es un lenguaje orientado a objetos, y en su documentación no se
encuentra nada sobre clases, objetos, instancias, etc. Sin embargo, hay
conceptos similares cuando nos adentramos en la definición de nuevos tipos
con &lt;em&gt;struct&lt;/em&gt; y también con los &lt;em&gt;traits&lt;/em&gt;, donde sí tenemos cosas como la
herencia.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/structs.html"&gt;Structs&lt;/a&gt;, "Estructuras" y tipos de datos complejos&lt;/h2&gt;
&lt;p&gt;Los tipos de datos propios en Rust se definen con la palabra clave
&lt;em&gt;struct&lt;/em&gt;. Para quien venga de C/C++ todo este código le será familiar.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Punto: ({}, {})&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Astruct%20Point%20%7B%0A%20%20%20%20x%3A%20i32%2C%0A%20%20%20%20y%3A%20i32%2C%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20p%20%3D%20Point%7Bx%3A%200%2C%20y%3A%200%7D%3B%0A%20%20%20%20println!(%22Punto%3A%20(%7B%7D%2C%20%7B%7D)%22%2C%20p.x%2C%20p.y)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;También existen estructuras de tipo tupla, &lt;em&gt;Tuple Structs&lt;/em&gt;, que no son más
que estructuras donde los atributos van sin nombre, por índice.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Punto: ({}, {})&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Astruct%20Point(i32%2C%20i32)%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20p%20%3D%20Point(0%2C%200)%3B%0A%20%20%20%20println!(%22Punto%3A%20(%7B%7D%2C%20%7B%7D)%22%2C%20p.0%2C%20p.1)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Los atributos de las estructuras son privados por defecto, esto quiere
decir que no son accesibles cuando se usan desde un módulo diferente al de
su definición, en el módulo de su definición, todos los atributos son
accesibles. Para hacer un atributo accesible a todo el mundo tan sólo hay
que añadir la palabra clave &lt;em&gt;pub&lt;/em&gt; delante, en la definición.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Métodos&lt;/h3&gt;
&lt;p&gt;Además de los atributos normales de las estructuras, también se pueden
definir métodos que &lt;em&gt;implementa&lt;/em&gt; esta estructura. Esto es muy similar a los
métodos de la programación orientada a objetos, y en realidad serán
llamados de forma similar, con el "&lt;em&gt;.&lt;/em&gt;".&lt;/p&gt;
&lt;p&gt;Para implementar métodos para una estructura se utiliza la palabra clave
&lt;em&gt;impl&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;moveup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;moveup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;distancia: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Astruct%20Point%20%7B%0A%20%20%20%20x%3A%20i32%2C%0A%20%20%20%20y%3A%20i32%2C%0A%7D%0A%0Aimpl%20Point%20%7B%0A%20%20%20%20fn%20new()%20-%3E%20Point%20%7B%0A%20%20%20%20%20%20%20%20Point%7Bx%3A%200%2C%20y%3A%200%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20fn%20distance(%26self%2C%20p%3A%20%26Point)%20-%3E%20f32%20%7B%0A%20%20%20%20%20%20%20%20let%20d1%20%3D%20(self.x%20-%20p.x).pow(2)%3B%0A%20%20%20%20%20%20%20%20let%20d2%20%3D%20(self.y%20-%20p.y).pow(2)%3B%0A%0A%20%20%20%20%20%20%20%20f32%3A%3Asqrt((d1%20%2B%20d2)%20as%20f32)%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20Point%20%7B%0A%20%20%20%20fn%20moveup(%26mut%20self)%20%7B%0A%20%20%20%20%20%20%20%20self.y%20%2B%3D%201%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20p1%20%3D%20Point%3A%3Anew()%3B%0A%20%20%20%20p1.moveup()%3B%0A%0A%20%20%20%20let%20p2%20%3D%20Point%7Bx%3A%2024%2C%20y%3A%20-30%7D%3B%0A%0A%20%20%20%20println!(%22distancia%3A%20%7B%7D%22%2C%20p2.distance(%26p1))%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo hay varias cosas interesantes. Lo primero es el método
&lt;em&gt;new&lt;/em&gt;, que es un método estático, osea, no se llama desde una estructura
instanciada, sino con el nombre de la estructura y el operador &lt;em&gt;::&lt;/em&gt;. En
este caso se usa como un constructor.&lt;/p&gt;
&lt;p&gt;Luego se implementa el método para calcular la distancia, que recibe un
primer parámetro sin tipo, pero llamado &lt;em&gt;self&lt;/em&gt;, este parámetro es la
estructura en sí, y como en python es explícito, hay que ponerlo en la
lista de argumentos. En este caso se define como una referencia, pero al
igual que todas las definiciones de variables en Rust dependerá del uso que
queramos darle, si vamos a modificar debería ser un &lt;em&gt;&amp;amp;mut self&lt;/em&gt; o si queremos
que vaya por &lt;em&gt;copia/movimiento&lt;/em&gt; un simple &lt;em&gt;self&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La otra cosa interesante de este ejemplo es que hay dos declaraciones de
&lt;em&gt;impl&lt;/em&gt; para la estructura &lt;em&gt;Point&lt;/em&gt;, y en realidad puede haber cuantas se
quiera, incluso se pueden añadir métodos a estructuras desde módulos
diferentes, pero no desde &lt;em&gt;crates&lt;/em&gt; diferentes.&lt;/p&gt;
&lt;p&gt;Con esto casi podríamos decir que tenemos lo mismo que en otros lenguajes
orientados a objetos, pero no tenemos herencia, polimorfismo ni nada de
eso, para ello existen los &lt;em&gt;Traits&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/traits.html"&gt;Traits&lt;/a&gt;, "Rasgos" de tipos&lt;/h2&gt;
&lt;p&gt;Los &lt;em&gt;traits&lt;/em&gt; no son más que una lista de métodos con o sin implementación
que las estructuras o los tipos deben implementar para cumplir ese &lt;em&gt;trait&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Se definen con la palabra clave &lt;em&gt;trait&lt;/em&gt; y una lista de funciones que
definen la &lt;em&gt;interfaz&lt;/em&gt; y luego se implementa con la construcción &lt;strong&gt;impl&lt;/strong&gt; TRAIT &lt;strong&gt;for&lt;/strong&gt; TYPE.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;distancia: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Astruct%20Point%20%7B%0A%20%20%20%20x%3A%20i32%2C%0A%20%20%20%20y%3A%20i32%2C%0A%7D%0A%0Atrait%20Distance%20%7B%0A%20%20%20%20fn%20distance(%26self%2C%20p%3A%20%26Point)%20-%3E%20f32%3B%0A%7D%0A%0Aimpl%20Distance%20for%20Point%20%7B%0A%20%20%20%20fn%20distance(%26self%2C%20p%3A%20%26Point)%20-%3E%20f32%20%7B%0A%20%20%20%20%20%20%20%20let%20d1%20%3D%20(self.x%20-%20p.x).pow(2)%3B%0A%20%20%20%20%20%20%20%20let%20d2%20%3D%20(self.y%20-%20p.y).pow(2)%3B%0A%0A%20%20%20%20%20%20%20%20f32%3A%3Asqrt((d1%20%2B%20d2)%20as%20f32)%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20p1%20%3D%20Point%7Bx%3A%200%2C%20y%3A%200%7D%3B%0A%20%20%20%20let%20p2%20%3D%20Point%7Bx%3A%2024%2C%20y%3A%20-30%7D%3B%0A%0A%20%20%20%20println!(%22distancia%3A%20%7B%7D%22%2C%20p2.distance(%26p1))%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Los &lt;em&gt;traits&lt;/em&gt; se pueden usar en las definiciones de las funciones o de las
estructuras, en lugar de los tipos, para implementar funciones o tipos
&lt;em&gt;genéricos&lt;/em&gt;, con la sintaxis de tipo genérico &lt;strong&gt;&amp;lt;T: TRAIT&amp;gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;También se pueden definir implementaciones por defecto en los métodos de
los &lt;em&gt;traits&lt;/em&gt;, por lo que no es obligatorio ofrecer una implementación para
esos métodos, si se ofrece una implementación estaremos sobreescribiendo
ese método, si no se utilizará la implementación por defecto.&lt;/p&gt;
&lt;p&gt;Por ejemplo, podemos definir un &lt;em&gt;trait&lt;/em&gt; para tipos que tengan posición en
un plano 2D, &lt;strong&gt;HasPosition&lt;/strong&gt;, y podemos definir la distancia del &lt;em&gt;trait&lt;/em&gt;
&lt;strong&gt;Distance&lt;/strong&gt; como un método que recibe un tipo que tiene posición como
segundo argumento.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Circle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HasPosition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;gety&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getx&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gety&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HasPosition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;gety&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HasPosition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;gety&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;distancia: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Astruct%20Point%20%7B%0A%20%20%20%20x%3A%20i32%2C%0A%20%20%20%20y%3A%20i32%2C%0A%7D%0A%0Astruct%20Circle%20%7B%0A%20%20%20%20x%3A%20i32%2C%0A%20%20%20%20y%3A%20i32%2C%0A%20%20%20%20r%3A%20i32%2C%0A%7D%0A%0Atrait%20HasPosition%20%7B%0A%20%20%20%20fn%20getx(%26self)%20-%3E%20i32%3B%0A%20%20%20%20fn%20gety(%26self)%20-%3E%20i32%3B%0A%0A%20%20%20%20fn%20pos(%26self)%20-%3E%20Point%20%7B%0A%20%20%20%20%20%20%20%20Point%20%7B%20x%3A%20self.getx()%2C%20y%3A%20self.gety()%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0Aimpl%20HasPosition%20for%20Circle%20%7B%0A%20%20%20%20fn%20getx(%26self)%20-%3E%20i32%20%7B%20self.x%20%7D%0A%20%20%20%20fn%20gety(%26self)%20-%3E%20i32%20%7B%20self.y%20%7D%0A%7D%0A%0Aimpl%20HasPosition%20for%20Point%20%7B%0A%20%20%20%20fn%20getx(%26self)%20-%3E%20i32%20%7B%20self.x%20%7D%0A%20%20%20%20fn%20gety(%26self)%20-%3E%20i32%20%7B%20self.y%20%7D%0A%7D%0A%0Atrait%20Distance%20%7B%0A%20%20%20%20fn%20distance%3CT%3A%20HasPosition%3E(%26self%2C%20p%3A%20%26T)%20-%3E%20f32%3B%0A%7D%0A%0Aimpl%20Distance%20for%20Point%20%7B%0A%20%20%20%20fn%20distance%3CT%3A%20HasPosition%3E(%26self%2C%20p%3A%20%26T)%20-%3E%20f32%20%7B%0A%20%20%20%20%20%20%20%20let%20d1%20%3D%20(self.x%20-%20p.pos().x).pow(2)%3B%0A%20%20%20%20%20%20%20%20let%20d2%20%3D%20(self.y%20-%20p.pos().y).pow(2)%3B%0A%0A%20%20%20%20%20%20%20%20f32%3A%3Asqrt((d1%20%2B%20d2)%20as%20f32)%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20p1%20%3D%20Point%7Bx%3A%200%2C%20y%3A%200%7D%3B%0A%20%20%20%20let%20p2%20%3D%20Circle%7Bx%3A%2024%2C%20y%3A%20-30%2C%20r%3A%201%7D%3B%0A%0A%20%20%20%20println!(%22distancia%3A%20%7B%7D%22%2C%20p1.distance(%26p2))%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se definen dos estructuras, &lt;strong&gt;Point&lt;/strong&gt; y &lt;strong&gt;Circle&lt;/strong&gt; y dos
&lt;em&gt;traits&lt;/em&gt;, &lt;strong&gt;HasPosition&lt;/strong&gt; y &lt;strong&gt;Distance&lt;/strong&gt;, así podemos comparar distancias
no sólo entre puntos, sino que también entre puntos y círculos, ya que
estas dos estructuras implementan el &lt;em&gt;trait&lt;/em&gt; &lt;strong&gt;HasPosition&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Los métodos &lt;em&gt;getx&lt;/em&gt; y &lt;em&gt;gety&lt;/em&gt; se tienen que implementar obligatoriamente, ya
que no se ofrece una implementación por defecto, sin embargo, el método
&lt;em&gt;pos&lt;/em&gt; no se está sobreescribiendo en ninguna de las dos estructuras, y por
lo tanto se usa la implementación por defecto del &lt;em&gt;trait&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Combinación de &lt;em&gt;Traits&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;En ocasiones queremos que un tipo implemente varios &lt;em&gt;traits&lt;/em&gt; y esto se
puede definir utilizando el símbolo "&lt;strong&gt;+&lt;/strong&gt;":&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;K&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Implementación de la función&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En esta definición se puede ver cómo el tipo &lt;em&gt;K&lt;/em&gt; tiene que implementar tres
&lt;em&gt;traits&lt;/em&gt; mientras que el tipo &lt;em&gt;T&lt;/em&gt; sólo ha de implementar uno. Aquí también
introduzco el uso de &lt;em&gt;where&lt;/em&gt; para que la cabecera de la función quede más
clara.&lt;/p&gt;
&lt;h3&gt;Herencia&lt;/h3&gt;
&lt;p&gt;Como he comentado antes, &lt;em&gt;Rust&lt;/em&gt; no es un lenguaje orientado a objetos como
tal, los &lt;em&gt;structs&lt;/em&gt; y los &lt;em&gt;traits&lt;/em&gt; no son clases, aunque el código pueda ser
similar.&lt;/p&gt;
&lt;p&gt;Aún así, con los &lt;em&gt;traits&lt;/em&gt; se puede hacer algo similar a la herencia,
utilizando el operador "&lt;strong&gt;:&lt;/strong&gt;". Con esta definición se obliga a que si se
implementa un &lt;em&gt;trait&lt;/em&gt; también se tengan que implementar el resto de
&lt;em&gt;traits&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;HasPosition&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se define el &lt;em&gt;trait&lt;/em&gt; &lt;strong&gt;Distance&lt;/strong&gt;, que depende del &lt;em&gt;trait&lt;/em&gt;
&lt;strong&gt;HasPosition&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En la &lt;em&gt;herencia&lt;/em&gt; también se puede utilizar la combinación de &lt;em&gt;traits&lt;/em&gt; con
el operador "&lt;strong&gt;+&lt;/strong&gt;".&lt;/p&gt;
&lt;p&gt;Pero en realidad, no se puede considerar esto como herencia, ya que no hay
posibilidad de llamar al método &lt;em&gt;padre&lt;/em&gt;, por lo que no es posible encadenar
llamadas de métodos por defecto cuando una estructura implementa un
&lt;em&gt;trait&lt;/em&gt;. Si se sobreescribe un método de un &lt;em&gt;trait&lt;/em&gt; se tiene que escribir
todo el código, no es posible utilizar la implementación por defecto para
sobreescribir el método.&lt;/p&gt;
&lt;h2&gt;Conclusiones&lt;/h2&gt;
&lt;p&gt;Con las estructuras y los &lt;em&gt;traits&lt;/em&gt; se puede escribir código reutilizable,
definiendo funciones que reciban tipos &lt;em&gt;genéricos&lt;/em&gt; que implementen una
serie de interfaces (&lt;em&gt;traits&lt;/em&gt;) de tal forma que el mismo código sirva para
diferentes tipos.&lt;/p&gt;
&lt;p&gt;En &lt;em&gt;Rust&lt;/em&gt; todo el código de la librería estándar está fuertemente basado en
&lt;em&gt;traits&lt;/em&gt; y por lo tanto hay una serie de &lt;em&gt;traits&lt;/em&gt; que es necesario conocer,
porque sirven para implementar funcionamiento básico, como por ejemplo,
&lt;a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html"&gt;Iterator&lt;/a&gt;,
&lt;a href="https://doc.rust-lang.org/std/marker/trait.Copy.html"&gt;Copy&lt;/a&gt;,
&lt;a href="https://doc.rust-lang.org/std/clone/trait.Clone.html"&gt;Clone&lt;/a&gt;,
&lt;a href="https://doc.rust-lang.org/std/fmt/trait.Debug.html"&gt;Debug&lt;/a&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 19 Feb 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-02-19:/rust-traits.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Cargo: Dependencias, crates y módulos en Rust</title><link>https://danigm.net/cargo.html</link><description>&lt;h2&gt;Cargo&lt;/h2&gt;
&lt;p&gt;Rust viene con una herramienta por defecto para gestionar dependencias,
crear proyectos y realizar otras tareas comunes, esta herramienta se llama
&lt;em&gt;&lt;a href="http://doc.crates.io/guide.html"&gt;Cargo&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Esta herramienta ofrece algo similar a lo que sería &lt;em&gt;pip&lt;/em&gt; y &lt;em&gt;virtualenv&lt;/em&gt; en
python, pero además realiza otras tareas como los test y la generación de
documentación.&lt;/p&gt;
&lt;p&gt;Por lo tanto Cargo sirve para:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Crear nuevos proyectos Rust a partir de templates (&lt;strong&gt;new&lt;/strong&gt;, &lt;strong&gt;init&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Compilar el proyecto actual (&lt;strong&gt;run&lt;/strong&gt;, &lt;strong&gt;build&lt;/strong&gt;, &lt;strong&gt;install&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Gestionar dependencias del proyecto (&lt;strong&gt;search&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Publicar el proyecto en &lt;a href="http://crates.io"&gt;crates.io&lt;/a&gt; (&lt;strong&gt;publish&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Generar la documentación del proyecto (&lt;strong&gt;doc&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Ejecutar los tests (&lt;strong&gt;test&lt;/strong&gt;, &lt;strong&gt;bench&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Es una herramienta genial que engloba casi todas las utilidades para llevar
un proyecto de forma sencilla. Cuando empecé a trastear con Rust es una de
las cosas que más me gustó, porque te simplifica la vida a la hora de usar
el lenguaje y en &lt;em&gt;crates.io&lt;/em&gt; cada vez hay más módulos, lo que enriquece a
Rust, ya que puedes encontrar fácilmente bibliotecas para casi todo.&lt;/p&gt;
&lt;h3&gt;Creando un proyecto&lt;/h3&gt;
&lt;p&gt;Con Cargo se pueden crear por defecto dos tipos de proyectos, un ejecutable
o una biblioteca. La diferencia básica es el punto de entrada, por defecto
el fichero &lt;em&gt;src/main.rs&lt;/em&gt; es el punto de entrada, lo que se ejecuta, para los
proyectos ejecutables, y el fichero &lt;em&gt;src/lib.rs&lt;/em&gt; es el punto de entrada para
las bibliotecas.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;new&lt;span class="w"&gt; &lt;/span&gt;--bin&lt;span class="w"&gt; &lt;/span&gt;ejemplo
&lt;span class="w"&gt;     &lt;/span&gt;Created&lt;span class="w"&gt; &lt;/span&gt;binary&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;application&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ejemplo&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;project
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto nos crea un directorio &lt;em&gt;ejemplo&lt;/em&gt; con los ficheros básicos:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;tree&lt;span class="w"&gt; &lt;/span&gt;ejemplo
ejemplo/
├──&lt;span class="w"&gt; &lt;/span&gt;Cargo.toml
└──&lt;span class="w"&gt; &lt;/span&gt;src
&lt;span class="w"&gt;    &lt;/span&gt;└──&lt;span class="w"&gt; &lt;/span&gt;main.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El comando además de estos ficheros también nos crea, por defecto, un
repositorio git, por lo tanto existen los ficheros ocultos &lt;em&gt;.git&lt;/em&gt; y
&lt;em&gt;.gitignore&lt;/em&gt;. Este comportamiento se puede modificar con la configuración
&lt;em&gt;--vcs&lt;/em&gt;, que puede ser: &lt;strong&gt;git&lt;/strong&gt;, &lt;strong&gt;hg&lt;/strong&gt; o &lt;strong&gt;none&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-la&lt;span class="w"&gt; &lt;/span&gt;ejemplo/
total&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;
drwxr-xr-x.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;.
drwxr-xr-x.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;..
-rw-r--r--.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;Cargo.toml
drwxr-xr-x.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;180&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;.git
-rw-r--r--.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;.gitignore
drwxr-xr-x.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt; &lt;/span&gt;danigm&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;feb&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;08&lt;/span&gt;:59&lt;span class="w"&gt; &lt;/span&gt;src
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aparte del vcs, se crean dos ficheros, el fichero &lt;em&gt;Cargo.toml&lt;/em&gt;, que es el
fichero de configuración, y el fichero &lt;em&gt;src/main.rs&lt;/em&gt;, que es donde va el
código, el punto de entrada que se usará para generar el binario.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;ejemplo/Cargo.toml
&lt;span class="o"&gt;[&lt;/span&gt;package&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ejemplo&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0.1.0&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;authors&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Daniel García Moreno &amp;lt;danigm@wadobo.com&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;dependencies&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como vemos en el fichero de configuración por defecto van una serie de
variables básicas con el nombre, la versión y los autores, aunque hay
muchas más cosas que se pueden especificar &lt;a href="http://doc.crates.io/manifest.html"&gt;aquí&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;También está aquí el listado de dependencias, que por defecto está vacío,
pero que iremos rellenando según vayamos necesitando módulos externos y
&lt;em&gt;Cargo&lt;/em&gt; se encargará de descargar esas dependencias y compilarlas por
nosotros.&lt;/p&gt;
&lt;h3&gt;Primera ejecución&lt;/h3&gt;
&lt;p&gt;Una vez creado el proyecto, ejecutarlo es tan fácil como:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ejemplo
$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;run
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;ejemplo&lt;span class="w"&gt; &lt;/span&gt;v0.1.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;file:///tmp/cargo/ejemplo&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Finished&lt;span class="w"&gt; &lt;/span&gt;debug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;unoptimized&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;debuginfo&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.38&lt;span class="w"&gt; &lt;/span&gt;secs
&lt;span class="w"&gt;     &lt;/span&gt;Running&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;target/debug/ejemplo&lt;span class="sb"&gt;`&lt;/span&gt;
Hello,&lt;span class="w"&gt; &lt;/span&gt;world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esto compila el proyecto y lo ejecuta, si no ha cambiado, simplemente lo
ejecuta, no se pierde el tiempo compilando.&lt;/p&gt;
&lt;p&gt;Como se puede ver, lo que ejecuta es lo que hay dentro del fichero
&lt;em&gt;src/main.rs&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El comando &lt;em&gt;run&lt;/em&gt; compila en modo debug, esto quiere decir que no está
optimizado el ejecutable que se genera. Para generar un ejecutable final se
puede usar el comando:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;build&lt;span class="w"&gt; &lt;/span&gt;--release
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;ejemplo&lt;span class="w"&gt; &lt;/span&gt;v0.1.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;file:///tmp/cargo/ejemplo&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Finished&lt;span class="w"&gt; &lt;/span&gt;release&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;optimized&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.15&lt;span class="w"&gt; &lt;/span&gt;secs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Los binarios se generan en el directorio &lt;em&gt;target&lt;/em&gt;, en su correspondiente
carpeta según sean de &lt;em&gt;debug&lt;/em&gt; o &lt;em&gt;release&lt;/em&gt;, &lt;strong&gt;target/debug/ejemplo&lt;/strong&gt; y
&lt;strong&gt;target/release/ejemplo&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Usando dependencias externas&lt;/h2&gt;
&lt;p&gt;Como hemos visto antes, el listado de dependencias está vacío por defecto.
Vamos a añadir alguna:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# fichero Cargo.toml&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;[dependencies]&lt;/span&gt;
&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;regex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0.2&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Es muy fácil añadir dependencias, que se pueden buscar con el comando
&lt;em&gt;cargo search&lt;/em&gt; o directamente en la web &lt;a href="http://crates.io"&gt;crates.io&lt;/a&gt;, y además, cargo
soporta una &lt;a href="http://doc.crates.io/specifying-dependencies.html"&gt;sintaxis rica&lt;/a&gt; para especificar números de versión, además
de poder especificar otras fuentes para descargar las dependencias, por si
son privadas o no están en &lt;a href="http://crates.io"&gt;crates.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Si ejecutamos ahora &lt;em&gt;cargo build&lt;/em&gt;, se descargarán las dependencias y se
compilarán.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;cargo&lt;span class="w"&gt; &lt;/span&gt;build
&lt;span class="w"&gt;    &lt;/span&gt;Updating&lt;span class="w"&gt; &lt;/span&gt;registry&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;https://github.com/rust-lang/crates.io-index&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Downloading&lt;span class="w"&gt; &lt;/span&gt;aho-corasick&lt;span class="w"&gt; &lt;/span&gt;v0.6.2
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;libc&lt;span class="w"&gt; &lt;/span&gt;v0.2.20
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;utf8-ranges&lt;span class="w"&gt; &lt;/span&gt;v1.0.0
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;void&lt;span class="w"&gt; &lt;/span&gt;v1.0.2
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;regex-syntax&lt;span class="w"&gt; &lt;/span&gt;v0.4.0
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;unreachable&lt;span class="w"&gt; &lt;/span&gt;v0.1.1
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;memchr&lt;span class="w"&gt; &lt;/span&gt;v1.0.1
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;v0.1.36
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;thread-id&lt;span class="w"&gt; &lt;/span&gt;v3.0.0
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;thread_local&lt;span class="w"&gt; &lt;/span&gt;v0.3.2
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;aho-corasick&lt;span class="w"&gt; &lt;/span&gt;v0.6.2
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;regex&lt;span class="w"&gt; &lt;/span&gt;v0.2.1
&lt;span class="w"&gt;   &lt;/span&gt;Compiling&lt;span class="w"&gt; &lt;/span&gt;ejemplo&lt;span class="w"&gt; &lt;/span&gt;v0.1.0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;file:///tmp/cargo/ejemplo&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;Finished&lt;span class="w"&gt; &lt;/span&gt;debug&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;unoptimized&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="w"&gt; &lt;/span&gt;debuginfo&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;target&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;.35&lt;span class="w"&gt; &lt;/span&gt;secs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;El fichero &lt;em&gt;Cargo.lock&lt;/em&gt; contiene la información de todas las dependencias
descargadas y su versión, permitiendo así compilaciones exactamente
iguales.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/book/crates-and-modules.html"&gt;Crates&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hemos hablado de dependencias y &lt;em&gt;crates&lt;/em&gt; y hemos visto cómo &lt;em&gt;cargo&lt;/em&gt;
gestiona e instala las dependencias de forma sencilla.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Crate&lt;/em&gt; es como se llaman a las bibliotecas en &lt;em&gt;Rust&lt;/em&gt;. Traducido
literalmente significa &lt;em&gt;Cajón&lt;/em&gt;, y se podría decir que un &lt;em&gt;crate&lt;/em&gt; es un
proyecto Rust completo, un fichero &lt;em&gt;Cargo.toml&lt;/em&gt; que especifica su nombre,
versión, etc y una serie de ficheros en &lt;em&gt;src&lt;/em&gt; donde se definen los
diferentes &lt;em&gt;módulos&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Para usar un &lt;em&gt;crate&lt;/em&gt; en nuestro proyecto se usa &lt;em&gt;extern crate XXX&lt;/em&gt;, así
podemos usar las dependencias que hemos añadido anteriormente, sería algo
similar al &lt;em&gt;import&lt;/em&gt; de python o al &lt;em&gt;include&lt;/em&gt; de C o C++.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello, world! {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En el momento en el que declaramos el &lt;em&gt;extern crate time&lt;/em&gt; ya es posible
utilizar el módulo time.&lt;/p&gt;
&lt;p&gt;Además del uso de &lt;em&gt;extern crate&lt;/em&gt;, en Rust existe otra palabra clave para
&lt;em&gt;importar&lt;/em&gt; módulos o funciones externas en el ámbito local, algo similar a
lo que en python se hace con &lt;em&gt;from X import Y&lt;/em&gt;. En Rust la sintaxis
utilizada es &lt;em&gt;use&lt;/em&gt;, por ejemplo en nuestro caso podríamos tener:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hello, world! {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hemos usado aquí una sintaxis compacta, pero se puede definir uno por línea
o incluso todo a la vez:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;format_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Módulos&lt;/h2&gt;
&lt;p&gt;Como hemos visto, en Rust las bibliotecas se llaman &lt;em&gt;crates&lt;/em&gt; y en estas
bibliotecas puede haber diferentes agrupaciones que se llaman &lt;em&gt;modules&lt;/em&gt;, o
módulos en español. Así que tenemos un cajón que tiene uno o más módulos
dentro.&lt;/p&gt;
&lt;p&gt;El módulo por defecto se define en el fichero &lt;em&gt;src/lib.rs&lt;/em&gt;, donde se pueden
definir directamente funciones, estructuras, etc. o submódulos.&lt;/p&gt;
&lt;p&gt;Por defecto en Rust todo es privado, por lo que si queremos que desde fuera
de un módulo se pueda usar algo definido dentro, debemos usar la palabra
clave &lt;em&gt;pub&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Podemos definir un par de funciones en un nuevo fichero &lt;em&gt;src/lib.rs&lt;/em&gt;, para
usar después en &lt;em&gt;src/main.rs&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d/%m/%Y&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%H:%M&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En nuestro proyecto de ejemplo, tenemos el &lt;em&gt;crate&lt;/em&gt;, que es el proyecto en
sí, y el módulo por defecto, que es &lt;em&gt;src/lib.rs&lt;/em&gt;, donde hemos definido dos
funciones públicas, &lt;em&gt;fecha&lt;/em&gt; y &lt;em&gt;hora&lt;/em&gt;. Esto lo podemos utilizar en nuestro
ejecutable, exactamente igual que usamos una dependencia externa, con el
uso de &lt;em&gt;extern crate&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fecha: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hora: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Submódulos&lt;/h2&gt;
&lt;p&gt;En el ejemplo anterior hemos visto cómo se define el módulo por defecto de
un &lt;em&gt;crate&lt;/em&gt;, que no es más que el fichero &lt;em&gt;src/lib.rs&lt;/em&gt;. Pero en cualquier
proyecto que no sea un ejemplo habrá que definir más de un módulo, no puede
estar todo junto en el mismo.&lt;/p&gt;
&lt;p&gt;Para definir submódulos en Rust se puede usar &lt;strong&gt;mod&lt;/strong&gt;, que sirve
exactamente para definir submódulos:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// fichero src/lib.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;fecha&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ahora&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;hora&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ahora&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se definen dos módulos, &lt;em&gt;fecha&lt;/em&gt; y &lt;em&gt;hora&lt;/em&gt;. La única
diferencia con el caso anterior es que ahora podemos agrupar en módulos las
diferentes funciones que definamos. También hay que tener en cuenta que en
cada módulo en ámbito es diferente, de ahí la necesidad de hacer el
&lt;em&gt;extern crate time&lt;/em&gt; en los dos módulos, aunque estén en el mismo fichero.&lt;/p&gt;
&lt;p&gt;El uso en el &lt;em&gt;main.rs&lt;/em&gt; sería similar:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fecha: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ahora&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hora: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ahora&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Módulos en ficheros separados&lt;/h3&gt;
&lt;p&gt;Pero este uso tiene poca utilidad real, normalmente los módulos han de ir
en ficheros separados o incluso en carpetas, creando una jerarquía de
ficheros que simboliza exactamente la jerarquía de los módulos.&lt;/p&gt;
&lt;p&gt;En nuestro ejemplo, podemos crear un nuevo fichero con el contenido del
módulo &lt;em&gt;fecha&lt;/em&gt;, un fichero llamado &lt;em&gt;src/fecha.rs&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// fecha.rs&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ahora&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Se puede observar que ya no es necesario el uso de &lt;em&gt;mod&lt;/em&gt;, puesto que al
estar en un fichero separado, es implícito.&lt;/p&gt;
&lt;p&gt;Y en el fichero módulo por defecto sólo tendremos que declarar este módulo
como público para que sea accesible desde &lt;em&gt;main.rs&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;De esta forma ya tenemos nuestros módulos en ficheros diferentes y son
accesibles desde fuera.&lt;/p&gt;
&lt;p&gt;Además de ficheros con el nombre del módulo, en Rust se pueden declarar
carpetas, y dentro de esa carpeta debe existir el fichero &lt;em&gt;mod.rs&lt;/em&gt;, sería
algo similar a los ficheros &lt;em&gt;&lt;strong&gt;init&lt;/strong&gt;.py&lt;/em&gt; en los módulos python.&lt;/p&gt;
&lt;p&gt;Podríamos tener una estructura de ficheros tal que así:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ejemplo/
├──&lt;span class="w"&gt; &lt;/span&gt;Cargo.toml
└──&lt;span class="w"&gt; &lt;/span&gt;src
&lt;span class="w"&gt;    &lt;/span&gt;├──&lt;span class="w"&gt; &lt;/span&gt;main.rs
&lt;span class="w"&gt;    &lt;/span&gt;├──&lt;span class="w"&gt; &lt;/span&gt;lib.rs
&lt;span class="w"&gt;    &lt;/span&gt;├──&lt;span class="w"&gt; &lt;/span&gt;fecha.rs
&lt;span class="w"&gt;    &lt;/span&gt;└──&lt;span class="w"&gt; &lt;/span&gt;hora
&lt;span class="w"&gt;        &lt;/span&gt;├──&lt;span class="w"&gt; &lt;/span&gt;mod.rs
&lt;span class="w"&gt;        &lt;/span&gt;├──&lt;span class="w"&gt; &lt;/span&gt;local.rs
&lt;span class="w"&gt;        &lt;/span&gt;└──&lt;span class="w"&gt; &lt;/span&gt;utc.rs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;main.rs&lt;/strong&gt; es el ejecutable, si estamos hablando de una biblioteca, no
   existiría este fichero.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;lib.rs&lt;/strong&gt; define el módulo principal, este fichero puede no existir si
   estamos hablando de un crate ejecutable, sin módulos propios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fecha.rs&lt;/strong&gt; un módulo más del proyecto, que para ser accesible debe
   debe estar declarado en el módulo por defecto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;hora&lt;/strong&gt; es una carpeta que contiene otro módulo, que al igual que
   &lt;em&gt;fecha.rs&lt;/em&gt; debe estar definido en &lt;em&gt;lib.rs&lt;/em&gt; para ser accesible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;mod.rs&lt;/strong&gt; definición del módulo &lt;em&gt;hora&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;local.rs y utc.rs&lt;/strong&gt; submódulos de hora, que deben estar definidos en
   &lt;em&gt;mod.rs&lt;/em&gt; para ser accesibles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Además del uso de módulos desde fuera, por ejemplo en el &lt;em&gt;main.rs&lt;/em&gt; o si lo
usamos como dependencia en otro proyecto, pueden existir módulos internos
en el proyecto, que no exportemos como públicos, y que sólo se usen de
manera interna. Por defecto las importaciones son relativas al módulo por
defecto:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; importación relativa al módulo actual&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; importación absoluta, llevaría a src/fecha.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; relativo al módulo actual, por ejemplo no funcionaría&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; si se usara esto dentro de *hora/mod.rs*, aunque sí&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; en otro módulo al nivel de fecha.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; con super se puede acceder al módulo padre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Con estas declaraciones podemos hacer uso de unos módulos en otros, variará
lo que tengamos que usar según nuestra estructura de ficheros.&lt;/p&gt;
&lt;p&gt;También se puede cambiar el nombre de un módulo en una declaración &lt;em&gt;use&lt;/em&gt;,
para evitar conflictos de nombres, con la palabra reservada &lt;em&gt;as&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ahora&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ejemplo&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ahora&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{} - {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fecha&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hora&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;La verdad es que el sistema de módulos de &lt;em&gt;Rust&lt;/em&gt; es muy parecido al de
python, podríamos decir que &lt;em&gt;self&lt;/em&gt; sería el &lt;em&gt;from . import&lt;/em&gt; de python y el
super podría ser &lt;em&gt;from .. import&lt;/em&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 11 Feb 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-02-11:/cargo.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category><category>cargo</category></item><item><title>Rust: Introducción a la gestión de memoria</title><link>https://danigm.net/rust-borrow.html</link><description>&lt;h2&gt;Gestión de memoria sin recolector de basura&lt;/h2&gt;
&lt;p&gt;Una de las características principales de Rust es la seguridad de la
memoria, que se comprueba en tiempo de compilación, sin recolector de
basura.&lt;/p&gt;
&lt;p&gt;En teoría, con &lt;strong&gt;Rust&lt;/strong&gt; no es &lt;em&gt;posible&lt;/em&gt; que ocurra un &lt;em&gt;segmentation fault&lt;/em&gt;,
porque no hay manera de que se acceda a una posición de memoria inválida y
además, tampoco es &lt;em&gt;posible&lt;/em&gt; que haya &lt;em&gt;memory leaks&lt;/em&gt;, y esto se verifica en
tiempo de compilación, por lo que no es necesario un recolector de basura y
por lo tanto, el rendimiento es similar al de lenguajes como &lt;strong&gt;C&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Esto se consigue en Rust con el concepto de &lt;strong&gt;propiedad&lt;/strong&gt; de la definición
de las variables.&lt;/p&gt;
&lt;h2&gt;Concepto de propiedad de la memoria (&lt;a href="https://doc.rust-lang.org/book/ownership.html"&gt;ownership&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;En &lt;strong&gt;Rust&lt;/strong&gt; cada declaración de variable asigna la propiedad de el valor a
esa variable, así cuando la variable sale del ámbito, la memoria se libera.&lt;/p&gt;
&lt;p&gt;Para garantizar la seguridad de la memoria sólo puede existir un
propietario de una zona de memoria, porque si no, el compilador no sabe
cuándo debe liberar esa memoria y podría existir en el tiempo una variable
apuntando a una zona de memoria inválida.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Por ejemplo, esta asignación crea un vector en memoria con tres elementos,
y asigna la propiedad de ese vector a la variable &lt;em&gt;v&lt;/em&gt;. Como está dentro de
la función &lt;em&gt;foo&lt;/em&gt;, esa variable existirá hasta el final de esa función, y
cuando se sale de la función, se elimina de la memoria el vector.&lt;/p&gt;
&lt;h3&gt;Mover, copiar y clonar (Copy, Clone)&lt;/h3&gt;
&lt;h4&gt;Mover&lt;/h4&gt;
&lt;p&gt;Como he comentado antes, Rust se asegura de que una zona de memoria sólo es
propiedad de una única variable, para poder asegurar en tiempo de
compilación que no se accede a memoria liberada.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;¿Qué ocurre entonces en este caso? Tenemos el vector cuyo propietario es &lt;em&gt;v&lt;/em&gt;,
pero declaramos otra variable, &lt;em&gt;v2&lt;/em&gt; a la que le asignamos el valor de &lt;em&gt;v&lt;/em&gt;,
por lo tanto, tendríamos dos variables apuntando a la misma zona de
memoria. Pero este caso lo resuelve &lt;em&gt;Rust&lt;/em&gt; con el &lt;strong&gt;movimiento&lt;/strong&gt; del valor,
osea, la propiedad pasa de &lt;em&gt;v&lt;/em&gt; a &lt;em&gt;v2&lt;/em&gt; en esta asignación, asegurando así
que sólo hay un propietario de ese valor, y por tanto, el vector se
eliminará cuando &lt;em&gt;v2&lt;/em&gt; salga del ámbito.&lt;/p&gt;
&lt;p&gt;Pero claro, esto podría crear inconsistencias, porque si &lt;em&gt;v2&lt;/em&gt; se elimina
antes que &lt;em&gt;v&lt;/em&gt;, hay un instante de tiempo en el que tenemos a alguien
apuntando a una zona no válida de memoria. Y esto lo resuelve el compilador
no dejándote acceder a &lt;em&gt;v&lt;/em&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v[0] is: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// error: use of moved value: `v`&lt;/span&gt;
&lt;span class="c1"&gt;// println!(&amp;quot;v[0] is: {}&amp;quot;, v[0]);&lt;/span&gt;
&lt;span class="c1"&gt;//                         ^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20vec!(1%2C%202%2C%203)%3B%0A%20%20%20%20let%20v2%20%3D%20v%3B%0A%20%20%20%20println!(%22v%5B0%5D%20is%3A%20%7B%7D%22%2C%20v%5B0%5D)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;No podemos acceder al vector usando &lt;em&gt;v&lt;/em&gt;, después de haber movido el valor,
porque ya no es el propietario. En este caso sólo podríamos acceder con &lt;em&gt;v2&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Esto también ocurre cuando se pasa la variable a una función:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// lo que ocurre aquí dentro no es relevante&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v[0] is: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Afn%20take(v%3A%20Vec%3Ci32%3E)%20%7B%0A%20%20%20%20%2F%2F%20Lo%20que%20pase%20aqu%C3%AD%20no%20es%20relevante%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20vec!(1%2C%202%2C%203)%3B%0A%20%20%20%20take(v)%3B%0A%20%20%20%20println!(%22v%5B0%5D%20is%3A%20%7B%7D%22%2C%20v%5B0%5D)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Esto nos dará el mismo error, en este caso, la propiedad pasa de la
variable &lt;em&gt;v&lt;/em&gt; declarada en el ámbito de &lt;em&gt;main&lt;/em&gt; al atributo &lt;em&gt;v&lt;/em&gt; declarado en
la función &lt;em&gt;take&lt;/em&gt;. Por lo tanto, el vector se eliminará después de la
llamada a &lt;em&gt;take&lt;/em&gt;, se ha movido el valor, así que si el compilador nos
dejara acceder a &lt;em&gt;v[0]&lt;/em&gt;, tendríamos acceso a memoria ya liberada, de ahí la
importancia de la propiedad en &lt;em&gt;Rust&lt;/em&gt;, nos asegura que la memoria se libera
y que no hay ninguna variable apuntando a donde no debe en ningún momento.&lt;/p&gt;
&lt;h4&gt;Copiar&lt;/h4&gt;
&lt;p&gt;Sin embargo, esto no ocurre con los tipos básicos, ya que en lugar de
&lt;em&gt;moverse&lt;/em&gt;, estos se &lt;em&gt;copian&lt;/em&gt;. Existe un &lt;em&gt;&lt;a href="https://doc.rust-lang.org/book/traits.html"&gt;trait&lt;/a&gt;&lt;/em&gt; llamado &lt;em&gt;Copy&lt;/em&gt;, que
implementan los tipos básicos y que hace que en lugar de mover los valores
en una asignación se haga una copia completa. Por lo tanto todo tipo que
implemente &lt;em&gt;Copy&lt;/em&gt; se copiará y por tanto nos permite asignar a diferentes
variables, porque realmente son zonas de memoria distintas e
independientes.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v: {}, v2: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// v: 2, v2: 4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Afn%20double(x%3A%20i32)%20-%3E%20i32%20%7B%0A%20%20%20%20x%20*%202%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%202%3B%0A%20%20%20%20let%20v2%20%3D%20double(v)%3B%0A%20%20%20%20println!(%22v%3A%20%7B%7D%2C%20v2%3A%20%7B%7D%22%2C%20v%2C%20v2)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este caso, podemos acceder al valor de &lt;em&gt;v&lt;/em&gt; en el &lt;em&gt;println&lt;/em&gt; porque el
tipo &lt;em&gt;i32&lt;/em&gt; implementa &lt;em&gt;Copy&lt;/em&gt;, por lo tanto en la llamada a &lt;em&gt;double&lt;/em&gt; se
copia el valor, no se mueve, &lt;em&gt;x&lt;/em&gt; existe sólo durante el ámbito de &lt;em&gt;double&lt;/em&gt;
y tiene el valor &lt;em&gt;2&lt;/em&gt; copiado de &lt;em&gt;v&lt;/em&gt;, ambas son accesibles en sus diferentes
ámbitos en independientes.&lt;/p&gt;
&lt;h4&gt;Clonar&lt;/h4&gt;
&lt;p&gt;Existe otra forma de copiar variables en Rust, en lugar de &lt;em&gt;copiar&lt;/em&gt; lo que
hacemos es &lt;em&gt;clonar&lt;/em&gt;. Es básicamente lo mismo salvo que el copiado es
implícito y el clonado es explícito. Además, en Rust no está permitido
reimplementar el copiado, siempre será una copia literal de memoria, sin
embargo, el clonado sí que se puede reimplementar y hacer un copiado más
ligero o ejecutar cualquier código para gestionar el tipo.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// lo que pase aquí es irrelevante&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v[0]: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// v[0]: 1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Afn%20take(v%3A%20Vec%3Ci32%3E)%20%7B%0A%20%20%20%20%2F%2F%20lo%20que%20pase%20aqu%C3%AD%20es%20irrelevante%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20vec!(1%2C%202%2C%203)%3B%0A%20%20%20%20take(v.clone())%3B%0A%20%20%20%20println!(%22v%5B0%5D%3A%20%7B%7D%22%2C%20v%5B0%5D)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Volviendo al ejemplo anterior, donde la llamada a una función movía el
vector y por tanto lo hacía inaccesible, podemos solucionarlo usando clone,
ya que el tipo &lt;em&gt;Vec&lt;/em&gt; implementa &lt;em&gt;&lt;a href="https://doc.rust-lang.org/std/clone/trait.Clone.html"&gt;Copy&lt;/a&gt;&lt;/em&gt;, así en la función &lt;em&gt;take&lt;/em&gt;
tenemos una copia del vector, son dos vectores diferentes.&lt;/p&gt;
&lt;h2&gt;Tomar prestado y referencias (&lt;a href="https://doc.rust-lang.org/book/references-and-borrowing.html"&gt;borrow&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;Con el copiado y el clonado, podemos hacer uso de las diferentes variables
en llamadas a métodos y demás, pero esto no es nada eficiente si tenemos
estructuras de datos grandes, ya que estamos copiando constantemente y no
nos permite modificar una variable dentro de una función, todo cambio
debería hacerse en valor de devolución, si queremos añadir un elemento a un
vector, tendríamos que copiar el vector, añadir el elemento y devolver el
nuevo vector, en lugar de añadirlo directamente.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;addone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;addone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Afn%20addone(mut%20w%3A%20Vec%3Ci32%3E%2C%20element%3A%20i32)%20-%3E%20Vec%3Ci32%3E%20%7B%0A%20%20%20%20w.push(element)%3B%0A%20%20%20%20w%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20vec!(1%2C%202%2C%203)%3B%0A%20%20%20%20let%20v2%20%3D%20addone(v.clone()%2C%204)%3B%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20v)%3B%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20v2)%3B%0A%7D%0A&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Para evitar copiar el vector, en &lt;em&gt;Rust&lt;/em&gt; existen las referencias "&lt;strong&gt;&amp;amp;&lt;/strong&gt;".
Cuando se crea una referencia a un valor, en lugar de mover o copiar ese
valor, tenemos realmente dos variables apuntando a la misma zona de
memoria. Sin embargo, hemos dicho que esto no es posible si queremos
mantener la seguridad de la memoria... Y para solucionar esto, el concepto
que añade &lt;em&gt;Rust&lt;/em&gt; es el de &lt;strong&gt;borrowing&lt;/strong&gt; o tomar prestado.&lt;/p&gt;
&lt;p&gt;Una zona de memoria sólo tiene un propietario, pero puede que alguna otra
variable quiera acceder a esa zona de memoria, por lo tanto la pide
prestada, "&lt;strong&gt;borrow&lt;/strong&gt;", y ya es como si en ese momento fuera el
propietario.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v[0]: {}, v2[0]: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este caso, tenemos que la variable &lt;em&gt;v2&lt;/em&gt; es una referencia a &lt;em&gt;v&lt;/em&gt; y por
tanto lo que hace es pedir prestado el vector, haciendo accesible tanto a
&lt;em&gt;v&lt;/em&gt; como &lt;em&gt;v2&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Estas referencias son inmutables, lo que no nos permite modificar la zona
de memoria, por lo tanto, podemos &lt;em&gt;Rust&lt;/em&gt; nos permite tener tantas
referencias inmutables como queramos a una zona de memoria, siempre y
cuando estas referencias no estén en un ámbito superior al propietario, es
decir, que no pueden existir las referencias más allá que el propietario,
ya que cuando el propietario salga del ámbito, la memoria se liberará.&lt;/p&gt;
&lt;p&gt;Para poder modificar los valores por referencia hay que hacer uso de las
referencias mutables "&lt;strong&gt;&amp;amp;mut&lt;/strong&gt;". A diferencia de las referencias
inmutables, sólo está permitido que exista una referencia mutable para un
valor determinado. Esto es así para evitar que una zona de memoria sea
modificada por dos variables a la vez.&lt;/p&gt;
&lt;p&gt;No sólo no es posible tener más de una referencia mutable a un valor, sino
que una vez que se hace una referencia mutable, no es posible hacer ninguna
referencia inmutable, es decir, que mientras que exista una referencia
mutable no puede existir ninguna otra referencia.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20main()%20%7B%0Alet%20mut%20x%20%3D%205%3B%0A%7B%0A%20%20%20%20let%20y%20%3D%20%26mut%20x%3B%0A%20%20%20%20*y%20%2B%3D%201%3B%0A%7D%0Aprintln!(%22%7B%7D%22%2C%20x)%3B%0A%7D"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se puede ver el uso de una referencia mutable. Para que el
compilador no se queje en la llamada a &lt;em&gt;prinlnt&lt;/em&gt;, hay que añadir las
llaves, que crean un ámbito nuevo. La variable &lt;em&gt;y&lt;/em&gt; sólo existe en ese
ámbito, por lo tanto, al salir nos permite llamar a &lt;em&gt;println&lt;/em&gt; con &lt;em&gt;x&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;El "*" se usa en este ejemplo para hacer una derreferencia explícita y
poder modificar realmente el valor que estamos referenciando y no la
referencia en sí, ya que y no es realmente del tipo &lt;em&gt;i32&lt;/em&gt;, sino que es del
tipo &lt;em&gt;&amp;amp;mut i32&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Con las referencias mutables podemos simplificar el ejemplo anterior de
añadir un elemento a un vector:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;addone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;addone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20addone(w%3A%20%26mut%20Vec%3Ci32%3E%2C%20element%3A%20i32)%20%7B%0A%20%20%20%20w.push(element)%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20mut%20v%20%3D%20vec!(1%2C%202%2C%203)%3B%0A%20%20%20%20addone(%26mut%20v%2C%204)%3B%0A%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20v)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este caso no es necesario añadir las llaves para crear un ámbito nuevo
para la referencia mutable, ya que ésta sólo existe en el ámbito de la
función &lt;em&gt;addone&lt;/em&gt;, por lo tanto, después de la llamada no existe ninguna
referencia a &lt;em&gt;v&lt;/em&gt; y por tanto esta es accesible de nuevo.&lt;/p&gt;
&lt;h2&gt;Tiempo de vida (&lt;a href="https://doc.rust-lang.org/book/lifetimes.html"&gt;lifetimes&lt;/a&gt;)&lt;/h2&gt;
&lt;p&gt;No voy a entrar en detalle con respecto a los tiempos de vida de las
variables, en este artículo introductorio, pero sí voy a comentar lo básico
para saber qué significa y cómo se usa.&lt;/p&gt;
&lt;p&gt;Cuando se hace una referencia, tenemos dos variables apuntando a una misma
zona de memoria, y como he comentado anteriormente, una referencia no puede
existir más allá que el propietario de la memoria.&lt;/p&gt;
&lt;p&gt;Normalmente el compilador es capaz de determinar la vida de las variables y
las referencias para asegurarse de que esta regla se cumple, pero hay
ocasiones en las que el compilador no es capaz de determinar si una
referencia dura más o menos, por lo que hay que especificarlo.&lt;/p&gt;
&lt;p&gt;Esto se da normalmente en definiciones de funciones que reciben varias
referencias y devuelven otra referencia. El compilador no sabe a cuál
parámetro de entrada está ligada esta referencia, por lo que hay que
especificarlo con una nueva sintaxis:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;skip_prefix&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;lang:en=Hello World!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;lang:{}=&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// -+ `p` comes into scope.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;skip_prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_str&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;//  |&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;                                       &lt;/span&gt;&lt;span class="c1"&gt;// -+ `p` goes out of scope.&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=fn%20main()%20%7B%0Afn%20skip_prefix%3C%27a%2C%20%27b%3E(line%3A%20%26%27a%20str%2C%20prefix%3A%20%26%27b%20str)%20-%3E%20%26%27a%20str%20%7B%0A%20%20%20%20%2F%2F%20...%0A%20%20line%0A%7D%0A%0Alet%20line%20%3D%20%22lang%3Aen%3DHello%20World!%22%3B%0Alet%20lang%20%3D%20%22en%22%3B%0A%0Alet%20v%3B%0A%7B%0A%20%20%20%20let%20p%20%3D%20format!(%22lang%3A%7B%7D%3D%22%2C%20lang)%3B%20%20%2F%2F%20-%2B%20%60p%60%20comes%20into%20scope.%0A%20%20%20%20v%20%3D%20skip_prefix(line%2C%20p.as_str())%3B%20%20%2F%2F%20%20%7C%0A%7D%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20-%2B%20%60p%60%20goes%20out%20of%20scope.%0Aprintln!(%22%7B%7D%22%2C%20v)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se definen dos tiempos de vida, en la declaración de
&lt;em&gt;skip_prefix&lt;/em&gt;, &lt;em&gt;a&lt;/em&gt; y &lt;em&gt;b&lt;/em&gt;. La primera referencia tiene el ámbito &lt;em&gt;a&lt;/em&gt; y la
segunda el ámbito &lt;em&gt;b&lt;/em&gt;, y se devuelve una referencia que tiene el ámbito
&lt;em&gt;a&lt;/em&gt;. Si no definimos los tiempos de vida, el compilador se quejará, porque
no sabría a qué refiere el valor de retorno.&lt;/p&gt;
&lt;p&gt;El tiempo de vida también puede ser necesario definirlo en estructuras que
tengan referencias. Normalmente no te tienes que preocupar de esto hasta
que el compilador no se queje, si no es capaz de inferir los tiempos de
vida te lo dirá y tendrás que especificarlo en el código.&lt;/p&gt;
&lt;h2&gt;Uso básico de referencias, Rc/RefCell y Arc/Mutex&lt;/h2&gt;
&lt;p&gt;Debido a las restricciones del uso de memoria de &lt;em&gt;Rust&lt;/em&gt; la gestión de
referencias, los tiempos de vida y demás nos pueden complicar un poco la
vida. Sin embargo existen unos tipos que nos permiten hacer uso de
&lt;em&gt;referencias&lt;/em&gt; de una forma mucho más simple y manteniendo la seguridad de
memoria que nos ofrece &lt;em&gt;Rust&lt;/em&gt; en tiempo de compilación, estoy hablando de
&lt;em&gt;Rc&lt;/em&gt; y &lt;em&gt;RefCell&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/std/cell/index.html"&gt;Cell y RefCell&lt;/a&gt;, tipos mutables a través de referencias&lt;/h2&gt;
&lt;p&gt;Como hemos visto antes, sólo puede haber una referencia mutable a un valor,
los tipos &lt;em&gt;Cell&lt;/em&gt; y &lt;em&gt;RefCell&lt;/em&gt; nos permiten modificar valores con una
referencia no mutable, por lo que podemos tener varias referencias a un
&lt;em&gt;Cell&lt;/em&gt; y en cualquier momento editar el contenido.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cell&lt;/em&gt; sólo es compatible con los tipos que soporta &lt;em&gt;Copy&lt;/em&gt;, en otro caso
hay que utilizar &lt;em&gt;RefCell&lt;/em&gt;. Con &lt;em&gt;Cell&lt;/em&gt; podemos modificar o acceder al
contenido llamando a los métodos &lt;em&gt;set&lt;/em&gt; y &lt;em&gt;get&lt;/em&gt;, con &lt;em&gt;RefCell&lt;/em&gt; tenemos que
hacer un &lt;em&gt;borrow_mut()&lt;/em&gt; para obtener una referencia mutable.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v: {}, v2: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// RefCell&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow_mut&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v4: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v3: {}, v5: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Ause%20std%3A%3Acell%3A%3ACell%3B%0Ause%20std%3A%3Acell%3A%3ARefCell%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%201%3B%0A%20%20%20%20let%20v2%20%3D%20Cell%3A%3Anew(v)%3B%0A%20%20%20%20v2.set(3)%3B%0A%20%20%20%20println!(%22v%3A%20%7B%7D%2C%20v2%3A%20%7B%7D%22%2C%20v%2C%20v2.get())%3B%0A%20%20%20%20%0A%20%20%20%20%2F%2F%20RefCell%0A%20%20%20%20let%20v3%20%3D%20RefCell%3A%3Anew(5)%3B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20let%20mut%20v4%20%3D%20v3.borrow_mut()%3B%0A%20%20%20%20%20%20%20%20*v4%20%3D%207%3B%0A%20%20%20%20%20%20%20%20println!(%22v4%3A%20%7B%7D%22%2C%20*v4)%3B%0A%20%20%20%20%7D%0A%20%20%20%20let%20v5%20%3D%20v3.borrow()%3B%0A%20%20%20%20println!(%22v3%3A%20%7B%7D%2C%20v5%3A%20%7B%7D%22%2C%20*v3.borrow()%2C%20*v5)%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lo realmente interesante de este ejemplo es el uso de &lt;em&gt;RefCell&lt;/em&gt;, ya que con
&lt;em&gt;Cell&lt;/em&gt; tenemos una copia, lo único extra que tenemos es que nos evitamos el
&lt;em&gt;mut&lt;/em&gt; en la declaración de &lt;em&gt;v2&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;En un &lt;em&gt;RefCell&lt;/em&gt; podemos hacer tantos &lt;em&gt;borrow&lt;/em&gt; como queramos, pero sólo
puede existir un &lt;em&gt;borrow_mut&lt;/em&gt; en el ámbito, ya que estamos en las mismas,
la función &lt;em&gt;borrow&lt;/em&gt; fallará si existe un &lt;em&gt;borrow_mut&lt;/em&gt;, de ahí las llaves de
este ejemplo, para añadir un nuevo ámbito para &lt;em&gt;v4&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Estos tipos no nos ofrecen nada extraordinario, porque este mismo código lo
podemos tener con referencias básicas con algo así:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v4: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v3: {}, v5: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Estos tipos son útiles en combinación con los tipos &lt;em&gt;Rc&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/std/rc/"&gt;Rc&lt;/a&gt;, punteros con contador de referencias&lt;/h2&gt;
&lt;p&gt;El tipo &lt;em&gt;Rc&amp;lt;T&amp;gt;&lt;/em&gt; nos ofrece una propiedad compartida del valor de tipo &lt;em&gt;T&lt;/em&gt;.
Podemos llamar la función &lt;em&gt;clone&lt;/em&gt; para crear una nueva referencia al mismo
valor en memoria. El propio tipo se encarga de decrementar el número de
referencias cuando salen del ámbito y de liberar la memoria cuando ya no
hay ninguna referencia.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Rc&lt;/em&gt; no permite editar los valores, ya que las referencias no son mutables.
Para poder editar los valores compartidos con un &lt;em&gt;Rc&lt;/em&gt;, se puede usar en
combinación con &lt;em&gt;RefCell&lt;/em&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Rc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RefCell&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow_mut&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v: {:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;borrow&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Ause%20std%3A%3Arc%3A%3ARc%3B%0Ause%20std%3A%3Acell%3A%3ARefCell%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20Rc%3A%3Anew(RefCell%3A%3Anew(vec!(1%2C%202%2C%203)))%3B%0A%20%20%20%20let%20v1%20%3D%20v.clone()%3B%0A%20%20%20%20v1.borrow_mut().push(4)%3B%0A%20%20%20%20println!(%22v%3A%20%7B%3A%3F%7D%22%2C%20v.borrow())%3B%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo se puede ver cómo tenemos una referencia compartida al
vector, que además es editable a través de &lt;em&gt;borrow_mut&lt;/em&gt;. En la declaración
de &lt;em&gt;v1&lt;/em&gt; se llama a &lt;em&gt;clone&lt;/em&gt;, pero realmente no se copia la memoria del
vector, la edición en la línea siguiente modifica el vector original.&lt;/p&gt;
&lt;p&gt;Como he comentado antes, no es posible tener más de un &lt;em&gt;borrow_mut&lt;/em&gt; en el
mismo ámbito, en este caso, como el &lt;em&gt;borrow_mut&lt;/em&gt; no se asigna a ninguna
variable, sólo existe en esa línea, por lo que el &lt;em&gt;borrow&lt;/em&gt; que hay en el
&lt;em&gt;print&lt;/em&gt; funcionará.&lt;/p&gt;
&lt;p&gt;Con el uso de &lt;em&gt;Rc&lt;/em&gt; se pueden crear ciclos, con tipos que se referencian a
sí mismos y para evitar estos ciclos existe otro tipo que es &lt;em&gt;Weak&lt;/em&gt;, que es
una referencia, pero que no cuenta a la hora de eliminar el valor de
memoria, por lo tanto pueden existir referencias tipo &lt;em&gt;Weak&lt;/em&gt; que apunten a
memoria ya liberada, y por esto el tipo &lt;em&gt;Weak&lt;/em&gt; no se derreferencia
automáticamente, hay que llamar al método &lt;em&gt;upgrade&lt;/em&gt; que devuelve un
&lt;em&gt;Option&amp;lt;Rc&amp;gt;&lt;/em&gt;, y si la memoria ya se ha liberado será &lt;em&gt;None&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a href="https://doc.rust-lang.org/std/sync/struct.Arc.html"&gt;Arc y Mutex&lt;/a&gt;, Rc y RefCell pero thread-safe&lt;/h2&gt;
&lt;p&gt;La combinación &lt;em&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/em&gt; nos permite tener varias referencias a la
misma zona de memoria, y modificarla, pero no es posible pasar estos tipos
entre hilos. &lt;em&gt;Rust&lt;/em&gt; ofrece un par de tipos similares, pero que sí son
&lt;em&gt;thread-safe&lt;/em&gt;, lo que quiere decir que nos asegura que no hay &lt;em&gt;data race&lt;/em&gt;,
es decir, que la memoria siempre es consistente, aunque usemos diferentes
hilos para leer y modificar estas variables.&lt;/p&gt;
&lt;p&gt;Para esto podemos usar la combinación &lt;em&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;/em&gt; que se usa de forma
similar a &lt;em&gt;Rc&amp;lt;RefCell&amp;gt;&lt;/em&gt;, pero que nos asegura que es seguro usar entre
diferentes hilos:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="fm"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;v[3]: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// -&amp;gt; 4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://play.rust-lang.org/?code=%23%5Ballow(unused_variables)%5D%0A%23%5Ballow(dead_code)%5D%0A%0Ause%20std%3A%3Async%3A%3A%7BArc%2C%20Mutex%7D%3B%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20v%20%3D%20Arc%3A%3Anew(Mutex%3A%3Anew(vec!(1%2C2%2C3)))%3B%0A%20%20%20%20let%20v1%20%3D%20v.clone()%3B%0A%20%20%20%20v1.lock().unwrap().push(4)%3B%0A%20%20%20%20println!(%22v%5B3%5D%3A%20%7B%7D%22%2C%20v.lock().unwrap()%5B3%5D)%3B%20%2F%2F%20-%3E%204%0A%7D&amp;amp;version=stable&amp;amp;backtrace=0"&gt;ejecutar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En este ejemplo no hay ningún hilo, pero vale como ejemplo, similar al
ejemplo anterior. Aquí hay que hacer el &lt;em&gt;unwrap&lt;/em&gt; después del &lt;em&gt;lock&lt;/em&gt;, porque
esta llamada puede fallar, en este ejemplo no se controlan los errores,
pero en código de producción no se debería hacer el &lt;em&gt;unwrap&lt;/em&gt; directamente,
sino que se debería controlar el &lt;em&gt;Result&lt;/em&gt; que devuelve, si es del tipo &lt;em&gt;Ok&lt;/em&gt;
o &lt;em&gt;Err&lt;/em&gt;.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sat, 04 Feb 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-02-04:/rust-borrow.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Monkey Patching</title><link>https://danigm.net/monkey-patching.html</link><description>&lt;h2&gt;Qué es el Monkey Patching&lt;/h2&gt;
&lt;p&gt;El &lt;a href="https://en.wikipedia.org/wiki/Monkey_patch"&gt;Monkey Patching&lt;/a&gt; es una técnica de programación de los lenguajes
dinámicos que consiste en modificar el código en tiempo de ejecución.&lt;/p&gt;
&lt;p&gt;Esto quiere decir que en lugar de modificar el código fuente de una clase,
por ejemplo, en tiempo de ejecución asignamos otra función a ese método y
todas las llamadas posteriores en lugar de ejecutar el código definido en
la clase ejecutarán el código "parcheado".&lt;/p&gt;
&lt;p&gt;Esto está relacionado con el llamado &lt;a href="https://es.wikipedia.org/wiki/Duck_typing"&gt;Duck typing&lt;/a&gt;, que viene a decir
que si nada como un pato y suena como un pato, esto es un pato. Y esto del
pato hace referencia a que los tipos no tienen que cumplir una interfaz
estricta, simplemente, si se comportan como tal, es el tipo esperado. Y con
el Monkey Patching podemos hacer que un perro haga cuak como un pato,
modificando el objeto perro en tiempo de ejecución.&lt;/p&gt;
&lt;blockquote&gt;
If it walks like a duck and talks like a duck, it’s a duck, right? So if
this duck is not giving you the noise that you want, you’ve got to just
punch that duck until it returns what you expect.
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;-- Patrick Ewing&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Qué hay que tener en cuenta para el Monkey Patching&lt;/h2&gt;
&lt;p&gt;Para poder hacer Monkey Patching necesitamos, &lt;strong&gt;tipado dinámico&lt;/strong&gt;, ya que si
un método espera un objeto tipo pato y le pasamos uno tipo perro, pero
"parcheado", el método no debe quejarse.&lt;/p&gt;
&lt;p&gt;También tenemos que tener en cuenta la &lt;strong&gt;vida útil&lt;/strong&gt; de los módulos y
objetos. Si parcheamos un módulo, es necesario conocer el alcance de esas
modificaciones, si sólo afectarán a mi módulo o si pueden afectar a otros
módulos que lo importen, o si parcheamos una instancia, es necesario
conocer hasta dónde llegarán esas modificaciones.&lt;/p&gt;
&lt;p&gt;Y por supuesto también es necesario tener acceso a las partes del código
que se quieran modificar, si vamos a modificar un objeto con métodos
&lt;strong&gt;privados&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Por &lt;em&gt;suerte&lt;/em&gt;, en Python no tenemos métodos privados realmente, se suele
usar el guión bajo (_metodo), que según la herramienta lo oculta como
privado, pero en realidad en Python todo es accesible y por tanto podemos
parchear lo que queramos.&lt;/p&gt;
&lt;h2&gt;Algunos ejemplos&lt;/h2&gt;
&lt;h3&gt;Veamos el ejemplo que viene en la wikipedia:&lt;/h3&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;math&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;
&lt;span class="mf"&gt;3.141592653589793&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo se ve que se importa el módulo &lt;em&gt;math&lt;/em&gt; y se modifica el valor
de &lt;em&gt;math.pi&lt;/em&gt;. Fácil y sencillo. No tiene mucho sentido este cambio, pero si
lo hacemos en nuestro código, ya todo el código que venga después y use
&lt;em&gt;math.pi&lt;/em&gt; recibirá como valor 3, y esto afecta incluso a librerías de
terceros.&lt;/p&gt;
&lt;h3&gt;Algo más práctico con código Django:&lt;/h3&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shortcuts&lt;/span&gt;

&lt;span class="n"&gt;old_render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shortcuts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;custom_render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;old_render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Render time: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; seconds&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;

&lt;span class="n"&gt;shortcuts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;custom_render&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;En este ejemplo modificamos el comportamiento por defecto de la función
render de django. Reemplazamos esta función por otra que lo único que hace
es medir el tiempo que se tarda en la llamada a la función inicial y
sacarlo por pantalla.&lt;/p&gt;
&lt;h3&gt;Otro ejemplo con Django:&lt;/h3&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;password_logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;send_to_hacker_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;:&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;newp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real_set_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;admin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;real_set_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_password&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password_logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Aquí se muestra cómo se puede modificar una instancia. En este ejemplo se
modifica el método set_password del usuario admin, para que cuando se
llame a este método se envíe la nueva contraseña por email a un presunto
hacker.&lt;/p&gt;
&lt;p&gt;En el caso de los modelos de django no tiene mucho sentido modificar la
instancia, mejor sería modificar el modelo, la definición de la clase, pero
vale como ejemplo.&lt;/p&gt;
&lt;h2&gt;Cuándo usar el Monkey Patching&lt;/h2&gt;
&lt;p&gt;El Monkey Patching es una herramienta muy poderosa, pero a la vez, es algo
tremendamente peligroso, ya que hace que una clase o un módulo no se
ejecuten como se espera, como dice su definición y por tanto puede dar más
de un dolor de cabeza.&lt;/p&gt;
&lt;blockquote&gt;
Un gran poder conlleva una gran responsabilidad
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;-- Ben Parker&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Por esto hay que saber cuándo usar el Monkey Patching y cuando no.&lt;/p&gt;
&lt;h3&gt;Cuando SÍ:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Depuración o ejecución paso a paso&lt;/strong&gt;: pdb, ipdb, mientras depuramos un
   código para que nos saque información por pantalla, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;: Para reemplazar métodos, atributos o funciones en tiempo de
   ejecución en los tests, por ejemplo una función que genera números
   aleatorios la podemos transformar en algo predecible para testear otros
   métodos relacionados, o podemos reemplazar funciones que tarden mucho
   tiempo debido a sistemas externos, para que los tests se puedan ejecutar
   rápidamente.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fixs o arreglos de libs externas&lt;/strong&gt;: Para aplicar un parche o un
   arreglo de una biblioteca externa en una versión que aún no ha sido
   parcheada oficialmente.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cuando NO:&lt;/h3&gt;
&lt;p&gt;En la mayoría de las ocasiones, no es recomendable usar Monkey Patching.
Por lo tanto, si hay otra forma de hacer lo que queremos hacer, seguramente
sea mejor idea que el Monkey Patching.&lt;/p&gt;
&lt;p&gt;Como he comentado antes, el Monkey Patching hace que el código que se
ejecuta sea diferente del descrito en la definición de la clase o módulo,
por tanto, hay que evitarlo y cuando se use hay que documentarlo muy bien,
porque si no, puede enmascarar problemas o hacer que futuras modificaciones
al código original no tengan efecto.&lt;/p&gt;
&lt;p&gt;Resumiendo, el Monkey Patching está muy guay, pero úsalo bajo tu propia
responsabilidad.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 02 Feb 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-02-02:/monkey-patching.html</guid><category>blog</category><category>wadobo</category><category>python</category><category>programming</category><category>monkey patching</category></item><item><title>Rust</title><link>https://danigm.net/rust.html</link><description>&lt;h2&gt;El lenguaje de programación&lt;/h2&gt;
&lt;p&gt;Llevaba ya algún tiempo escuchando hablar de &lt;a href="http://rust-lang.org"&gt;Rust&lt;/a&gt;, en diferentes
círculos. La primera vez que escuché hablar de él fue en un FOSDEM, hace ya
unos años, cuando estaban empezando con servo, pero ahí no le presté
demasiada atención. Luego he visto varios comentarios por diferentes redes
sociales gente a la que sigo y cuya opinión sobre tecnología valoro
bastante y entonces me empezó a llamar más la atención.&lt;/p&gt;
&lt;p&gt;Pero realmente lo que me hizo interesarme de verdad por este lenguaje fue
el enlace que me apareció un día en mi firefox. Firefox pone de vez en
cuando mensajes y enlaces en la página de búsqueda por defecto y
hace unos días vi que hablaban de servo y pinché en el enlace.&lt;/p&gt;
&lt;p&gt;Y a partir de ahí empecé a leer sobre rust. Me interesó y me leí el
&lt;a href="https://doc.rust-lang.org/book/"&gt;The Rust Programming Language&lt;/a&gt; y me empezó a gustar. La sintaxis, la gestión
de memoria, la compatibilidad con C... Estuve jugando un poco con el
lenguaje, haciendo algunos ejemplos y programando. Y ya que estaba
interesado, también me leí el libro &lt;a href="http://www.oreilly.com/programming/free/why-rust.csp"&gt;Why Rust?&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Jugando con Rust&lt;/h2&gt;
&lt;p&gt;Para aprender a programar con un nuevo lenguaje no basta tan sólo con
leerse la documentación, lo más importante es ponerlo en práctica. Y para
eso, pensé en resolver algunos problemas matemáticos sencillos, y empecé a
resolver problemas de &lt;a href="https://projecteuler.net/"&gt;Project Euler&lt;/a&gt; con &lt;a href="https://github.com/danigm/rust-euler"&gt;rust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Con este proyecto empecé a trastear con la herramienta &lt;a href="http://doc.crates.io/"&gt;Cargo&lt;/a&gt;, que es
una de las cosas geniales de Rust, estuve tratando con los módulos, la
documentación y los tests. Pero realmente estos problemas son simples
problemas matemáticos, que no requieren de estructuras complejas y de más
de una o dos funciones, por lo que a nivel de programación, no me encontré
con ningún problema, ni estaba viendo lo realmente diferente de Rust con
respecto a otros lenguajes como C o C++.&lt;/p&gt;
&lt;p&gt;Así que decidí hacer algo un poco más grande, y ya que estaba, pues hacer
algo útil. Estuve valorando unos días, qué herramienta podría implementar,
y un día, explorando los crates publicados en &lt;a href="https://crates.io"&gt;crates.io&lt;/a&gt;, vi que no
había gran cosa sobre lectura de EPUB, así que me decidí a implementar algo
sencillo, ya que había estado trasteando con este formato para integrarlo
en &lt;a href="https://git.gnome.org/browse/libgepub/"&gt;gnome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Un EPUB no es más que un zip con ficheros XML dentro, por lo que para un
parseo básico se necesitan pocas dependencias. La parte de zip fue fácil,
porque el crate zip provee la lectura básica de ficheros. Donde me encontré
con problemas reales fue a la hora de parsear los XML y sacar la
información del documento.&lt;/p&gt;
&lt;p&gt;En un EPUB hay un documento XML donde se especifica toda la información del
libro, los metadatos, una lista de recursos y una lista con los
"capítulos", que no son más que referencias a recursos XML definidos
anteriormente. Mi objetivo era parsear este XML y poder acceder a
diferentes elementos y atributos de forma más o menos fácil. El crate de
XML que usé me daba una forma de parsear un XML, pero de manera secuencial,
no me devolvía ningún tipo de dato con la estructura del árbol XML, así que
me lo implementé.&lt;/p&gt;
&lt;p&gt;La implementación es algo sencillo, un nodo, que tiene una lista de nodos
hijos, y que puede tener un padre, para poder recorrerlo arriba y abajo.&lt;/p&gt;
&lt;p&gt;Y al implementar esta &lt;a href="https://github.com/danigm/epub-rs/blob/master/src/xmlutils.rs#L101"&gt;estructura en Rust&lt;/a&gt; me encontré con el borrow
checker y la gestión de memoria de Rust. Voy recorriendo el XML y creando
los nodos conforme me los voy encontrando, luego hay que añadir el nodo
hijo al padre y referenciar el padre en el hijo. Y eso me costó bastante.
Hasta que finalmente comprendí como va el tema de las referencias en Rust y
la "propiedad" de la memoria y variables. Esto está muy bien explicado en
el libro &lt;a href="http://www.oreilly.com/programming/free/why-rust.csp"&gt;Why Rust?&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Subí el repo &lt;a href="https://github.com/danigm/epub-rs.git"&gt;epub-rs&lt;/a&gt; a github y creé el &lt;a href="https://crates.io/crates/epub"&gt;crate&lt;/a&gt; correspondiente,
con la &lt;a href="https://danigm.github.io/epub-rs-doc/epub/index.html"&gt;documentación generada automáticamente&lt;/a&gt;, que además son tests
unitarios.&lt;/p&gt;
&lt;h2&gt;Lo malo de Rust&lt;/h2&gt;
&lt;p&gt;La sintaxis en algunos casos es demasiado ofuscada, lo que hace a primera
vista sea "feo", el uso de "!" para macros, el "&amp;amp;", "*", "-&amp;gt;", "=&amp;gt;", "::",
":", "&amp;lt;&amp;lt;&amp;gt;&amp;gt;", "| |", muchos símbolos de puntuación en el código.&lt;/p&gt;
&lt;p&gt;Las conversiones y transformaciones implícitas, hacen que muchas veces no
tengas que poner el "*" pero realmente se esté haciendo la dereferencia y
cosas similares. Viniendo de python, tengo bastante claro que siempre es
mejor explícito que implícito, porque siendo implícito tienes que conocer
al detalle el lenguaje para poder leerlo sin ambigüedad, y siendo
explícito, todo es mucho más coherente, sin tener que conocer detalles
internos.&lt;/p&gt;
&lt;h2&gt;Lo bueno de Rust&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Cargo: Un gestor de paquetes, compilador, generador de documentación,
   etc. Engloba todo lo básico para gestionar cualquier proyecto rust de
   forma fácil.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tests en la documentación: Esto es genial, en python están los
   &lt;a href="https://docs.python.org/3.5/library/doctest.html"&gt;doctest&lt;/a&gt;, pero en Rust esto es lo recomendado para documentar y la
   verdad es que unificar documentación y tests unitarios es lo mejor para
   que la documentación siempre sea coherente con la implementación.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compatibilidad con C gratis: Es trivial que una biblioteca Rust se pueda
   usar desde C y viceversa, por lo que en Rust tienes todo lo de C.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusiones&lt;/h2&gt;
&lt;p&gt;Rust es un lenguaje genial. Me he sentido muy cómodo programando en Rust,
en casi todo momento, excepto en las ocasiones en las que me he tenido que
pelear con el borrow checker, pero en teoría eso es lo que le da la
seguridad al lenguaje, así que mejor corregir los problemas en tiempo de
compilación que en lugar de encontrarte con segmentation faul o memory
leaks meses después.&lt;/p&gt;
&lt;p&gt;La comunidad que hay alrededor de Rust es bastante impresionante, teniendo
en cuenta es un lenguaje moderno, nacido en 2010, y parece su uso se está
extendiendo rápidamente.&lt;/p&gt;
&lt;p&gt;Por lo tanto, y a riesgo de equivocarme estrepitosamente, apostaría a que
Rust será en el corto/medio plazo uno de los lenguajes de programación más
importantes y habrá muchas cosa grandes y pequeñas hechas con Rust,
empezando por firefox.&lt;/p&gt;
&lt;p&gt;Principalmente programo en Python y de momento este lenguaje será mi
primera opción a la hora de resolver cualquier problema. Pero Rust no está
tan lejos de Python, por lo que será mi opción siempre que me encuentre con
el problema del rendimiento. En cualquier caso, no descarto reemplazar
Python por Rust como mi lenguaje para "todo" en un futuro, lo que sí tengo
claro es que a día de hoy elegiría Rust por delante de C, C++, java, go y scala.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 24 Jan 2017 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2017-01-24:/rust.html</guid><category>blog</category><category>wadobo</category><category>rust</category><category>programming</category></item><item><title>Demonio</title><link>https://danigm.net/demonio.html</link><description>&lt;h3&gt;Demonio&lt;/h3&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/demonio.png"&gt;
        &lt;img src="/pictures/demonio.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 27 Apr 2016 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2016-04-27:/demonio.html</guid><category>blog</category><category>dibujo</category><category>demoino</category><category>wacom</category></item><item><title>Super</title><link>https://danigm.net/super.html</link><description>&lt;h3&gt;Super&lt;/h3&gt;
&lt;p&gt;Me he comprado un portátil nuevo, un Lenovo Thinkpad X1 Yoga, que viene con
pantalla táctil y un lapiz, de tal forma que la pantalla funciona como una
tableta wacom, así que, he hecho un dibujo:&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/super.png"&gt;
        &lt;img src="/pictures/super.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;El dibujo está hecho con gimp 2.8, sobre una distro fedora 24, que me
instalé en el portátil. Me funciona casi todo el hardware en linux, sólo me
falta por configurar los acelerómetros y el lector de huellas digitales,
pero en cualquier caso no es nada imprescindible.&lt;/p&gt;
&lt;p&gt;La pantalla táctil funciona a la perfección y gnome3 está genial para el
modo tablet. Falla un poco el teclado en pantalla, que es muy básico, pero
teniendo el teclado físico no es ningún problema.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 06 Apr 2016 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2016-04-06:/super.html</guid><category>blog</category><category>dibujo</category><category>super</category><category>wacom</category></item><item><title>Donde todos eran ricos</title><link>https://danigm.net/ricos.html</link><description>&lt;h3&gt;Donde todos eran ricos&lt;/h3&gt;
&lt;p&gt;Existía un pequeñito pueblo, sin nada particular, un pueblo como muchos
otros, donde vivían diferentes personas y cada cual desempeñaba su trabajo.
Había un carpintero que ponía puertas y hacía sillas y mesas, un panadero
que hacía el pan todos los días, un ganadero que ordeñaba las vacas y
vendía la leche cada día y así toda una serie de personas con ocupaciones
variadas.&lt;/p&gt;
&lt;p&gt;El pueblo no funcionaba ni bien ni mal, era algo normal. Todo el mundo se
levantaba temprano para trabajar y la mayoría de la gente era buena y
deseaba lo mejor para los demás. Cada cual tenía su trabajo, ganaba su
sueldo y se gastaba lo ganado en las necesidades de la vida dando así
trabajo a otra persona del pueblo.&lt;/p&gt;
&lt;p&gt;Al no ser estas personas adineradas, todo el mundo tenía que trabajar. La
rutina no es algo agradable y a todo el mundo le gustaría ser rico, así que
todo el mundo en el pueblo compraba lotería.&lt;/p&gt;
&lt;p&gt;Si sabes algo de estadística sabrás que es una tontería comprar lotería,
pero la probabilidad siempre está ahí, y resultó que un día, por cosas del
destino, a todo el mundo en el pueblo le tocó el gordo. Desde ese día todos
eran ricos. Nadie tendría que volver a trabajar.&lt;/p&gt;
&lt;p&gt;Resultó que el panadero al ser rico pensó que no tendría que trabajar toda
la noche para tener el pan para todo el pueblo. Igualmente el carpintero
pensó que al ser rico no tendría que estar tantas horas lijando madera. El
ganadero pensó lo mismo y dejó de ordeñar sus vacas.&lt;/p&gt;
&lt;p&gt;El carpintero, sintiéndose liberado del trabajo por el afortunado incidente
de la lotería se levantó tarde al día siguiente y pensó que desayunaría
churros en el bar. Salió de su casa y se sorprendió al ver que el bar
estaba cerrado. Claro, al del bar también le había tocado la lotería y
todo el mundo sabe que un hombre rico no se va a levantar temprano para
ponerse a hacer churros.&lt;/p&gt;
&lt;p&gt;Se quedó con las ganas de comerse unos churros, pero entonces se le pasó
por la cabeza que podía comprar una barra de pan recién echa y un poco de
jamón y hacerse un buen bocadillo. Se llevó una sorpresa cuando llegó a la
panadería y vio que también estaba cerrada. Claro, el panadero también era
rico y ahora no trabajaba.&lt;/p&gt;
&lt;p&gt;Y así, todo el pueblo dejó de trabajar. Claro, todos eran ricos, no
necesitaban trabajar para ganar más dinero porque tenían todo el que
pudieran desear.&lt;/p&gt;
&lt;p&gt;Sin embargo el carpintero, el primer día de rico no pudo desayunar, y pasó
hambre. Al panadero se le rompió una puerta, pero no había ningún
carpintero que la arreglase. El ganadero quiso ampliar su pequeña casa
ahora que por fin tenía dinero, pero no había un albañil que lo hiciera.&lt;/p&gt;
&lt;p&gt;El día que todo el pueblo fue rico, en realidad todos y cada uno de los
ciudadanos no pudieron cubrir sus necesidades, y por lo tanto, todos
comenzaron a vivir como antes. El panadero tuvo que volver a hacer pan que
le dio al carpintero a cambio de que le arreglara la puerta. Y así, todo el
pueblo volvió a trabajar para conseguir cubrir las necesidades de sus
vecinos. Nada cambió en ese pueblo.&lt;/p&gt;
&lt;p&gt;La única ventaja de ser rico es que exista gente más pobre que tú, de tal
forma que hagan lo que tú no quieres hacer. Que construyan tu casa por ti,
que arreglen tu coche, que preparen tu comida, en definitiva, ser rico no
tiene sentido si no hay pobres que quieran trabajar para ti.&lt;/p&gt;
&lt;p&gt;Cuando se plantea esto con claridad, ninguna persona decente debería desear
ser "rico" porque eso implica que lo que quiere realmente es que haya otras
personas "pobres" que trabajen por él.&lt;/p&gt;
&lt;p&gt;Luego vendrán los liberales diciendo que realmente quien más se esfuerce es
quién se merece ser más rico, y por tanto los pobres son pobres porque
quieren, porque no quieren trabajar o no han querido estudiar. Pero esto
que parece algo lógico es totalmente falso, porque parte de una premisa
incorrecta, y es que no todo el mundo parte desde la misma posición de
salida. No se puede comparar la carrera profesional del hijo de un médico y
una doctora en matemáticas con la del hijo de un barrendero y una
trabajadora del campo, porque no tienen ni los mismos medios materiales ni
la misma formación. El día en el que no exista la herencia, y cuando al
nacer se quite al niño del lado de sus padres para criar a todos los niños
por igual sin condiciones diferentes entonces podremos hablar de quién se
merece ser más rico o menos, mientras tanto, hay quien juega con ventaja y
los ricos serán cada vez más ricos y los pobres serán cada vez más pobres.&lt;/p&gt;
&lt;p&gt;Mientras tanto, yo no quiero ser rico, no quiero que nadie trabaje para mi
a cambio de nada, yo ofrezco mi trabajo como uno más. El dinero es sólo una
herramienta, nunca debe ser un fin.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Wed, 16 Oct 2013 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2013-10-16:/ricos.html</guid><category>blog</category><category>sociedad</category><category>filosofia</category><category>política</category></item><item><title>Mensajería</title><link>https://danigm.net/mensajeria.html</link><description>&lt;h3&gt;Mensajería&lt;/h3&gt;
&lt;p&gt;Esto de la tecnología es un mundo, desde que el mundo es mundo y dios creó
internet, la mensajería instantánea ha estado ahí. El correo electrónico
está muy bien, pero es "asíncrono" y hay muchas ocasiones en las que las
personas queremos hablar de una manera más directa sobre nuestras
tonterías.&lt;/p&gt;
&lt;p&gt;Recuerdo que cuando yo empecé a pasearme por los sitios de internet había
unos chats y esas cosas donde hablar con la gente. Luego descubrí el yahoo!
messenger y me creé una cuenta y hablaba con mis dos amigos que tenían
internet a partir de las seis de la tarde que es cuando empezaba la tarifa
plana esa. Poco después apareció el MSN messenger que iba con tu cuenta de
hotmail.&lt;/p&gt;
&lt;p&gt;Este segundo sistema de mensajería se hizo muy famoso en España (el
mesenyer) y fue el que utilizaba todo el mundo (incluso yo desde linux,
amsn, pidgin, etc) hasta que apareció gtalk.&lt;/p&gt;
&lt;p&gt;La transición a Gtalk fue lenta, pero como utilizaba xmpp por debajo y
además tenía el server2server, pues podías hablar con tus amigos "frikis" del
linux que tenían su cuenta en jabber.org y también con la gente "normal"
que empezaban a crearse cuentas en gmail por los gigas de correo y esas
cosas. Costó mucho tiempo y trabajo convencer a todos los familiares y
amigos que tenían el "mesenyer" para que se pasaran al gtalk y así poder
hablar con ellos con un protocolo estándar y bonito, con diferentes
clientes y desde diferentes plataformas.&lt;/p&gt;
&lt;p&gt;Mientras tanto también anda por ahí skype, con posibilidad de llamadas y
vídeo conferencias con varias personas que normalmente se entrecorta, pero
que mola para hablar con la gente.&lt;/p&gt;
&lt;p&gt;Luego llegaron los móviles estos de mierda sin botones, pantalla grande y
el internet "gratis" incluido (sólo por 20€ al mes), y mágicamente apareció
el whatsapp, una innovación técnica que te permitía hablar con tus amigos
"gratis". Otro sistema de mensajería pero más mierda, porque sólo está para
plataformas móviles y no para todas.&lt;/p&gt;
&lt;p&gt;Otra vez volvemos a no poder hablar con la gente, porque la mayoría tiene
el wasap este y a mi no me da la gana, yo estaba contento con el xmpp. Pero
habrá gente que haya dicho: "A la mierda, me pongo el wasap este" y luego
llegan los de wasap y dicen que ahora la app no es gratis, sino que vale 1€
y la gente coge y dice que mejor se instalan el line que es de gratis
y puedes hacer lo mismo y ya tenemos amigos con el wasap, amigos con el
line, amigos con el skype, otros con el facebook y otros con el tuenti.&lt;/p&gt;
&lt;p&gt;Y ahora va y google dice que su nuevo "hangout" no va a ir sobre xmpp, y
otra isla por ahí.&lt;/p&gt;
&lt;p&gt;¿Pero qué mierda es esta? La tecnología está ahí, existe desde antes de
internet y sin embargo estamos dando vueltas como tontos y yo sigo sin
poder hablar con mis amigos. Pues sí, estamos un poco locos. Al final son
diferentes intereses comerciales o yo qué sé.&lt;/p&gt;
&lt;p&gt;¿Y yo qué hago? Pues desde hace algún tiempo paso de todo y tiro por
estándares. Para el trabajo uso el IRC, que es lo más simple del mundo y
que funciona perfectamente. Si queremos hablar usamos el mumble con nuestro
propio servidor y así nos evitamos el pasar por skype. Sí, tengo mi
gtalk/xmpp y también me conecto al chat de facebook/xmpp pero como son
islas no me gustan y el día menos pensado no vuelvo a aparecer.&lt;/p&gt;
&lt;p&gt;Así que para hablar conmigo, un correo electrónico "casi" nunca falla,
sino, siempre estoy en freenode conectado como danigm. Creo que es hora de
recuperar el IRC con una bonita interfaz web/móvil que ofrece todo lo
necesario para mensajería instantánea.&lt;/p&gt;
&lt;p&gt;Otra cosa aparte es la gente que no sabe escribir correos electrónicos, no
es tan difícil poner un asunto a un correo electrónico que tenga algo que
ver con lo que has escrito o los correos en formato html, pero bueno de la
gente que no sabe usar el correo electrónico ya me quejaré otro día.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 17 May 2013 00:00:00 +0200</pubDate><guid isPermaLink="false">tag:danigm.net,2013-05-17:/mensajeria.html</guid><category>blog</category><category>tecnología</category></item><item><title>KungFu</title><link>https://danigm.net/kungfu.html</link><description>&lt;h3&gt;Kung Fu&lt;/h3&gt;
&lt;p&gt;Pues sí, he empezado a ir a clases de &lt;a href="http://es.wikipedia.org/wiki/Kungfu"&gt;"kungfu"&lt;/a&gt;. Normalmente suelo ir
al gimnasio por la mañana, de 12:30 a 13:30 todos los días, por eso de
moverme un poco y hacer deporte. Este mes han comenzado a dar clases
de kungfu por la mañana, así que he comenzado a ir.&lt;/p&gt;
&lt;p&gt;¿Quién no ha querido alguna vez saber artes marciales? Las grandes
películas con esas geniales coreografías, &lt;a href="https://es.wikipedia.org/wiki/The_Matrix"&gt;Matrix&lt;/a&gt;, todo lo de
&lt;a href="https://en.wikipedia.org/wiki/Jackie_chan"&gt;Jackie Chan&lt;/a&gt; y muchas otras películas que nos han enseñado lo
genial que son las artes marciales y lo bonito que es todo.&lt;/p&gt;
&lt;p&gt;Hace poco también pusieron en la sexta 3 las películas de &lt;a href="https://en.wikipedia.org/wiki/Ip_Man_%28film%29"&gt;Ip Man&lt;/a&gt;,
geniales películas que me encantaron no ya por lo genial de las
coreografías, sino por el mensaje que transmiten y tienen bastante
culpa de mi interés reciente por las artes marciales chinas.&lt;/p&gt;
&lt;p&gt;Como todo lo que vale la pena en esta vida el kungfu requiere una
constancia y dedicación prolongada en el tiempo para que de
resultados, llevo tres semanas yendo a clases y todavía no hago ni el
saludo correctamente, pero estoy decidido a aprender, es una manera
muy divertida de hacer deporte y mantenerse en forma.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/wushu.jpg"&gt;
        &lt;img src="/pictures/wushu.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Sin embargo desde el primer día voy notando los cambios y los
progresos que esta actividad me está reportando. El primer cambio
físico que estoy notando es la elasticidad. Ahora mismo soy una
alcayata, me doblo un poco, pero ni siquiera me toco las puntas de los
pies sin doblar las rodillas y desde que empecé a ir a las clases de
artes marciales estoy mejorando mucho en esto de la elasticidad y
también es lo que más estoy trabajando.&lt;/p&gt;
&lt;p&gt;La otra mejora que estoy notando desde que empecé a ir a clases es la
coordinación, agilidad y equilibrio. Con las artes marciales se
trabajan musculos y posturas que no se trabajan en la vida cotidiana y
al empezar a trabajar esto he experimentado un mayor control de mis
movimientos.&lt;/p&gt;
&lt;p&gt;Las artes marciales chinas son algo más que lucha, son un deporte
conocido como &lt;a href="http://es.wikipedia.org/wiki/Wushu_%28deporte%29"&gt;wushu&lt;/a&gt; que me recuerda un poco a la gimnasia con
respecto a la acrobacia que implica. De todo lo relacionado con las
artes marciales lo que más me ha llamado la atención siempre ha sido
la acrobacia, belleza y fluidez de movimientos, para mí la lucha es
algo secundario.&lt;/p&gt;
&lt;p&gt;El estilo que yo ando aprendiendo es el &lt;a href="https://es.wikipedia.org/wiki/Hung_Gar"&gt;Hung Gar&lt;/a&gt;, todavía no
tengo mucha idea sobre esto de las artes marciales chinas, pero poco a
poco iré aprendiendo.&lt;/p&gt;
&lt;p&gt;De momento voy aprendiendo algunas posturas básicas y las formas de
pasar de una a otra mezclando bloqueos y golpes, trabajando
coordinación, flexibilidad, fuerza y agilidad.&lt;/p&gt;
&lt;iframe src="http://player.vimeo.com/video/42816543" width="500"
height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen
allowFullScreen&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href="http://vimeo.com/42816543"&gt;Ip
Man 2 Fight Scene Challenge&lt;/a&gt; from &lt;a
href="http://vimeo.com/purposetv"&gt;Khalid Yasin&lt;/a&gt; on &lt;a
href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ahora mismo estoy muy ilusionado con este nuevo deporte que estoy
descubriendo poco a poco y siempre que puedo voy buscando fuentes para
satisfacer mi curiosidad y tratar de aprender lo máximo posible. De
momento entreno dos días a la semana y siempre me sabe a poco, estoy
pensando en complementar mi entrenamiento, pero claro, con todas mis
actividades extra escolares tampoco es que tenga mucho tiempo para
dedicar a una sola cosa. Tendré que hacer una valoración y ver en qué
quiero dedicar más tiempo.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 10 Mar 2013 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2013-03-10:/kungfu.html</guid><category>blog</category><category>kungfu</category><category>deporte</category></item><item><title>FOSDEM''13</title><link>https://danigm.net/fosdem13.html</link><description>&lt;h3&gt;Wadobo en el FOSDEM 2013&lt;/h3&gt;
&lt;p&gt;Este año, &lt;a href="http://wadobo.com/about/"&gt;Wadobo&lt;/a&gt; al completo se ha pasado por el &lt;a href="http://fosdem.org"&gt;FOSDEM (The
Free and Open source Software Developers’ European Meeting)&lt;/a&gt;, y
hemos aprovechado el evento para enterarnos de primera mano de qué es
lo que se está moviendo en el mundo del software libre.&lt;/p&gt;
&lt;p&gt;Este año, a diferencia del FOSDEM del 2011, donde &lt;a href="http://blog.edulix.es/"&gt;Edulix&lt;/a&gt; habló
sobre &lt;a href="https://www.youtube.com/watch?v=0ozJ89KFIF0"&gt;Timebank&lt;/a&gt; y también sobre &lt;a href="https://www.youtube.com/watch?v=FGa5eVh4w-g"&gt;Ágora&lt;/a&gt;, no hemos dado ninguna
charla, no por falta de ganas o temas sobre los que hablar, sino más
bien porque lo hemos ido dejando pasar y al final no hemos propuesto
nada. Supongo que el año que viene estaremos allí otra vez y esta vez
con alguna que otra charla.&lt;/p&gt;
&lt;h3&gt;Hacia dónde va el desarrollo&lt;/h3&gt;
&lt;p&gt;El FOSDEM es un gran evento que se desarrolla en un corto periodo de
tiempo y donde se presentan simultáneamente muchísimas charlas
realmente interesantes sobre diferentes tecnologías, sin embargo
personalmente he presenciado un ligero cambio en la masa de
desarrolladores, o más bien en el interés general.&lt;/p&gt;
&lt;p&gt;Mozilla tuvo una sala llena de charlas los dos días. Se habló de web,
de comunidad y de firefox, pero sobre todo se habló de &lt;a href="http://www.mozilla.org/en-US/firefoxos/"&gt;Firefox OS&lt;/a&gt;.
Y creo que es uno de los temas que más atención han recibido en este
FOSDEM.&lt;/p&gt;
&lt;p&gt;Actualmente las plataformas programables se han multiplicado y hoy en
día no sólo existen los ordenadores tradicionales, han aparecido
multitud de dispositivos y eso se está notando en la comunidad de
software libre, que parece empezar a buscar dispositivos realmente
libres sobre los que trabajar. Firefox OS promete algo más de
libertad, y también anda por ahí &lt;a href="http://www.ubuntu.com/devices/phone"&gt;ubuntu&lt;/a&gt; y otras cosas como
&lt;a href="http://jolla.com/"&gt;jolla&lt;/a&gt;. Por lo que me puedo aventurar a prever un gran movimiento
de desarrolladores a este tipo de proyectos que son realmente
prometedores llevando el software libre un poco más allá.&lt;/p&gt;
&lt;p&gt;Por lo tanto y viendo las diferentes charlas de este último FOSDEM me
da la impresión de que el interés en el mundo del software libre, y
creo que del desarrollo de software en general, está tendiendo hacia
los nuevos dispositivos. Y no creo que este creciente interés sobre
estas nuevas tecnologías vaya en detrimento de grandes proyectos que
en el pasado pudieron ser el gran foco de interés, como las grandes
distribuciones o los entornos de escritorio tradicionales, sino más
bien creo que la comunidad de software libre está creciendo y llegando
a lugares donde antes era imposible llegar.&lt;/p&gt;
&lt;h3&gt;Otras cosillas&lt;/h3&gt;
&lt;p&gt;Hay un par de cosas que han llamado mi atención durante el FOSDEM. Lo
primero es la tecnología &lt;a href="http://www.webrtc.org/"&gt;webrtc&lt;/a&gt;, me enteré de esta tecnología en
una charla de mozilla y la verdad es que es algo bastante
interesante. Esta charla ha motivado que me haya descargado y
compilado el firefox desde el repositorio para jugar un poco y tengo
pensado hacer algún tipo de aplicación de ejemplo para explorar las
posibilidades que ofrece.&lt;/p&gt;
&lt;p&gt;La otra cosa que me ha llamado la atención durante este evento ha sido
el anuncio de GNOME de la elección del lenguaje oficial para el
desarrollo de aplicaciones, y este no es otro que &lt;a href="http://www.j5live.com/2013/02/04/gnome-and-languages/"&gt;javascript&lt;/a&gt;.
Aún siendo un defensor de python para todo tengo que decir que no es
ninguna locura, javascript es un lenguaje de alto nivel y junto con
gobject-instrospection gjs es una herramienta bastante potente. A
partir de ahora lo único que hay que hacer es generar buena
documentación y el número de aplicaciones para gnome en js crecerá
considerablemente, gnome puede convertirse en una buena plataforma de
desarrollo.&lt;/p&gt;
&lt;h3&gt;Lo peor&lt;/h3&gt;
&lt;p&gt;El FOSDEM es un evento bastante popular y cada vez va más gente lo que
en principio es bueno, pero el espacio es finito y se convierte en un
problema el pillar sitio para ir a las charlas interesantes. Por
ejemplo este año había un track de python donde había bastantes
charlas muy interesantes y no pudimos ver ninguna de ellas porque era
una sala medianamente pequeña y estaba llena desde primera hora.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="http://www.linuxhispano.net/tira/fosdem.png"&gt;
        &lt;img src="http://www.linuxhispano.net/tira/fosdem.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Mon, 11 Feb 2013 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2013-02-11:/fosdem13.html</guid><category>blog</category><category>fosdem</category><category>wadobo</category><category>open source</category></item><item><title>FTask, gestión de tareas con Flask y mongodb</title><link>https://danigm.net/ftask.html</link><description>&lt;h3&gt;Simplificando la gestión de tareas (&lt;a href="http://trello.com/"&gt;Trello&lt;/a&gt;)&lt;/h3&gt;
&lt;p&gt;La gestión de tareas y las listas de cosas por hacer es un problema
general de la vida al que casi todo el mundo se ha tenido que
enfrentar alguna vez.&lt;/p&gt;
&lt;p&gt;Se han desarrollado multitud de soluciones, agendas, bloc de notas,
folios, post-its... Incluso se han desarrollado completas teorías como
&lt;a href="http://en.wikipedia.org/wiki/Getting_Things_Done"&gt;GTD&lt;/a&gt; con las que se han hartado de vender libros desarrollando la
fabulosa metodología de apuntar las cosas en una lista e ir tachando
una a una.&lt;/p&gt;
&lt;p&gt;Con respecto al mundo de las aplicaciones informáticas, también ha
habido multitud de aproximaciones con más o menos éxito. El mayor
problema que nos encontramos en la mayoría de las aplicaciones
informáticas de gestión de tareas es que aunque en un principio pueden
ser simples normalmente se van complicando más y más hasta que hacen
multitud de cosas y en realidad el apuntar algo para hacerlo luego se
convierte en una tarea tediosa, por lo que mucha gente acaba acudiendo
a los bonitos post-its pegados en la pantalla.&lt;/p&gt;
&lt;p&gt;Recientemente he conocido la fabulosa aplicación web &lt;a href="http://trello.com/"&gt;Trello&lt;/a&gt;, que
no es más que otra solución a este problema mundialmente conocido. El
enfoque que dan desde Trello a la gestión de tareas es bien sencillo,
implementa un modelo de tablones-listas-tareas en una aplicación web
con una interfaz realmente sencilla.&lt;/p&gt;
&lt;p&gt;La aplicación es bien sencilla, tienes tablones, donde puedes definir
listas y cada lista tiene una serie de tareas. Las tareas se pueden
mover entre listas, y de primeras te proponen tres listas: To Do,
Doing, Done. Es muy simple empezar apuntando cosas en la lista To Do,
cuando estás haciendo algo coges y arrastras la tarea a la lista Doing
y una vez terminas la mueves a Done. Algo simple, sencillo y muy
similar a tener un montón de post-its pero en tu pantalla.&lt;/p&gt;
&lt;p&gt;Otra gran genialidad de Trello es la edición colaborativa, varias
personas pueden estar trabajando en un mismo tablón y los cambios se
ven en tiempo real.&lt;/p&gt;
&lt;p&gt;Por lo tanto Trello es una gran herramienta para gestión de tareas. Es
algo simple, que hace completamente su función y que permite trabajar
en equipo de una manera más o menos simple.&lt;/p&gt;
&lt;h3&gt;Haciendolo libre&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://trello.com/"&gt;Trello&lt;/a&gt; está muy bien, peeero, no es libre, no puedo descargarme
el código, modificarlo y usarlo en el servidor de &lt;a href="http://wadobo.com/"&gt;mi empresa&lt;/a&gt; para
gestionar mis tareas.&lt;/p&gt;
&lt;p&gt;Estando así las cosas y siendo un poco talibán del software libre, qué
mejor que implementar un &lt;a href="https://github.com/wadobo/Ftask"&gt;clon libre&lt;/a&gt; de esta fabulosa herramienta,
y si además durante el proceso aprendemos algunas tecnologías nuevas,
pues mejor.&lt;/p&gt;
&lt;p&gt;Así pues, desde &lt;a href="http://wadobo.com/"&gt;wadobo labs&lt;/a&gt;, nos hemos puesto a desarrollar él
clon con una licencia libre AGPLv3.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/trello.png"&gt;
        &lt;img src="/pictures/trello.png" /&gt;
    &lt;/a&gt;
    Trello.com en funcionamiento
&lt;/p&gt;

&lt;p class="img"&gt;
    &lt;a href="/pictures/ftask.png"&gt;
        &lt;img src="/pictures/ftask.png" /&gt;
    &lt;/a&gt;
    Ftask en funcionamiento
&lt;/p&gt;

&lt;h3&gt;Un nombre...&lt;/h3&gt;
&lt;p&gt;Todo proyecto merece un nombre, y la selección del nombre es uno de
los momentos cruciales en el desarrollo. En este caso, en un alarde de
originalidad y creatividad el nombre elegido ha sido &lt;a href="https://github.com/wadobo/Ftask"&gt;FTask&lt;/a&gt;,
porque elegí &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; como framework de desarrollo y se parece mucho
Flask a Task, así que combiné las dos palabras et voilá.&lt;/p&gt;
&lt;p&gt;Vale, no es un buen nombre. No se me ocurrió uno mejor, siempre
podemos cambiarlo más adelante.&lt;/p&gt;
&lt;h3&gt;Arquitectura&lt;/h3&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/ftask-arch.png"&gt;
        &lt;img src="/pictures/ftask-arch.png" /&gt;
    &lt;/a&gt;
    Arquitectura del proyecto FTask
&lt;/p&gt;

&lt;p&gt;Para el desarrollo de este proyecto quería separar la interfaz de la
aplicación.&lt;/p&gt;
&lt;p&gt;Normalmente las aplicaciones web tienen una interfaz HTML ligada. Pero
últimamente estoy observando que el modelo de simplificar la interfaz
facilita el desarrollo y las pruebas de la aplicación. Por lo tanto
decidí separar la aplicación en una aplicación básica con una interfaz
JSON y una interfaz HTML con todo el acceso al backend a través de
AJAX.&lt;/p&gt;
&lt;p&gt;Esta arquitectura permite una separación más clara entre aplicación e
interfaz y por tanto es mucho más difícil mezclar cosas. Además
facilita el desarrollo de futuras aplicaciones no web ya sea
integración con escritorio o aplicaciones para dispositivos móviles.&lt;/p&gt;
&lt;h3&gt;Flask y Mongo&lt;/h3&gt;
&lt;p&gt;Como ya he dicho antes, he elegido &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; como framework para el
desarrollo de esta aplicación. Dado que mi lenguaje favorito de
programación es python&lt;a href="http://python.org"&gt;10&lt;/a&gt;, estaba claro que el framework de
desarrollo tenía que ser en este lenguaje.&lt;/p&gt;
&lt;p&gt;El framework con el que más he trabajado es &lt;a href="http://djangoproject.com"&gt;django&lt;/a&gt;, y es un gran
framework, pero tiene muchas cosas que no uso y para este proyecto
quería usar un micro-framework, algo más pequeño y modular. Ya he
trabajado antes con &lt;a href="http://webpy.org"&gt;web.py&lt;/a&gt; e incluso con &lt;a href="http://www.cherrypy.org/"&gt;cherrypy&lt;/a&gt;, pero
desde hacía ya algún tiempo venía oyendo hablar de &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; y tenía
ganas de hacer algo con este framework, así que el motivo principal
por el que elegí este framework fue porque no lo conocía.&lt;/p&gt;
&lt;p&gt;Con respecto al almacenamiento tenía muchas ganas de hacer algo con
una base de datos no relacional, algo NoSQL. Ya había cacharreado algo
con &lt;a href="http://www.mongodb.com/"&gt;Mongo&lt;/a&gt;, pero no había hecho nada serio. Así que decidí
utilizar esta base de datos NoSQL.&lt;/p&gt;
&lt;h3&gt;Tiempo real y Backbone&lt;/h3&gt;
&lt;p&gt;Como todos los datos de la interfaz se obtienen a través de peticiones
AJAX de la API JSON de la aplicación decidí que lo mejor para
controlar todos estos datos y mantener sincronizada la interfaz era
usar &lt;a href="http://backbonejs.org/"&gt;backbone&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Con &lt;a href="http://backbonejs.org/"&gt;backbone&lt;/a&gt; es relativamente sencillo tener "edición
colaborativa en tiempo real" en la aplicación, ya que usando
medianamente bien la biblioteca js se separa la representación de los
datos y simplemente haciendo polling a la API cada poco tiempo se
actualiza automáticamente la interfaz.&lt;/p&gt;
&lt;p&gt;Esta parte de &lt;a href="http://backbonejs.org/"&gt;backbone&lt;/a&gt; en &lt;a href="https://github.com/wadobo/Ftask"&gt;Ftask&lt;/a&gt; es muy mejorable, porque
actualmente se hace polling y es bastante costoso en tráfico, esas
peticiones se pueden optimizar para que sean lo mínimo necesario e
incluso se podría utilizar websocket para evitar el polling. Por
suerte &lt;a href="http://backbonejs.org/"&gt;backbone&lt;/a&gt; permite cambiar de polling al uso de websocket de
manera más o menos sencilla, por lo que esa tarea la he ido delegando
para el momento en el que haya que optimizar.&lt;/p&gt;
&lt;h3&gt;Versión usable y colaboraciones&lt;/h3&gt;
&lt;p&gt;Actualmente hay una versión &lt;a href="http://ftask.wadobo.com/"&gt;usable en el servidor de wadobo&lt;/a&gt;, pero
hay muchas cosas y mejoras que se pueden ir añadiendo, desde copias
literales de funcionalidad de &lt;a href="http://trello.com/"&gt;trello&lt;/a&gt; a nueva funcionalidad que a
cualquiera se le pueda ocurrir.&lt;/p&gt;
&lt;p&gt;El desarrollo de este proyecto es totalmente abierto y estando el
código en &lt;a href="https://github.com/wadobo/Ftask"&gt;github&lt;/a&gt; es muy fácil hacer un fork y empezar a hacer
cositas por ahí, como siempre, toda colaboración será bienvenida.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Sun, 13 Jan 2013 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2013-01-13:/ftask.html</guid><category>blog</category><category>wadobo</category><category>ftask</category><category>flask</category><category>mongodb</category><category>trello</category></item><item><title>PIWEEK!</title><link>https://danigm.net/piweek.html</link><description>&lt;p&gt;Hoy ha finalizado la tercera edición de la &lt;a href="http://piweek.es/"&gt;PIWEEK&lt;/a&gt;, que para quien
no lo sepa, es una idea genial a las que nos hemos apuntado desde
&lt;a href="http://wadobo.com/"&gt;wadobo&lt;/a&gt;. Copio la descripción de la misma web:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ΠWEEK viene de Personal Innovation Week y persigue promover la
innovación y creatividad en un entorno multicompañía prácticamente sin
límites. No se exige propósito comercial, no se impone un filtro
específico, sólo es una semana para que todo el mundo haga lo que más
desee.&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;&lt;a href="http://piweek.es/?page_id=2"&gt;piweek&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yo me enteré de la existencia de esta genial idea a través de
&lt;a href="http://yaco.es"&gt;Yaco&lt;/a&gt;, quienes participaron en la última edición y a partir de eso
en &lt;a href="http://wadobo.com/"&gt;wadobo&lt;/a&gt; decidimos que esto encajaba directamente con nuestra
forma de trabajar y por eso nos apuntamos a esta.&lt;/p&gt;
&lt;h3&gt;Propuesta de trabajos&lt;/h3&gt;
&lt;p&gt;En la semana anterior a la ΠWEEK se hace una presentación de ideas de
proyectos para intentar captar gente e ir creando los grupos de
trabajo.&lt;/p&gt;
&lt;p&gt;En esta edición se han propuestos varios proyectos bastante
interesantes. &lt;a href="https://edulix.wordpress.com/"&gt;Edulix&lt;/a&gt; propuso &lt;a href="http://agoravoting.com/"&gt;Agora&lt;/a&gt; como proyecto. Es verdad
que no es un proyecto para hacer en una semana y ya hay algo hecho,
pero se propuso un objetivo en concreto y en eso hemos estado
trabajando.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/agora-piweek.jpg"&gt;
        &lt;img src="/pictures/agora-piweek.jpg" /&gt;
    &lt;/a&gt;
    El equipo de trabajo de Agora Ciudadana en las oficinas de Kaleidos
&lt;/p&gt;

&lt;p&gt;Para mi la parte más importante y el gran potencial de la ΠWEEK es la
colaboración entre empresas, la posibilidad de trabajar y aprender
junto a gente de otras empresas y otros lugares, por eso quería
colaborar en algún proyecto propuesto por alguien con quién no hubiera
trabajado, pero finalmente y por estar un podo a medias en este evento
he trabajado solamente en &lt;a href="http://agoravoting.com/"&gt;Agora&lt;/a&gt;. Por suerte y aún habiendo
trabajado en este proyecto con &lt;a href="https://edulix.wordpress.com/"&gt;Edulix&lt;/a&gt; también hemos tenido la
suerte de trabajar con gente de &lt;a href="http://kaleidos.net/"&gt;Kaleidos&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Kaleidos&lt;/h3&gt;
&lt;p&gt;Yo he estado trabajando la mitad de la semana desde Córdoba, pero el
jueves me acerqué a Madrid para vivir el evento en toda su plenitud.&lt;/p&gt;
&lt;p&gt;Lo primero que tengo que decir es que &lt;a href="http://kaleidos.net/"&gt;Kaleidos&lt;/a&gt; es una empresa
genial, me he sentido como uno más los dos días que he estado por allí
y nos han tratado muy bien. He tenido la gran oportunidad de conocer a
mucha gente y de trabajar allí un par de días y viendo el ambiente y
las oficinas me ha recordado mucho a &lt;a href="http://yaco.es"&gt;Yaco&lt;/a&gt; y a ese gran ambiente
que sólo se consigue juntando a gente muy buena en un ambiente
agradable.&lt;/p&gt;
&lt;p&gt;Muchas gracias a toda la gente de &lt;a href="http://kaleidos.net/"&gt;Kaleidos&lt;/a&gt; por organizar estas
cosas y por tratarnos tan bien.&lt;/p&gt;
&lt;h3&gt;Agora&lt;/h3&gt;
&lt;p&gt;El proyecto &lt;a href="http://agoravoting.com/"&gt;Agora ciudadana&lt;/a&gt; ya tiene un largo recorrido y la web
está en producción, hay gente usándola y sobretodo &lt;a href="https://edulix.wordpress.com/"&gt;Edulix&lt;/a&gt;, sigue
trabajando en esto.&lt;/p&gt;
&lt;p&gt;La propuesta para esta semana era refactorizar, trastocar todo el
código para hacer la aplicación mejor internamente para facilitar
futuros desarrollos y el mantenimiento de la plataforma.&lt;/p&gt;
&lt;p&gt;El trabajo principal que hemos estado realizando ha sido el de
finalizar la API rest, documentarla y sobretodo, trasladar la lógica
de interfaz a cliente utilizando tecnologías como &lt;a href="http://backbonejs.org"&gt;Backbone&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Qué hemos aprendido&lt;/h3&gt;
&lt;p&gt;Yo personalmente he aprendido mucho de &lt;a href="http://backbonejs.org"&gt;Backbone&lt;/a&gt; y javascript en
general. Ya he trabajado con javascript muchas veces y es algo que
conozco, pero nunca había hecho las cosas tal y como las hemos hecho
en ágora y la verdad es que he aprendido mucho.&lt;/p&gt;
&lt;p&gt;También hemos tenido la oportunidad de discutir la estructura y ver
cuál sería una organización mejor para un entendimiento y desarrollo del
proyecto más fácil.&lt;/p&gt;
&lt;p&gt;La conclusión técnica más importante que he sacado del trabajo de toda
la semana en &lt;a href="http://agoravoting.com/"&gt;Agora&lt;/a&gt; es que cuando un proyecto comienza a hacerse
grande hay que dividir. Hay que buscar siempre la simplicidad y
trabajar para que las capas de comunicación entre componentes simples
también sea simple, buscando conseguir hacer algo complejo pero
entendible por partes. Osea, evitar código espagueti, organizar por
funcionalidad y no mezclar funcionalidades. Lo que cuentan todos esos
libros de diseño de software y patrones y esas cosas.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Fri, 21 Dec 2012 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2012-12-21:/piweek.html</guid><category>blog</category><category>wadobo</category><category>piweek</category><category>agora</category></item><item><title>Jugando al baloncesto</title><link>https://danigm.net/basket.html</link><description>&lt;h3&gt;Vuelta al deporte&lt;/h3&gt;
&lt;p&gt;Allá por el 2003 dejé mi pueblo y me fui a la ciudad, primero Granada
y luego Sevilla, a estudiar una carrera. Desde entonces abandoné un
poco el deporte y me centré primero en los estudios y luego en el
trabajo.&lt;/p&gt;
&lt;p&gt;En 2011, cuando monté &lt;a href="http://wadobo.com"&gt;wadobo&lt;/a&gt; y empecé a trabajar desde casa, no
tenía mucho sentido el seguir viviendo en Sevilla, por lo que decidí
volverme a mi pueblo, donde las cosas son más baratas y se vive mejor.&lt;/p&gt;
&lt;p&gt;Entonces fue cuando me reencontré con antiguos compañeros de
baloncesto y cuando empezamos a montar un equipo para volver a jugar.&lt;/p&gt;
&lt;p&gt;Ese verano montamos el equipo senior y jugamos la liga provincial de
Córdoba, consiguiendo ganar un partido y quedando últimos de la liga.
Por lo que se puede decir que fue todo un éxito el poder volver a
jugar al baloncesto. Además coincidió que el año pasado inauguraron el
pabellón deportivo de &lt;a href="http://www.fernannunez.es/"&gt;Fernán Nuñez&lt;/a&gt;, por lo que ya no tenemos por
qué jugar a la intemperie en pistas de mala muerte.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/basket.jpg"&gt;
        &lt;img src="/pictures/basket.jpg" /&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;Historial deportivo&lt;/h3&gt;
&lt;p&gt;El baloncesto ha sido el deporte que más habré practicado en mi vida,
pero tampoco es que sea un experto. Jugué algún partido en categoría
alevín, pero nada oficial. Luego estuve un año entero con un equipo de
una categoría superior, porque no había de mi edad y tampoco jugué
demasiado.&lt;/p&gt;
&lt;p&gt;Después de eso estuve jugando al fútbol. Empecé jugando al fútbol
sala, de portero y luego seguí jugando al fútbol 7. Cuando pasé a
jugar al fútbol 11 ya me aburrí de ser portero y pasé a jugar de
defensa. Ese año llevé todo adelante y además de jugar al fútbol
jugaba al baloncesto y algún que otro día iba a jugar al tenis.&lt;/p&gt;
&lt;p&gt;Cuando llegué a cadete ya me aburrí de todo y me centré en lo que más
me gustaba, el baloncesto. Mi último año como jugador federado tuvo
que ser fuera de mi pueblo, porque no había gente para montar un
equipo juvenil, por lo que me fui a jugar ese año a La Rambla.&lt;/p&gt;
&lt;p&gt;Tengo que decir que en todos estos años de jugar al baloncesto,
realmente gané muy pocos partidos, siempre había poca gente para
jugar y para los partidos completábamos con jugadores de categorías
inferiores.&lt;/p&gt;
&lt;p&gt;Así pues, jugando al baloncesto fue cuando aprendí a perder. Y bien
que aprendí, porque no hacía otra cosa, sin embargo disfrutaba jugando
como un enano.&lt;/p&gt;
&lt;h3&gt;Habilidades&lt;/h3&gt;
&lt;p&gt;El baloncesto es un deporte para gente grande, y yo no lo soy. Es
verdad que una vez lo fui. Crecí rápido y en un momento dado era de
los más grandes, por lo que desde siempre he jugado de pivot, y no se
me daba demasiado mal. Sin embargo, ya en juveniles, con mi 1.73 de
altura el jugar de pivot empezaba a chirriar un poco. Aún así, en
juveniles jugué de 4 y competí con gente bastante más alta que yo,
cosa que nunca me ha dado miedo.&lt;/p&gt;
&lt;p&gt;No tengo buen tiro. Nunca he tirado bien, no es que tire mal, ni que
tenga una mecánica rara, simplemente es que no hago dos tiros iguales.
Puedo hacer un tiro perfecto, de manual, y el siguiente que no de ni
aro. Puede que esta habilidad tenga que ver con la miopía que calzo,
pero jugando con lentillas no debería afectar. Sin embargo el tiro es
uno de mis puntos flacos y algo en lo que estoy trabajando para
mejorar día a día.&lt;/p&gt;
&lt;p&gt;Si tengo que destacar alguna habilidad, podría decir que tengo buena
vista. En defensa sé posicionarme bastante bien, aunque no sea rápido
y en ataque sé moverme. Veo los cortes y movimientos de los otros
jugadores y normalmente meto balones en lugares imposibles. Sin
embargo, soy muy temerario y la mitad de los pases que doy no llegan a
ninguna parte.&lt;/p&gt;
&lt;h3&gt;Por qué juego al baloncesto&lt;/h3&gt;
&lt;p&gt;Si no soy grande, ni tengo una habilidad destacada en este deporte,
¿por qué juego al baloncesto? Pues principalmente porque es un deporte
muy divertido. Es el deporte más completo que he conocido, donde todo
jugador participa en todo momento y donde un equipo de verdad marca la
diferencia sobre el juego individual.&lt;/p&gt;
&lt;p&gt;En un partido de baloncesto puedes correr mucho, si te gusta jugar al
contraataque y el juego rápido. También puedes jugar a otro ritmo y
hacer jugadas más largas y elaboradas.&lt;/p&gt;
&lt;p&gt;Otra de las cosas que me gustan mucho de baloncesto es que tienes
muchas oportunidades para probar e inventar. En cualquier partido
tienes multitud de ataques y defensas, por lo que dependiendo del
rival puedes ir probando y aprendiendo cómo defender o como atacar y
por lo tanto cada ataque o defensa es un reto.&lt;/p&gt;
&lt;p&gt;Pero realmente, lo más importante de este deporte es que es un deporte
de equipo. Cuando empiezas a jugar con alguien y realmente te
entiendes el juego es algo maravilloso, sabes dónde va a estar y cómo
jugar con esa persona y es cuando la magia comienza a surgir, cuando
los pases salen sólos y cuando simplemente viéndolo ya estás
disfrutando.&lt;/p&gt;
&lt;iframe width="500" height="315" src="http://www.youtube.com/embed/Tcw9YjnVqw8" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Pues eso, que me lo paso requetebien jugando al baloncesto, me importa
una mierda ganar o perder, porque cada segundo que estoy en la pista
estoy disfrutando y seguiré jugando hasta que el cuerpo aguante.&lt;/p&gt;
&lt;p&gt;Este año estamos ganando partidos y siendo más competitivos, pero a
cambio estoy jugando mucho menos, sin embargo me da igual, porque sigo
entrenando y tratando de mejorar y sigo jugando que es de lo que se
trata esto de la vida, de jugar y pasarlo bien.&lt;/p&gt;
&lt;p&gt;Lo mejor de haber estudiado Informática y de dedicarme al desarrollo
es que puedo trabajar desde casa y lo mejor de trabajar desde casa es
que he vuelto a jugar al baloncesto. Hoy en día el baloncesto es uno
de los factores más importantes en mi vida y ahora mismo no cambiaría
esto por nada.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 06 Dec 2012 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2012-12-06:/basket.html</guid><category>blog</category><category>baloncesto</category><category>deporte</category></item><item><title>Hackatón de Ágora Ciuadana</title><link>https://danigm.net/hackaton-agora.html</link><description>&lt;p&gt;Después de tres días dedicandome casi plenamente a enviar y recibir
correos, hoy voy a volver a programar y nada menos que hasta que el
cuerpo aguante.&lt;/p&gt;
&lt;p&gt;Tenemos planificado para hoy un &lt;a href="https://blog.agoravoting.com/index.php/2012/11/22/sprint-de-programacion-de-agora-ciudadana-el-jueves-29-de-noviembre/"&gt;hackaton de Ágora&lt;/a&gt;, es
completamente abierto a todo el mundo, ágora es un proyecto libre y el
desarrollo es completamente libre. Estámos en el canal #agoraciuadana
de irc.freenode.net, para el que quiera colaborar.&lt;/p&gt;
&lt;p&gt;La idea es hacer una gran refactorización, así que hoy toca programar
mucho y la verdad es que ya iba siendo hora.&lt;/p&gt;
&lt;p class="img"&gt;
    &lt;a href="/pictures/hack-20121129.png"&gt;
        &lt;img src="/pictures/hack-20121129.png" /&gt;
    &lt;/a&gt;
&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Thu, 29 Nov 2012 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2012-11-29:/hackaton-agora.html</guid><category>blog</category><category>agora</category><category>dibujo</category><category>wadobo</category></item><item><title>Nuevo blog, el ciclo de la web y otras cosas</title><link>https://danigm.net/nuevo-blog.html</link><description>&lt;p&gt;Hacía ya bastante tiempo que venía queriendo cambiar mi
&lt;a href="http://old.danigm.net"&gt;antiguo blog&lt;/a&gt;, tenía un &lt;a href="http://drupal.org"&gt;drupal&lt;/a&gt;. La decisión de poner un drupal como
blog fue algo que tomé así a la ligera, lo mismo que puse un drupal
podría haber puesto un wordpress&lt;a href="http://wordpress.org"&gt;4&lt;/a&gt;. La cosa es que cuando monté mi blog
en mi servidor personal era cuando se pusieron de moda los CMS estos y
yo opté por drupal.&lt;/p&gt;
&lt;h3&gt;Problemas con drupal&lt;/h3&gt;
&lt;p&gt;Drupal está muy bien, pero para un blog es algo así como matar moscas
a cañonazos. No es que yo tenga problemas de rendimiento o algo así en
mi blog, pero tener una base de datos, y todo el tema de php ahí
montado a día de hoy es una exageración para tener un simple blog.&lt;/p&gt;
&lt;p&gt;Estos son los principales problemas con los que me he encontrado a la
hora de usar drupal como sistema de blog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Urls limpias: Como servidor web estoy usando lighttpd &lt;a href="http://lighttpd.net"&gt;3&lt;/a&gt; y no es
fácil hacer que un drupal te muestre urls sin parámetros por get con
este servidor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Actualizaciones: Las actualizaciones de drupal no es que sean
complicadas de llevar a cabo, pero hay muchas cosas que hay que hacer
manualmente y que me molesta tener que hacer, no por falta de tiempo,
sino por pereza.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Comentarios: Últimamente me estaba empezando a entrar un montón de
spam diario en el blog a través de los comentarios, y eso que tenía
activado el módulo de recaptcha. Llegó hasta tal punto que decidí
desactivar los comentarios anónimos en mi blog.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tema: Durante el tiempo que he tenido el blog en drupal he cambiado
un par de veces de tema. Sin embargo, como soy así un poco especialito,
no me gusta poner un tema así tal cual, sino que me gusta meterle mis
modificaciones y ponerlo un poquito más a mi gusto. Pues bien, cambiar
un tema de drupal no es muy buena idea si no lo vas a mantener, porque
las actualizaciones suelen romper los temas.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;El ciclo de la web&lt;/h3&gt;
&lt;p&gt;Desde hace ya algún tiempo me he dado cuenta de que la web está
volviendo hacia atrás. Estamos volviendo un poco al pasado. Tras la
explosión de los blogs, cuando todo el mundo tenía uno, se hizo muy
famoso wordpress, drupal y este tipo de CMS, que tienen un montón de
funcionalidad, son modulares, extensibles, tienen sus temas y esas
cosas. Sin embargo, la mayoría de los blogs/páginas tienen un
contenido más bien estático y lo único realmente dinámico son los
comentarios.&lt;/p&gt;
&lt;p&gt;Antes de la llegada del php y el código en servidor, la mayoría de las
páginas webs eran simples documentos html, que se actualizaban cuando
cambiaba el contenido. No había base de datos ni nada de eso. La web
era más estática, pero requería menos mantenimiento y recursos.&lt;/p&gt;
&lt;p&gt;Hoy en día se está volviendo un poco a eso, en algunas partes. Muchas
webs están tendiendo a este tipo de soluciones por temas de
rendimiento y seguridad, servir documentos html sin código que se
ejecute en servidor es muchísimo más rápido y seguro que utilizar una
web php/python/cgi o lo que sea. Pero también se está volviendo a este
tipo de despliegues web porque es mucho más sencillo y lo anterior, en
muchos casos no tenía sentido.&lt;/p&gt;
&lt;p&gt;Aún así, la vuelta atrás no implica perder funcionalidad ni facilidad.
No tiene sentido volver a escribir las webs en html, teniendo que
copiar o repetir partes de código como cabeceras, menus, etc. Ni
tampoco tiene sentido perder funcionalidad tan importante como son los
comentarios y la interacción de los visitantes.&lt;/p&gt;
&lt;p&gt;La aparición de aplicaciones web que dan servicios son uno de los
factores que han facilitado esta vuelta atrás, por ejemplo
&lt;a href="http://disqus.com"&gt;disqus&lt;/a&gt;, que te proporciona comentarios en tu web de forma fácil,
y así te olvidas tanto de almacenarlos como del spam (en gran medida).&lt;/p&gt;
&lt;p&gt;Por esto han nacido multitud de sistemas de publicación/generación web
offline, que hacen la función de CMS, facilitando al usuario o gestor
de contenidos la tarea de la publicación y encargándose de generar el
código html que irá en el servidor.&lt;/p&gt;
&lt;p&gt;El funcionamiento de estos generadores de sitios web estáticos es
relativamente sencillo. Se basan en una serie de plantillas que
rellenan con los ficheros de contenido que se van encontrando. Los
ficheros de contenido suelen ser ficheros con un formato tipo
&lt;a href="http://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt; o algo así, para facilitar su escritura. Y buscando por
Internet se pueden encontrar &lt;a href="http://iwantmyname.com/blog/2011/02/list-static-website-generators.html"&gt;muchos diferentes&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Salto a Pelican&lt;/h3&gt;
&lt;p&gt;De entre todos los diferentes sistemas de generación de contenido
estático que existen me decanté por &lt;a href="http://docs.getpelican.com/"&gt;pelican&lt;/a&gt;. Esta elección es
meramente técnica. Pelican está escrito en python, que es un lenguaje
que domino, y utiliza el sistema de plantillas &lt;a href="http://jinja.pocoo.org/"&gt;jinja&lt;/a&gt;, que es lo
que se usa en &lt;a href="http://djangoproject.com"&gt;django&lt;/a&gt; y por lo tanto estoy familiarizado con él.&lt;/p&gt;
&lt;h3&gt;Ventajas de Pelican&lt;/h3&gt;
&lt;p&gt;La principal ventaja de utilizar Pelican es que a partir de ahora me
puedo olvidar de tener que administrar el CMS, ni actualizaciones ni
nada. El blog en el servidor será html plano, por lo que si no quiero
actualizar a la última versión de Pelican no me arriesgo a que haya
problemas de seguridad explotables o cosas así.&lt;/p&gt;
&lt;p&gt;Además de esto, el uso de Pelican trae consigo una serie de ventajas
que no podemos pasar por alto:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Gestión del blog y cambios utilizando git&lt;a href="http://git-scm.com/"&gt;11&lt;/a&gt;, esto hace que para mí
como desarrollador y usuario diario de git sea mucho más fácil
controlar los cambios que vaya haciendo en el blog, tanto de contenido
como de visualización. Además lo tengo alojado en &lt;a href="https://github.com/danigm/danigm.net"&gt;github&lt;/a&gt;, por lo
que tengo backup automágico.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Escritura de entradas del blog con &lt;a href="http://www.vim.org/"&gt;vim&lt;/a&gt;. Al escribir el
contenido desde mi máquina puedo utilizar mi editor de textos favorito
y además escribo los posts utilizando la sintaxis &lt;a href="http://en.wikipedia.org/wiki/Markdown"&gt;Markdown&lt;/a&gt; y
luego ya Pelican se encarga de transformar eso en html.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mayor control, al controlar la tecnología con la que está hecha la
herramienta de generación puedo modificar a mi gusto y tengo control
absoluto sobre mi blog.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Comentarios externalizados, con lo que me olvido del tema del
spam... Al menos por ahora.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Contras de este nuevo modelo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Comentarios externalizados, de momento así será, pero no me gusta
que haya contenido por ahí desperdigado en servidores que no conozco y
que a saber qué hacen con los comentarios que la gente hace en mi
blog. Si fuera software libre me montaría mi propio servidor de
comentarios integrado, pero al fin y al cabo esto es más fácil y al
final la desidia es lo que tiene. Sin embargo esto me duele y tarde o
temprano lo cambiaré por otra cosa que sea software libre y que me
pueda instalar en mi propio servidor controlando así que ningún ente
externo esté haciendo cosas por ahí.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No hay edición web. Esto sería un problema si quisiera poder
escribir en mi blog desde cualquier parte y con cualquier dispositivo.
Pero no es el caso, así que es un problema menor, y en un momento dado
sería solucionable metiendo una pequeña aplicación de gestión de
ficheros markdown.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Cambio mi blog por otra cosa. Esto es otra moda, como lo fue en su día
drupal y de igual manera me dejo influenciar por estas modas y cambio
mi blog a esta &lt;em&gt;nueva&lt;/em&gt; tecnología. Esto me sirve para seguir
aprendiendo cosas nuevas y ya de paso le doy un poco de vidilla a
esto, que no se puede quedar parado.&lt;/p&gt;
&lt;p&gt;Y así nos va :P&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">danigm</dc:creator><pubDate>Tue, 27 Nov 2012 00:00:00 +0100</pubDate><guid isPermaLink="false">tag:danigm.net,2012-11-27:/nuevo-blog.html</guid><category>blog</category><category>pelican</category><category>web</category></item></channel></rss>