Skip to content

RemoteMap returns copies instead of references, leading to unintuitive/unfriendly behaviour #261

@phodge

Description

@phodge

If I have a vim global variable that contains a dict, e.g. g:foo = {"a": "A"}, then the current implementation of RemoteMap leads to some unexpected, unintuitive behaviours when I try to manipulate it in python. For example:

foo = nvim.vars["foo"]
foo["b"] = "B"
print(nvim.vars["foo"].keys())  # -> ["a"]

In python, dicts are normally assigned by reference so a python programmer would expect a change to the local variable foo to also affect the Vim variable. But instead, they are only changing a copy. This is particularly confusing when you write a line of code like this:

nvim.vars["foo"]["b"] = "B"

This doesn't raise an exception when you run it, and it's such a simple line of code that programmers familiar with python won't suspect that it contains a bug. It's just assigning a value to a dict, how can it possibly be broken? But it is broken because when python assigns "B" to the key "b" it is only modifying a copy of g:foo, and the copy is immediately garbage collected and the change never makes it back to neovim.


I can think of three separate actions which will address this in different ways:

  1. Instead of using __get__() and __set__() for RemoteMap key access, have .read() and .write() methods that A) make it obvious that you're getting a copy of the variable and B) make it obvious how many RPC calls are happening. This isn't as slick as __get__(), but at least you intuitively know what's going on.

  2. Bring back the __get__() and __set__() for RemoteMap, but have them return pointers to variables that are generally assigned by reference (vim and python both conveniently have the same opinions on what should be copied vs referenced). This has the disadvantage that a RemoteMap gets returned in place of a simple dict, meaning every key lookup is a separate RPC call, but this might be what the users want.

  3. Document how the .vars RemoteMaps work. Obviously documentation is already a big TODO for this project, but we need to make sure this behaviour is specifically covered if we want to make this API friendly to newcomers.


This issue was also discussed in the neovim gitter starting here: https://gitter.im/neovim/neovim?at=591e0de4631b8e4e61ed6a20

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions