[vim/vim] Vim9: cannot use number to test existence of number key from dictionary with "has_key()" (#8542)

4 views
Skip to first unread message

lacygoill

unread,
Jul 10, 2021, 9:46:38 AM7/10/21
to vim/vim, Subscribed

Describe the bug

In Vim9 script, we cannot use a number to test the existence of a number key from a dictionary with has_key().

To Reproduce

Run this shell command:

vim -Nu NONE -S <(cat <<'EOF'
    vim9script
    def Func()
        var d = {123: 'value'}
        var n = 123
        echo d->has_key(n)
    enddef
    defcompile
EOF
)

E1013 is raised:

E1013: Argument 2: type mismatch, expected string but got number

Expected behavior

No error is raised.

Environment

  • Vim version: 8.2 Included patches: 1-3135
  • OS: Ubuntu 20.04.2 LTS
  • Terminal: XTerm(353)

Additional context

The exact same code doesn't give any error at the script level:

vim9script
var d = {123: 'value'}
var n = 123
echo d->has_key(n)
1

Which is inconsistent.


Regression introduced in 8.2.3135.


One might argue that the error is expected because keys in a dictionary are strings, not numbers, hence why has_key() expects a string as its second argument.

True, but it's also:

  • inconvenient to use string()
  • inconsistent with how we add and get keys from a dictionary

Regarding the 2nd bullet point:

vim9script
var d = {123: 'value'}
var n = 123
echo d[n]
value

Notice that Vim didn't complain; it automatically coerced the value of the n number variable (123) into a string ('123').

This is inconsistent. We don't need to manually coerce a number key to get its value with the [n] notation, but we do need to coerce it to test its existence with has_key().

I understand that type checking is important, but I think it should be enforced only when it helps. And I don't think it will help here to find and fix bugs. I think it's just annoying. I'm not alone:

I do think that using a number or bool as the key is very useful, and requiring string() is not helping.

Source.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

bfrg

unread,
Jul 10, 2021, 12:42:14 PM7/10/21
to vim/vim, Subscribed

It would certainly be more efficient to store the keys in the dictionary as numbers when numbers are required. Though, I don't know if that's possible with the current implementation.

I encountered the same issue when I used a dictionary as a replacement for a set to store unique numbers.

Bram Moolenaar

unread,
Jul 11, 2021, 7:25:20 AM7/11/21
to vim/vim, Subscribed


> It would certainly be more efficient to store the keys in the
> dictionary as numbers when numbers are required. Though, I don't know
> if that's possible with the current implementation.
>
> I encountered the same issue when I used a dictionary as a replacement
> for a set to store unique numbers.

Using a number is just a convenient way to pass in a the key, which is
always a string in the end. It's explained at the help for E713:

A key is always a String. You can use a Number, it will be converted to a
String automatically. Thus the String '4' and the number 4 will find the same
entry. Note that the String '04' and the Number 04 are different, since the
Number will be converted to the String '4'. The empty string can also be used
as a key.


The current implementation always uses a string. Using a number key
would add a lot of code and it's not much more efficient. Mainly
computing the hash of the key can be skipped. The overhead from
searching for the entry is the same. And resizing the dictionary is the
same. I don't think it's worth it.

--
hundred-and-one symptoms of being an internet addict:
113. You are asked about a bus schedule, you wonder if it is 16 or 32 bits.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Bram Moolenaar

unread,
Jul 11, 2021, 8:56:27 AM7/11/21
to vim/vim, Subscribed

Closed #8542 via 1aeddeb.

lacygoill

unread,
Jul 11, 2021, 10:58:13 AM7/11/21
to vim/vim, Subscribed

Something else is still broken by the same patch:

vim9script
def Func()
    virtcol([1, 1])
enddef
defcompile
E1013: Argument 1: type mismatch, expected list<string> but got list<number>

There should be no error. It worked before, and while this code is useless, it's a simplification of a code which is useful.

Also, it's inconsistent for 2 reasons:

vim9script
virtcol([1, 1])

No error at the script level, but error in compiled code.

vim9script
def Func()
    virtcol([1, '$'])
enddef
defcompile

No error in compiled code if one of the items is the string '$'. This means that Vim is ok with list<any>. But the previous error said that Vim expected list<string>.

To be consistent, Vim should accept list<any> at the script level and in compiled code.

lacygoill

unread,
Jul 11, 2021, 10:59:26 AM7/11/21
to vim/vim, Subscribed

To be consistent, Vim should accept list at the script level and in compiled code.

And it should accept list<number>.

Yegappan Lakshmanan

unread,
Jul 11, 2021, 11:11:33 AM7/11/21
to vim_dev, reply+ACY5DGH7PFLSGKB5CS...@reply.github.com, vim/vim, Subscribed
Hi,

On Sun, Jul 11, 2021 at 7:58 AM lacygoill <vim-dev...@256bit.org> wrote:

Something else is still broken by the same patch:

vim9script
def Func()
    virtcol([1, 1])
enddef
defcompile
E1013: Argument 1: type mismatch, expected list<string> but got list<number>

There should be no error. It worked before, and while this code is useless, it's a simplification of a code which is useful.


I have created PR 8545 to address this issue.

Regards,
Yegappan

vim-dev ML

unread,
Jul 11, 2021, 11:11:49 AM7/11/21
to vim/vim, vim-dev ML, Your activity

Hi,


On Sun, Jul 11, 2021 at 7:58 AM lacygoill ***@***.***> wrote:

> Something else is still broken by the same patch:
>
> vim9scriptdef Func()
> virtcol([1, 1])enddefdefcompile
>
> E1013: Argument 1: type mismatch, expected list<string> but got list<number>
>
> There should be no error. It worked before, and while this code is
> useless, it's a simplification of a code which is useful.
>

I have created PR 8545 to address this issue.

Regards,
Yegappan


> Also, it's inconsistent for 2 reasons:
>
> vim9scriptvirtcol([1, 1])

>
> No error at the script level, but error in compiled code.
>
> vim9scriptdef Func()
> virtcol([1, '$'])enddefdefcompile
>
> No error in compiled code if one of the items is the string '$'. This
> means that Vim is ok with list<any>. But the previous error said that Vim
> expected list<string>.
>
> To be consistent, Vim should accept list<any> at the script level and in
> compiled code.
>
>
>
Reply all
Reply to author
Forward
0 new messages