`Mix.install(:decimal)` should also work out of the box IMO. On Thu, 21 Jan 2021 03:18:44 -0800 (PST) "woj...@wojtekmach.pl" <woj...@wojtekmach.pl> wrote:
> A minor addition: I'd like to add a shortcut so you can write > `Mix.install([:decimal])` instead of `Mix.install([{:decimal, ">= > 0.0.0"}])`. > > > The only downside of this approach compared to global dependencies > > is > that each IEx session is a blank session - but that can be > streamlined in the future. > > Agreed. I didn't mention this in the proposal but here's a trick I've > been using: > > # ~/.iex.exs > unless Code.ensure_loaded?(Mix) do > Mix.install([ > :decimal, > :jason, > :nimble_csv, > {:requests, github: "wojtekmach/requests"} > ]) > end > > This means however that when you start a session, you won't be able > to call `Mix.install` again. In those cases I'd `iex --dot-iex ""` to > ignore my global config. > > > czwartek, 21 stycznia 2021 o 12:05:18 UTC+1 José Valim napisał(a): > > > I have discussed this with Wojtek and I am in favor of this > > proposal. > > > > Elixir was designed to support scripting but I constantly hear that > > the lack of some quality of life features, such as trapping exits, > > limited IO handling, lack of support for dependencies, etc make it > > so even advanced Elixir developers don't end-up using Elixir for > > regular single-file scripts. > > > > I have never been a fan of global dependencies. Between global > > dependencies (not easily reproducible and with implicit > > dependencies) and Mix projects (fully reproducible with explicit > > dependencies), this sounds like a reasonable compromise (explicit > > dependencies reproducible within requirements). The only downside > > of this approach compared to global dependencies is that each IEx > > session is a blank session - but that can be streamlined in the > > future. > > > > Note the goal here is not to replace escripts either. Escripts have > > the full-backing of a project, with dependencies, multiple source > > files and tests. If it is anything beyond experimentation or more > > than a couple dozen lines, then you do want a complete project. > > > > TL;DR: +1 > > > > On Thu, Jan 21, 2021 at 11:40 AM woj...@wojtekmach.pl < > > woj...@wojtekmach.pl> wrote: > > > >> Today, the only way to use dependencies in Elixir is by first > >> adding them to the current Mix project or installing them as > >> archives. This makes Elixir less than ideal for simple tasks where > >> you'd usually use a scripting language, e.g. download a JSON file, > >> parse it, extract some data. This is also adding pressure for a > >> more "batteries-included" approach in the stdlib to make these > >> simple tasks more convenient to accomplish and require neither > >> creating a Mix project nor installing dependencies. > >> > >> I'd like to propose adding a `Mix.install` function that will > >> download, compile, and load given dependencies into the VM. > >> > >> Here's how we could use it from an IEx session: > >> > >> $ iex > >> iex> Decimal.new(42) > >> ** (UndefinedFunctionError) function Decimal.new/1 is > >> undefined (module Decimal is not available) > >> Decimal.new(42) > >> iex> Mix.install([{:decimal, "~> 2.0"}]) > >> :ok > >> iex> Decimal.new(42) > >> #Decimal<42> > >> > >> Or from a script: > >> > >> $ cat run.exs > >> Mix.install([ > >> {:decimal, "~> 2.0"}, > >> {:jason, "~> 1.0"} > >> ]) > >> IO.puts Jason.encode!(Decimal.new(42)) > >> > >> $ elixir run.exs > >> "42" > >> > >> You need to call `Mix.install` in your VM and explicitly list all > >> your dependencies. And if you start a new VM, you'd have to call > >> `Mix.install` again. > >> > >> Under the hood, the `Mix.install` starts Mix and creates a > >> temporary Mix project to install and load the dependencies and > >> unloads the temporary project when it's done. For simplicity, the > >> initial implementation allows you to only call this function > >> outside of a Mix project and you can only call it once in a given > >> VM. > >> > >> The temporary project is preserved across runs so if you start > >> another VM and call `Mix.install` with the same set of > >> dependencies, they'll be loaded right away without needing to > >> download or compile them. Each set of dependencies will have it's > >> own temporary directory, roughly: > >> `/tmp/mix_installs/<md5_of_deps>`. > >> > >> The location and the layout of the temporary project is considered > >> an implementation detail that users shouldn't depend on. > >> > >> The fact that the resulting `mix.lock` file is hidden from the > >> users presents challenges around reproducibility and updating > >> deps. If you pin your deps to specific versions, a call to > >> `Mix.install` will give consistent results, however if you use > >> version requirements like `~> 1.0`, it may give different results > >> depending on what the deps resolve to at at given time. Similarly, > >> if there's a new version of a package that satisfies a given > >> version requirement, `Mix.install` won't automatically install it > >> as it already cached the dependency. For this, you'll be able to > >> pass a `force: true` flag to bypass the cache and install & > >> compile from scratch for a given set of dependencies. This will > >> also help if your install somehow got into an inconsistent state. > >> > >> ### Reproducibility > >> > >> Another way of quickly installing and using dependencies is via > >> workspaces, you'd install and automatically load dependencies > >> within a given workspace. That brings questions about > >> reproducibility. > >> > >> Imagine you write a piece of Elixir code that uses dependencies > >> and share it with people, how reproducible is it? > >> > >> - using Mix project, the dependencies are fully reproducible given > >> the Mix project maintains a `mix.lock` file > >> > >> - using `Mix.install`, the dependencies are reproducible within > >> the specified version requirements > >> > >> - using global state like workspaces, the dependencies are not > >> reproducible. If you ask a user to run your script, you need to > >> tell them what dependencies they need to install > >> > >> Between global dependencies having very weak reproducibility and > >> Mix projects being fully reproducible, `Mix.install` is a > >> compromise where you can reasonably reproduce things within a list > >> of requirements. > >> > >> ### Further reading > >> > >> Thanks to https://hex.pm/packages/teex authors for exploring some > >> of these ideas! > >> > >> Also see https://github.com/wojtekmach/playground for an earlier > >> proof-of-concept and > >> https://github.com/elixir-lang/elixir/compare/master...wojtekmach:wm-mix-install > >> > >> for a work-in-progress implementation. > >> > >> -- > >> You received this message because you are subscribed to the Google > >> Groups "elixir-lang-core" group. > >> To unsubscribe from this group and stop receiving emails from it, > >> send an email to elixir-lang-co...@googlegroups.com. > >> To view this discussion on the web visit > >> https://groups.google.com/d/msgid/elixir-lang-core/ed320491-005c-4414-b1a9-5ca0e540bd3dn%40googlegroups.com > >> > >> <https://groups.google.com/d/msgid/elixir-lang-core/ed320491-005c-4414-b1a9-5ca0e540bd3dn%40googlegroups.com?utm_medium=email&utm_source=footer> > >> . > >> > > > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/6009712d.1c69fb81.3d284.a452SMTPIN_ADDED_MISSING%40gmr-mx.google.com.