Vim: What's the difference between let and set?

Vim

Vim Problem Overview


What's the difference between let and set in the vim editor?

I've always wondered why both of them exist?

Also, I'd be interested to hear its historical background.

Vim Solutions


Solution 1 - Vim

:set is for setting options, :let for assigning a value to a variable.

It happens that the value for an option is linked to the name of the option prepended by a & (the &option-name construct then behaves very similar to "ordinary" variables). So, the following are equivalent:

:set  tw=40
:let &tw=40

But, for example, assigning 50 to the global variable foo (:let g:foo=50) cannot be achieved with a :set command (because g:foo is a variable and not an option).

Some options are boolean like. When setting these, no value is needed (as in :set noic and the opposite :set ic).

Solution 2 - Vim

Set is a more user-friendly interface specialized for options

E.g.

:verbose set

to display all options in effect.

:set tw=40

Will work as a shorthand for set textwidth=40

:set wrap&

Will set the default value for option wrap

:set nowrap

Will unset the option

:set wrap!

Will toggle the option

Most importantly,

> :set Tab # to get tab completion!

Few of the above can (easily) be achieved with let.

Solution 3 - Vim

:set only works with options, and sehe's answer showcases some good usage examples.

:let on the other hand can do almost everything that :set can do, plus more. It can assign a value to

  • a variable, e.g. let vi = 'vim'
  • an option, e.g. let &tw = 40
  • a register, e.g. let @a = $HOME . '/vimfiles'
  • an environment variable, e.g. let $NOTHING = 'NOTHING'

Another major difference is that the right hand side of :let is an expression, meaning you can do things like string concatenation (as seen in my register example above) and arithmetic operations (e.g. let &tw = 40 + 60). This also means that you have to quote the value if it's a string. :set on the other hand reads the value verbatim.

It's easier to use :set with options even though :let can also do most of it, Here are some comparison using sehe's examples ("n/a" means no way to do it with :let)

  • :verbose set vs n/a (don't think there's another way to list all options)
  • :set tw=40 vs :let &tw = 40 (yes, you can use the same shorthand in let too)
  • :set wrap& vs n/a
  • :set nowrap vs :let &wrap = 0 (for boolean options, 0 is false and 1 is true)
  • :set wrap! vs :let &wrap = !&wrap

A few more examples

  • print the value of an option: :set formatoptions? vs :echo &formatoptions (let doesn't print values, unlike set)

  • assigning to multiple options at the same time:

      :set et sw=4 sts=4 
    

    vs

      :let [&et, &sw, &sts] = [0, 4, 4]
    
  • set global option: setglobal et vs let &g:et = 1

  • set local option: setlocal et vs let &l:et = 1

See :h :set and :h :let for more details


tl;dr

:set only works with options but the syntax is much simpler. :let works with not just options but also variables, registers, and environment variables. Unlike :set, the right hand side of :let is an expression.

Solution 4 - Vim

Expanding on what people have written about :let, I've noticed that it can be used to assign a value in a variable to an option, something :set can't do. For example, this function uses let to assign the value in the global variable orig_tw to the textwidth option:

" Toggle Autowrap
" Default of 72 but can be overridden by tw settings in other vimrc files
let g:orig_tw = 72
function Toggle_autowrap_mode()
    if &textwidth == 0
        " Must use let instead of set here in order for g:orig_tw to be
        " evaluated properly
        let &textwidth = g:orig_tw
        echo "Autowrap mode on tw=" . &textwidth
    else
        let g:orig_tw = &textwidth
        set textwidth=0
        echo "Autowrap mode off tw=" . &textwidth
    endif
endfunction

noremap _A :call Toggle_autowrap_mode()<CR>

Solution 5 - Vim

It's very simple.
As people have said set is for options and works better because of the limitation. Also set is the historical command that all versions of vi use to set their options. Most (all?) other versions of vi don't have let.

But possibly most important is that set works on all versions of vim, the let command can be omitted when you compile vim. The standard tiny and small builds do this.

If it's missing let gives you the error:
E319: Sorry, the command is not available in this version

Note: if and endif are not implemented either in vim.tiny but in this case the commands do not give an error, instead everything between the two commands is skipped INCLUDING else.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDave HalterView Question on Stackoverflow
Solution 1 - VimRené NyffeneggerView Answer on Stackoverflow
Solution 2 - VimseheView Answer on Stackoverflow
Solution 3 - VimdoubleDownView Answer on Stackoverflow
Solution 4 - VimWill FiveashView Answer on Stackoverflow
Solution 5 - Vimuser3710044View Answer on Stackoverflow