From b319138d57f10534da3b8843d76350be8ed902b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20M=C3=A4nnchen?= Date: Mon, 1 Jun 2026 12:53:32 +0200 Subject: [PATCH 1/2] Update Broken Links / Migrate to HTTPS --- .github/workflows/check-links.yml | 44 +++++ .gitignore | 3 +- .ruby-version | 2 +- Gemfile | 1 + Gemfile.lock | 182 ++++++++++++------ README.md | 10 +- _includes/important-links.html | 4 +- _includes/top.html | 4 +- _layouts/redirect.html | 27 ++- ...inside-elixir-s-parallel-compiler.markdown | 2 +- ...2012-05-25-elixir-v0-5-0-released.markdown | 4 +- ...2012-08-01-elixir-v0-6-0-released.markdown | 2 +- ...2012-11-18-elixir-v0-7-1-released.markdown | 6 +- ...2013-01-27-elixir-v0-8-0-released.markdown | 4 +- ...-04-19-google-summer-of-code-2013.markdown | 6 +- _posts/2013-05-02-elixir-on-xen.markdown | 10 +- ...2013-05-23-elixir-v0-9-0-released.markdown | 4 +- ...013-07-13-elixir-v0-10-0-released.markdown | 6 +- .../2013-08-08-elixir-design-goals.markdown | 4 +- ...013-11-05-elixir-v0-11-0-released.markdown | 6 +- ...xir-s-new-continuable-enumerators.markdown | 2 +- ...014-04-21-elixir-v0-13-0-released.markdown | 10 +- ...014-06-17-elixir-v0-14-0-released.markdown | 2 +- ...014-08-07-elixir-v0-15-0-released.markdown | 2 +- ...2014-09-18-elixir-v1-0-0-released.markdown | 6 +- ...2015-09-28-elixir-v1-1-0-released.markdown | 6 +- ...2016-06-21-elixir-v1-3-0-released.markdown | 4 +- .../2016-07-14-announcing-genstage.markdown | 18 +- ...2017-01-05-elixir-v1-4-0-released.markdown | 2 +- ...2017-07-25-elixir-v1-5-0-released.markdown | 6 +- ...ng-and-data-generation-for-elixir.markdown | 6 +- ...2018-01-17-elixir-v1-6-0-released.markdown | 4 +- ...2018-07-25-elixir-v1-7-0-released.markdown | 2 +- ...int-a-new-http-library-for-elixir.markdown | 2 +- ...2019-06-24-elixir-v1-9-0-released.markdown | 12 +- ...020-10-06-elixir-v1-11-0-released.markdown | 2 +- ...collaboration-with-elixir-at-slab.markdown | 2 +- ...essaging-with-elixir-at-community.markdown | 2 +- ...telligence-with-elixir-at-pepsico.markdown | 6 +- ...021-05-19-elixir-v1-12-0-released.markdown | 4 +- ...ual-spaces-with-elixir-at-mozilla.markdown | 2 +- ...yer-server-with-elixir-at-x-plane.markdown | 4 +- ...f-ecological-transition-in-france.markdown | 12 +- ...021-12-03-elixir-v1-13-0-released.markdown | 2 +- ...-type-system-updates-research-dev.markdown | 2 +- ...9-20-strong-arrows-gradual-typing.markdown | 4 +- ...023-12-22-elixir-v1-16-0-released.markdown | 4 +- _posts/2024-03-05-veeps-elixir-case.markdown | 4 +- ...zier-bdds-for-set-theoretic-types.markdown | 2 +- ...type-inference-of-all-and-next-15.markdown | 2 +- _scripts/check-links | 29 +++ atom.xml | 4 +- crash-course.markdown | 2 +- css/style.css | 8 +- development.markdown | 6 +- erlang.csv | 2 +- .../mix-otp/config-and-releases.markdown | 1 + .../dependencies-and-umbrella-apps.markdown | 1 + ...ependencies-and-umbrella-projects.markdown | 1 + .../mix-otp/distributed-tasks.markdown | 1 + getting-started/mix-otp/ets.markdown | 1 + install.markdown | 8 +- js/toc/README.md | 4 +- learning.markdown | 14 +- opensearch.xml | 8 +- 65 files changed, 357 insertions(+), 202 deletions(-) create mode 100644 .github/workflows/check-links.yml create mode 100755 _scripts/check-links diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml new file mode 100644 index 000000000..0dff79cc6 --- /dev/null +++ b/.github/workflows/check-links.yml @@ -0,0 +1,44 @@ +name: Check Links + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '0 8 * * 1' + +jobs: + check-links: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + bundler-cache: true + + - name: Build site + run: bundle exec jekyll build + + - name: Restore htmlproofer cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: tmp/.htmlproofer + key: htmlproofer-${{ runner.os }}-${{ hashFiles('tmp/.htmlproofer/cache.json') }} + restore-keys: htmlproofer-${{ runner.os }}- + + - name: Check links + run: _scripts/check-links; echo "exit_code=$?" >> "$GITHUB_OUTPUT" + id: check-links + + - name: Save htmlproofer cache + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: tmp/.htmlproofer + key: htmlproofer-${{ runner.os }}-${{ hashFiles('tmp/.htmlproofer/cache.json') }} + + - name: Fail on broken links + run: exit "$EXIT_CODE" + env: + EXIT_CODE: ${{ steps['check-links'].outputs.exit_code }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 05dfac0b9..84dc3b57d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ /downloads/cheatsheets/*.aux /downloads/cheatsheets/*.log /.bundle -/vendor \ No newline at end of file +/vendor +/tmp \ No newline at end of file diff --git a/.ruby-version b/.ruby-version index 944880fa1..15a279981 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.0 +3.3.0 diff --git a/Gemfile b/Gemfile index f24d05f4a..771b2e468 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,4 @@ gem 'webrick', '>= 1.8' gem 'csv', '~> 3.3' gem 'base64', '~> 0.2.0' gem 'bigdecimal', '~> 3.1' +gem 'html-proofer', '~> 5.0' diff --git a/Gemfile.lock b/Gemfile.lock index a9529d2bc..56e6521d9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,61 +1,82 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.2.3.1) + Ascii85 (2.0.1) + activesupport (8.1.3) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) - minitest (>= 5.1, < 6) + minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) addressable (2.9.0) public_suffix (>= 2.0.2, < 8.0) + afm (1.0.0) + async (2.39.0) + console (~> 1.29) + fiber-annotation + io-event (~> 1.11) + metrics (~> 0.12) + traces (~> 0.18) base64 (0.2.0) benchmark (0.5.0) - bigdecimal (3.1.9) + bigdecimal (3.3.1) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.11.1) + coffee-script-source (1.12.2) colorator (1.1.0) - commonmarker (0.23.10) + commonmarker (0.23.12) concurrent-ruby (1.3.6) connection_pool (3.0.2) - csv (3.3.3) - dnsruby (1.61.9) - simpleidn (~> 0.1) + console (1.35.1) + fiber-annotation + fiber-local (~> 1.1) + json + csv (3.3.5) + dnsruby (1.73.1) + base64 (>= 0.2) + logger (~> 1.6) + simpleidn (~> 0.2.1) drb (2.2.3) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) - ethon (0.16.0) + ethon (0.18.0) ffi (>= 1.15.0) + logger eventmachine (1.2.7) - execjs (2.8.1) + execjs (2.10.1) faraday (2.14.2) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-net_http (3.4.2) + faraday-net_http (3.4.3) net-http (~> 0.5) - ffi (1.15.5) + ffi (1.17.4) + ffi (1.17.4-x86_64-linux-gnu) + fiber-annotation (0.2.0) + fiber-local (1.1.0) + fiber-storage + fiber-storage (1.0.1) forwardable-extended (2.6.0) - gemoji (3.0.1) - github-pages (228) - github-pages-health-check (= 1.17.9) - jekyll (= 3.9.3) - jekyll-avatar (= 0.7.0) - jekyll-coffeescript (= 1.1.1) - jekyll-commonmark-ghpages (= 0.4.0) - jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.15.1) + gemoji (4.1.0) + github-pages (232) + github-pages-health-check (= 1.18.2) + jekyll (= 3.10.0) + jekyll-avatar (= 0.8.0) + jekyll-coffeescript (= 1.2.2) + jekyll-commonmark-ghpages (= 0.5.1) + jekyll-default-layout (= 0.1.5) + jekyll-feed (= 0.17.0) jekyll-gist (= 1.5.0) - jekyll-github-metadata (= 2.13.0) + jekyll-github-metadata (= 2.16.1) jekyll-include-cache (= 0.2.1) jekyll-mentions (= 1.6.0) jekyll-optional-front-matter (= 0.3.2) @@ -82,30 +103,44 @@ GEM jekyll-theme-tactile (= 0.2.0) jekyll-theme-time-machine (= 0.2.0) jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.12.0) - kramdown (= 2.3.2) + jemoji (= 0.13.0) + kramdown (= 2.4.0) kramdown-parser-gfm (= 1.1.0) liquid (= 4.0.4) mercenary (~> 0.3) minima (= 2.5.1) - nokogiri (>= 1.13.6, < 2.0) - rouge (= 3.26.0) + nokogiri (>= 1.16.2, < 2.0) + rouge (= 3.30.0) terminal-table (~> 1.4) - github-pages-health-check (1.17.9) + webrick (~> 1.8) + github-pages-health-check (1.18.2) addressable (~> 2.3) dnsruby (~> 1.60) - octokit (~> 4.0) - public_suffix (>= 3.0, < 5.0) + octokit (>= 4, < 8) + public_suffix (>= 3.0, < 6.0) typhoeus (~> 1.3) + hashery (2.1.2) html-pipeline (2.14.3) activesupport (>= 2) nokogiri (>= 1.4) - http_parser.rb (0.8.0) + html-proofer (5.2.1) + addressable (~> 2.3) + async (~> 2.1) + benchmark (~> 0.5) + nokogiri (~> 1.13) + pdf-reader (~> 2.11) + rainbow (~> 3.0) + typhoeus (~> 1.3) + yell (~> 2.0) + zeitwerk (~> 2.5) + http_parser.rb (0.8.1) i18n (1.14.8) concurrent-ruby (~> 1.0) - jekyll (3.9.3) + io-event (1.16.1) + jekyll (3.10.0) addressable (~> 2.4) colorator (~> 1.0) + csv (~> 3.0) em-websocket (~> 0.5) i18n (>= 0.7, < 2) jekyll-sass-converter (~> 1.0) @@ -116,27 +151,28 @@ GEM pathutil (~> 0.9) rouge (>= 1.7, < 4) safe_yaml (~> 1.0) - jekyll-avatar (0.7.0) + webrick (>= 1.0) + jekyll-avatar (0.8.0) jekyll (>= 3.0, < 5.0) - jekyll-coffeescript (1.1.1) + jekyll-coffeescript (1.2.2) coffee-script (~> 2.2) - coffee-script-source (~> 1.11.1) + coffee-script-source (~> 1.12) jekyll-commonmark (1.4.0) commonmarker (~> 0.22) - jekyll-commonmark-ghpages (0.4.0) - commonmarker (~> 0.23.7) - jekyll (~> 3.9.0) + jekyll-commonmark-ghpages (0.5.1) + commonmarker (>= 0.23.7, < 1.1.0) + jekyll (>= 3.9, < 4.0) jekyll-commonmark (~> 1.4.0) rouge (>= 2.0, < 5.0) - jekyll-default-layout (0.1.4) - jekyll (~> 3.0) - jekyll-feed (0.15.1) + jekyll-default-layout (0.1.5) + jekyll (>= 3.0, < 5.0) + jekyll-feed (0.17.0) jekyll (>= 3.7, < 5.0) jekyll-gist (1.5.0) octokit (~> 4.2) - jekyll-github-metadata (2.13.0) + jekyll-github-metadata (2.16.1) jekyll (>= 3.4, < 5.0) - octokit (~> 4.0, != 4.4.0) + octokit (>= 4, < 7, != 4.4.0) jekyll-include-cache (0.2.1) jekyll (>= 3.7, < 5.0) jekyll-mentions (1.6.0) @@ -207,80 +243,98 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - jemoji (0.12.0) - gemoji (~> 3.0) + jemoji (0.13.0) + gemoji (>= 3, < 5) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - json (2.6.3) - kramdown (2.3.2) + json (2.19.7) + kramdown (2.4.0) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) liquid (4.0.4) - listen (3.8.0) + listen (3.10.0) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logger (1.7.0) mercenary (0.3.6) + metrics (0.15.0) mini_portile2 (2.8.9) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.27.0) + minitest (6.0.6) + drb (~> 2.0) + prism (~> 1.5) net-http (0.9.1) uri (>= 0.11.1) nokogiri (1.19.3) mini_portile2 (~> 2.8.2) racc (~> 1.4) + nokogiri (1.19.3-x86_64-linux-gnu) + racc (~> 1.4) octokit (4.25.1) faraday (>= 1, < 3) sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (4.0.7) + pdf-reader (2.15.1) + Ascii85 (>= 1.0, < 3.0, != 2.0.0) + afm (>= 0.2.1, < 2) + hashery (~> 2.0) + ruby-rc4 + ttfunk + prism (1.9.0) + public_suffix (5.1.1) racc (1.8.1) + rainbow (3.1.1) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - rexml (3.4.2) - rouge (3.26.0) - rubyzip (2.3.2) + rexml (3.4.4) + rouge (3.30.0) + ruby-rc4 (0.1.5) + rubyzip (2.4.1) safe_yaml (1.0.5) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sawyer (0.9.2) + sawyer (0.9.3) addressable (>= 2.3.5) faraday (>= 0.17.3, < 3) securerandom (0.4.1) - simpleidn (0.2.1) - unf (~> 0.1.4) + simpleidn (0.2.3) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - typhoeus (1.4.0) - ethon (>= 0.9.0) + traces (0.18.2) + ttfunk (1.8.0) + bigdecimal (~> 3.1) + typhoeus (1.6.0) + ethon (>= 0.18.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) unicode-display_width (1.8.0) uri (1.1.1) - webrick (1.8.2) + webrick (1.9.2) + yell (2.2.2) + zeitwerk (2.8.2) PLATFORMS ruby + x86_64-linux-gnu DEPENDENCIES base64 (~> 0.2.0) bigdecimal (~> 3.1) csv (~> 3.3) github-pages + html-proofer (~> 5.0) json (>= 2.0.0) webrick (>= 1.8) BUNDLED WITH - 2.5.23 + 2.7.2 diff --git a/README.md b/README.md index a091828d8..ec2d743f9 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ it, nice instructions are available #### 2. Install Ruby This website is compiled into a static website using -[Jekyll](http://jekyllrb.com), a static-site generator written in Ruby. To +[Jekyll](https://jekyllrb.com), a static-site generator written in Ruby. To install Ruby you can follow [this guide](https://www.ruby-lang.org/en/documentation/installation/). To check that Ruby is installed correctly, run `ruby --version` in your shell; it should be @@ -23,7 +23,7 @@ Ruby is installed correctly, run `ruby --version` in your shell; it should be #### 3. Install Bundler to manage dependencies -[Bundler](http://bundler.io) handles Ruby dependencies. To install it, simply +[Bundler](https://bundler.io) handles Ruby dependencies. To install it, simply run: ```bash @@ -63,8 +63,8 @@ guide](https://github.com/elixir-lang/elixir/#contributing). * "Elixir" and the Elixir logo are registered trademarks of the Elixir team. See [our trademark policy](https://elixir-lang.org/trademarks). -* The HTML and CSS are copyrighted to [AlienWp](http://alienwp.com/) under [GPL license, version 2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html). +* The HTML and CSS are copyrighted to [AlienWp](https://alienwp.com/) under [GPL license, version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). -* The Social Icons are copyrighted to [Xeloader](http://xeloader.deviantart.com/art/Socialis-2-Freebie-213292616). +* The Social Icons are copyrighted to [Xeloader](https://xeloader.deviantart.com/art/Socialis-2-Freebie-213292616). -* The written textual contents available in the guides and blog are licensed under [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). +* The written textual contents available in the guides and blog are licensed under [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/_includes/important-links.html b/_includes/important-links.html index c4d5c0702..b577f9aee 100644 --- a/_includes/important-links.html +++ b/_includes/important-links.html @@ -28,8 +28,8 @@

Join the Community

  • Hex.pm package manager
  • @elixirlang on Twitter
  • #elixir on irc.libera.chat
  • -
  • Elixir Forum
  • -
  • Elixir on Slack
  • +
  • Elixir Forum
  • +
  • Elixir on Slack
  • Elixir on Discord
  • - + - + {% seo title=false %} diff --git a/_layouts/redirect.html b/_layouts/redirect.html index 66ee7a8f8..227d74b7e 100644 --- a/_layouts/redirect.html +++ b/_layouts/redirect.html @@ -1,14 +1,35 @@ +{% if page.redirect_to %} +{% if page.redirect_version %} + + + +{% else %} +{% endif %} +{% else %} + + + +{% endif %}

    Redirecting...

    -
    Click here if you are not redirected. + {% if page.redirect_to %} + {% if page.redirect_version %} + Click here if you are not redirected. + + {% else %} + Click here if you are not redirected. + {% endif %} + {% else %} + Click here if you are not redirected. + + {% endif %} - - + \ No newline at end of file diff --git a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown index 591610198..1d6e639b5 100644 --- a/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown +++ b/_posts/2012-04-24-a-peek-inside-elixir-s-parallel-compiler.markdown @@ -75,7 +75,7 @@ In order to customize this process, we are going to take a look at Erlang's erro ## Custom error handler -By default, Elixir (and Erlang) code is autoloaded. This means that, if we invoke `List.delete` and the module `List` was not loaded yet, the Erlang VM is going to look into the `ebin` directory (the directory where we put compiled files) and try to load it. This process is controlled by the [`error_handler` module in Erlang](http://www.erlang.org/doc/man/error_handler.html) via two callback functions: `undefined_function` and `undefined_lambda`. +By default, Elixir (and Erlang) code is autoloaded. This means that, if we invoke `List.delete` and the module `List` was not loaded yet, the Erlang VM is going to look into the `ebin` directory (the directory where we put compiled files) and try to load it. This process is controlled by the [`error_handler` module in Erlang](https://www.erlang.org/doc/man/error_handler.html) via two callback functions: `undefined_function` and `undefined_lambda`. As discussed in the previous section, we want to extend the error handler to actually stop the currently running process whenever a module is not found and resume the process only after we ensure the module is compiled. To do that, we can simply define our own error handler and ask Erlang to use it. Our custom error handler is defined as follows: diff --git a/_posts/2012-05-25-elixir-v0-5-0-released.markdown b/_posts/2012-05-25-elixir-v0-5-0-released.markdown index 3889f1b2a..952db450f 100644 --- a/_posts/2012-05-25-elixir-v0-5-0-released.markdown +++ b/_posts/2012-05-25-elixir-v0-5-0-released.markdown @@ -22,13 +22,13 @@ After not feeling productive enough with that Elixir version, I have decided to It was around October 2011, during a short stay in San Francisco, that I came up with what would be [the foundation of Elixir's current version](https://github.com/josevalim/lego-lang) with the help of Yehuda Katz. Development of the new Elixir version started a few days before 2012 and continued steady when the new year came in. -Around February of that year, feeling confident enough about the direction the language was moving (and initial benchmarks I had made at that point), I have pitched Elixir to [my company, Plataformatec](http://plataformatec.com.br/), and they have accepted to sponsor Elixir. With their help, Elixir developed even faster and that's what we are going to take a look next. +Around February of that year, feeling confident enough about the direction the language was moving (and initial benchmarks I had made at that point), I have pitched Elixir to [my company, Plataformatec](https://plataformatec.com.br/), and they have accepted to sponsor Elixir. With their help, Elixir developed even faster and that's what we are going to take a look next. ## Where we are One of the goals we have set was to have a good website and documentation before the next official release. With the help of the Plataformatec team, we created a logo for Elixir and put this website live. -At the same time, [we were working on pygments support](https://bitbucket.org/birkenfeld/pygments-main/pull-request/57/add-elixir-and-elixir-console-lexers), a [documentation generation tool](https://github.com/elixir-lang/ex_doc) and many others. Soon, GitHub was able to syntax highlight Elixir code and [our API documentation was online](/). +At the same time, [we were working on pygments support](https://web.archive.org/web/20160804045840/https://bitbucket.org/birkenfeld/pygments-main/pull-requests/57/add-elixir-and-elixir-console-lexers), a [documentation generation tool](https://github.com/elixir-lang/ex_doc) and many others. Soon, GitHub was able to syntax highlight Elixir code and [our API documentation was online](/). At the same time, people started to gather around #elixir-lang channel on irc.freenode.net (now migrated to #elixir on irc.libera.chat) to [play with Elixir](https://github.com/elixir-lang/elixir/tree/main/lib/mix), [start their](https://github.com/guedes/exdate) [own projects](https://github.com/yrashk/validatex) and [tutorials](https://github.com/alco/elixir/wiki/Erlang-Syntax:-A-Crash-Course). diff --git a/_posts/2012-08-01-elixir-v0-6-0-released.markdown b/_posts/2012-08-01-elixir-v0-6-0-released.markdown index 5ae592b90..5ad512bd0 100644 --- a/_posts/2012-08-01-elixir-v0-6-0-released.markdown +++ b/_posts/2012-08-01-elixir-v0-6-0-released.markdown @@ -15,7 +15,7 @@ We have finally released [Elixir](/) v0.6.0! This release includes a build tool When [we released version v0.5.0](/blog/2012/05/25/elixir-v0-5-0-released/), we have set three major goals for release v0.6.0: 1. Provide a build tool that makes it easy to create, compile and test Elixir projects; -2. Support [Erlang typespecs](http://www.erlang.org/doc/reference_manual/typespec.html); +2. Support [Erlang typespecs](https://www.erlang.org/doc/reference_manual/typespec.html); 3. Improve IO and File modules to be more robust and complete. Our interactive shell (IEx) also had many improvements, thanks to the Elixir developer community. We now have easy access to documentation, remote shells, autocomplete and much more. In order to show you a bit of what you can do in this release, we have prepared a short (~6 min) screencast: diff --git a/_posts/2012-11-18-elixir-v0-7-1-released.markdown b/_posts/2012-11-18-elixir-v0-7-1-released.markdown index 92ade906a..b33108e1c 100644 --- a/_posts/2012-11-18-elixir-v0-7-1-released.markdown +++ b/_posts/2012-11-18-elixir-v0-7-1-released.markdown @@ -10,13 +10,13 @@ excerpt: Elixir v0.7.1 was released to celebrate the end of a two months journey Elixir v0.7.1 was released this weekend to celebrate the end of a two months journey traveling around Europe, United States and Brazil talking about and exposing Elixir to new developers. -This is a minor release that contains a couple enhancements regarding UTF-8, [dialyzer](http://www.erlang.org/doc/man/dialyzer.html) support and bug fixes. +This is a minor release that contains a couple enhancements regarding UTF-8, [dialyzer](https://www.erlang.org/doc/man/dialyzer.html) support and bug fixes. -During this time traveling around, we have spoken at many conferences, as [Strange Loop](http://thestrangeloop.com/), [Øredev](http://oredev.org/), [QCon SP](http://qconsp.com/) and [Rupy](http://rupy.eu/) as well as at different companies. Developers from different backgrounds have shown interest in Elixir, [written about it](http://spin.atomicobject.com/2012/10/31/elixir-erlang-and-the-dining-philosophers/), and contributed to the language. As of today, Elixir is powered by 51 different contributors! +During this time traveling around, we have spoken at many conferences, as [Strange Loop](https://thestrangeloop.com/), [Øredev](https://oredev.org/), [QCon SP](https://web.archive.org/web/20131228191344/http://qconsp.com/) and [Rupy](https://web.archive.org/web/20130113224620/http://rupy.eu/) as well as at different companies. Developers from different backgrounds have shown interest in Elixir, [written about it](https://spin.atomicobject.com/2012/10/31/elixir-erlang-and-the-dining-philosophers/), and contributed to the language. As of today, Elixir is powered by 51 different contributors! In case you missed any of those conferences, [the talk I presented at Øredev is available and you can watch it now](https://vimeo.com/53221562). The slides are also available below. If you want to hear more about Elixir at a conference or an event, please let us know. Thank you and don't forget to [give Elixir a try](https://elixir.hexdocs.pm/introduction.html)! - + diff --git a/_posts/2013-01-27-elixir-v0-8-0-released.markdown b/_posts/2013-01-27-elixir-v0-8-0-released.markdown index c20d78166..7c8f87c70 100644 --- a/_posts/2013-01-27-elixir-v0-8-0-released.markdown +++ b/_posts/2013-01-27-elixir-v0-8-0-released.markdown @@ -29,7 +29,7 @@ Elixir favors the use of UTF-8 binaries since its first release. In the latest r String.capitalize("fiN") #=> "Fin" ``` -The example above contains a string with only two codepoints, [the codepoint fi](http://www.fileformat.info/info/unicode/char/FB01/index.htm) and [the codepoint n](http://www.fileformat.info/info/unicode/char/006E/index.htm). Look how Elixir properly capitalizes the string, returning a new string made of three codepoints (all ascii letters). +The example above contains a string with only two codepoints, [the codepoint fi](https://www.fileformat.info/info/unicode/char/FB01/index.htm) and [the codepoint n](https://www.fileformat.info/info/unicode/char/006E/index.htm). Look how Elixir properly capitalizes the string, returning a new string made of three codepoints (all ascii letters). Learn more about [Unicode support with the String module](https://elixir.hexdocs.pm/String.html). @@ -79,7 +79,7 @@ Elixir v0.8 contains a bit of house cleaning too. We have created [the Path modu ## The new HashDict -For last but not least, Elixir ships with a [new HashDict implementation](https://github.com/elixir-lang/elixir/blob/main/lib/elixir/lib/hash_dict.ex). In Erlang, there are different key-value store implementations and often you need to pick which one is the best for you based on the average size of the dictionary. Generally speaking, [orddicts](http://www.erlang.org/doc/man/orddict.html) are efficient and fast when you want to hold a handful of items, otherwise you should consider [gb_trees](http://www.erlang.org/doc/man/gb_trees.html) unless you want to hold thousands of items, when then [dict](http://www.erlang.org/doc/man/dict.html) becomes your best option. The fact those implementations do not provide the same API, makes it harder to change your code when you realize another implementation would be better fit. +For last but not least, Elixir ships with a [new HashDict implementation](https://github.com/elixir-lang/elixir/blob/main/lib/elixir/lib/hash_dict.ex). In Erlang, there are different key-value store implementations and often you need to pick which one is the best for you based on the average size of the dictionary. Generally speaking, [orddicts](https://www.erlang.org/doc/man/orddict.html) are efficient and fast when you want to hold a handful of items, otherwise you should consider [gb_trees](https://www.erlang.org/doc/man/gb_trees.html) unless you want to hold thousands of items, when then [dict](https://www.erlang.org/doc/man/dict.html) becomes your best option. The fact those implementations do not provide the same API, makes it harder to change your code when you realize another implementation would be better fit. For Elixir, we decided to have a single dictionary implementation that would scale as needed. It would start as a compact representation for a handful of items and expand and rehash accordingly as new items are added or removed, providing fast access and modification times on all ranges. We are glad to say our goals were reached and a new `HashDict` implementation ships with Elixir v0.8. diff --git a/_posts/2013-04-19-google-summer-of-code-2013.markdown b/_posts/2013-04-19-google-summer-of-code-2013.markdown index d964d7c1b..2460864d4 100644 --- a/_posts/2013-04-19-google-summer-of-code-2013.markdown +++ b/_posts/2013-04-19-google-summer-of-code-2013.markdown @@ -8,12 +8,12 @@ excerpt: Elixir is taking part in Google Summer of Code 2013! Are you a student? --- We are pleased to announce that Elixir is taking part in Google Summer of Code 2013 -as member of the [BEAM Community](http://beamcommunity.github.io). This means that +as member of the [BEAM Community](https://beamcommunity.github.io). This means that students all around the world can get paid to work on Elixir during the summer! The rules require students to be enrolled in college full or part-time, and to be at least 18 years by May 27, 2013. You can find more information on -[Google Summer of Code 2013 website](http://www.google-melange.com/gsoc/homepage/google/gsoc2013). +[Google Summer of Code 2013 website](https://web.archive.org/web/20130319061251/http://www.google-melange.com/gsoc/homepage/google/gsoc2013). We have published [a list of ideas we would like to see and explore in Elixir](https://github.com/beamcommunity/beamcommunity.github.com/wiki/Project:-Elixir) that students can use as a basis, but students are also free to send their own @@ -22,7 +22,7 @@ course of three months to work on Elixir. Students can start submitting their proposals on April 22 and the deadline is May 23. Note the BEAM Community serves as a mentoring organization for many other projects -that run on the Erlang VM, including Elixir. To see the full list, [visit the website](http://beamcommunity.github.io). +that run on the Erlang VM, including Elixir. To see the full list, [visit the website](https://beamcommunity.github.io). We hope to work with you during this summer! If you have more questions, feel free to join the [BEAM Community mailing list](https://groups.google.com/d/forum/beam-community) diff --git a/_posts/2013-05-02-elixir-on-xen.markdown b/_posts/2013-05-02-elixir-on-xen.markdown index 9f1de4c2b..14b432230 100644 --- a/_posts/2013-05-02-elixir-on-xen.markdown +++ b/_posts/2013-05-02-elixir-on-xen.markdown @@ -7,7 +7,7 @@ category: Announcements excerpt: The Erlang on Xen team has added support for Elixir and we will tell you how you can use it! --- -Elixir uses Erlang underneath, all the way down. Thanks to this, an Elixir project can run on the recently revealed "OS-less" Erlang VM called LING VM. LING VM is the core technology of [Erlang on Xen](http://erlangonxen.org). +Elixir uses Erlang underneath, all the way down. Thanks to this, an Elixir project can run on the recently revealed "OS-less" Erlang VM called LING VM. LING VM is the core technology of [Erlang on Xen](https://erlangonxen.org). ## Why Xen? @@ -15,7 +15,7 @@ Elixir uses Erlang underneath, all the way down. Thanks to this, an Elixir proje Elixir on Xen runs on top of the Xen Hypervisor (via the LING VM) but with no traditional OS underneath it, taking away numerous administrative, scalability, and performance issues. This limits options of a malicious attacker, making it an excellent choice for high-security applications, and reduces startup latency, allowing developers to spawn new VMs in less than 100 milliseconds. -You can learn more about Xen and the LING VM on the [Erlang on Xen website](http://erlangonxen.org). +You can learn more about Xen and the LING VM on the [Erlang on Xen website](https://erlangonxen.org). ## Getting started @@ -41,7 +41,7 @@ to the mix tool (`lingex.build`, `lingex.image`, and `lingex.build_image`) password: "test" ] ] end -4. Optionally, you may register with the build service [here](http://build.erlangonxen.org/register) and update the credentials accordingly. For the complete list of recognized options see the build service documentation. +4. Optionally, you may register with the build service [here](https://web.archive.org/web/20150227101849/http://build.erlangonxen.org/register) and update the credentials accordingly. For the complete list of recognized options see the build service documentation. 5. Run `mix lingex.build_image`. This will archive all `*.beam` files of your project and submit them to the build service. @@ -66,6 +66,6 @@ This will bring you to Interactive Elixir and you can execute Elixir expressions ## Summing up -Running Elixir on Xen opens up many possibilities to Elixir developers. We are very thankful for the work done by [Erlang on Xen team](http://erlangonxen.org), who added support for Elixir and the `lingex` build tool. +Running Elixir on Xen opens up many possibilities to Elixir developers. We are very thankful for the work done by [Erlang on Xen team](https://erlangonxen.org), who added support for Elixir and the `lingex` build tool. -Erlang on Xen (and consequently Elixir on Xen) is still in active development, so don't forget to read more about its concepts, use cases and limitations on [Erlang on Xen website](http://erlangonxen.org/). +Erlang on Xen (and consequently Elixir on Xen) is still in active development, so don't forget to read more about its concepts, use cases and limitations on [Erlang on Xen website](https://erlangonxen.org/). diff --git a/_posts/2013-05-23-elixir-v0-9-0-released.markdown b/_posts/2013-05-23-elixir-v0-9-0-released.markdown index 7fb2b5d07..50a1a05c0 100644 --- a/_posts/2013-05-23-elixir-v0-9-0-released.markdown +++ b/_posts/2013-05-23-elixir-v0-9-0-released.markdown @@ -25,7 +25,7 @@ defrecord User, name: nil, age: nil Records are a good scenario because they are implemented in Elixir, using Elixir macros, and they also define a module underneath, which exercises the Erlang VM compilation stack. -We have used [fprof](http://www.erlang.org/doc/man/fprof.html) to identify the bottlenecks and made the compilation stack 35% faster. We have also identified bottlenecks coming from Erlang and [pushed some patches](https://github.com/erlang/otp/commit/32b194495f353dde014b00008a630eeff2a71056) that should benefit both Elixir and Erlang code. +We have used [fprof](https://www.erlang.org/doc/man/fprof.html) to identify the bottlenecks and made the compilation stack 35% faster. We have also identified bottlenecks coming from Erlang and [pushed some patches](https://github.com/erlang/otp/commit/32b194495f353dde014b00008a630eeff2a71056) that should benefit both Elixir and Erlang code. A special thanks to [Yurii Rashkovskii](https://github.com/yrashk) for the data and profiling. @@ -115,7 +115,7 @@ This approach solves all the problems above: * Reducers do not dictate how a type should be enumerated. This means types like `Range` and `HashDict` can provide a much faster implementation for Reducers; * Furthermore, the end result is a cleaner implementation of most of `Enum` functions (the [reducers pull request](https://github.com/elixir-lang/elixir/pull/1102) removes over 500LOC) and better performance! -Reducers also opens up room for lazy and parallel enumeration, as [the Clojure community has already proven](http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html) and something we are looking forward to explore on upcoming releases. +Reducers also opens up room for lazy and parallel enumeration, as [the Clojure community has already proven](https://clojure.org/news/2012/05/08/reducers) and something we are looking forward to explore on upcoming releases. A special thanks to [Eric Meadows-Jonsson](https://github.com/ericmj) for implementing this feature! diff --git a/_posts/2013-07-13-elixir-v0-10-0-released.markdown b/_posts/2013-07-13-elixir-v0-10-0-released.markdown index e7e0263cc..e8735f9cd 100644 --- a/_posts/2013-07-13-elixir-v0-10-0-released.markdown +++ b/_posts/2013-07-13-elixir-v0-10-0-released.markdown @@ -61,11 +61,11 @@ Stream.repeatedly(fn -> :random.uniform end) |> Enum.take(3) This release also adds [the Sets API](https://elixir.hexdocs.pm/Set.html) to Elixir and a HashSet implementation. The HashSet implementation follows [the same design goals as the HashDict implementation](/blog/2013/01/27/elixir-v0-8-0-released/) released at the beginning of this year, starting with a compact representation and expanding and contracting as needed. -This feature was a contribution from [Joseph Wilk](https://github.com/josephwilk) and he talks about its implementation and provides some benchmarks [on his blog](http://blog.josephwilk.net/elixir/sets-in-elixir.html). +This feature was a contribution from [Joseph Wilk](https://github.com/josephwilk) and he talks about its implementation and provides some benchmarks [on his blog](https://blog.josephwilk.net/elixir/sets-in-elixir.html). ## Pretty printing -Another addition to this release is pretty printing. The pretty printing started as an implementation of the [Wadler paper](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf) by [Jonns Mostovoys](https://github.com/manpages) which was then improved by [Gustavo Brunoro](https://github.com/brunoro) under his Google Summer of Code project as described in [Lindig's _Strictly Prettier_ paper](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.2200). +Another addition to this release is pretty printing. The pretty printing started as an implementation of the [Wadler paper](https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf) by [Jonns Mostovoys](https://github.com/manpages) which was then improved by [Gustavo Brunoro](https://github.com/brunoro) under his Google Summer of Code project as described in [Lindig's _Strictly Prettier_ paper](https://lindig.github.io/papers/strictly-pretty-2000.pdf). As soon as you upgrade to Elixir v0.10.0 and start IEx, you will get pretty printing for all data structures provided by Elixir. We have also added documentation to the `Inspect` module about [adding pretty printing to your own structures](https://elixir.hexdocs.pm/Inspect.html) as well as [using the document algebra for any other kind of formatting](https://elixir.hexdocs.pm/Inspect.Algebra.html). @@ -81,6 +81,6 @@ Other notable improvements are: * Meta-programming in Elixir was also improved by the addition of the `binding/0` and `binding/1` macros plus the additions of `Macro.expand_once/2` and `Macro.expand_all/2` to the [`Macro` module](https://elixir.hexdocs.pm/Macro.html); -There are also improvements to typespecs, error messages, many bug fixes and some backwards incompatible changes. We have posted a detailed [upgrade instructions on the mailing list](https://groups.google.com/forum/?fromgroups#!topic/elixir-lang-talk/ksrefrgK1eY). For a general overview, [check out the CHANGELOG](https://github.com/elixir-lang/elixir/blob/v0.10.0/CHANGELOG.md). +There are also improvements to typespecs, error messages, many bug fixes and some backwards incompatible changes. We have posted a detailed [upgrade instructions on the mailing list](https://groups.google.com/g/elixir-lang-talk/c/ksrefrgK1eY). For a general overview, [check out the CHANGELOG](https://github.com/elixir-lang/elixir/blob/v0.10.0/CHANGELOG.md). Give Elixir a try! You can start with our [getting started guide](https://elixir.hexdocs.pm/introduction.html), or check out our sidebar for other learning resources. diff --git a/_posts/2013-08-08-elixir-design-goals.markdown b/_posts/2013-08-08-elixir-design-goals.markdown index 47fa06cf1..adb8c1c54 100644 --- a/_posts/2013-08-08-elixir-design-goals.markdown +++ b/_posts/2013-08-08-elixir-design-goals.markdown @@ -25,9 +25,9 @@ We frequently say that **the Erlang VM is Elixir's strongest asset**. All Elixir code is executed inside light-weight processes (actors), each with its own state, that exchange messages between each other. The Erlang VM multiplexes those processes onto many cores, making it trivial to run code concurrently. -In fact if you compile any Elixir code, including the Elixir source, you will see all cores on your machine being used out of the box. With [technologies like Parallella](http://www.parallella.org/board/) becoming more accessible and affordable, it is hard to ignore the power you can get out of the Erlang VM. +In fact if you compile any Elixir code, including the Elixir source, you will see all cores on your machine being used out of the box. With [technologies like Parallella](https://www.parallella.org/board/) becoming more accessible and affordable, it is hard to ignore the power you can get out of the Erlang VM. -Finally, the Erlang VM was designed to build systems that run forever, self-heal and scale. Joe Armstrong, one of Erlang's creators, has recently given an excellent talk [about the design decisions behind OTP and the VM](http://www.infoq.com/presentations/self-heal-scalable-system). +Finally, the Erlang VM was designed to build systems that run forever, self-heal and scale. Joe Armstrong, one of Erlang's creators, has recently given an excellent talk [about the design decisions behind OTP and the VM](https://www.infoq.com/presentations/self-heal-scalable-system). Nothing that we are describing here is particularly new. Open source projects like CouchDB, Riak, RabbitMQ, Chef11 and companies like Ericsson, Heroku, Basho, Klarna and Wooga are already enjoying the benefits provided by the Erlang VM, some of them for quite a long time. diff --git a/_posts/2013-11-05-elixir-v0-11-0-released.markdown b/_posts/2013-11-05-elixir-v0-11-0-released.markdown index 669b41fe3..8abe93fdd 100644 --- a/_posts/2013-11-05-elixir-v0-11-0-released.markdown +++ b/_posts/2013-11-05-elixir-v0-11-0-released.markdown @@ -23,7 +23,7 @@ In this new release, IEx also supports a very simple debugging mechanism called ![IEx pry example](/images/contents/iex-pry.png) -In Elixir, your code runs in many processes that talk to each other and the Elixir shell is no different. `IEx.pry` allows another process to take over the shell, allowing the developer to inspect the binding and halt the execution of the process being "pried" (i.e. the one that invoked `IEx.pry`). We called this feature `pry` as a gentle reminder that you can only inspect existing information, you cannot change the binding over a pried process. For more information, check the docs for [`IEx.pry/1`](https://iex.hexdocs.pm/IEx.html#pry/1). +In Elixir, your code runs in many processes that talk to each other and the Elixir shell is no different. `IEx.pry` allows another process to take over the shell, allowing the developer to inspect the binding and halt the execution of the process being "pried" (i.e. the one that invoked `IEx.pry`). We called this feature `pry` as a gentle reminder that you can only inspect existing information, you cannot change the binding over a pried process. For more information, check the docs for [`IEx.pry/0`](https://iex.hexdocs.pm/IEx.html#pry/0). ## ExUnit @@ -62,9 +62,9 @@ fun.(1..3) You can learn more about the [new capture operator in our docs](https://elixir.hexdocs.pm/Kernel.SpecialForms.html#&/1). -We have also pushed improvements to [the String module](https://elixir.hexdocs.pm/String.html), including new APIs. In particular, in order to know that `String.length("josé")` has length 4 (even though it takes 5 bytes to be represented in UTF-8), we need to use some algorithms defined by the Unicode Standard. These have been implemented as specified in the [extended grapheme cluster algorithm, defined in the version 6.3.0 of the Unicode Standard](http://www.unicode.org/reports/tr29/). +We have also pushed improvements to [the String module](https://elixir.hexdocs.pm/String.html), including new APIs. In particular, in order to know that `String.length("josé")` has length 4 (even though it takes 5 bytes to be represented in UTF-8), we need to use some algorithms defined by the Unicode Standard. These have been implemented as specified in the [extended grapheme cluster algorithm, defined in the version 6.3.0 of the Unicode Standard](https://www.unicode.org/reports/tr29/). -In the optimization front, we have pushed the first iteration of a [feature called Protocol consolidation](https://groups.google.com/forum/#!topic/elixir-lang-core/RoXAUtoyjk4), which speeds up the polymorphic dispatch done by protocols, sometimes reducing the dispatching time to 10% of the original time. We will continue working in upcoming releases to integrate protocol consolidation as a regular part of the developer workflow. +In the optimization front, we have pushed the first iteration of a [feature called Protocol consolidation](https://groups.google.com/g/elixir-lang-core/c/RoXAUtoyjk4), which speeds up the polymorphic dispatch done by protocols, sometimes reducing the dispatching time to 10% of the original time. We will continue working in upcoming releases to integrate protocol consolidation as a regular part of the developer workflow. And finally, a minor but frequently asked feature has finally arrived into Elixir: variables follow the same rules as other identifiers in the language, which means developers can now name their variables `is_atom?`. For a general overview, [check out the CHANGELOG](https://github.com/elixir-lang/elixir/blob/v0.11.0/CHANGELOG.md). diff --git a/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown b/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown index b29807cb4..9ad5875a6 100644 --- a/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown +++ b/_posts/2013-12-11-elixir-s-new-continuable-enumerators.markdown @@ -98,7 +98,7 @@ producer "stop for now but be prepared to continue where you left off later". At CodeMeshIO José Valim and Jessica Kerr sat down and discussed this problem. They came up with a solution inspired by a [Monad.Reader -article](http://themonadreader.files.wordpress.com/2010/05/issue16.pdf) (third +article](https://themonadreader.files.wordpress.com/2010/05/issue16.pdf) (third article). It's an elegant extension of the old system, based on a simple idea. Instead of returning only an accumulator at every step (for every produced value) the consumer returns a combination of an accumulator and an instruction diff --git a/_posts/2014-04-21-elixir-v0-13-0-released.markdown b/_posts/2014-04-21-elixir-v0-13-0-released.markdown index 2d9c09b32..1adcefa00 100644 --- a/_posts/2014-04-21-elixir-v0-13-0-released.markdown +++ b/_posts/2014-04-21-elixir-v0-13-0-released.markdown @@ -15,7 +15,7 @@ Before we go into the changes, let's briefly talk about ElixirConf! ## ElixirConf -We are excited to announce [ElixirConf](http://elixirconf.com), the first ever Elixir conference, happening July 25-26, 2014 in Austin, TX. The Call For Proposals is open and we are waiting for your talks! +We are excited to announce [ElixirConf](https://elixirconf.com), the first ever Elixir conference, happening July 25-26, 2014 in Austin, TX. The Call For Proposals is open and we are waiting for your talks! The registration is also open and we hope you will join us on this exciting event. We welcome Elixir developers and enthusiasts that are looking forward to be part of our thrilling community! @@ -69,7 +69,7 @@ iex> %{"other" => value} = map A map pattern will match any map that has all the keys specified in the pattern. The values for the matching keys must also match. For example, `%{"hello" => world}` will match any map that has the key `"hello"` and assign the value to `world`, while `%{"hello" => "world"}` will match any map that has the key `"hello"` with value equals to `"world"`. An empty map pattern (`%{}`) will match all maps. -Developers can use the functions in the [`Map` module](https://elixir.hexdocs.pm/Map.html) to work with maps. For more information on maps and how they compare to other associative data structures in the language, please check the [Maps chapter in our new Getting Started guide](https://elixir.hexdocs.pm/keywords-and-maps.html). Elixir Sips has also released two episodes that cover maps ([part 1](http://elixirsips.com/episodes/054_maps_part_1.html) and [part 2](http://elixirsips.com/episodes/055_maps_part_2.html)). +Developers can use the functions in the [`Map` module](https://elixir.hexdocs.pm/Map.html) to work with maps. For more information on maps and how they compare to other associative data structures in the language, please check the [Maps chapter in our new Getting Started guide](https://elixir.hexdocs.pm/keywords-and-maps.html). Elixir Sips has also released two episodes that cover maps ([part 1](https://web.archive.org/web/20260514135945/http://elixirsips.com/episodes/054_maps_part_1.html) and [part 2](https://web.archive.org/web/20260514135945/http://elixirsips.com/episodes/055_maps_part_2.html)). Maps also provide special syntax for creating, accessing and updating maps with atom keys: @@ -145,7 +145,7 @@ Since maps are meant to replace many cases of records in Erlang, we saw with the 3. Compile-time structures with compile-time errors 4. The basic foundation for polymorphism in Elixir -Maps naturally solve issues `1.` and `2.` above. In particular, maps that have same keys share the same key-space in memory. That's why the update operation `%{map | ...}` we have seen above is relevant: if we know we are updating an existing key, the new map created as result of the update operation can share the same key space as the old map without extra checks. For more details on why Maps are efficient, I would recommend [reading Joe's blog post on the matter](http://joearms.github.io/2014/02/01/big-changes-to-erlang.html). +Maps naturally solve issues `1.` and `2.` above. In particular, maps that have same keys share the same key-space in memory. That's why the update operation `%{map | ...}` we have seen above is relevant: if we know we are updating an existing key, the new map created as result of the update operation can share the same key space as the old map without extra checks. For more details on why Maps are efficient, I would recommend [reading Joe's blog post on the matter](https://web.archive.org/web/20161220040820/http://joearms.github.io/2014/02/01/big-changes-to-erlang.html). Structs were added to address features `3.` and `4.`. A struct needs to be explicitly defined via `defstruct`: @@ -277,7 +277,7 @@ That said, in the next months we plan to: * Integrate applications configuration (provided by OTP) right into Mix; * Provide an Elixir logger that knows how to print and format Elixir exceptions and stacktraces; * Properly expose the functionality provided by Applications, Supervisors, GenServers and GenEvents and study how they can integrate with Elixir. For example, how to consume events from GenEvent as a [stream of data](https://elixir.hexdocs.pm/Stream.html)? -* Study how patterns like tasks and agents can be integrated into the language, often picking up the lessons learned by libraries like [e2](http://e2project.org/erlang.html) and [functionality exposed by OTP itself](http://www.erlang.org/doc/man/rpc.html); +* Study how patterns like tasks and agents can be integrated into the language, often picking up the lessons learned by libraries like [e2](https://e2project.org/erlang.html) and [functionality exposed by OTP itself](https://www.erlang.org/doc/man/rpc.html); * Rewrite the Mix and ExUnit guides to focus on applications and OTP as a whole, rebranding it to "Building Apps with Mix and OTP"; -You can learn more about Elixir in our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html) and download this release in the [v0.13 announcement](https://github.com/elixir-lang/elixir/releases/tag/v0.13.0). We hope to see you at [ElixirConf](http://elixirconf.com/) as well as pushing your packages to [hex.pm](https://hex.pm/). +You can learn more about Elixir in our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html) and download this release in the [v0.13 announcement](https://github.com/elixir-lang/elixir/releases/tag/v0.13.0). We hope to see you at [ElixirConf](https://elixirconf.com/) as well as pushing your packages to [hex.pm](https://hex.pm/). diff --git a/_posts/2014-06-17-elixir-v0-14-0-released.markdown b/_posts/2014-06-17-elixir-v0-14-0-released.markdown index e7a431f66..34672bf27 100644 --- a/_posts/2014-06-17-elixir-v0-14-0-released.markdown +++ b/_posts/2014-06-17-elixir-v0-14-0-released.markdown @@ -163,4 +163,4 @@ With v0.14.0 we have reached many of the milestones [we have set in the previous That's all for now! Elixir developers can see [a summary of all changes in v0.14.0 in the release notes](https://github.com/elixir-lang/elixir/releases/tag/v0.14.0). In case you are new around here, you can get started with Elixir by reading [our Getting Started guide](https://elixir.hexdocs.pm/introduction.html). -We hope to see you all this July at [ElixirConf](http://elixirconf.com/)! +We hope to see you all this July at [ElixirConf](https://elixirconf.com/)! diff --git a/_posts/2014-08-07-elixir-v0-15-0-released.markdown b/_posts/2014-08-07-elixir-v0-15-0-released.markdown index 7d2dab643..8a819a2ee 100644 --- a/_posts/2014-08-07-elixir-v0-15-0-released.markdown +++ b/_posts/2014-08-07-elixir-v0-15-0-released.markdown @@ -151,7 +151,7 @@ At the beginning of this summer, [Chris Hyndman](https://github.com/chyndman) jo Chris has also built an [Elixir Web Installer for Windows](https://github.com/elixir-lang/elixir-windows-setup). The web installer checks all available Elixir versions and allows you to pick which one to install. It will also fetch and install Erlang in your machine in case it has not been installed yet. -If you want to give Elixir and the Web Installer a try, you can [download the current version here](https://repo.hex.pm/elixir-websetup.exe). And, if [Chocolatey](https://chocolatey.org/) is your thing, remember you can also install Elixir on Windows by running `cinst elixir`. +If you want to give Elixir and the Web Installer a try, note that the original download link is no longer available, but Windows installers are now available on the [Elixir releases page](https://github.com/elixir-lang/elixir/releases). And, if [Chocolatey](https://chocolatey.org/) is your thing, remember you can also install Elixir on Windows by running `cinst elixir`. ## Welcome Alexei! diff --git a/_posts/2014-09-18-elixir-v1-0-0-released.markdown b/_posts/2014-09-18-elixir-v1-0-0-released.markdown index c79b2cd0f..010e3b74d 100644 --- a/_posts/2014-09-18-elixir-v1-0-0-released.markdown +++ b/_posts/2014-09-18-elixir-v1-0-0-released.markdown @@ -19,7 +19,7 @@ Elixir leverages the Erlang VM, known for running low-latency, distributed and f This release is the consolidation of all the work done through the years. With v1.0, we have reached a stable milestone for the growth of software and projects written in Elixir. -Elixir will follow [semantic versioning](http://semver.org), which means code written for Elixir v1.0 will continue to compile and run correctly for all versions under the v1 branch (e.g. v1.0.1, v1.1.0, v1.2.0). +Elixir will follow [semantic versioning](https://semver.org), which means code written for Elixir v1.0 will continue to compile and run correctly for all versions under the v1 branch (e.g. v1.0.1, v1.1.0, v1.2.0). Elixir is composed of 6 applications, all under the same versioning constraints: @@ -56,6 +56,6 @@ These expectations also apply to future releases under the v1 branch, except for You can get started with Elixir via our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html). There are quite some Elixir books out there too, now getting sent to the presses, quite a few can be found in the sidebar, which also includes screencasts and other resources. -You can also learn more about Elixir by checking out [the videos from ElixirConf 2014](http://www.confreaks.com/events/elixirconf2014), the first (and so far the best) Elixir conference ever! You can learn more about [the language history](http://www.confreaks.com/videos/4134-elixirconf2014-keynote-elixir), [how Elixir can change the way you code](http://www.confreaks.com/videos/4119-elixirconf2014-opening-keynote-think-different) or [even hear stories of how Elixir is being used in production](http://www.confreaks.com/videos/4131-elixirconf2014-otp-in-production-the-nitty-gritty-details-of-game-servers). +You can also learn more about Elixir by checking out [the videos from ElixirConf 2014](https://www.youtube.com/playlist?list=PLE7tQUdRKcyakbmyFcmznq2iNtL80mCsT), the first (and so far the best) Elixir conference ever! You can learn more about [the language history](https://www.youtube.com/watch?v=aZXc11eOEpI), [how Elixir can change the way you code](https://www.youtube.com/watch?v=5hDVftaPQwY) or [even hear stories of how Elixir is being used in production](https://www.youtube.com/watch?v=5LRDICEETRE). -Finally, by popular demand, we have [released some Elixir stickers](http://www.stickermule.com/user/1070631438/stickers), which are available with a discounted price to celebrate v1.0! +Finally, by popular demand, we have [released some Elixir stickers](https://web.archive.org/web/20141231001621/https://www.stickermule.com/user/1070631438/stickers), which are available with a discounted price to celebrate v1.0! diff --git a/_posts/2015-09-28-elixir-v1-1-0-released.markdown b/_posts/2015-09-28-elixir-v1-1-0-released.markdown index f81a53293..711498805 100644 --- a/_posts/2015-09-28-elixir-v1-1-0-released.markdown +++ b/_posts/2015-09-28-elixir-v1-1-0-released.markdown @@ -11,11 +11,11 @@ Elixir v1.1 has been released and it brings enhancements, bug fixes, performance Elixir v1.1 supports both Erlang 17 and Erlang 18. This is, however, the last release supporting Erlang 17, so upgrading to Erlang 18 is advised. Elixir v1.2 will introduce features that are Erlang 18 only. -On the standard library side, about 40 new functions have been added to Elixir public APIs. For example, [`Enum`](/docs/v1.1/elixir/Enum.html) got [`dedup/1`](/docs/v1.1/elixir/Enum.html#dedup/1), [`random/1`](/docs/v1.1/elixir/Enum.html#random/1), and a couple more. The [`String`](/docs/v1.1/elixir/String.html) module can now [calculate the distance between strings](/docs/v1.1/elixir/String.html#jaro_distance/2). We use this feature to provide suggestions whenever an unknown task name is given when using Mix. You can also [yield to](/docs/v1.1/elixir/Task.html#yield/2) and [shutdown](/docs/v1.1/elixir/Task.html#shutdown/2) tasks in the [`Task`](/docs/v1.1/elixir/Task.html) module. +On the standard library side, about 40 new functions have been added to Elixir public APIs. For example, [`Enum`](https://elixir.hexdocs.pm/1.1.0/Enum.html) got [`dedup/1`](https://elixir.hexdocs.pm/1.1.0/Enum.html#dedup/1), [`random/1`](https://elixir.hexdocs.pm/1.1.0/Enum.html#random/1), and a couple more. The [`String`](https://elixir.hexdocs.pm/1.1.0/String.html) module can now [calculate the distance between strings](https://elixir.hexdocs.pm/1.1.0/String.html#jaro_distance/2). We use this feature to provide suggestions whenever an unknown task name is given when using Mix. You can also [yield to](https://elixir.hexdocs.pm/1.1.0/Task.html#yield/2) and [shutdown](https://elixir.hexdocs.pm/1.1.0/Task.html#shutdown/2) tasks in the [`Task`](https://elixir.hexdocs.pm/1.1.0/Task.html) module. -The applications that ship with Elixir also has seen improvements and bug fixes. [ExUnit](/docs/v1.1/ex_unit/ExUnit.html), Elixir's test framework, now has support for skipping tests via tags `@tag :skip`, as well as the ability to capture logs via `@tag :capture_log`, ensuring that all log messages during the tests are captured. Even better, in case of failures, all captured log messages are printed along-side the test error report. +The applications that ship with Elixir also has seen improvements and bug fixes. [ExUnit](https://ex-unit.hexdocs.pm/1.1.0/ExUnit.html), Elixir's test framework, now has support for skipping tests via tags `@tag :skip`, as well as the ability to capture logs via `@tag :capture_log`, ensuring that all log messages during the tests are captured. Even better, in case of failures, all captured log messages are printed along-side the test error report. -Mix ships with a [`mix profile.fprof`](/docs/v1.1/mix/Mix.Tasks.Profile.Fprof.html), useful for profiling your application code. The [`mix app.start`](/docs/v1.1/mix/Mix.Tasks.App.Start.html) has also been publicly documented. Although you likely won't invoke it directly through the command line, it is useful when writing your own tasks that require the current application to be up and running. +Mix ships with a [`mix profile.fprof`](https://mix.hexdocs.pm/1.1.0/Mix.Tasks.Profile.Fprof.html), useful for profiling your application code. The [`mix app.start`](https://mix.hexdocs.pm/1.1.0/Mix.Tasks.App.Start.html) has also been publicly documented. Although you likely won't invoke it directly through the command line, it is useful when writing your own tasks that require the current application to be up and running. Mix also provides faster re-compilation times. Every time you compile your Elixir code, Mix generates a graph of the dependencies between source files. For example, if `a.ex` depends on `b.ex`, every time `b.ex` changes, `a.ex` must be recompiled. Elixir v1.1 improves this tracking by separating compile-time dependencies from runtime ones, recompiling a file only if a compile-time dependency changed. In projects that have a main dispatch entity, like a web-app router, we have seen `mix compile` go from recompiling the whole project to one or two files per run. diff --git a/_posts/2016-06-21-elixir-v1-3-0-released.markdown b/_posts/2016-06-21-elixir-v1-3-0-released.markdown index e6a63616c..ade15de8b 100644 --- a/_posts/2016-06-21-elixir-v1-3-0-released.markdown +++ b/_posts/2016-06-21-elixir-v1-3-0-released.markdown @@ -9,7 +9,7 @@ excerpt: Elixir v1.3 brings many improvements to the language, the compiler and Elixir v1.3 brings many improvements to the language, the compiler and its tooling, specially Mix (Elixir's build tool) and ExUnit (Elixir's test framework). The most notable additions are the new Calendar types, the new cross-reference checker in Mix, and the assertion diffing in ExUnit. We will explore all of them and a couple more enhancements below. -With this release, we also welcome [Andrea Leopardi](http://github.com/whatyouhide) to Elixir Core Team. He has contributed greatly to this release and maintains important packages in the community, like [Gettext](https://github.com/elixir-lang/gettext) and [Redix](https://github.com/whatyouhide/redix). +With this release, we also welcome [Andrea Leopardi](https://github.com/whatyouhide) to Elixir Core Team. He has contributed greatly to this release and maintains important packages in the community, like [Gettext](https://github.com/elixir-lang/gettext) and [Redix](https://github.com/whatyouhide/redix). ## Language improvements @@ -146,7 +146,7 @@ plug └── elixir ``` -The `--format dot` option can also be given to generate graph files to be opened by [GraphViz](http://www.graphviz.org). For example, here is the output of running `mix deps.tree --format dot --only prod` in the [Phoenix web framework](http://phoenixframework.org): +The `--format dot` option can also be given to generate graph files to be opened by [GraphViz](https://www.graphviz.org). For example, here is the output of running `mix deps.tree --format dot --only prod` in the [Phoenix web framework](https://phoenixframework.org):

    mix deps.tree for Phoenix in production diff --git a/_posts/2016-07-14-announcing-genstage.markdown b/_posts/2016-07-14-announcing-genstage.markdown index 72e3cbcd7..d40b9a0bf 100644 --- a/_posts/2016-07-14-announcing-genstage.markdown +++ b/_posts/2016-07-14-announcing-genstage.markdown @@ -9,7 +9,7 @@ excerpt: GenStage is a new Elixir behaviour for exchanging events with back-pres Today we are glad to announce the official release of GenStage. GenStage is a new Elixir behaviour for exchanging events with back-pressure between Elixir processes. In the short-term, we expect GenStage to replace the use cases for GenEvent as well as providing a composable abstraction for consuming data from third-party systems. -In this blog post we will cover the background that led us to GenStage, some example use cases, and what we are exploring for future releases. If instead you are looking for a quick reference, [check the project source code](https://github.com/elixir-lang/gen_stage) and [access its documentation](https://gen-stage.hexdocs.pm/GenStage.html). +In this blog post we will cover the background that led us to GenStage, some example use cases, and what we are exploring for future releases. If instead you are looking for a quick reference, [check the project source code](https://github.com/elixir-lang/gen_stage) and [access its documentation](https://gen-stage.hexdocs.pm/0.3.0/Experimental.GenStage.html). ## Background @@ -52,7 +52,7 @@ The solution above allows us to work with large datasets without loading them al That said, how could we leverage concurrency in the example above? -During my ElixirConf 2015 keynote, [I discussed one of the most immediate solutions to this problem](http://confreaks.tv/videos/elixirconf2015-keynote) which was to convert parts of your pipeline to separate processes: +During my ElixirConf 2015 keynote, [I discussed one of the most immediate solutions to this problem](https://www.youtube.com/watch?v=9RB1JCKe3GY) which was to convert parts of your pipeline to separate processes: ```elixir File.stream!("path/to/some/file") @@ -193,7 +193,7 @@ Process.sleep(:infinity) By simply starting multiple consumers, the stage `B` will now receive demand from multiple stages and dispatch events to those stages which are now running concurrently, always picking the stage that is able to process more items. We can also leverage concurrency from the opposite direction: if the producer is the slow stage in a pipeline, you can start multiple producers and have each consumer subscribe to them. -In order to know which consumer should receive a particular event, producer stages depend on a behaviour called [`GenStage.Dispatcher`](https://gen-stage.hexdocs.pm/Experimental.GenStage.Dispatcher.html). The default dispatcher is the `GenStage.DemandDispatcher` we have briefly described above: it will collect the demand from different consumers and dispatch to the one with highest demand. This means if one consumer is slow, maybe because we increased its sleeping time to 10 seconds, it will receive less items. +In order to know which consumer should receive a particular event, producer stages depend on a behaviour called [`GenStage.Dispatcher`](https://gen-stage.hexdocs.pm/0.3.0/Experimental.GenStage.Dispatcher.html). The default dispatcher is the `GenStage.DemandDispatcher` we have briefly described above: it will collect the demand from different consumers and dispatch to the one with highest demand. This means if one consumer is slow, maybe because we increased its sleeping time to 10 seconds, it will receive less items. ### GenStage for data-ingestion @@ -207,7 +207,7 @@ During the Elixir London Meetup, I have live-coded a short example that shows ho Another scenario where GenStage can be useful today is to replace cases where developers would have used [GenEvent](https://elixir.hexdocs.pm/GenEvent.html) in the past. For those unfamiliar with GenEvent, it is a behaviour where events are sent to an "event manager" which then proceeds to invoke "event handlers" for each event. GenEvent, however, has one big flaw: the event manager and all event handlers run in the same process. This means GenEvent handlers cannot easily leverage concurrency without forcing developers to implement those mechanisms themselves. Furthermore, GenEvent handlers have very awkward error semantics. Because event handlers are not separate processes, we cannot simply rely on supervisors restarting them. -GenStage solves those problems by having a producer as the event manager. The producer itself should be configured to use [`GenStage.BroadcastDispatcher`](https://gen-stage.hexdocs.pm/Experimental.GenStage.BroadcastDispatcher.html) as its dispatcher. The broadcast dispatcher will guarantee events are dispatched to all consumers in a way that does not exceed the demand of any of the consumers. This allows us to leverage concurrency and having the "event manager" as a producer gives us much more flexibility in terms of buffering and reacting to failures. +GenStage solves those problems by having a producer as the event manager. The producer itself should be configured to use [`GenStage.BroadcastDispatcher`](https://gen-stage.hexdocs.pm/0.3.0/Experimental.GenStage.BroadcastDispatcher.html) as its dispatcher. The broadcast dispatcher will guarantee events are dispatched to all consumers in a way that does not exceed the demand of any of the consumers. This allows us to leverage concurrency and having the "event manager" as a producer gives us much more flexibility in terms of buffering and reacting to failures. Let's see an example of building an event manager as a producer: @@ -295,7 +295,7 @@ Such guarantees that, if a supervised `EventHandler` crashes, the supervisor wil With the release of GenStage v0.3.0, we have reached an important milestone as `GenStage` can be used as both event managers and a way to exchange events between processes, often external data sources, with back-pressure. -The v0.3.0 release also includes the [`GenStage.stream`](https://gen-stage.hexdocs.pm/Experimental.GenStage.html#stream/1) function, which allows us to consume data from a GenStage as a stream, and [`GenStage.from_enumerable`](https://gen-stage.hexdocs.pm/Experimental.GenStage.html#from_enumerable/2) which allows us to use an enumerable or a stream, like `File.stream!`, as a producer. Closing the gap between stages and streams. +The v0.3.0 release also includes the [`GenStage.stream`](https://gen-stage.hexdocs.pm/0.3.0/Experimental.GenStage.html#stream/1) function, which allows us to consume data from a GenStage as a stream, and [`GenStage.from_enumerable`](https://gen-stage.hexdocs.pm/0.3.0/Experimental.GenStage.html#from_enumerable/2) which allows us to use an enumerable or a stream, like `File.stream!`, as a producer. Closing the gap between stages and streams. However, we are far from done! @@ -320,7 +320,7 @@ File.stream!("path/to/some/file") |> Enum.to_list() ``` -While the above is helpful when working with large or infinite collections, it still does not leverage concurrency. To address that, we are currently exploring a solution named [`GenStage.Flow`](https://gen-stage.hexdocs.pm/Experimental.Flow.html), that allows us to express our computations similarly to streams, except they will run across multiple stages instead of a single process: +While the above is helpful when working with large or infinite collections, it still does not leverage concurrency. To address that, we are currently exploring a solution named [`GenStage.Flow`](https://gen-stage.hexdocs.pm/0.5.0/Experimental.Flow.html), that allows us to express our computations similarly to streams, except they will run across multiple stages instead of a single process: ```elixir alias Experimental.GenStage.Flow @@ -351,12 +351,12 @@ File.stream!("path/to/some/file", read_ahead: 100_000) # NEW! |> Enum.to_list() ``` -Flow will look at the computations we want to perform and start a series of stages to execute our code while keeping the amount of data being transferred between processes to a minimum. If you are interested in `GenStage.Flow` and how the computations above are spread across multiple stages, [we have written some documentation based on the prototypes we have built so far](https://gen-stage.hexdocs.pm/Experimental.Flow.html). The code itself is coming in future GenStage releases. We will also have to consider how the `GenStage.Flow` API mirrors the functions in `Enum` and `Stream` to make the path from eager to concurrent clearer. +Flow will look at the computations we want to perform and start a series of stages to execute our code while keeping the amount of data being transferred between processes to a minimum. If you are interested in `GenStage.Flow` and how the computations above are spread across multiple stages, [we have written some documentation based on the prototypes we have built so far](https://gen-stage.hexdocs.pm/0.5.0/Experimental.Flow.html). The code itself is coming in future GenStage releases. We will also have to consider how the `GenStage.Flow` API mirrors the functions in `Enum` and `Stream` to make the path from eager to concurrent clearer. For the word counting problem with a fixed data, early experiments show a linear increase in performance with a fixed overhead of 20%. In other words, a dataset that takes 60s with a single core, takes 36s on a machine with 2 cores and 18s in one with 4 cores. All of those gains by simply moving your computations from streams to Flow. We plan to benchmark on machines with over 40 cores soon. -We are very excited with the possibilities GenStage brings to developers and all new paths it allows us to explore and research. So give it a try and let us know! [GenStage, Flows, and more will also be the topic of my keynote at ElixirConf 2016](http://www.elixirconf.com/) and we hope to see you there. +We are very excited with the possibilities GenStage brings to developers and all new paths it allows us to explore and research. So give it a try and let us know! [GenStage, Flows, and more will also be the topic of my keynote at ElixirConf 2016](https://www.elixirconf.com/) and we hope to see you there. -Finally, we want to thank the [akka-streams and reactive-streams projects](http://reactive-streams.io) which provided us guidance in implementing the demand-driven exchange between stages as well as the [Apache Spark](http://spark.apache.org/) and [Apache Beam](http://beam.incubator.apache.org/) initiatives that inspire the work behind `GenStage.Flow`. +Finally, we want to thank the [akka-streams and reactive-streams projects](https://github.com/reactive-streams) which provided us guidance in implementing the demand-driven exchange between stages as well as the [Apache Spark](https://spark.apache.org/) and [Apache Beam](https://beam.incubator.apache.org/) initiatives that inspire the work behind `GenStage.Flow`. Happy coding! diff --git a/_posts/2017-01-05-elixir-v1-4-0-released.markdown b/_posts/2017-01-05-elixir-v1-4-0-released.markdown index aa818a916..4df2f1227 100644 --- a/_posts/2017-01-05-elixir-v1-4-0-released.markdown +++ b/_posts/2017-01-05-elixir-v1-4-0-released.markdown @@ -30,7 +30,7 @@ iex> Registry.lookup(MyRegistry, "hello") [{self(), 1}] ``` -Finally, huge thanks to [Bram Verburg](https://twitter.com/voltonez) who has performed [extensive benchmarks](https://docs.google.com/spreadsheets/d/1MByRZJMCnZ1wPiLhBEnSRRSuy1QXp8kr27PIOXO3qqg/edit#gid=0) on the registry to show it scales linearly with the number of cores by increasing the number of partitions. +Finally, huge thanks to [Bram Verburg](https://twitter.com/voltonez) who has performed [extensive benchmarks](https://docs.google.com/spreadsheets/d/1MByRZJMCnZ1wPiLhBEnSRRSuy1QXp8kr27PIOXO3qqg/edit) on the registry to show it scales linearly with the number of cores by increasing the number of partitions. ## Syntax coloring diff --git a/_posts/2017-07-25-elixir-v1-5-0-released.markdown b/_posts/2017-07-25-elixir-v1-5-0-released.markdown index 13c63772a..750198b4d 100644 --- a/_posts/2017-07-25-elixir-v1-5-0-released.markdown +++ b/_posts/2017-07-25-elixir-v1-5-0-released.markdown @@ -27,9 +27,9 @@ Or: saudação = "Bom dia!" ``` -Elixir follows the recommendations in [Unicode Annex #31](http://unicode.org/reports/tr31/) to make Elixir more accessible to other languages and communities. Identifiers must still be a sequence of letters, followed by digits and combining marks. This means symbols, such as mathematical notations and emoji, are not allowed in identifiers. +Elixir follows the recommendations in [Unicode Annex #31](https://unicode.org/reports/tr31/) to make Elixir more accessible to other languages and communities. Identifiers must still be a sequence of letters, followed by digits and combining marks. This means symbols, such as mathematical notations and emoji, are not allowed in identifiers. -For a complete reference on Elixir syntax, see the [Syntax Reference](https://elixir.hexdocs.pm/1.5/syntax-reference.html). For technical details on Unicode support, see [Unicode Syntax](https://elixir.hexdocs.pm/1.5/unicode-syntax.html). +For a complete reference on Elixir syntax, see the [Syntax Reference](https://elixir.hexdocs.pm/1.5.0/syntax-reference.html). For technical details on Unicode support, see [Unicode Syntax](https://elixir.hexdocs.pm/1.5.0/unicode-syntax.html). ## IEx helpers and breakpoints @@ -118,7 +118,7 @@ children = [ The modules `Agent`, `Registry`, `Task`, and `Task.Supervisor` have been updated to include a `child_spec/1` function, allowing them to be used directly in a supervision tree similar to the examples above. `use Agent`, `use GenServer`, `use Supervisor`, and `use Task` have also been updated to automatically define an overridable `child_spec/1` function. -Finally, child specifications are now provided as maps (data-structures) instead of the previous `Supervisor.Spec.worker/3` and `Supervisor.Spec.supervisor/3` APIs. This behaviour also aligns with how supervisors are configured in Erlang/OTP 18+. See the updated [`Supervisor`](https://elixir.hexdocs.pm/1.5/Supervisor.html) docs for more information, as well as the new `Supervisor.init/2` and `Supervisor.child_spec/2` functions. +Finally, child specifications are now provided as maps (data-structures) instead of the previous `Supervisor.Spec.worker/3` and `Supervisor.Spec.supervisor/3` APIs. This behaviour also aligns with how supervisors are configured in Erlang/OTP 18+. See the updated [`Supervisor`](https://elixir.hexdocs.pm/1.5.0/Supervisor.html) docs for more information, as well as the new `Supervisor.init/2` and `Supervisor.child_spec/2` functions. ## @impl diff --git a/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown b/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown index 242c28635..ba459d7f4 100644 --- a/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown +++ b/_posts/2017-10-31-stream-data-property-based-testing-and-data-generation-for-elixir.markdown @@ -173,11 +173,11 @@ The reasons for writing a new property-based testing library from scratch are be **Update Jun/2020:** after careful consideration, the Elixir team decided to not include `StreamData` in Elixir itself, and keep it as package, as it is able to provide all of the necessary features without a need for direct integration with the language. [stream_data]: https://github.com/whatyouhide/stream_data -[quickcheck-paper]: http://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/quick.pdf +[quickcheck-paper]: https://www.cs.tufts.edu/~nr/cs257/archive/john-hughes/quick.pdf [test.check]: https://github.com/clojure/test.check [Hypothesis]: https://github.com/HypothesisWorks/hypothesis-python -[QuickCheck]: http://quviq.com -[propertesting.com]: http://propertesting.com +[QuickCheck]: https://quviq.com +[propertesting.com]: https://propertesting.com [PropEr]: https://github.com/manopapad/proper [quickcheck-pr]: https://github.com/elixir-lang/elixir/pull/5022#issuecomment-233195478 [pollution]: https://github.com/pragdave/pollution diff --git a/_posts/2018-01-17-elixir-v1-6-0-released.markdown b/_posts/2018-01-17-elixir-v1-6-0-released.markdown index 7f743f30c..8a8193e0c 100644 --- a/_posts/2018-01-17-elixir-v1-6-0-released.markdown +++ b/_posts/2018-01-17-elixir-v1-6-0-released.markdown @@ -60,7 +60,7 @@ end `%User{age: age}` is matching on a `User` struct with an age field and `when age >= 16` is the guard. -Since only a handful of constructs are [allowed in guards](https://elixir.hexdocs.pm/guards.html#content), if you were in a situation where you had to check the age to be more than or equal to 16 in multiple places, extracting the guard to a separate function would be [less than obvious and error prone](https://github.com/elixir-lang/elixir/issues/2469). To address those issues, [this release introduces `defguard/1` and `defguardp/1`](https://elixir.hexdocs.pm/Kernel.html#defguard/1): +Since only a handful of constructs are [allowed in guards](https://elixir.hexdocs.pm/1.6.0/guards.html), if you were in a situation where you had to check the age to be more than or equal to 16 in multiple places, extracting the guard to a separate function would be [less than obvious and error prone](https://github.com/elixir-lang/elixir/issues/2469). To address those issues, [this release introduces `defguard/1` and `defguardp/1`](https://elixir.hexdocs.pm/Kernel.html#defguard/1): ```elixir defguard is_old_to_drive(age) when age >= 16 @@ -146,7 +146,7 @@ mix xref graph --format stats --label compile Those improvements will help developers better understand the relationship between files and reveal potentially complex parts of their systems. -Other improvements in Mix include [better compiler diagnostics](https://mix.hexdocs.pm/Mix.Task.Compiler.html) for editor integration, support for [the `--slowest N` flag in `mix test`](https://mix.hexdocs.pm/Mix.Tasks.Test.html) that shows the slowest tests in your suite, and a new [`mix profile.eprof` task](https://mix.hexdocs.pm/Mix.Tasks.Eprof.html) that provides time based profiling, complementing the existing [`mix profile.cprof` (count based)](https://mix.hexdocs.pm/Mix.Tasks.Profile.Cprof.html) and [`mix profile.fprof` (flame based)](https://mix.hexdocs.pm/Mix.Tasks.Profile.Fprof.html). +Other improvements in Mix include [better compiler diagnostics](https://mix.hexdocs.pm/Mix.Task.Compiler.html) for editor integration, support for [the `--slowest N` flag in `mix test`](https://mix.hexdocs.pm/Mix.Tasks.Test.html) that shows the slowest tests in your suite, and a new [`mix profile.eprof` task](https://mix.hexdocs.pm/Mix.Tasks.Profile.Eprof.html) that provides time based profiling, complementing the existing [`mix profile.cprof` (count based)](https://mix.hexdocs.pm/Mix.Tasks.Profile.Cprof.html) and [`mix profile.fprof` (flame based)](https://mix.hexdocs.pm/Mix.Tasks.Profile.Fprof.html). ## Summing up diff --git a/_posts/2018-07-25-elixir-v1-7-0-released.markdown b/_posts/2018-07-25-elixir-v1-7-0-released.markdown index 8e44c1521..72a680467 100644 --- a/_posts/2018-07-25-elixir-v1-7-0-released.markdown +++ b/_posts/2018-07-25-elixir-v1-7-0-released.markdown @@ -13,7 +13,7 @@ We are also glad to welcome Michał Muskała to the Elixir Core team. Prior to j ## Documentation metadata -Elixir v1.7 implements [EEP 48](http://www.erlang.org/eep/eeps/eep-0048.html). EEP 48 aims to bring documentation interoperability across all languages running on the Erlang VM. +Elixir v1.7 implements [EEP 48](https://www.erlang.org/eeps/eep-0048). EEP 48 aims to bring documentation interoperability across all languages running on the Erlang VM. Furthermore, EEP 48 introduces the ability to annotate documentation with metadata, which we have made possible to leverage from Elixir: diff --git a/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown b/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown index 272893459..6b447590c 100644 --- a/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown +++ b/_posts/2019-02-25-mint-a-new-http-library-for-elixir.markdown @@ -15,7 +15,7 @@ To validate this we built out the library with a common API supporting both HTTP Mint HTTP connections are managed directly in the process that starts the connection, which means no connection pool is used nor new processes spawned when a connection is opened. This allows the user of the library to build their own process structure that fits their application. -With Mint each connection has a single immutable data structure that the user needs to manage. Mint uses ["active mode"](http://www.erlang.org/doc/man/inet.html#setopts-2) sockets. This means data and events from the socket are sent as messages to the process that started the connection. The user passes the messages to the `stream/2` function that returns the updated connection and a list of "responses". Responses are streamed back which means you won't receive a single full HTTP response back from `stream/2`, instead the response is returned in partial response chunks. A chunk can be the status line, HTTP headers, or part of the response body. +With Mint each connection has a single immutable data structure that the user needs to manage. Mint uses ["active mode"](https://www.erlang.org/doc/apps/kernel/inet.html#setopts/2) sockets. This means data and events from the socket are sent as messages to the process that started the connection. The user passes the messages to the `stream/2` function that returns the updated connection and a list of "responses". Responses are streamed back which means you won't receive a single full HTTP response back from `stream/2`, instead the response is returned in partial response chunks. A chunk can be the status line, HTTP headers, or part of the response body. Let's look at an example of sending a request with Mint: diff --git a/_posts/2019-06-24-elixir-v1-9-0-released.markdown b/_posts/2019-06-24-elixir-v1-9-0-released.markdown index 55f98a42c..5bf9a492f 100644 --- a/_posts/2019-06-24-elixir-v1-9-0-released.markdown +++ b/_posts/2019-06-24-elixir-v1-9-0-released.markdown @@ -19,9 +19,9 @@ The main feature in Elixir v1.9 is the addition of releases. A release is a self Releases have always been part of the Elixir community thanks to Paul Schoenfelder's work on [Distillery](https://github.com/bitwalker/distillery) (and EXRM before that). Distillery was announced in July 2016. Then in 2017, [DockYard](https://dockyard.com/) hired Paul to work on improving deployments, an effort that would lead to [Distillery 2.0](https://dockyard.com/blog/2018/08/23/announcing-distillery-2-0). Distillery 2.0 provided important answers in areas where the community was struggling to establish conventions and best practices, such as configuration. -At the beginning of this year, thanks to [Plataformatec](http://plataformatec.com.br/), I was able to prioritize the work on bringing releases directly into Elixir. Paul was aware that we wanted to have releases in Elixir itself and during [ElixirConf 2018](https://elixirconf.com) I announced that releases was the last planned feature for Elixir. +At the beginning of this year, thanks to [Plataformatec](https://plataformatec.com.br/), I was able to prioritize the work on bringing releases directly into Elixir. Paul was aware that we wanted to have releases in Elixir itself and during [ElixirConf 2018](https://elixirconf.com) I announced that releases was the last planned feature for Elixir. -The goal of Elixir releases was to double down on the most important concepts provided by Distillery and provide extensions points for the other bits the community may find important. [Paul](http://github.com/bitwalker/) and [Tristan](https://github.com/tsloughter) (who maintains [Erlang's relx](https://github.com/erlware/relx)) provided excellent feedback on Elixir's implementation, which we are very thankful for. [The Hex package manager is already using releases in production](https://dashbit.co/blog/updating-hex-pm-to-use-elixir-releases) and we also got feedback from other companies doing the same. +The goal of Elixir releases was to double down on the most important concepts provided by Distillery and provide extensions points for the other bits the community may find important. [Paul](https://github.com/bitwalker/) and [Tristan](https://github.com/tsloughter) (who maintains [Erlang's relx](https://github.com/erlware/relx)) provided excellent feedback on Elixir's implementation, which we are very thankful for. [The Hex package manager is already using releases in production](https://dashbit.co/blog/updating-hex-pm-to-use-elixir-releases) and we also got feedback from other companies doing the same. Enough background, let's see why you would want to use releases and how to assemble one. @@ -77,7 +77,7 @@ We have written [extensive documentation on releases](https://mix.hexdocs.pm/Mix We also use the work on releases to streamline Elixir's configuration API. A new `Config` module has been added to Elixir. The previous configuration API, `Mix.Config`, was part of the Mix build tool. However, since releases provide runtime configuration and Mix is not included in releases, we ported the `Mix.Config` API to Elixir. In other words, `use Mix.Config` has been soft-deprecated in favor of `import Config`. -Another important change related to configuration is that `mix new` will no longer generate a `config/config.exs` file. [Relying on configuration is undesired for most libraries](https://elixir.hexdocs.pm/library-guidelines.html#avoid-application-configuration) and the generated config files pushed library authors in the wrong direction. Furthermore, `mix new --umbrella` will no longer generate a configuration for each child app, instead all configuration should be declared in the umbrella root. That's how it has always behaved, we are now making it explicit. +Another important change related to configuration is that `mix new` will no longer generate a `config/config.exs` file. [Relying on configuration is undesired for most libraries](https://elixir.hexdocs.pm/1.9.0/library-guidelines.html#avoid-application-configuration) and the generated config files pushed library authors in the wrong direction. Furthermore, `mix new --umbrella` will no longer generate a configuration for each child app, instead all configuration should be declared in the umbrella root. That's how it has always behaved, we are now making it explicit. ## Other improvements @@ -87,9 +87,9 @@ There are many other enhancements in Elixir v1.9. The Elixir CLI got a handful o As mentioned earlier, releases was the last planned feature for Elixir. We don't have any major user-facing feature in the works nor planned. I know for certain some will consider this fact the most excing part of this announcement! -Of course, it does not mean that v1.9 is the last Elixir version. We will continue shipping new releases every 6 months with enhancements, bug fixes and improvements. You can see the [Issues Tracker](http://github.com/elixir-lang/elixir/issues) for more details. +Of course, it does not mean that v1.9 is the last Elixir version. We will continue shipping new releases every 6 months with enhancements, bug fixes and improvements. You can see the [Issues Tracker](https://github.com/elixir-lang/elixir/issues) for more details. -We also are working on some structural changes. One of them is move the `mix xref` pass straight into the compiler, which would allow us to emit undefined function and deprecation warnings in more places. We are also considering a move to [Cirrus-CI](https://cirrus-ci.org/), so we can test Elixir on Windows, Unix, and FreeBSD through a single service. +We also are working on some structural changes. One of them is move the `mix xref` pass straight into the compiler, which would allow us to emit undefined function and deprecation warnings in more places. We are also considering a move to [Cirrus-CI](https://cirrus-ci.com/), so we can test Elixir on Windows, Unix, and FreeBSD through a single service. It is also important to highlight that there are two main reasons why we can afford to have an empty backlog. @@ -97,6 +97,6 @@ First of all, Elixir is built on top of Erlang/OTP and we simply leverage all of Second, Elixir was designed to be an extensible language. The same tools and abstractions we used to create and enhance the language are also available to libraries and frameworks. This means the community can continue to improve the ecosystem without a need to change the language itself, which would effectively become a bottleneck for progress. -Check [the Install section](/install.html) to get Elixir installed and read our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html) to learn more. We have also updated our [advanced Mix & OTP](https://elixir.hexdocs.pm/introduction-to-mix.html) to talk about releases. If you are looking for a more fast paced introduction to the language, see the [How I Start: Elixir](http://howistart.org/posts/elixir/1/index.html) tutorial, which has also been brought to the latest and greatest. +Check [the Install section](/install.html) to get Elixir installed and read our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html) to learn more. We have also updated our [advanced Mix & OTP](https://elixir.hexdocs.pm/introduction-to-mix.html) to talk about releases. If you are looking for a more fast paced introduction to the language, see the [How I Start: Elixir](https://howistart.org/posts/elixir/1/index.html) tutorial, which has also been brought to the latest and greatest. Have fun! diff --git a/_posts/2020-10-06-elixir-v1-11-0-released.markdown b/_posts/2020-10-06-elixir-v1-11-0-released.markdown index fe6b1e0b9..9be867499 100644 --- a/_posts/2020-10-06-elixir-v1-11-0-released.markdown +++ b/_posts/2020-10-06-elixir-v1-11-0-released.markdown @@ -17,7 +17,7 @@ For now, let's focus on what's new in Elixir v1.11. On the footsteps of v1.10, we have further integrated with Erlang's new logger by adding four new log levels: `notice`, `critical`, `alert`, and `emergency`, matching all log levels found in the Syslog standard. The `Logger` module now supports structured logging by passing maps and keyword lists to its various functions. It is also possible to specify the log level per module, via the [`Logger.put_module_level/2`](https://logger.hexdocs.pm/Logger.html#put_module_level/2) function. Log levels per application will be added in future releases. -IEx also has been improved to show the documentation for Erlang modules directly from your Elixir terminal. For example, here is a clip of me accessing the documentation for [Erlang's gen_server module](erlang.org/doc/man/gen_server.html): +IEx also has been improved to show the documentation for Erlang modules directly from your Elixir terminal. For example, here is a clip of me accessing the documentation for [Erlang's gen_server module](https://www.erlang.org/doc/apps/stdlib/gen_server.html):

    See the example in asciinema

    diff --git a/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown b/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown index 41fadf9a9..21911867c 100644 --- a/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown +++ b/_posts/2020-11-17-real-time-collaboration-with-elixir-at-slab.markdown @@ -54,7 +54,7 @@ Later on, when running the system in production, the platform continued to impre There are other few notable tools in Slab's stack. -Back in 2017, they migrated to GraphQL [powered by Elixir's Absinthe](http://absinthe-graphql.org/). There were concerns about adopting the query language, as it was a relatively new technology. Still, they felt it would address a real issue: they had different components in the application needing distinct data, and managing all of these possible combinations was becoming complex. This was one of the main problems GraphQL was designed to solve. +Back in 2017, they migrated to GraphQL [powered by Elixir's Absinthe](https://absinthe.hexdocs.pm/). There were concerns about adopting the query language, as it was a relatively new technology. Still, they felt it would address a real issue: they had different components in the application needing distinct data, and managing all of these possible combinations was becoming complex. This was one of the main problems GraphQL was designed to solve. They are also running on Google Cloud with Kubernetes (K8s), and, as many Elixir engineers, they wondered [how the Erlang VM fit in a world with Docker and K8s](https://dashbit.co/blog/kubernetes-and-the-erlang-vm-orchestration-on-the-large-and-the-small). Today they run on 6 nodes, 5 of them running application code. The sixth one handles [cron jobs](https://en.wikipedia.org/wiki/Cron) and stays on standby for new deployments. They use [the peerage library](https://github.com/mrluc/peerage) to establish Distributed Erlang connections between the nodes. diff --git a/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown b/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown index e105822f1..7fc98c519 100644 --- a/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown +++ b/_posts/2021-02-03-social-messaging-with-elixir-at-community.markdown @@ -55,7 +55,7 @@ The vast majority of those services run Elixir, with Python covering the data sc [RabbitMQ](https://www.rabbitmq.com/) handles the communication between services. The Erlang-backed message queue is responsible for broadcasting messages and acting as [their RPC backbone](https://andrealeopardi.com/posts/rpc-over-rabbitmq-with-elixir/). Messages between services are encoded with Protocol Buffers via [the protobuf-elixir library](https://github.com/elixir-protobuf/protobuf). -Initially, they used [the GenStage library](http://github.com/elixir-lang/gen_stage/) to interface with RabbitMQ, but they have migrated to the higher level [Broadway](https://github.com/dashbitco/broadway) library over the last year. Andrea Leopardi, one of their engineers, outlines their challenges: "Our system has to handle different traffic patterns when receiving and delivering data. Incoming data may arrive at any time and be prone to spikes caused by specific events powered by actions within Communities. On the other hand, we deliver SMSes in coordination with partners who impose different restrictions on volumes, rate limiting, etc." +Initially, they used [the GenStage library](https://github.com/elixir-lang/gen_stage/) to interface with RabbitMQ, but they have migrated to the higher level [Broadway](https://github.com/dashbitco/broadway) library over the last year. Andrea Leopardi, one of their engineers, outlines their challenges: "Our system has to handle different traffic patterns when receiving and delivering data. Incoming data may arrive at any time and be prone to spikes caused by specific events powered by actions within Communities. On the other hand, we deliver SMSes in coordination with partners who impose different restrictions on volumes, rate limiting, etc." He continues: "both GenStage and Broadway have been essential in providing abstractions to handle these requirements. They provide back-pressure, ensure that spikes never overload the system, and guarantee we never send more messages than the amount defined by our delivery partners". As they implemented the same patterns over and over in different services, they found Broadway to provide the ideal abstraction level for them. diff --git a/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown b/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown index dc81c1aa8..aa64c9128 100644 --- a/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown +++ b/_posts/2021-04-02-marketing-and-sales-intelligence-with-elixir-at-pepsico.markdown @@ -37,11 +37,11 @@ Furthermore, the reports generated by PepsiCo's marketing and sales teams often ## Libraries and frameworks -David Antaramian is quick to praise the Erlang runtime and its standard library. He says: "Since we are working with large amounts of data, it is also essential to avoid hitting the database whenever possible. Thankfully, Erlang ships with an in-memory table storage called [ETS](http://www.erlang.org/doc/man/ets.html), which we use to store hundreds of thousands of rows". +David Antaramian is quick to praise the Erlang runtime and its standard library. He says: "Since we are working with large amounts of data, it is also essential to avoid hitting the database whenever possible. Thankfully, Erlang ships with an in-memory table storage called [ETS](https://www.erlang.org/doc/man/ets.html), which we use to store hundreds of thousands of rows". -The Erlang standard library was also handy when communicating to some data stores. In particular, the Snowflake platform requires ODBC connections. The PepsiCo team built a library called [Snowflex](https://github.com/pepsico-ecommerce/snowflex), designed on top of [Erlang's built-in ODBC drivers](http://www.erlang.org/doc/man/odbc.html). +The Erlang standard library was also handy when communicating to some data stores. In particular, the Snowflake platform requires ODBC connections. The PepsiCo team built a library called [Snowflex](https://github.com/pepsico-ecommerce/snowflex), designed on top of [Erlang's built-in ODBC drivers](https://www.erlang.org/doc/man/odbc.html). -The Elixir ecosystem nicely complements the Erlang one. The front-end, written in React, talks to the server via [the Absinthe GraphQL toolkit](http://absinthe-graphql.org/) running on top of [the Phoenix web framework](http://phoenixframework.org/). The [Ecto database library](https://github.com/elixir-ecto/ecto) manages the communication to PostgreSQL. They also use the [esaml](https://github.com/handnot2/esaml) and [Samly](https://github.com/handnot2/samly) libraries to provide authentication within PepsiCo's organization - another example of leveraging the tools within both Erlang and Elixir communities. +The Elixir ecosystem nicely complements the Erlang one. The front-end, written in React, talks to the server via [the Absinthe GraphQL toolkit](https://absinthe.hexdocs.pm/) running on top of [the Phoenix web framework](https://phoenixframework.org/). The [Ecto database library](https://github.com/elixir-ecto/ecto) manages the communication to PostgreSQL. They also use the [esaml](https://github.com/handnot2/esaml) and [Samly](https://github.com/handnot2/samly) libraries to provide authentication within PepsiCo's organization - another example of leveraging the tools within both Erlang and Elixir communities. Finally, the team also recognizes the [Erlang Ecosystem Foundation](https://erlef.org/)'s efforts, which PepsiCo are sponsors of, particularly the Observability Working Group. David remarks: "The adoption of Telemetry by the ecosystem has been a massive help in bringing monitoring visibility and metrics to our system. Now when we see spikes in one place, we can easily correlate them with other system parts". diff --git a/_posts/2021-05-19-elixir-v1-12-0-released.markdown b/_posts/2021-05-19-elixir-v1-12-0-released.markdown index b361d5f55..dda24bb3e 100644 --- a/_posts/2021-05-19-elixir-v1-12-0-released.markdown +++ b/_posts/2021-05-19-elixir-v1-12-0-released.markdown @@ -40,7 +40,7 @@ This is particularly useful when your tests get stuck and you want to know which [Erlang/OTP 24 ships with JIT compilation](https://blog.erlang.org/My-OTP-24-Highlights/) and Elixir developers don't have to do anything to reap its benefits. There are many other features in Erlang/OTP 24 to look forwards to and Elixir v1.12 provides integration with many of them: such as support for 16bit floats in bitstrings as well as performance improvements in the compiler and during code evaluation. -Another excellent feature in Erlang/OTP 24 is the implementation of [EEP 54](http://www.erlang.org/eeps/eep-0054.html), which provides extended error information for many functions in Erlang's stdlib. Elixir v1.12 fully leverages this feature to improve reporting for errors coming from Erlang. For example, in earlier OTP versions, inserting an invalid argument into an ETS table that no longer exists would simply error with `ArgumentError`: +Another excellent feature in Erlang/OTP 24 is the implementation of [EEP 54](https://www.erlang.org/eeps/eep-0054.html), which provides extended error information for many functions in Erlang's stdlib. Elixir v1.12 fully leverages this feature to improve reporting for errors coming from Erlang. For example, in earlier OTP versions, inserting an invalid argument into an ETS table that no longer exists would simply error with `ArgumentError`: @@ -95,7 +95,7 @@ Elixir v1.12 has also added many functions across the standard library. The `Enu The `Code` module got a [`cursor_context/2`](https://elixir.hexdocs.pm/1.12/Code.html#cursor_context/2) function, which is now used to power `IEx` autocompletion and it is [used by projects such as Livebook to provide intellisense](https://user-images.githubusercontent.com/17034772/115117125-533b2900-9f9d-11eb-94a9-a2cf2ccb7388.mp4). -The EEx application has also been extended to provide metadata on text segments. This has enabled the Surface and Phoenix LiveView teams to implement [a new template language called HEEx](https://github.com/phoenixframework/phoenix_live_view/pull/1440), which validates both HTML and EEx. Finally, the `Registry` module supports the `:compressed` option, which is useful for GraphQL applications managing hundreds of thousands of subscriptions via [Absinthe](http://absinthe-graphql.org/). +The EEx application has also been extended to provide metadata on text segments. This has enabled the Surface and Phoenix LiveView teams to implement [a new template language called HEEx](https://github.com/phoenixframework/phoenix_live_view/pull/1440), which validates both HTML and EEx. Finally, the `Registry` module supports the `:compressed` option, which is useful for GraphQL applications managing hundreds of thousands of subscriptions via [Absinthe](https://absinthe.hexdocs.pm/). For a complete list of all changes, see the [full release notes](https://github.com/elixir-lang/elixir/releases/tag/v1.12.0). Check [the Install section](/install.html) to get Elixir installed and read our [Getting Started guide](https://elixir.hexdocs.pm/introduction.html) to learn more. diff --git a/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown b/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown index 51244a2e2..9594d404b 100644 --- a/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown +++ b/_posts/2021-06-02-social-virtual-spaces-with-elixir-at-mozilla.markdown @@ -43,7 +43,7 @@ Hubs Cloud launched in February 2020 and it has been a hit. [New York University Their cloud version uses Amazon CloudFormation to instantiate Hubs inside the user's account. This approach brought different challenges to the Hubs team: "we want Hubs Cloud to be as affordable and straightforward as possible. The Phoenix app has already been a massive help on this front. We have also moved some features to Amazon Lambda and made them optional, such as image resizing and video conversion" - details John. -Since Hubs is also open source, developers can run their own Hubs instance in whatever platform they choose or change it however they want. That's the path Greg Fodor recently took when he announced [Jel](https://jel.app/): "Jel is the video game for work. It is a mashup of Minecraft and Discord, where everything is 3D. My goal is to spark new directions and ideas to get people excited about VR". +Since Hubs is also open source, developers can run their own Hubs instance in whatever platform they choose or change it however they want. That's the path Greg Fodor recently took when he announced [Jel](https://web.archive.org/web/20220123203842/https://jel.app/): "Jel is the video game for work. It is a mashup of Minecraft and Discord, where everything is 3D. My goal is to spark new directions and ideas to get people excited about VR". ## Summing up diff --git a/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown b/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown index 23a777822..34a096c00 100644 --- a/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown +++ b/_posts/2021-07-29-bootstraping-a-multiplayer-server-with-elixir-at-x-plane.markdown @@ -41,7 +41,7 @@ Ready to give Elixir a try, Tyler picked up a couple books but soon realized the However, instead of jumping headfirst into the multiplayer server, he decided to give Elixir a try on a smaller problem. He wrote a web proxy to the National Oceanic and Atmospheric Administration (NOAA) weather services and put it in production. This experience taught him the importance of leveraging all of the instrumentation and metrics provided by the Erlang VM. They chose [AppSignal](https://www.appsignal.com/) to help consume and digest this information. -Two weeks later, he started working on the server by implementing [the UDP-centric RakNet protocol in Elixir](https://en.wikipedia.org/wiki/RakNet). Unfortunately, there is little documentation, so they had to refer to the reference implementation in C++ most of the time. Luckily, thanks to its roots in telecommunication and network services, [Elixir and Erlang have built-in support for parsing binary packets](https://elixir.hexdocs.pm/Kernel.SpecialForms.html#%3C%3C%3E%3E/1), which made the task a joy. The team also mapped each UDP connection to distinct lightweight threads of execution in Elixir, which we call _processes_. Elixir processes are cheap, isolated, concurrent, and are fairly scheduled by the runtime. This design allowed the X-Plane team to fully leverage the properties of robustness and predictable latency that first attracted them to the platform. Their implementation is written on top of Erlang's [gen_udp](http://www.erlang.org/doc/man/gen_udp.html) and [is open source](https://github.com/X-Plane/elixir-raknet). +Two weeks later, he started working on the server by implementing [the UDP-centric RakNet protocol in Elixir](https://web.archive.org/web/20250214141931/https://en.wikipedia.org/wiki/RakNet). Unfortunately, there is little documentation, so they had to refer to the reference implementation in C++ most of the time. Luckily, thanks to its roots in telecommunication and network services, [Elixir and Erlang have built-in support for parsing binary packets](https://elixir.hexdocs.pm/Kernel.SpecialForms.html#%3C%3C%3E%3E/1), which made the task a joy. The team also mapped each UDP connection to distinct lightweight threads of execution in Elixir, which we call _processes_. Elixir processes are cheap, isolated, concurrent, and are fairly scheduled by the runtime. This design allowed the X-Plane team to fully leverage the properties of robustness and predictable latency that first attracted them to the platform. Their implementation is written on top of Erlang's [gen_udp](https://www.erlang.org/doc/man/gen_udp.html) and [is open source](https://github.com/X-Plane/elixir-raknet). Five months after choosing Elixir, they began welcoming beta testers into the server. The community's reaction was overwhelmingly positive, and the new multiplayer experience led to a strong uptick in the number of subscriptions as it went live a month later. @@ -51,6 +51,6 @@ At the moment, X-Plane's player base in North America is powered by a single ser For deployments, they use a blue-green strategy, alternating between two servers of the same capacity. Tyler explains: "We are aware the Erlang VM provides hot code swapping and distribution, but we are taking the simplest route whenever possible. It is much easier for us to alternate between two servers during deployments, as the servers are stable and we don't deploy frequently. Similarly, when it comes to distribution, we prefer to scale vertically or set up different servers in different regions for players across the globe." -Paul McCarty, who joined the project after launch, can attest to its simplicity: "even without prior Elixir experience, I was able to jump in and add new functionality to our HTTP APIs early on." Those APIs are built on top of [Plug](http://github.com/elixir-lang/plug) to power their chat services, provide information about connected users, and more. He concludes: "When adding new features, the server development is never the bottleneck." +Paul McCarty, who joined the project after launch, can attest to its simplicity: "even without prior Elixir experience, I was able to jump in and add new functionality to our HTTP APIs early on." Those APIs are built on top of [Plug](https://github.com/elixir-lang/plug) to power their chat services, provide information about connected users, and more. He concludes: "When adding new features, the server development is never the bottleneck." Paul and Tyler finished our conversation with a curious anecdote: a couple months ago, they distributed an updated client version with debug code in it. This additional code caused each connected user to constantly ping the server every 100ms, even if not in multiplayer mode. This caused their traffic to increase 1000x! They only discovered this increase 2 weeks later when they saw the CPU usage in their Elixir server went from 5% to 21%. Once they found out the root cause and how the system handled it, they realized they didn't have to rush a client update to remove the debug code and they chose to maintain their regular release cycle. At the end of the day, it was a perfect example of the confidence they gained and built around the language and platform. diff --git a/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown b/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown index 7326c7d57..edcd6e671 100644 --- a/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown +++ b/_posts/2021-11-10-embracing-open-data-with-elixir-at-the-ministry-of-ecological-transition-in-france.markdown @@ -23,7 +23,7 @@ State Startups are a match between a team and a mission. They help "intrapreneur The insight is: instead of trying to convince other stakeholders to work towards specific goals, it is better to empower innovation and those who want to drive change. Those individuals are given a budget and the autonomy to choose the technology and assemble their team. In exchange, they must open-source and publicly document all code, costs, metrics, and statistics. -The first State Startup was [data.gouv.fr](https://www.data.gouv.fr/en), which transformed France's open data efforts from a catalog of spreadsheets into a social platform that closed the gap between the citizens consuming the data and the institutions providing them. The tool is fully [open-source](https://github.com/opendatateam/udata), allowing other countries to use it in production too. +The first State Startup was [data.gouv.fr](https://www.data.gouv.fr/), which transformed France's open data efforts from a catalog of spreadsheets into a social platform that closed the gap between the citizens consuming the data and the institutions providing them. The tool is fully [open-source](https://github.com/opendatateam/udata), allowing other countries to use it in production too. At the time of writing, [261 State Startups](https://beta.gouv.fr/startups/) have been launched and are in various states of development. @@ -31,7 +31,7 @@ At the time of writing, [261 State Startups](https://beta.gouv.fr/startups/) hav In 2017, a team was assembled to begin a new State Startup focused on transportation data. An incoming European delegated regulation would make it mandatory for institutions and corporations to make transportation data public. The State Startup aimed at preparing the ecosystem actors for this regulatory change. -To address this, the team decided to build a web application to search and visualize the existing transportation data available in [data.gouv.fr](https://www.data.gouv.fr). They initially targeted public transportation information provided by cities about buses, subways, and trams, all available in a static format called General Transit Feed Specification ([GTFS](https://gtfs.org/)) ([live example](https://transport.data.gouv.fr/resources/50471#visualization)). +To address this, the team decided to build a web application to search and visualize the existing transportation data available in [data.gouv.fr](https://www.data.gouv.fr). They initially targeted public transportation information provided by cities about buses, subways, and trams, all available in a static format called General Transit Feed Specification ([GTFS](https://gtfs.org/)) ([live example](https://web.archive.org/web/20211207101320/https://transport.data.gouv.fr/resources/50471)). The two developers of the team, Vincent Lara and Mauko Quiroga, had heard about Elixir and were interested in learning more. They understood it could provide a robust but flexible and fun platform to explore the problem space. So [they bootstrapped the application](https://github.com/etalab/transport-site/commit/837a048c37ac31151b51ac09432dbcbff3917de5) with the [Phoenix web framework](https://phoenixframework.org/). @@ -43,7 +43,7 @@ Between 2017 and 2021, the multi-disciplinary team (one public servant, “busin In 2021, the State Startup has "graduated" from its “beta gouv” incubator and is now part of France's Ministry of Ecological Transition. Now composed by Francis Chabouis, Thibaut Barrère, and Antoine Augusti, the technical part of the team is tackling new use cases and challenges as the platform grows in terms of needs and versatility. -Many of those are driven by the adoption of new data formats by governments and corporations. For example, [GTFS](https://github.com/google/transit/tree/master/gtfs/spec/en) provides a static (theoretical) itinerary: if a bus is currently delayed, this information would not be available in the feed. Enter the [GTFS-RT](https://github.com/google/transit/tree/master/gtfs-realtime/spec/en) format, where RT stands for real-time, to address those gaps. The General Bikeshare Feed Specification ([GBFS](https://nabsa.net/resources/gbfs/)) ([live example](https://transport.data.gouv.fr/datasets/velos-libre-service-creteil-cristolib-disponibilite-en-temps-reel/)) tracks bicycles, scooters, carpooling, etc. Plus the [SIRI](https://en.wikipedia.org/wiki/Service_Interface_for_Real_Time_Information) (Service Interface for Real-time Information) and [NeTEx](https://en.wikipedia.org/wiki/NeTEx) families of protocols. +Many of those are driven by the adoption of new data formats by governments and corporations. For example, [GTFS](https://github.com/google/transit/tree/master/gtfs/spec/en) provides a static (theoretical) itinerary: if a bus is currently delayed, this information would not be available in the feed. Enter the [GTFS-RT](https://github.com/google/transit/tree/master/gtfs-realtime/spec/en) format, where RT stands for real-time, to address those gaps. The General Bikeshare Feed Specification ([GBFS](https://nabsa.net/resources/gbfs/)) ([live example](https://web.archive.org/web/20211201004733/https://transport.data.gouv.fr/datasets/velos-libre-service-creteil-cristolib-disponibilite-en-temps-reel/)) tracks bicycles, scooters, carpooling, etc. Plus the [SIRI](https://en.wikipedia.org/wiki/Service_Interface_for_Real_Time_Information) (Service Interface for Real-time Information) and [NeTEx](https://en.wikipedia.org/wiki/NeTEx) families of protocols. Some of those formats have supporting technologies (validators, converters) written in other languages (Java, Rust, etc), which would be beneficial to integrate with. The team then realized the way forward is to adapt their Elixir system to orchestrate and coordinate those subsystems. Luckily, Elixir has shown to be exceptionally well suited to this task, thanks to the underlying Erlang Virtual Machine, designed for communication systems. Francis Chabouis expands: "We currently need to integrate with internal and external services in a variety of formats. Some are static, some require periodic pulls, and others keep open connections to push data. Elixir allows us to experiment, iterate, and scale those ideas quickly". @@ -55,7 +55,7 @@ Overall, the data catalog now includes: * Private parking areas * Location of rental cars, scooters, bicycles, and others -Many of those formats also bring real-time concerns as they evolve the application to sample and show events as they happen. This is where the team is currently working at leveraging [Phoenix LiveView](http://github.com/phoenixframework/phoenix_live_view) to build the interactivity and functionality they need while keeping their stack simple and productive. +Many of those formats also bring real-time concerns as they evolve the application to sample and show events as they happen. This is where the team is currently working at leveraging [Phoenix LiveView](https://github.com/phoenixframework/phoenix_live_view) to build the interactivity and functionality they need while keeping their stack simple and productive. The technical team has also recently grown to three developers, totaling seven members altogether. To prepare themselves for the new team members, Thibaut Barrère was responsible for upgrading their dependencies, including Elixir and Erlang, which were largely unchanged from 2017. While performing such changes can often be daunting in other stacks, Thibaut shares a very positive experience: "we did not see any breaking changes after performing long-due updates. Overall, the language and libraries seem quite stable and careful to avoid breaking changes. This experience gives us the confidence we can continue focusing on the needs of our users as we move forward". @@ -63,8 +63,8 @@ The technical team has also recently grown to three developers, totaling seven m As with any other team, some challenges go beyond the technical aspects. For example, they sometimes spot companies and cities that do not make their transportation data available, which is against European Law. The team often heard concerns about making parts of their systems public, which could lead to failures in critical infrastructure. -To address this, the team built [a small Phoenix application](https://github.com/etalab/transport-site/tree/master/apps/unlock) that works as a simple proxy to those systems. The proxy caches the data for specific intervals, helping those entities address the security and traffic concerns around their critical systems. The application uses [Cachex](https://github.com/whitfin/cachex) and provides a real-time dashboard, built with LiveView, where they can configure the system, track application load, and see cache usage data. +To address this, the team built [a small Phoenix application](https://github.com/etalab/transport-site/tree/master/apps/transport/lib/unlock) that works as a simple proxy to those systems. The proxy caches the data for specific intervals, helping those entities address the security and traffic concerns around their critical systems. The application uses [Cachex](https://github.com/whitfin/cachex) and provides a real-time dashboard, built with LiveView, where they can configure the system, track application load, and see cache usage data. -Another area the team is actively investigating is how to make the data itself more accessible to developers who want to consume it. A non-trivial amount of work is required between fetching the city data, parsing it, and displaying it on a map, which can discourage developers from beginning their open data journey. To this end, they plan to assemble a collection of [Livebooks](http://github.com/livebook-dev/livebook), a recently released tool for writing code notebooks in Elixir that allows developers to get up and running quickly and obtain immediate feedback on their code. +Another area the team is actively investigating is how to make the data itself more accessible to developers who want to consume it. A non-trivial amount of work is required between fetching the city data, parsing it, and displaying it on a map, which can discourage developers from beginning their open data journey. To this end, they plan to assemble a collection of [Livebooks](https://github.com/livebook-dev/livebook), a recently released tool for writing code notebooks in Elixir that allows developers to get up and running quickly and obtain immediate feedback on their code. Thibaut remarks how the growth of the language and its ecosystem supports their application and needs: "every time we faced a new challenge, a solution was readily available to us. When we needed to orchestrate multiple subsystems, the stack excelled at it. When we required real-time features, Phoenix and LiveView had first-class support for it. Now we need to promote education and access to open data, and Livebook is shaping to be precisely what we need". diff --git a/_posts/2021-12-03-elixir-v1-13-0-released.markdown b/_posts/2021-12-03-elixir-v1-13-0-released.markdown index 6839fb973..ccbfc7c4a 100644 --- a/_posts/2021-12-03-elixir-v1-13-0-released.markdown +++ b/_posts/2021-12-03-elixir-v1-13-0-released.markdown @@ -142,7 +142,7 @@ We are looking forward to see how this new functionality will be used by communi The `Code` module has also been augmented with two functions: [`Code.string_to_quoted_with_comments/2`](https://elixir.hexdocs.pm/Code.html#string_to_quoted_with_comments/2) and [`Code.quoted_to_algebra/2`](https://elixir.hexdocs.pm/Code.html#quoted_to_algebra/2). Those functions allow someone to retrieve the Elixir AST with their original source code comments, and then convert this AST to formatted code. In other words, those functions provide a wrapper around the Elixir Code Formatter, supporting developers who wish to create tools that directly manipulate and custom format Elixir source code. -`elixir --short-version` has been added to quickly get the Elixir version, without booting the Erlang VM. The `Task` module includes performance optimizations and [new](https://elixir.hexdocs.pm/Task.html#ignore/1) [functions](https://elixir.hexdocs.pm/Task.html#completed/1). Finally, `mix test --profile-require=time` has been added to debug loading times of test suites and the recently added [`Mix.install/2`](https://mix.hexdocs.pm/Mix.html#install#2) has been improved with new options and environment variables. +`elixir --short-version` has been added to quickly get the Elixir version, without booting the Erlang VM. The `Task` module includes performance optimizations and [new](https://elixir.hexdocs.pm/Task.html#ignore/1) [functions](https://elixir.hexdocs.pm/Task.html#completed/1). Finally, `mix test --profile-require=time` has been added to debug loading times of test suites and the recently added [`Mix.install/2`](https://mix.hexdocs.pm/Mix.html#install/2) has been improved with new options and environment variables. ## Learn more diff --git a/_posts/2023-06-22-type-system-updates-research-dev.markdown b/_posts/2023-06-22-type-system-updates-research-dev.markdown index 1765f7830..cfebc21e5 100644 --- a/_posts/2023-06-22-type-system-updates-research-dev.markdown +++ b/_posts/2023-06-22-type-system-updates-research-dev.markdown @@ -81,5 +81,5 @@ will be assumed to be of the `dynamic()` type. If successful, then we will effectively have introduced a type system into the language. This new exciting development stage is sponsored by [Fresha](https://www.fresha.com) ([they are hiring!](https://www.fresha.com/careers/openings?department=engineering)), -[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/jobs/experienced-elixir-developer)), +[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/)), and [Dashbit](https://dashbit.co). diff --git a/_posts/2023-09-20-strong-arrows-gradual-typing.markdown b/_posts/2023-09-20-strong-arrows-gradual-typing.markdown index cd62f8c33..348d88129 100644 --- a/_posts/2023-09-20-strong-arrows-gradual-typing.markdown +++ b/_posts/2023-09-20-strong-arrows-gradual-typing.markdown @@ -100,7 +100,7 @@ def identity(arg), do: arg But at the end of the day it will simply expand to intersections. The important bit is that, at the semantic level, there is no need for additional constructs and representations. -> Note: for the type-curious readers, set-theoretic types implement [a limited form of bounded quantification *à la* Kernel Fun](http://lucacardelli.name/Papers/OnUnderstanding.pdf). In a nutshell, it means we can only compare functions if they have the same bounds. For example, our type system states `a -> a when a: integer() or boolean()` is not a subtype of `a -> a when a: integer()`. +> Note: for the type-curious readers, set-theoretic types implement [a limited form of bounded quantification *à la* Kernel Fun](https://web.archive.org/web/20260430221541/http://lucacardelli.name/Papers/OnUnderstanding.pdf). In a nutshell, it means we can only compare functions if they have the same bounds. For example, our type system states `a -> a when a: integer() or boolean()` is not a subtype of `a -> a when a: integer()`. We also get lower bounds for free. If intersections allow us to place an upper bound on a type variable, a union is equivalent to a lower bound as it specifies the type variable will always be augmented by the union-ed type. For example, `a or atom()` says the result will always include atoms plus whatever else specified by `a` (which may be an atom, `atom()` itself, or a completely disjoint type such as `integer()`). @@ -289,5 +289,5 @@ In particular, we have been exploring a gradual set-theoretic type system for El While our efforts have officially moved from research into development, and [we have outlined an implementation plan](https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/), we haven't yet fully implemented nor assessed the usability of set-theoretic types in existing Elixir codebases, either large or small. There is much to implement and validate, and we don't rule the possibility of finding unforeseen deal breakers that could send us back to square one. Yet we are pleased and cautiously excited with the new developments so far. The development of Elixir's type system is sponsored by [Fresha](https://www.fresha.com) ([they are hiring!](https://www.fresha.com/careers/openings?department=engineering)), -[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/jobs/experienced-elixir-developer)), +[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/)), and [Dashbit](https://dashbit.co). diff --git a/_posts/2023-12-22-elixir-v1-16-0-released.markdown b/_posts/2023-12-22-elixir-v1-16-0-released.markdown index a918e0b57..cd46cb6ee 100644 --- a/_posts/2023-12-22-elixir-v1-16-0-released.markdown +++ b/_posts/2023-12-22-elixir-v1-16-0-released.markdown @@ -127,7 +127,7 @@ we are glad to continue to raise the bar for the whole ecosystem. Elixir v1.16 incorporates and extends the work on [Understanding Code Smells in Elixir Functional Language](https://github.com/lucasvegi/Elixir-Code-Smells/blob/main/etc/2023-emse-code-smells-elixir.pdf), -by Lucas Vegi and Marco Tulio Valente, from [ASERG/DCC/UFMG](http://aserg.labsoft.dcc.ufmg.br/), +by Lucas Vegi and Marco Tulio Valente, from [ASERG/DCC/UFMG](https://aserg.labsoft.dcc.ufmg.br/), into [the official documention in the form of anti-patterns](https://elixir.hexdocs.pm/what-anti-patterns.html). Our goal is to provide examples of potential pitfalls for library and application developers, with additional context and guidance on how @@ -166,7 +166,7 @@ the initial core for set-theoretic types into the Elixir compiler, with the goal of running automated analysis in patterns and guards. This is [the first step outlined in a previous article](/blog/2023/06/22/type-system-updates-research-dev/) and is sponsored by [Fresha](https://www.fresha.com) ([they are hiring!](https://www.fresha.com/careers/openings?department=engineering)), -[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/jobs/experienced-elixir-developer)), +[Starfish*](https://starfish.team) ([they are hiring!](https://starfish.team/)), and [Dashbit](https://dashbit.co). ## Learn more diff --git a/_posts/2024-03-05-veeps-elixir-case.markdown b/_posts/2024-03-05-veeps-elixir-case.markdown index c97922883..abea308f2 100644 --- a/_posts/2024-03-05-veeps-elixir-case.markdown +++ b/_posts/2024-03-05-veeps-elixir-case.markdown @@ -71,7 +71,7 @@ Different parts of the Veeps system have different scalability requirements. For Say you have 250,000 people watching a concert: the Beaconing service needs to handle thousands of requests per second for a few hours at a time. As a result, it needs to scale differently from other parts of the system, such as the merchandise e-commerce or backstage management. -To tackle this issue, they built a distributed system. They packaged each subsystem as an [Elixir release](https://elixir.hexdocs.pm/config-and-releases.html#releases), totaling five releases. For the communication layer, they used distributed Erlang, which is built into Erlang/OTP, allowing seamless inter-process communication across networked nodes. +To tackle this issue, they built a distributed system. They packaged each subsystem as an [Elixir release](https://elixir.hexdocs.pm/1.18.3/config-and-releases.html#releases), totaling five releases. For the communication layer, they used distributed Erlang, which is built into Erlang/OTP, allowing seamless inter-process communication across networked nodes. In a nutshell, each node contains several processes with specific responsibilities. Each of these processes belongs to their respective [distributed process group](https://www.erlang.org/doc/man/pg.html). If node A needs billing information, it will reach out to any process within the "billing process group", which may be anywhere in the cluster. @@ -80,7 +80,7 @@ When deploying a new version of the system, they deploy a new cluster altogether ### Service-oriented architecture within a monorepo -Although they run a distributed system, they organize the code in only one repository, following the monorepo approach. To do that, they use the [Umbrella Project feature](https://elixir.hexdocs.pm/dependencies-and-umbrella-projects.html#content) from Mix, the build tool that ships with Elixir. +Although they run a distributed system, they organize the code in only one repository, following the monorepo approach. To do that, they use the [Umbrella Project feature](https://elixir.hexdocs.pm/1.18.3/dependencies-and-umbrella-projects.html#content) from Mix, the build tool that ships with Elixir. Their umbrella project consists of 16 applications (at the time of writing), which they [sliced into five OTP releases](https://mix.hexdocs.pm/Mix.Tasks.Release.html#module-umbrellas). The remaining applications contain code that needs to be shared between multiple applications. For example, one of the shared applications defines all the structs sent as messages across the subsystems, guaranteeing that all subsystems use the same schemas for that exchanged data. diff --git a/_posts/2025-12-02-lazier-bdds-for-set-theoretic-types.markdown b/_posts/2025-12-02-lazier-bdds-for-set-theoretic-types.markdown index c3b7662c0..ccfd23a60 100644 --- a/_posts/2025-12-02-lazier-bdds-for-set-theoretic-types.markdown +++ b/_posts/2025-12-02-lazier-bdds-for-set-theoretic-types.markdown @@ -8,7 +8,7 @@ category: Internals excerpt: "This article explores the data structures used to represent set-theoretic types and the recent optimizations we have applied to them" --- -[The Elixir team and the CNRS are working on a set-theoretic type system for Elixir](https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/) which, simply put, is a type-system powered by unions, intersections, and negations. As part of the implementation of said type systems, we need an efficient way of representing said operations. This article discusses the existing approaches found in theory and practice, as well as the improvements we have introduced as part of [Elixir v1.19](/blog/2025/10/16/elixir-v1-19-0-released.markdown/). +[The Elixir team and the CNRS are working on a set-theoretic type system for Elixir](https://elixir-lang.org/blog/2023/06/22/type-system-updates-research-dev/) which, simply put, is a type-system powered by unions, intersections, and negations. As part of the implementation of said type systems, we need an efficient way of representing said operations. This article discusses the existing approaches found in theory and practice, as well as the improvements we have introduced as part of [Elixir v1.19](/blog/2025/10/16/elixir-v1-19-0-released/). This article covers the implementation details of the type system. You don't need to understand these internals to use the type system, just as you don't need to know virtual machine bytecodes or compiler passes to use a programming language. Our goal is to document our progress and provide guidance for future maintainers and implementers. Let's get started. diff --git a/_posts/2026-01-09-type-inference-of-all-and-next-15.markdown b/_posts/2026-01-09-type-inference-of-all-and-next-15.markdown index 889562f46..163eab247 100644 --- a/_posts/2026-01-09-type-inference-of-all-and-next-15.markdown +++ b/_posts/2026-01-09-type-inference-of-all-and-next-15.markdown @@ -210,7 +210,7 @@ The first release candidate for Elixir v1.20 is out and includes type inference * Feb-Mar/2026: inference across clauses, few or none false positives, assess performance! * Apr-May/2026: inference across dependencies, assess performance! -Every release will have a thread in the [Elixir Forum](http://elixirforum.com) for discussion. +Every release will have a thread in the [Elixir Forum](https://elixirforum.com) for discussion. Check our documentation to learn more about our [overall work on set-theoretic types](https://elixir.hexdocs.pm/1.20.0-rc.0/gradual-set-theoretic-types.html). This release also includes [our official types cheatsheet](https://elixir.hexdocs.pm/1.20.0-rc.0/types-cheat.html). diff --git a/_scripts/check-links b/_scripts/check-links new file mode 100755 index 000000000..7e5696c42 --- /dev/null +++ b/_scripts/check-links @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +ignore_urls=$(cat <<'EOF' | tr '\n' ',' | sed 's/,$//' +http://localhost:4000 +https://www.computerhope.com/issues/ch000549.htm +https://elixir-lang.slack.com/join/shared_invite/zt-eivteker-k_nArD59XHjjN_r8qeH6dw#/shared-invite/email +https://www.fastcompany.com/90848907/most-innovative-companies-music-2023 +https://medium.com/making-change-org/our-elixir-bandit-service-e2b6af6eebc4 +https://gtfs.org/ +EOF +) + +cache=$(cat <<'JSON' +{ + "timeframe": { + "external": "1w", + "internal": "1w" + } +} +JSON +) + +bundle exec htmlproofer \ + --log-level :debug \ + --ignore-urls "$ignore_urls" \ + --cache "$cache" \ + --no-check-external-hash \ + ./_site diff --git a/atom.xml b/atom.xml index 052b63a8e..08bbfc29c 100644 --- a/atom.xml +++ b/atom.xml @@ -1,9 +1,9 @@ --- layout: null -elixir_url: http://elixir-lang.org +elixir_url: https://elixir-lang.org --- - + Elixir Lang diff --git a/crash-course.markdown b/crash-course.markdown index acbb6da09..e73bc93c3 100644 --- a/crash-course.markdown +++ b/crash-course.markdown @@ -442,7 +442,7 @@ HelloModule.Utils.priv() [This chapter][3] from the Erlang book provides a detailed description of pattern matching and function syntax in Erlang. Here, we briefly cover the main points and provide sample code both in Erlang and Elixir. -[3]: http://learnyousomeerlang.com/syntax-in-functions +[3]: https://learnyousomeerlang.com/syntax-in-functions ### Pattern matching diff --git a/css/style.css b/css/style.css index e4d6c8839..c1e77da83 100644 --- a/css/style.css +++ b/css/style.css @@ -1,16 +1,16 @@ /** * Theme Name: Origin - * Theme URI: http://alienwp.com/themes/origin/ + * Theme URI: https://alienwp.com/themes/origin/ * Description: Minimalistic, mobile-optimized theme with responsive layout. The theme settings include options for uploading favicon and logo images, color picker, typography settings, and a nice selection of Google fonts. * Version: 0.2.8 * Author: Galin Simeonov - * Author URI: http://alienwp.com + * Author URI: https://alienwp.com * Tags: flexible-width, theme-options, threaded-comments, microformats, translation-ready, rtl-language-support, one-column, two-columns, right-sidebar, sticky-post, custom-background, featured-images * License: GNU General Public License v2.0 - * License URI: http://www.gnu.org/licenses/gpl-2.0.html + * License URI: https://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2011 - 2012 Galin Simeonov. All rights reserved. - * http://alienwp.com + * https://alienwp.com */ /* Normalize diff --git a/development.markdown b/development.markdown index 282cbc6fd..9114c9411 100644 --- a/development.markdown +++ b/development.markdown @@ -17,18 +17,18 @@ Elixir runs on top of the Erlang Virtual Machine, which provides a scalable and Elixir's source code is under the [Apache 2 License](https://github.com/elixir-lang/elixir/blob/main/LICENSE) and is maintained by the [Elixir Team](#team). The source code and contribution guidelines can be found on [the language repository](https://github.com/elixir-lang/elixir). -Elixir v1.0 was released in September 2014 and a new minor version is released every 6 months, around May and November of every year. New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann) with a link to the complete CHANGELOG. All security releases [will be tagged with "[security]"](https://groups.google.com/forum/#!searchin/elixir-lang-ann/%5Bsecurity%5D%7Csort:date). Security vulnerabilities should be disclosed to [elixir-security@googlegroups.com](mailto:elixir-security@googlegroups.com). Our [compatibility and deprecation policies](https://elixir.hexdocs.pm/compatibility-and-deprecations.html#content) are also documented. +Elixir v1.0 was released in September 2014 and a new minor version is released every 6 months, around May and November of every year. New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann) with a link to the complete CHANGELOG. All security releases [will be tagged with "[security]"](https://groups.google.com/g/elixir-lang-ann/search?q=%5Bsecurity%5D). Security vulnerabilities should be disclosed to [elixir-security@googlegroups.com](mailto:elixir-security@googlegroups.com). Our [compatibility and deprecation policies](https://elixir.hexdocs.pm/compatibility-and-deprecations.html#content) are also documented. Since v1.0, the language development has become focused to provide a compact and consistent core. The Elixir team focuses on language features that: 1. are necessary for developing the language itself 2. bring important concepts/features to the community in a way its effect can only be maximized or leveraged by making it part of the language -The language development is open, both in terms of source code and of collaborations. All features and bug fixes planned for the next releases can be found [in the issues tracker](https://github.com/elixir-lang/elixir/issues). Features that may cause a larger impact on the ecosystem are first proposed to the community in [the Elixir mailing list](https://groups.google.com/group/elixir-lang-core) as well as in [the "Elixir News" section in the Elixir Forum](https://elixirforum.com/c/elixir-news). +The language development is open, both in terms of source code and of collaborations. All features and bug fixes planned for the next releases can be found [in the issues tracker](https://github.com/elixir-lang/elixir/issues). Features that may cause a larger impact on the ecosystem are first proposed to the community in [the Elixir mailing list](https://groups.google.com/group/elixir-lang-core) as well as in [the "Elixir News" section in the Elixir Forum](https://elixirforum.com/c/elixir-news-announcements). Community members are welcome to propose new features for Elixir. Before submitting a proposal, members are encouraged to gather feedback from around the community in whatever venues seem best. However, in order for a proposal to be considered for inclusion by the Elixir Core team, it must go through the Elixir mailing list. This often includes discussion and refinement of the proposal. The Elixir Core team has the final say on whether a proposal is accepted or rejected. While members are encouraged to gain support from the rest of the community, popularity does not mean that a proposal will be accepted. -To remain focused, Elixir trusts its ecosystem to bring diversity and broaden its use cases. Therefore the language was designed to be extensible: the constructs available to build the language are also available for developers to extend the language and bring it to different domains. Projects such as [the Phoenix web framework](http://phoenixframework.org), [the Nerves embedded framework](http://nerves-project.org), and [Numerical Elixir](https://github.com/elixir-nx/nx) are such examples. +To remain focused, Elixir trusts its ecosystem to bring diversity and broaden its use cases. Therefore the language was designed to be extensible: the constructs available to build the language are also available for developers to extend the language and bring it to different domains. Projects such as [the Phoenix web framework](https://phoenixframework.org), [the Nerves embedded framework](https://nerves-project.org), and [Numerical Elixir](https://github.com/elixir-nx/nx) are such examples. Elixir also relies on a vibrant community to support its growth. The community is behind the meetups, events, learning resources, open source projects, and more. See the sidebar, the [Learning Resources](/learning.html) and [the Hex Package Manager website](https://hex.pm/) for some examples and more information. diff --git a/erlang.csv b/erlang.csv index 7f0e37d55..9aa93f3c6 100644 --- a/erlang.csv +++ b/erlang.csv @@ -2,4 +2,4 @@ version_otp,version_erts,url_win32,url_win64 25.3,13.3,https://github.com/erlang/otp/releases/download/OTP-25.3.1/otp_win32_25.3.1.exe,https://github.com/erlang/otp/releases/download/OTP-25.3.1/otp_win64_25.3.1.exe 24.3,12.3,https://github.com/erlang/otp/releases/download/OTP-24.3.4.2/otp_win32_24.3.4.2.exe,https://github.com/erlang/otp/releases/download/OTP-24.3.4.2/otp_win64_24.3.4.2.exe 23.3,11.2,https://github.com/erlang/otp/releases/download/OTP-23.3.4.8/otp_win32_23.3.4.8.exe,https://github.com/erlang/otp/releases/download/OTP-23.3.4.8/otp_win64_23.3.4.8.exe -22.3,10.7,http://www.erlang.org/download/otp_win32_22.3.exe,http://www.erlang.org/download/otp_win64_22.3.exe +22.3,10.7,https://www.erlang.org/download/otp_win32_22.3.exe,https://www.erlang.org/download/otp_win64_22.3.exe diff --git a/getting-started/mix-otp/config-and-releases.markdown b/getting-started/mix-otp/config-and-releases.markdown index 6a141bef9..32b6168ca 100644 --- a/getting-started/mix-otp/config-and-releases.markdown +++ b/getting-started/mix-otp/config-and-releases.markdown @@ -2,4 +2,5 @@ layout: redirect sitemap: false redirect_to: config-and-releases +redirect_version: "1.18.3" --- diff --git a/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown b/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown index 946955ce2..b4c56404e 100644 --- a/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown +++ b/getting-started/mix-otp/dependencies-and-umbrella-apps.markdown @@ -2,4 +2,5 @@ layout: redirect sitemap: false redirect_to: dependencies-and-umbrella-projects +redirect_version: "1.18.3" --- diff --git a/getting-started/mix-otp/dependencies-and-umbrella-projects.markdown b/getting-started/mix-otp/dependencies-and-umbrella-projects.markdown index 946955ce2..b4c56404e 100644 --- a/getting-started/mix-otp/dependencies-and-umbrella-projects.markdown +++ b/getting-started/mix-otp/dependencies-and-umbrella-projects.markdown @@ -2,4 +2,5 @@ layout: redirect sitemap: false redirect_to: dependencies-and-umbrella-projects +redirect_version: "1.18.3" --- diff --git a/getting-started/mix-otp/distributed-tasks.markdown b/getting-started/mix-otp/distributed-tasks.markdown index a75f95d9a..fe8b1e772 100644 --- a/getting-started/mix-otp/distributed-tasks.markdown +++ b/getting-started/mix-otp/distributed-tasks.markdown @@ -2,4 +2,5 @@ layout: redirect sitemap: false redirect_to: distributed-tasks +redirect_version: "1.18.3" --- diff --git a/getting-started/mix-otp/ets.markdown b/getting-started/mix-otp/ets.markdown index 22e0a0978..0175c46f3 100644 --- a/getting-started/mix-otp/ets.markdown +++ b/getting-started/mix-otp/ets.markdown @@ -2,4 +2,5 @@ layout: redirect sitemap: false redirect_to: erlang-term-storage +redirect_version: "1.18.3" --- diff --git a/install.markdown b/install.markdown index 7c03d0933..b00557860 100644 --- a/install.markdown +++ b/install.markdown @@ -197,7 +197,7 @@ make clean compile The only prerequisite for Elixir is Erlang, version {{ stable.minimum_otp }} or later. When installing Elixir, Erlang is generally installed automatically for you. However, if you want to install Erlang manually, you might check: - * [Source code distribution and Windows installers from Erlang's official website](http://www.erlang.org/downloads.html) + * [Source code distribution and Windows installers from Erlang's official website](https://www.erlang.org/downloads.html) * [Precompiled packages for some Unix-like installations](https://www.erlang-solutions.com/resources/download.html) * [A general list of installation methods from the Riak documentation](https://docs.riak.com/riak/kv/latest/setup/installing/source/erlang/) @@ -211,7 +211,7 @@ Notice that depending on how you installed Erlang, Erlang binaries might not be It is highly recommended to add Elixir's bin path to your PATH environment variable to ease development. -On Windows, there are [instructions for different versions](http://www.computerhope.com/issues/ch000549.htm) explaining the process. +On Windows, there are [instructions for different versions](https://www.computerhope.com/issues/ch000549.htm) explaining the process. On Unix systems, you need to [find your shell profile file](https://unix.stackexchange.com/a/117470/101951), and then add to the end of this file the following line reflecting the path to your Elixir installation: @@ -224,8 +224,8 @@ export PATH="$PATH:/path/to/elixir/bin" After Elixir is up and running, it is common to have questions as you learn and use the language. There are many places where you can ask questions, here are some of them: * [#elixir on irc.libera.chat](irc://irc.libera.chat/elixir) - * [Elixir Forum](http://elixirforum.com) - * [Elixir on Slack](https://elixir-slack.community) + * [Elixir Forum](https://elixirforum.com) + * [Elixir on Slack](https://elixir-lang.slack.com/join/shared_invite/zt-eivteker-k_nArD59XHjjN_r8qeH6dw#/shared-invite/email) * [Elixir on Discord](https://discord.gg/elixir) * [elixir tag on StackOverflow](https://stackoverflow.com/questions/tagged/elixir) diff --git a/js/toc/README.md b/js/toc/README.md index 2d9412d0f..208f7ff5b 100644 --- a/js/toc/README.md +++ b/js/toc/README.md @@ -41,7 +41,7 @@ rdiscount: ### How It Works The script works by looking for headers (h1, h2, h3, h4, h5, h6) which have an `id`. -An id is added automatically if you're using Jekyll and [Markdown](http://daringfireball.net/projects/markdown/syntax#header). +An id is added automatically if you're using Jekyll and [Markdown](https://daringfireball.net/projects/markdown/syntax#header). The table of contents automatically handles nesting of headers. For example, this Markdown post: @@ -72,7 +72,7 @@ $('#toc').toc({ listType: 'ul' }); ``` #### Header Styling -The script also adds an `` tag next to each header. This uses the class `icon-arrow-up`, which if you're using [Bootstrap](http://twitter.github.io/bootstrap/), will be an arrow pointing to the top of the page. +The script also adds an `` tag next to each header. This uses the class `icon-arrow-up`, which if you're using [Bootstrap](https://twitter.github.io/bootstrap/), will be an arrow pointing to the top of the page. Clicking that arrow will scroll you to the top, while clicking on a header will get a permanent link to that particular header (using `window.location.hash`). If you don't want this feature, add this setting: diff --git a/learning.markdown b/learning.markdown index 0a1a0a019..4f0e55fbd 100644 --- a/learning.markdown +++ b/learning.markdown @@ -50,7 +50,7 @@ Learn the best practices for the whole life of your application, from design and

    Joy of Elixir

    -Joy of Elixir +Joy of Elixir Joy of Elixir is a gentle introduction to programming, aimed at people who already know some things about computers, but who have little-to-no programming experience. @@ -69,9 +69,9 @@ Elixir's straightforward syntax and this guided tour give you a clean, simple pa

    The Toy Robot Walkthrough

    -Toy Robot +Toy Robot -The Toy Robot is a common interview exercise for new programmers. This short book will take you through how to implement it in Elixir in a BDD-style, with some great explanations and imagery along the way. +The Toy Robot is a common interview exercise for new programmers. This short book will take you through how to implement it in Elixir in a BDD-style, with some great explanations and imagery along the way. If you're a new Elixir developer who's gone through some basic Elixir tutorials and you're looking for the next thing to build your skills, this book is a great start. It covers the Toy Robot exercise from start to finish, testing with Elixir features such as ExUnit and Doctests along the way. @@ -115,7 +115,7 @@ Learn different ways of writing concurrent code in Elixir and increase your appl

    Erlang in Angerfree

    -Erlang in Anger cover +Erlang in Anger cover This book intends to be a little guide about how to be the Erlang medic in a time of war. It is first and foremost a collection of tips and tricks to help understand where failures come from, and a dictionary of different code snippets and practices that helped developers debug production systems that were built in Erlang. @@ -125,7 +125,7 @@ This book intends to be a little guide about how to be the Erlang medic in a tim

    Elixir Schoolfree

    -Elixir School +Elixir School Elixir-School is an open and community driven effort inspired by Twitter's Scala School. The site's content consists of peer-reviewed lessons on various Elixir topics that range in difficulty. The lessons are currently available in over 10 languages to help make programming Elixir more accessible to non-English speakers. @@ -177,7 +177,7 @@ The course covers getting setup with Elixir, the data types, how to pattern matc

    LearnElixir.tv

    - + LearnElixir.tv cover @@ -250,7 +250,7 @@ Episodes range from beginner focused to more moderate and advanced topics. Come

    Alchemist Campfree

    -Alchemist Camp cover +Alchemist Camp cover Alchemist Camp is the largest producer of free Elixir screencasts and has dozens of hours of screencasts on YouTube. The videos are often longer-form and focused around projects, such as building a small Phoenix clone, or an OTP worker to regularly collect statistics from multiple APIs. Content is driven by viewer request. diff --git a/opensearch.xml b/opensearch.xml index 4e982e7c5..5eaaf86f3 100644 --- a/opensearch.xml +++ b/opensearch.xml @@ -2,14 +2,14 @@ Search Elixir website - http://elixir-lang.org/ - http://elixir-lang.org/ + https://elixir-lang.org/ + https://elixir-lang.org/ UTF-8 en elixir-lang.org - + - http://elixir-lang.org/favicon.ico + https://elixir-lang.org/favicon.ico \ No newline at end of file From 0ad07c57ad39f2b6aed9f1697747255e51e33d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Mon, 1 Jun 2026 13:54:49 +0200 Subject: [PATCH 2/2] Delete .github/workflows/check-links.yml --- .github/workflows/check-links.yml | 44 ------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 .github/workflows/check-links.yml diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml deleted file mode 100644 index 0dff79cc6..000000000 --- a/.github/workflows/check-links.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Check Links - -on: - push: - branches: [main] - pull_request: - schedule: - - cron: '0 8 * * 1' - -jobs: - check-links: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 - with: - bundler-cache: true - - - name: Build site - run: bundle exec jekyll build - - - name: Restore htmlproofer cache - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: tmp/.htmlproofer - key: htmlproofer-${{ runner.os }}-${{ hashFiles('tmp/.htmlproofer/cache.json') }} - restore-keys: htmlproofer-${{ runner.os }}- - - - name: Check links - run: _scripts/check-links; echo "exit_code=$?" >> "$GITHUB_OUTPUT" - id: check-links - - - name: Save htmlproofer cache - uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: tmp/.htmlproofer - key: htmlproofer-${{ runner.os }}-${{ hashFiles('tmp/.htmlproofer/cache.json') }} - - - name: Fail on broken links - run: exit "$EXIT_CODE" - env: - EXIT_CODE: ${{ steps['check-links'].outputs.exit_code }} \ No newline at end of file