Re: [elixir-core:9670] System.get_env/0 Performance Improvement

2020-08-18 Thread Alexei Sholik
The same is true for String.split, that's not the point.

On Tue, Aug 18, 2020 at 3:47 PM Trevor Brown  wrote:

> :binary.split only works on binaries and os:getenv/0 returns a list of
> lists.
>
> On Tuesday, August 18, 2020 at 4:04:00 AM UTC-4, alco wrote:
>>
>> The use of String.split instead of :binary.split seems excessive here.
>> Could be a small but quick win.
>>
>> On Tue, Aug 18, 2020 at 9:03 AM José Valim  wrote:
>>
>>> We need to go route 2, as 1 can change at any time (including if 2 is
>>> implemented). So thank you for opening an issue on Erlang's issues tracker,
>>> I am now watching it and I can act based on its status. :)
>>>
>>> On Mon, Aug 17, 2020 at 11:45 PM Trevor Brown 
>>> wrote:
>>>
>>>> Background
>>>>
>>>> I was recently working on a project that invoked `System.get_env/0` on
>>>> every request it handled. Someone changed the infrastructure the
>>>> application was deployed on and greatly increased the number of environment
>>>> variables (3x more) in the environment the Elixir application ran in, and
>>>> the performance of the application degraded by about that same amount (3x
>>>> slower than before). When I profiled the application I quickly found that
>>>> most of the request handling was spent waiting for the `System.get_env/0`
>>>> function to return. I changed the code so `System.get_env/0` was only
>>>> invoked on startup and the performance issue was resolved.
>>>>
>>>> Problem
>>>>
>>>> When I was working on the performance issue in the app the flame graphs
>>>> revealed something interesting - Erlang was actually formatting the
>>>> environment variables from a proplist to a list of strings in certain
>>>> format, and then Elixir was undoing the formatting by parsing the strings
>>>> back to a map! Because of this the performance of the `System.get_env/0`
>>>> function call is tied to the number of variables in the environment.
>>>>
>>>>
>>>>- The Erlang code that formats the variables:
>>>>https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl#L118
>>>>- The Elixir code that parses them and puts them in a dictionary:
>>>>
>>>> https://github.com/elixir-lang/elixir/blob/v1.10.3/lib/elixir/lib/system.ex#L438
>>>>
>>>>
>>>> Possible Solutions
>>>>
>>>> *1. Update the `System.get_env/0` function to use `os:list_env_vars/0`
>>>> function*
>>>>
>>>> This function already exists returns a proplists in the format
>>>> `{VariableName, VariableValue}`. All we need to do is replace the existing
>>>> code with
>>>>
>>>> def get_env do
>>>>Enum.into(:os.list_env_vars(), %{})
>>>> end
>>>>
>>>> This would solve the performance issue and simplify the Elixir code!
>>>> The downside is that `os:list_env_vars/0` is not a documented function,
>>>> which I assume means it's not recommended for other applications to rely on
>>>> it.
>>>>
>>>> *2. Wait for Erlang to change*
>>>>
>>>> Because I assumed `os:list_env_vars/0` is not a function that Elixir
>>>> should be relying on (although nothing prevents it from doing so), I have
>>>> created an enhancement ticket on the Erlang issue tracker to document
>>>> `os:list_env_vars/0` or implement another function that returns the
>>>> environment variables in a proplist with `{VariableName, VariableValue}`
>>>> tuples - https://bugs.erlang.org/browse/ERL-1332.
>>>> <https://bugs.erlang.org/browse/ERL-1332> Once Erlang implements a
>>>> documented function that does this we could then begin updating Elixir.
>>>>
>>>> Thoughts? I doubt this is something that is run into very often but it
>>>> could be easily improved.
>>>>
>>>> --
>>>> 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-l...@googlegroups.com.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/elixir-lang-core/0aecb090-2cbb-46af-8ff4-e34337b123d4o%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/0aec

Re: [elixir-core:9668] System.get_env/0 Performance Improvement

2020-08-18 Thread Alexei Sholik
The use of String.split instead of :binary.split seems excessive here.
Could be a small but quick win.

On Tue, Aug 18, 2020 at 9:03 AM José Valim  wrote:

> We need to go route 2, as 1 can change at any time (including if 2 is
> implemented). So thank you for opening an issue on Erlang's issues tracker,
> I am now watching it and I can act based on its status. :)
>
> On Mon, Aug 17, 2020 at 11:45 PM Trevor Brown  wrote:
>
>> Background
>>
>> I was recently working on a project that invoked `System.get_env/0` on
>> every request it handled. Someone changed the infrastructure the
>> application was deployed on and greatly increased the number of environment
>> variables (3x more) in the environment the Elixir application ran in, and
>> the performance of the application degraded by about that same amount (3x
>> slower than before). When I profiled the application I quickly found that
>> most of the request handling was spent waiting for the `System.get_env/0`
>> function to return. I changed the code so `System.get_env/0` was only
>> invoked on startup and the performance issue was resolved.
>>
>> Problem
>>
>> When I was working on the performance issue in the app the flame graphs
>> revealed something interesting - Erlang was actually formatting the
>> environment variables from a proplist to a list of strings in certain
>> format, and then Elixir was undoing the formatting by parsing the strings
>> back to a map! Because of this the performance of the `System.get_env/0`
>> function call is tied to the number of variables in the environment.
>>
>>
>>- The Erlang code that formats the variables:
>>https://github.com/erlang/otp/blob/master/lib/kernel/src/os.erl#L118
>>- The Elixir code that parses them and puts them in a dictionary:
>>
>> https://github.com/elixir-lang/elixir/blob/v1.10.3/lib/elixir/lib/system.ex#L438
>>
>>
>> Possible Solutions
>>
>> *1. Update the `System.get_env/0` function to use `os:list_env_vars/0`
>> function*
>>
>> This function already exists returns a proplists in the format
>> `{VariableName, VariableValue}`. All we need to do is replace the existing
>> code with
>>
>> def get_env do
>>Enum.into(:os.list_env_vars(), %{})
>> end
>>
>> This would solve the performance issue and simplify the Elixir code! The
>> downside is that `os:list_env_vars/0` is not a documented function, which I
>> assume means it's not recommended for other applications to rely on it.
>>
>> *2. Wait for Erlang to change*
>>
>> Because I assumed `os:list_env_vars/0` is not a function that Elixir
>> should be relying on (although nothing prevents it from doing so), I have
>> created an enhancement ticket on the Erlang issue tracker to document
>> `os:list_env_vars/0` or implement another function that returns the
>> environment variables in a proplist with `{VariableName, VariableValue}`
>> tuples - https://bugs.erlang.org/browse/ERL-1332.
>> <https://bugs.erlang.org/browse/ERL-1332> Once Erlang implements a
>> documented function that does this we could then begin updating Elixir.
>>
>> Thoughts? I doubt this is something that is run into very often but it
>> could be easily improved.
>>
>> --
>> 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/0aecb090-2cbb-46af-8ff4-e34337b123d4o%40googlegroups.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/0aecb090-2cbb-46af-8ff4-e34337b123d4o%40googlegroups.com?utm_medium=email_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/CAGnRm4KHzHHTw_mU6vCUoK3yPYT5cQQBWicMkQ5cGTpZTmT26Q%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KHzHHTw_mU6vCUoK3yPYT5cQQBWicMkQ5cGTpZTmT26Q%40mail.gmail.com?utm_medium=email_source=footer>
> .
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6eMy9APxCjX5OCjdrKEByQTzzPQ4NMWQJuNCXzuXO-Xtyw%40mail.gmail.com.


Re: [elixir-core:9572] Loading arbitrary packages during plain iex sessions

2020-06-15 Thread Alexei Sholik
It's possible to experiment with this by creating a custom mix task,
installing it as an archive and then running `iex -S mix try.package ...`.

On Mon, Jun 15, 2020 at 11:47 AM Abdullah Esmail 
wrote:

> Hello,
>
> I believe it would be extremely helpful to old and new elixir developers
> to be able to try out packages without the need to create a whole project.
> Developers coming from different backgrounds (python, ruby, etc) are used
> to getting into the interactive shell and just importing/requiring the
> package they need and start playing with it.
>
> I don't know if this is technically possible with iex, but it would
> definitely change how I work with elixir in general.
>
> Something like:
> iex --hex  
>
> Even if it takes longer to start, at least I could try those packages
> without creating a dummy project and including those packages as
> dependencies and then compiling everything.
> One command to rule them all.
>
> Maybe `iex --hex` could create a temporary dummy project behind the scenes?
>
> For what it's worth, I'd be *very* willing to help work on implementing
> this if it's going to happen.
>
> I apologize if this has been discussed or brought up before. I couldn't
> find a similar topic.
>
> --
> 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/40ef0ab9-7d92-4601-b445-de7c5796c046o%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/40ef0ab9-7d92-4601-b445-de7c5796c046o%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6eO4AD_1YK9eSLo9iybWz2F2w3N9G3Pj8534vuPLwcRiDg%40mail.gmail.com.


Re: [elixir-core:9547] [Proposal] Add Map.put_if/4

