Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get rid of the Access protocol #2973

Closed
josevalim opened this issue Dec 29, 2014 · 11 comments

Comments

4 participants
@josevalim
Copy link
Member

commented Dec 29, 2014

foo[...] should use the Dict API instead.

Because the Access protocol relies on the code server in development and test mode (when protocol consolidation is not applied), we have heard multiple reports of the system suffering greatly in performance as the code server becomes a bottleneck with multiple processes. This happens because the Access protocol ends up being invoked thousands of times and there isn't much we can do to improve it (in contrast to the Enumerable protocol where most of the list cases are inlined).

The decision has then become to limit the scope of the Access protocol to work only with dictionaries (i.e. entities that implement the Dict behaviour).

Since we are treating this as a performance bug, v1.1 will include a deprecation to the Access protocol (but they will still work). The implication is that we will need to add get_and_update to the Dict API.

@Kabie

This comment has been minimized.

Copy link
Contributor

commented Jan 1, 2015

Will foo[...] works out of box for structs?

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Jan 1, 2015

No, it will work only for dictionaries.

@josevalim josevalim modified the milestone: v1.1.0 Jan 4, 2015

@whatyouhide

This comment has been minimized.

Copy link
Member

commented Jan 24, 2015

I'd love to try and work on this. A couple of questions:

  • Access provides a get/2 function while Dict provides both get/2 and get/3. Would it be fine to just use Dict.get/2 in functions like Kernel.{put,get}_in and friends? I guess it makes sense since implementations of Access.get/2 have to return nil when the key is not found in the container.
  • The Access protocol only specifies get/2 and get_and_update/3, but the implementation of Access for maps also defines a get!/2 function (defined here). A quick grep in the source of Elixir shows that that function isn't called anywhere. Should we nuke it?

I'll post other questions here if I bounce into something I need help understanding :).

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Jan 24, 2015

We shouldn't do anything now regarding this issue. All we are going to do
for 1.1 is emit a warning if someone, besides ourselves, implement the
protocol and add get_and_update to the Dict behavior. :)

José Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Lead Developer

@whatyouhide

This comment has been minimized.

Copy link
Member

commented Jan 24, 2015

Oh, ok! I'm not sure how I would implement the warning (I mean, on my feet I can't come up with a good way to emit a warning if someone defimpls the Access protocol while still not emitting the warning when the protocol is defimpled in the core library).

As for Dict.get_and_update, I'd be glad to give an implementation of it a shot. Maybe we can just @doc false it so that we have it ready to go but no one will actually use it.

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Jan 24, 2015

We should just hardcode inside Protocol the Access protocol and skip the
warning if it is an Atom, List, Map or HashDict.

About get_and_update, there is no need to make it @doc false as it is going
to be part of the Dict API.

José Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Lead Developer

@jemc

This comment has been minimized.

Copy link

commented Mar 19, 2015

Will there be a non-deprecated way to delegate the container[key] syntax to a custom function for a given module/struct?

The most common use I have for this behavior is delegating the access syntax to an inner map of attributes with arbitrary keys that I don't know at compile time:

defmodule Foo do
  defstruct bar: nil, baz: nil, attributes: %{} 
end
defimpl Access, for: Foo do
  def get(%Foo { attributes: attributes }, key) do
    attributes[key]
  end
end
foo = %Foo { bar: 88, baz: 99, attributes: %{ "some_key" => "some_value" } }
IO.inspect foo.bar #=> 88
IO.inspect foo.baz #=> 99
IO.inspect foo.attributes["some_key"] #=> "some_value"
IO.inspect foo["some_key"] #=> "some_value"

Will there be a non-deprecated way to do this?

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Mar 20, 2015

No. Or you need to implement the Dict api for it or it won't work.

@jemc

This comment has been minimized.

Copy link

commented Mar 20, 2015

@josevalim
I saw the deprecation message about implementing the Dict behaviour, and tried to do this with use Dict and implementing the required functions, but couldn't get it to work - Elixir kept telling me the Access protocol was not implemented for my module when I tried to use the bracket syntax. (I'm using Elixir 1.1.0-dev, last pulled from master on March 4)

Can you give an equivalent example to the one I gave using the Dict behaviour here in this issue for me and others who come to this issue after me with the same question?

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Mar 21, 2015

@jemc the point is exactly that your data structure is not a dictionary. Those are exactly the cases we are asking to not implement the Access protocol because it is not a dictionary. Have a helper function to read the attributes directly or something of sorts.

@josevalim

This comment has been minimized.

Copy link
Member Author

commented Aug 10, 2015

Gone!

@josevalim josevalim closed this Aug 10, 2015

jemc added a commit to attm2x/m2x-elixir that referenced this issue Feb 22, 2016

tpoulsen added a commit to tpoulsen/elixir-array that referenced this issue Oct 12, 2016

Implements callbacks for Access behaviour
Access was changed from a protocol to a behaviour in 2015.

Ref: elixir-lang/elixir#2973

cschneid added a commit to cschneid/red_black_tree that referenced this issue May 3, 2017

Remove the Access protocol implementation
The Access protocol was removed from Elixir, see:
elixir-lang/elixir#2973

cruessler added a commit to cruessler/lafamiglia that referenced this issue Jun 26, 2018

Explicitly access fields via dot syntax
Accessing structs via `foo[bar]` has been deprecated in Elixir 1.1.

See elixir-lang/elixir#2973
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.