Oops, this is the correct `~/.iex.exs`. The idea is I want to use
Mix.install when using `iex` but _not_ (as it will fail) when using `iex -S
mix`.
if :mix not in Enum.map(Application.started_applications(), &elem(&1, 0)) do
Mix.install([
:decimal,
:jason,
:nimble_csv,
{:requests, github: "wojtekmach/requests"}
])
end
czwartek, 21 stycznia 2021 o 12:18:45 UTC+1 [email protected] napisał(a):
> 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/8c51fd5f-01ff-4ac6-9b17-9e048745c1cfn%40googlegroups.com.