2020-06-05 Thread Alexei Sholik
ut(:bar, bar)
>>>>   |> Map.put(:baz, baz)
>>>>   |> Enum.filter(fn {_k, v} -> v end)
>>>>   |> Enum.into(%{})
>>>> end
>>>>
>>>> This is more concise, but it creates intermediate maps that are
>>>> immediately thrown away. Moreover, if the initial map is very large, the
>>>> filter operation is expensive since it traverses the whole map.
>>>>
>>>>
>>>> *Implementing a maybe_put helper function*
>>>>
>>>> def some_fun(s) do
>>>>   MyStruct{
>>>> foo: foo,
>>>> bar: bar,
>>>> baz: baz
>>>>   } = s
>>>>
>>>>   %{a: "hello", b: 42}
>>>>   |> maybe_put(:foo, foo)
>>>>   |> maybe_put(:bar, bar)
>>>>   |> maybe_put(:baz, baz)
>>>> end
>>>>
>>>> defp maybe_put(map, _key, nil), do: map
>>>> defp maybe_put(map, key, value), do: Map.put(map, key, value)
>>>>
>>>> This is the solution I end implementing almost always. It is present in
>>>> multiple modules across the codebase I work on (and/or put in a generic
>>>> Utils module), and talking with my colleagues I found out that is a utility
>>>> function that they also have to implement often and it has turned up at
>>>> least a couple times[1][2] also in the Elixir Forum.
>>>>
>>>> [1]
>>>> https://elixirforum.com/t/elixir-way-to-conditionally-update-a-map/17952/21?u=rbino
>>>> [2]
>>>> https://elixirforum.com/t/is-there-way-to-create-map-and-conditionally-exclude-some-keys/23315/5?u=rbino
>>>>
>>>> This brings me to my proposal, which is a more generic version of
>>>> maybe_put.
>>>>
>>>> *Proposal*
>>>>
>>>> Add Map.put_if/4 to the Map module. This is more generic (and imho
>>>> clearer) than maybe_put and can be used to solve the same problem without
>>>> creating intermediate results and allowing the code to be clear and 
>>>> concise.
>>>>
>>>>
>>>> def some_fun(s) do
>>>>   MyStruct{
>>>> foo: foo,
>>>> bar: bar,
>>>> baz: baz
>>>>   } = s
>>>>
>>>>   %{a: "hello", b: 42}
>>>>   |> Map.put_if(:foo, foo, foo != nil)
>>>>   |> Map.put_if(:bar, bar, bar != nil)
>>>>   |> Map.put_if(:baz, baz, baz != nil)
>>>> end
>>>>
>>>> Let me know if you need any other information.
>>>> --
>>>> Riccardo
>>>>
>>>> --
>>>> 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-l...@googlegroups.com.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/elixir-lang-core/f513b901-fd93-4f28-88a2-f496a3c84a21o%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/f513b901-fd93-4f28-88a2-f496a3c84a21o%40googlegroups.com?utm_medium=email_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-l...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K_QVpD-eRG6JUOMYV5pVTLchpTgbO0fqN6pPCmuSL4NA%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K_QVpD-eRG6JUOMYV5pVTLchpTgbO0fqN6pPCmuSL4NA%40mail.gmail.com?utm_medium=email_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-l...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/CANmTJ6thcegKJjb7aKPhtQoqfo5%3DCgJo2-KnORRg8B2UcEB%3D-A%40mail.gmail.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/CANmTJ6thcegKJjb7aKPhtQoqfo5%3DCgJo2-KnORRg8B2UcEB%3D-A%40mail.gmail.com?utm_medium=email_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/45a9ec20-f997-4fdf-a4c0-ea88388a8fabo%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/45a9ec20-f997-4fdf-a4c0-ea88388a8fabo%40googlegroups.com?utm_medium=email_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/4F9BCFD1-91CB-4A45-B6C2-BC1E534889DF%40channelviewestates.co.uk
> <https://groups.google.com/d/msgid/elixir-lang-core/4F9BCFD1-91CB-4A45-B6C2-BC1E534889DF%40channelviewestates.co.uk?utm_medium=email_source=footer>
> .
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6ePNqjxHozP%2B39GD2yoKihsM8EKudEbnCdRvfGGWqipMTg%40mail.gmail.com.


Re: [elixir-core:9419] [Proposal] Mix deps.get option to avoid updating the lockfile

2020-03-17 Thread Alexei Sholik
Sometimes the lockfile is updated when its format changes, but all the deps
remain at the same versions. I've seen that a number of times when
upgrading the version of Hex and/or Elixir.

On Tue, Mar 17, 2020 at 5:08 PM Wojtek Mach  wrote:

> Yeah, `mix deps.get` would create the lock file if there isn’t one, but I
> also believe it would not update it unless you also change your deps. If
> that isn’t the case I would also argue that’s a bug (i.e. —frozen-lockfile
> would be implicit. An exception is where we change the lock file format,
> e.g. recent hex checksum changes.)
>
> On 17 Mar 2020, at 16:06, Alessio 'Blaster' Biancalana <
> dottorblas...@gmail.com> wrote:
>
> Hi José,
> Wow, this is an unexpected turn of events. :-D I will track if it happens
> again, sometimes my provisioning scripts (ansible roles and stuff like
> that) find local modifications in my repos so it definitely gets updated. I
> will come back with a more detailed analysis then, thank you for the kind
> reply!
>
> Alessio
>
> On Tue, Mar 17, 2020 at 4:01 PM José Valim  wrote:
>
>> AFAIK, mix deps.get doesn't update the lockfile. If it does, it is a bug.
>> :)
>>
>> On Tue, Mar 17, 2020 at 3:54 PM Alessio Biancalana <
>> dottorblas...@gmail.com> wrote:
>>
>>> Hello,
>>> It's my first time proposing a feature for a programming language so I
>>> don't know how to deal with it and I hope to do it right :-)
>>>
>>> Coming from other ecosystems I saw that some platforms offer a way to
>>> avoid updating the lockfile while downloading dependencies for a project,
>>> mainly for software delivery and continuous integration purposes. One
>>> example of this is the `npm ci` command, or `yarn install
>>> --frozen-lockfile` command, for JavaScript projects.
>>>
>>> I love the idea to provide an option to operate with a project avoiding
>>> generating new files or modifying existing ones, so I was thinking about
>>> adding something like `mix deps.get --ci` or `mix deps.get
>>> --avoid-lockfile-update`. I basically didn't want to steal the "frozen
>>> lockfile" name, even if it is nice :-D
>>>
>>> From my point of view this could be a nice improvement, looking forward
>>> to hearing from you,
>>>
>>> Alessio
>>>
>>>
>>> --
>>> 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/7538c297-6b3a-4d63-9324-4a1bd00b0cbe%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/7538c297-6b3a-4d63-9324-4a1bd00b0cbe%40googlegroups.com?utm_medium=email_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/CAGnRm4%2BFoCt%2BXQdTr-E-RWX%2BLy%3DuR%3DzTupJX8UGoFOq7rV9TQg%40mail.gmail.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BFoCt%2BXQdTr-E-RWX%2BLy%3DuR%3DzTupJX8UGoFOq7rV9TQg%40mail.gmail.com?utm_medium=email_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/CAK6%2BgZJWU76JtqgCKF8G2%2B5BO0Uc8f0p2%3D7pkR1PerrDrRsa7g%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAK6%2BgZJWU76JtqgCKF8G2%2B5BO0Uc8f0p2%3D7pkR1PerrDrRsa7g%40mail.gmail.com?utm_medium=email_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/A06806CB-0ED7-4DD2-B432-5C71294C1997%40wojtekmach.pl
> <https://groups.google.com/d/msgid/elixir-lang-core/A06806CB-0ED7-4DD2-B432-5C71294C1997%40wojtekmach.pl?utm_medium=email_source=footer>
> .
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6eMUOV53HKsWQcyk_kh7ZrYJHJvu3PbHtckVgAW4BSVsrQ%40mail.gmail.com.


