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 [email protected] <
> [email protected]> 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 [email protected].
>> 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/77c21ba1-788c-488c-be8e-67597dc22c71n%40googlegroups.com.