Square bracket indentation style

dbohdan 2014-07-24: I haven't found discussions on the matter on the wiki, so I made this page.

What do you guys think of the following style of indentation for functional-leaning Tcl code?

# style #1
return [
    join [
        ltrim [
            struct::list mapfor x $msgLines {string range $x $indent end}
    ] "\n"

Its main benefit over "Lispish" indentation like

# style #2
return \
  [join \
    [ltrim \
      [struct::list mapfor x $msgLines {string range $x $indent end}]] "\n"]


# style #3
return [join \
    [ltrim \
        [struct::list mapfor x $msgLines {string range $x $indent end}]] "\n"]

is that it doesn't break when a backslash at the end of a line goes missing. The respective downside is that when you can't tell whether a command at the beginning of the line is being quoted or substituted from just looking at it; you have to see whether the line above it ends with a [ or a {.

On a related note, have you programmed your text editor to manage the backslashes within square brackets for the second/third style of indentation? I'm considering doing that but it still seems brittle: insert one newline in another editor (e.g., vi on the command line) and it breaks.

An rather more ugly example:

# style #1
set conn [
    ::ftp::Open [
        dict get $websiteConfig deployFtpServer
    ] [
        dict get $websiteConfig deployFtpUser
    ] [
        dict get $websiteConfig deployFtpPassword
    ] -port [
        dict-default-get 21 $websiteConfig deployFtpPort
    ] -mode passive


# style #3
set conn [::ftp::Open \
    [dict get $websiteConfig deployFtpServer] \
    [dict get $websiteConfig deployFtpUser] \
    [dict get $websiteConfig deployFtpPassword] \
    -port [dict-default-get 21 $websiteConfig deployFtpPort] \
    -mode passive]

aspect - vote #1 for me. I hate line-continuation backslashes and will try to avoid them wherever possible. The difficulty distinguishing bracket-continuations from brace-continuations hasn't proven a problem for me - I think mostly because deeply nested code isn't particularly fun in Tcl under normal circumstances.

Your last example (style #3) invokes another situation where I will use continuation backslashes though: calling a procedure with lots of arguments. In this case I'll double-indent the arguments, which seems to be advocated in the Tcl Style Guide:

$w configure \
        -label [dict get $state what_it_is_called] \
        -command [lambda {} {puts "Hello, world!"}] \
        -otherattribute some-really-long-continued-value \
;# end $w configure

Note the comment at the end - that's a flourish of my own (?) which I add so the argument lines can be freely rearranged without the risk of forgetting to remove the last \.

And I think struct::list mapfor is obsoleted by lmap -- if not, I'd interp alias it to a less ugly name for common use :-).

dzach 2014-7-27 : One other useful aspect of the proposed style, when used within a proc, is that it preserves the white space, including line feeds, when doing [info body], thus allowing the regeneration of the initial appearance of a proc during an introspection.

AMG: Indeed. Sadly, Tcl strips backslash-newline-whitespace inside braces, which would otherwise be unmolested. I'd love to see this misfeature removed in Tcl 9.

PYK 2014-07-28: I started using this style in my code and on the wiki last year. aspect mentioned on my page sometimes using this style. I tend to use a more vertically compressed variant, like this:

set conn [
    ::ftp::Open [
        dict get $websiteConfig deployFtpServer] [
        dict get $websiteConfig deployFtpUser] [
        dict get $websiteConfig deployFtpPassword] -port [
        dict-default-get 21 $websiteConfig deployFtpPort] -mode passive]

I would write the "configure" example from above like this:

$w configure -label [dict get $state what_it_is_called] -command [
    lambda {} {puts {Hello, world!}}] -otherattribute \

I guess that puts me in the allergic-to-backslashes-and-even-more-allergic-to-vertical-sprawl camp. I recognize that the human eye is better at vertical than horizontal scanning, so will go vertical when the information seems to merit it.

aspect 2014-08-02: This seems like a good time to mention convenience wrappers folks have written for long argument lists: Convenient list arguments - larg and Scripted list.