Re: [elixir-core:9300] [Proposal] defrecord syntactic sugar like defstruct

2020-01-03 Thread Alexei Sholik
And it's also possible to update selected fields of an existing record.
This is all described in the docs:

iex(5)> r = bb()
{:bb, 1}
iex(6)> r1 = bb(r, a: 2)
{:bb, 2}
iex(7)> bb(r1, :a)
2
iex(8)> bb(a: x) = r1
{:bb, 2}
iex(9)> x
2

On Fri, Jan 3, 2020 at 11:19 AM Alexei Sholik  wrote:

> It's already possible to match on record's individual fields, you just
> need to import it:
>
> iex(2)> import B
> B
> iex(3)> bb(a: i) = bb()
> {:bb, 1}
> iex(4)> i
> 1
>
> On Fri, Jan 3, 2020 at 9:07 AM Kevin Johnson 
> wrote:
>
>> First proposal for 2020!
>>
>> Just like a `struct` is an extension over a `map` with its own dedicated
>> syntactic sugar, what prevents to regard a `record` to be an extension over
>> a `tuple` with syntactic sugar en par with that of a `struct`?
>>
>> When we introduce a `struct`:
>>
>> defmodule A do
>>  defstruct a: 1
>> end
>>
>> Instead of interacting with it like:
>> %{__struct__: A, a: i} = a
>>
>> We can interact with it as:
>>
>> %A{a: i}= a
>>
>> and likewise we can pattern match the same on function arguments:
>>
>> def set(m =%A{},i), do:%{m|a: i}
>>
>>
>> According to the documentation <https://hexdocs.pm/elixir/Record.html> a
>> variety of `macro`s have already been introduced to abstract away from the
>> underlying `tuple` as a data structure.
>>
>> I am wondering if there would be any merit if a `Record` could be
>> accorded with its own special notation that would allow us to pattern match
>> accordingly?
>>
>> Currently the equivalent of the `set`-`method` above is to be written
>> using a `guard`, e.g.:
>> defmodule B do
>>  import Record
>>  defrecord(:bb, a: 1)
>>
>>   def set(record, i) when is_record(record, :bb) do
>> bb(record, a: i)
>>  end
>> end
>>
>>
>> and pattern matching on a specific value can only be done by resorting to
>> the underlying tuple implementation:
>>
>> require B
>> {:bb, i}= B.bb()
>>
>>
>> It would be nice if we could introduce a special notation such as:
>> ~bb{a: 1}
>>
>> So then we could:
>> def set(record = ~bb{}, i) do
>>
>> and:
>> require B
>> ~B.bb{a: i} = B.bb()
>>
>>
>>
>> These two aspects are the core aspects of my proposal. In addition to
>> this, I would like to highlight that it would be helpful if we could bridge
>> the gap even more by being able to do:
>> defmodule B do
>> import Record
>> defrecord(__MODULE__, a: 1)
>>
>> def set(record = ~__MODULE__{}, i) do
>> ...
>> which in itself is possible, but at the expense of losing access to the
>> underlying macros as enumerated in the documentation.
>>
>> You would not be able to do:
>> require B
>> # B()
>> # B.B()
>>
>> Also it would be nice to be able to update similar to a map:
>> defmodule B do
>> import Record
>> defrecord(__MODULE__, a: 1)
>>
>> def set(record = ~__MODULE__{}, i) do
>> ~__MODULE__{record | a: i}
>> end
>> end
>>
>>
>> These last two suggestions are mainly to illustrate how the end result
>> could potentially look like if we were to fully bridge the gap so to say,
>> but the most essential one is the pattern matching aspect detailed above.
>>
>> --
>> 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/36e4c070-4efc-4641-8341-f3a95c71a905%40googlegroups.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/36e4c070-4efc-4641-8341-f3a95c71a905%40googlegroups.com?utm_medium=email_source=footer>
>> .
>>
>
>
> --
> Best regards
> Alexei Sholik
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6eNk_of%2B-JDVNSdpQEt9sdy9GiRi%3DqnKVCzw3HMydmtNSA%40mail.gmail.com.


Re: [elixir-core:9299] [Proposal] defrecord syntactic sugar like defstruct

2020-01-03 Thread Alexei Sholik
It's already possible to match on record's individual fields, you just need
to import it:

