chapters/35.markdown @ 35d6b25d0335

Merge pull request #75 from nikkypx/fix-error-in-26

Fix grammar
author Steve Losh <steve@stevelosh.com>
date Mon, 06 Feb 2017 12:23:24 +0000
parents 5868e6263612
children (none)
Lists
=====

We've worked a lot with variables so far, but we haven't talked about aggregates
at all yet!  Vim has two main aggregate types, and we'll look at the first now:
lists.

Vimscript lists are ordered, heterogeneous collections of elements.  Run the
following command:

    :::vim
    :echo ['foo', 3, 'bar']

Vim displays the list.  Lists can of course be nested.  Run the following
command:

    :::vim
    :echo ['foo', [3, 'bar']]

Vim happily displays the list.

Indexing
--------

Vimscript lists are zero-indexed, and you can get at the elements in the usual
way.  Run this command:

    :::vim
    :echo [0, [1, 2]][1]

Vim displays `[1, 2]`.  You can also index from the end of the list, much like
Python.  Try this command:

    :::vim
    :echo [0, [1, 2]][-2]

Vim displays `0`.  The index `-1` refers to the last element in the list, `-2`
is the second-to-last, and so on.

Slicing
-------

Vim lists can also be sliced.  This will *look* familiar to Python programmers,
but it does *not* always act the same way!  Run this command:

    :::vim
    :echo ['a', 'b', 'c', 'd', 'e'][0:2]

Vim displays `['a', 'b', 'c']` (elements 0, 1 and 2).  You can safely exceed the
upper bound as well.  Try this command:

    :::vim
    :echo ['a', 'b', 'c', 'd', 'e'][0:100000]

Vim simply displays the entire list.

Slice indexes can be negative.  Try this command:

    :::vim
    :echo ['a', 'b', 'c', 'd', 'e'][-2:-1]

Vim displays `['d', 'e']` (elements -2 and -1).

When slicing lists you can leave off the first index to mean "the beginning"
and/or the last index to mean "the end".  Run the following commands:

    :::vim
    :echo ['a', 'b', 'c', 'd', 'e'][:1]
    :echo ['a', 'b', 'c', 'd', 'e'][3:]

Vim displays `['a', 'b']` and `['d', 'e']`.

Like Python, Vimscript allows you to index and slice strings too.  Run the
following command:

    :::vim
    :echo "abcd"[0:2]

Vim displays `abc`. However, you can't use negative bare indices with strings.
You *can* use negative indices when slicing strings though!  Run the following
command:

    :::vim
    :echo "abcd"[-1] . "abcd"[-2:]

Vim displays `cd` (using a negative index silently resulted in an empty string).

Concatenation
-------------

You can combine Vim lists with `+`.  Try this command:

    :::vim
    :echo ['a', 'b'] + ['c']

Vim, unsurprisingly, displays `['a', 'b', 'c']`.  There's not much else to say
here -- Vimscript lists are surprisingly sane compared to the rest of the
language.

List Functions
--------------

Vim has a number of built-in functions for working with lists.  Run these
commands:

    :::vim
    :let foo = ['a']
    :call add(foo, 'b')
    :echo foo

Vim mutates the list `foo` in-place to append `'b'` and displays `['a', 'b']`.
Now run this command:

    :::vim
    :echo len(foo)

Vim displays `2`, the length of the list.  Try these commands:

    :::vim
    :echo get(foo, 0, 'default')
    :echo get(foo, 100, 'default')

Vim displays `a` and `default`.  The `get` function will get the item at the
given index from the given list, or return the given default value if the index
is out of range in the list.

Run this command:

    :::vim
    :echo index(foo, 'b')
    :echo index(foo, 'nope')

Vim displays `1` and `-1`.  The `index` function returns the first index of the
given item in the given list, or `-1` if the item is not in the list.

Now run this command:

    :::vim
    :echo join(foo)
    :echo join(foo, '---')
    :echo join([1, 2, 3], '')

Vim displays `a b`, `a---b`, and `123`.  `join` will join the items in the given
list together into a string, separated by the given separator string (or a space
if none is given), coercing each item to a string if necessary/possible.

Run the following commands:

    :::vim
    :call reverse(foo)
    :echo foo
    :call reverse(foo)
    :echo foo

Vim displays `['b', 'a']` and then `['a', 'b']`.  `reverse` reverses the given
list *in place*.

Exercises
---------

Read `:help List`.  All of it.  Notice the capital `L`.

Read `:help add()`.

Read `:help len()`.

Read `:help get()`.

Read `:help index()`.

Read `:help join()`.

Read `:help reverse()`.

Skim `:help functions` to find some other list-related functions I haven't
mentioned yet.  Run `:match Keyword /\clist/` to case-insensitively highlight
the word `list` to make it easier to find what you're looking for.