iex(2)> import B
B
iex(3)> bb(a: i) = bb()
{:bb, 1}
iex(4)> i
1

On Fri, Jan 3, 2020 at 9:07 AM Kevin Johnson 
wrote:

> First proposal for 2020!
>
> Just like a `struct` is an extension over a `map` with its own dedicated
> syntactic sugar, what prevents to regard a `record` to be an extension over
> a `tuple` with syntactic sugar en par with that of a `struct`?
>
> When we introduce a `struct`:
>
> defmodule A do
>  defstruct a: 1
> end
>
> Instead of interacting with it like:
> %{__struct__: A, a: i} = a
>
> We can interact with it as:
>
> %A{a: i}= a
>
> and likewise we can pattern match the same on function arguments:
>
> def set(m =%A{},i), do:%{m|a: i}
>
>
> According to the documentation <https://hexdocs.pm/elixir/Record.html> a
> variety of `macro`s have already been introduced to abstract away from the
> underlying `tuple` as a data structure.
>
> I am wondering if there would be any merit if a `Record` could be accorded
> with its own special notation that would allow us to pattern match
> accordingly?
>
> Currently the equivalent of the `set`-`method` above is to be written
> using a `guard`, e.g.:
> defmodule B do
>  import Record
>  defrecord(:bb, a: 1)
>
>   def set(record, i) when is_record(record, :bb) do
> bb(record, a: i)
>  end
> end
>
>
> and pattern matching on a specific value can only be done by resorting to
> the underlying tuple implementation:
>
> require B
> {:bb, i}= B.bb()
>
>
> It would be nice if we could introduce a special notation such as:
> ~bb{a: 1}
>
> So then we could:
> def set(record = ~bb{}, i) do
>
> and:
> require B
> ~B.bb{a: i} = B.bb()
>
>
>
> These two aspects are the core aspects of my proposal. In addition to
> this, I would like to highlight that it would be helpful if we could bridge
> the gap even more by being able to do:
> defmodule B do
> import Record
> defrecord(__MODULE__, a: 1)
>
> def set(record = ~__MODULE__{}, i) do
> ...
> which in itself is possible, but at the expense of losing access to the
> underlying macros as enumerated in the documentation.
>
> You would not be able to do:
> require B
> # B()
> # B.B()
>
> Also it would be nice to be able to update similar to a map:
> defmodule B do
> import Record
> defrecord(__MODULE__, a: 1)
>
> def set(record = ~__MODULE__{}, i) do
> ~__MODULE__{record | a: i}
> end
> end
>
>
> These last two suggestions are mainly to illustrate how the end result
> could potentially look like if we were to fully bridge the gap so to say,
> but the most essential one is the pattern matching aspect detailed above.
>
> --
> 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/36e4c070-4efc-4641-8341-f3a95c71a905%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/36e4c070-4efc-4641-8341-f3a95c71a905%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
Best regards
Alexei Sholik

-- 
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/CAAPY6eP_Ci43cfeocGFR9GfD_8pvX_dm87FDygsasuY%2BWa-OGg%40mail.gmail.com.


Re: [elixir-core:9109] Prefix/Suffix map keys proposal

2019-09-20 Thread Alexei Sholik
It's functionality that is very specific to a particular use case to be
added to a standard library module. Plus, it either needs to create new
atoms (which standard library will never do) or fail for some inputs (which
is again not generally useful):

iex(1)> m = %{key_1: :val_1, key_2: :val_2}
iex(4)> m |> Map.take([:key_1, :key_2]) |> Map.new(fn {key, val} ->
{String.to_existing_atom("prefix_#{key}"), val} end)
** (ArgumentError) argument error
:erlang.binary_to_existing_atom("prefix_key_1", :utf8)
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:240: :erl_eval.expr/5
(elixir) lib/map.ex:216: Map.new_transform/3
iex(4)> :prefix_key_1
:prefix_key_1
iex(5)> :prefix_key_2
:prefix_key_2
iex(6)> m |> Map.take([:key_1, :key_2]) |> Map.new(fn {key, val} ->
{String.to_existing_atom("prefix_#{key}"), val} end)
%{prefix_key_1: :val_1, prefix_key_2: :val_2}

On Fri, Sep 20, 2019 at 4:07 PM Tiago Botelho 
wrote:

> A common pattern that I've found myself using is having to prefix a few
> keys (namely `ids`) which I do with following approach:
>
> ```
> %{}
> |> Map.put(:prefix_key_1, map.key_1)
> |> Map.put(:prefix_key_2, map.key_2)
>
> => %{prefix_key_1: :val_1, prefix_key_2: :val_2}
> ```
>
> or
>
> ```
> %{prefix_key_1: map.key_1, prefix_key_2: map.key_2}
>
> => %{prefix_key_1: :val_1, prefix_key_2: :val_2}
> ```
>
> It seems to me that we already have good functionality for taking specific
> keys out of a map by using Map.take/2
> (which is effectively the same thing we are doing in the examples above)
> but no good way of bulk updating specific key names.
>
> My proposal would be to be able to pass a `prefix` as an option to
> `Map.take` which would look roughly like the following:
>
> ```
> Map.take(map, [:key_1, :key_2, :key_3], prefix: :prefix)
>
> => %{prefix_key_1: :val_1, prefix_key_2: :val_2, prefix_key_3: :val_3}
> ```
>
> Pros:
>
> * A simpler interface to take keys from a map and "rename" them according
> to the context they will be used for
>
> Cons:
>
> * Using the `prefix` option would mean that all the keys would get
> prefixed, a mixed approach would still require the examples showed above.
> * Might make Map.take do too much at once
>
> Since the Cons might be might seem to discourage this approach, another
> proposal would be to introduce Map.prefix/2 and Map.suffix/2 which would
> only
> update the chosen keys in a map like so:
>
>
>  ```
>  map
>  |> Map.take([:key_1, :key_2, :key_3, :key_4])
>  |> Map.prefix([:key_3, :key_4], :prefix)
>
>  => %{key_1: :val_1, key_2: val_2, prefix_key_3: :val_3, prefix_key_4:
> :val_4}
> ```
>
> Interested in hearing your thoughts 
>
> Thank you,
> Tiago
>
> --
> 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/d7ee27af-814a-419e-8b3c-280fbad4191e%40googlegroups.com
> 
> .
>

-- 
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/CAAPY6eP0zCrsazkHHimMgMwbq_-jOs0et5vBEAwftgp8%2BxRNtg%40mail.gmail.com.


Re: [elixir-core:9058] [Proposal] Map.filter/2 based on :maps.filter

2019-08-15 Thread Alexei Sholik
The simplest alternative is to use :maps.filter(). It's not as easy to pipe
into, but that's a minor concern for me.

As another alternative, this should be faster and have lower memory
footprint than using Enum, although you'd need to benchmark it as well to
be sure:

map
|> Stream.filter(predicate)
|> Map.new()

Personally, I would love to see an extension for Map.new() that would allow
filtering the first argument in addition to the currently supported
transformation. So instead of the current

Map.new(enumerable, fn thing -> {key, val} end)

we could have

Map.new(enumerable, map: fn thing -> {key, val} end, filter: fn {_key, val}
-> predicate(val) end)

Such an extension is unlikely to be added though because it would be
another way of doing what is already possible with Enum, Stream, and Map.

On Thu, Aug 15, 2019 at 10:29 AM Roman Smirnov  wrote:

> Since OTP 18 there is a pretty convenient function :maps.filter
> .
>
> I think it would be nice to have Map.filter(map, predicate) in Elixir as
> well instead of doing
>
>
> map|> Enum.filter(predicate)|> Enum.into(%{})
>
>
> or
>
> for {key, value} <- map, some_filter(key, value), into: %{}, do: {key, value}
>
> The first one alternative is slower, b/c of 2-step transformation, and the
> second one consume more memory, could not be piped and has a lack
> of expressiveness (too imperative way to do a simple filtration).
> There were benchmarks and a small discussion in PR:
> https://github.com/elixir-lang/elixir/pull/9292, but the discussion
> should be moved to this mailing list.
>
>
> --
> 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/5d403c4a-91f8-4c4d-8dc0-297185a2aed8%40googlegroups.com
> 
> .
>

-- 
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/CAAPY6eO5aDifRxHxv7QtD4%3Di_bYbUw1sphxMhq4jEjuR9naPSQ%40mail.gmail.com.


Re: [elixir-core:8513] Aliases of non existent modules

2019-03-01 Thread Alexei Sholik
Mix does warn about it when you try to call a function from a non-existent
module:

$ mix compile
Compiling 1 file (.ex)
warning: function This.Module.Does.Not.Exist.foo/0 is undefined (module
This.Module.Does.Not.Exist is not available)

It does so because `mix xref` runs automatically on each compilation. The
base Elixir compiler doesn't perform such checks.

On Fri, Mar 1, 2019 at 4:08 PM Jan Ziniewicz 
wrote:

>
> Hi everyone,
>
> Please take a look at this line of code:
>
> alias This.Module.Does.Not.Exist
>
> In my opinion compiler should emit an error or at least warning when
> trying to alias a non existent module? However, this line is perfectly
> valid  piece of code.
> Asking just out of curiosity, is this a bug or a feature?
>
> Best, Jan
>
> --
> 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/3bc43a69-ad37-4323-be65-f7ddac4aaead%40googlegroups.com
> 
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6ePFexxHpxBGmR4Bjxa_xQgXAibTsEnAU97S%2BrF1udPPkQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:8382] Enum.sum/2

2018-12-02 Thread Alexei Sholik
The first advantage (write less code) is defeated by adding one more
function to the module, thereby increasing the API surface.

As for the second one, this code does one pass through the list:

Stream.map([1,2,3], & &1*2) |> Enum.sum

On Sat, Dec 1, 2018 at 6:19 PM Sean Handley  wrote:

> Hello,
>
> I'd like to propose *Enum.sum/2*, where the second argument is a function.
>
> This will allow writing
>
> Enum.sum([1, 2, 3], &(&1 * 2))
>
> instead of
>
> Enum.map([1,2,3], &(&1 * 2)) |> Enum.sum()
>
> The advantages are:
>
> - Write less code.
> - One few iteration across the collection.
>
> I have a branch prepared -
> https://github.com/elixir-lang/elixir/compare/master...seanhandley:map_with_func
>
> Please let me know your thoughts.
>
> Cheers,
> Sean
>
> --
> 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/a6cb1e15-f32a-4e27-848d-ac8b80f080c0%40googlegroups.com
> 
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6eMtmpyK7DPGHQ4FLU%2BC8iHhn3SXAJ_i%3DvSWH-gFVYK2bg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:7426] [Proposal] Support keyword list short hand with the cons operator

2017-09-14 Thread Alexei Sholik
Questions like this should be asked on the Elixir Forum.

The problem with the expression `[x: 1, y: 2 | [z: 3]]` is that it is
parsed as `[x: 1, y: (2 | [z: 3])]`. As you may guess, the subexpression `2
| [z: 3]` does not make sense.

There's actually a working way to build the keyword list you want: [x: 1,
y: 2] ++ [z: 3].

On Wed, Sep 13, 2017 at 3:56 PM, Allen Madsen  wrote:

> Yesterday I wrote code like the following:
>
> [x: 1, y: 2 | [z: 3]]
>
> I was really surprised when it didn't compile:
>
> ** (CompileError) iex:1: undefined function |/2
> (stdlib) lists.erl:1354: :lists.mapfoldl/3
> (stdlib) lists.erl:1355: :lists.mapfoldl/3
>
> The non-shorthand version works fine.
>
> [{:x, 1}, {:y, 2} | [z: 3]]
> #=> [x: 1, y: 2, z: 3]
>
> --
> 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/6e89a635-6642-4f42-ace8-
> 4a36119fa4e5%40googlegroups.com
> 
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6ePPtOKu%3D1%2BrxN0yXQF1Qm%3D%2BL0Q1ZtHmmmfjoLMWtn5Waw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


[elixir-core:6392] Proposal: Introduce `use GenServer, strict: true`

2016-09-23 Thread Alexei Sholik
Hi,

We all love the ability to `use GenServer` in order to provide default
stubs for callback functions, saving us time and effort of writing the same
boilerplate over and over again.

However, I'm sure many of you have also been bitten by this very feature
where you made a typo in the signature of init/1 or handle_info/2 and was
left scratching your head wondering why the gen server's state looks so
weird or whether it receives any messages sent to it.

I'd like to propose an addition that will make the default stubs stricter
in terms of handling unexpected input. The idea is basically adding the
`strict` option to the `use GenServer` call. When that option is supplied
with value `true`, the following changes will take effect:

  1. There will be no default implementation of init/1. If the user forgets
to implement it or implements it incorrectly by supplying a different
number of arguments, the compiler will warn about the missing init/1
implementation.

  2. The default implementation of handle_info/1 will exit on any incoming
message, in the same way handle_cast/2 and handle_call/3 already do.

The change will be backwards-compatible if we make `strict: false` the
default. However, we should mention in the docs that calling `use
GenServer, strict: true` is the recommended way for any serious purpose and
that `use GenServer` should be reserved for playground or throw-away code.

Here's a proof of concept –
https://github.com/elixir-lang/elixir/compare/master...alco:alco/strict-gen-server

Best regards,
Alex

-- 
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/CAAPY6eOSggAn6T3k3E0crKx1H381XUdrccw7KTZhqA9iod6jhA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:6224] Elixir way to handle errors in pipes

2016-08-15 Thread Alexei Sholik
The Elixir way is to use the pipe and `with` where each is more suitable
for the task. So if you need to write a sequence of function calls where
some or all are expected to return an error, `with` would be the most
appropriate tool to use.

One key difference between a pipeline and `with` is that the latter stops
evaluation as soon as it encounters the first failed match. Whereas with a
pipeline you'd have to wrap all constituent functions to pass the error
from a previous step down to the next one. I see it as a downside to trying
to use the pipe in places where it is more important to explicitly handle
errors.

On Mon, Aug 15, 2016 at 2:12 PM, Alvise Susmel 
wrote:

> Hi,
>
> I've started thinking about this, as maybe many of you, when I needed to
> stop the pipe when an error is returned. I've seen that there are different
> conversation about this, but I haven't clear what is the *elixir way* to
> handle errors using pipes.
>
> I see two ways for achieving the same result.* The first* is to use the
> *pipe* *|>* and for each function catch the error and propagate it down.
> The error has to be always returned with the same pattern, like {:error,
> reason}
>
> connect
> |> receive_image
> |> resize
> |> rotate
> |> save
>
>
> If *receive_image* returns an error,  *resize* needs to handle it
>
> def resize({:error, _}=error), do:error
>
> and to propagate it down through the pipe. So *rotate* needs to do the
> same, etc..
>
> *The* *second* way I see is using the *with*, which to me seems to be
> more generic (and less clean)
>
> with {:ok, pid} <- connect,
>{:ok, image} <- receive_image(pid),
>{:ok, resized_image} <- resize(image),
>   {:ok, rotated_image} <- rotate(resized_image),
>   :ok <- save(rotated_image)
> do: IO.puts "saved"
>
>
> Now, the cool thing about *with* is that when one of the assignments
> fails, it exits returning the value that failed the pattern match.
>
> So, to you, what is the elixir way on handling the return errors on pipes
> ? Could *"with" *be seen as a new (and more generic) way of piping with
> error handling ?
>
> Thanks
>
> Alvise
>
> --
> 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/1dc86df2-eca0-4fa5-b883-
> 7b9c2df36444%40googlegroups.com
> 
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6eOixE%3DTyrvFgabb-ErY%2BKOSz52x_A6uNeD_SSDQACEWDA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:6140] Feature Request: @see_also attribute

2016-07-19 Thread Alexei Sholik
ExDoc already supports auto-linking for modules and functions inside the
docstring. See, for example,
http://elixir-lang.org/docs/stable/elixir/Enum.html#filter/2.

On Tue, Jul 19, 2016 at 1:41 AM, eksperimental 
wrote:

> I have been craving for this feature for a long time.
> I think it will help with a lot with things such as including
> discoverability of functions or leading people in the right direction
> with very little effort from the documentation side.
>
> A @see_also (it could be named @related, or any other better name).
>
> Let's say in Enum module
>
>   @spec at(t, index, default) :: element | default
>   @see_also [:fetch!/2, :fetch/2]
>   def at(enumerable, index, default \\ nil) do
> case fetch(enumerable, index) do
>   {:ok, h} -> h
>   :error   -> default
> end
>   end
>
>   @spec filter(t, (element -> as_boolean(term))) :: list
>   @see_also :reject
>   def filter(enumerable, fun) when is_list(enumerable)
>   and is_function(fun, 1) do
>...
>
> ExDoc could take advantage of such feature, and automatically linked to
> suggested functions.
>
> --
> 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/20160719054127.7a04ed2d.eksperimental%40autistici.org
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6eP4L3ojoqZN5QSOVHm7zqFaQ69iRSm3-cvjb%2Brw0iDUkA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:6052] The 'else' clause in 'with' does not support guards

2016-07-07 Thread Alexei Sholik
https://github.com/elixir-lang/elixir/issues/4957

On Thu, Jul 7, 2016 at 4:31 PM, José Valim <jose.va...@plataformatec.com.br>
wrote:

> Accidental omission. Please open up an issue. :)
>
>
>
> *José Valim*
> www.plataformatec.com.br
> Skype: jv.ptec
> Founder and Director of R
>
> On Thu, Jul 7, 2016 at 3:30 PM, Alexei Sholik <alcosho...@gmail.com>
> wrote:
>
>> Trying to compile the following piece of code
>>
>> with :ok <- {:error, :foo} do
>>   :ok
>> else
>>   {:error, reason} when reason in [:foo, :bar] ->
>> :some_error
>>   {:error, _} ->
>> :generic_error
>> end
>>
>>
>> results in this error
>>
>> ** (CompileError) iex:1: cannot invoke local when/2 inside match, called
>> as: {:error, reason} when :erlang.or(:erlang.=:=(reason, :bar),
>> :erlang.=:=(reason, :foo))
>>
>>
>> I wonder if there's a specific reason for not supporting everything the
>> 'case' expression supports in the 'else' clause? It looks like an
>> accidental omission to me.
>>
>> --
>> 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/CAAPY6eMv0%2BZ1_jiJmjTBC2-zn3n7SZ13%2BYnM9-WhyARFLA44Ow%40mail.gmail.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/CAAPY6eMv0%2BZ1_jiJmjTBC2-zn3n7SZ13%2BYnM9-WhyARFLA44Ow%40mail.gmail.com?utm_medium=email_source=footer>
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> 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/CAGnRm4J6ktWrt-zpbGpop_B%2Bpf797m05RE9hw%3DsOaX93ZZFi3g%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J6ktWrt-zpbGpop_B%2Bpf797m05RE9hw%3DsOaX93ZZFi3g%40mail.gmail.com?utm_medium=email_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6eNv%2BZVG3OHz54Vv_bAFWCSE4%2B5og%3Dt6m111b52gd3a-dA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [elixir-core:5863] Proposal: Enum.find_map/4

2016-05-27 Thread Alexei Sholik
Greg is right. In Elixir 1.3 it'll become possible to access map fields
when using get_in(). So the first code snippet from the original post may
become this

foo = get_in(Enum.find(list, _check/1), [Access.field(:bar)])


However, given the fact that OP uses both field access and Map.get, it's
not clear what the actual desired behaviour is. Maybe this would suffice

foo = get_in(Enum.find(list, _check/1), [:bar])


which already works in Elixir 1.2.x.

On Fri, May 27, 2016 at 4:46 PM, Greg Vaughn  wrote:

> I think you'll be able to achieve this cleanly with Kernel.get_in and
> Kernel.update_in with Elixir 1.3. I'm sure there's more info somewhere, but
> this is the extent of my knowledge at this time:
> https://twitter.com/elixirlang/status/735942800039088129
>
> -Greg
>
> > On May 27, 2016, at 6:56 AM, Thijs Klaver  wrote:
> >
> > Hello,
> >
> > In the same sense as Enum.filter_map/3, Enum.map_join/3, I propose
> Enum.find_map/4 (or Enum.find_transform/4).
> > Right now you would do something like
> >
> > foo =
> >   Enum.find list, nil, fn item -> some_check(item) end
> >   |> if(foo, do: foo.bar)
> >
> > With Enum.find_map you could do something like this
> >
> > foo = Enum.find list, nil, fn item -> some_check(item) end, fn item ->
> Map.get item, :bar end
> >
> > This way you don't have to check if Enum.find actually found something
> before transforming it.
> >
> > --
> > 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/8d31a0c3-1902-480b-aeb7-38182726c884%40googlegroups.com
> .
> > For more options, visit https://groups.google.com/d/optout.
>
> --
> 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/8E2F654A-BB47-4896-87A2-1BE0A8160AD9%40gmail.com
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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/CAAPY6eNtLVh%3DsDUimB%3Dm2dGV_Z%2B2dV0wHvnGb-_0ihbhf8YhjA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.