четверг, октября 24, 2013

Do not mix tabs and spaces

After participating in peer assessment at Coursera's Programming languages I formulated one very common problem: mixing tabs and spaces.

Original post at Coursera's proglang discussion forum is here.

If student writes his code in editor which inserts tabs as is (as '\t' character) it is OK. However when student starts to add extra formatting with spaces (e.g. align if, then and else) his code becomes a problem. Look at the example with tab width 4 (tabs are shown as ->, spaces as spaces):

fun foo x =
--->let val abs = if x > 0
--->--->--->--->  then x
--->--->--->--->  else -x
--->in
--->--->(* ... *)
--->end

And see what happens when another student opens this code with tab width 2:

fun foo x =
->let val abs = if x > 0
->->->->  then x
->->->->  else -x
->in
->->(* ... *)
->end

then and else lines become unaligned and in complicated functions with nested case/if expressions it's very confusing.

There are 2 solutions for this problem:

  • Do not use tabs for alignment. In such case given example should look like:

    fun foo x =
    --->let val abs = if x > 0
    --->              then x
    --->              else -x
    --->in
    --->--->(* ... *)
    --->end
    

    Thus your code will look great with any tab width (e.g. 2):

    fun foo x =
    ->let val abs = if x > 0
    ->              then x
    ->              else -x
    ->in
    ->->(* ... *)
    ->end
    

    But it's quite hard to format code like this without help of your editor (however there are plugins for Vim/Emacs and other IDEs, maybe not perfectly working).

  • Do not use tabs at all. It means to insert needed amount of spaces instead of tab character ('\t'). And the example:

    fun foo x =
        let val abs = if x > 0
                      then x
                      else -x
        in
            (* ... *)
        end
    

    Thus your code will look identically with any tab width. This may be uncomfortable for some of you but this solution guarantees ideal formatting of your code in any possible editor.

    All editors support such mode of inserting spaces when you hit tab:

    • Vim: add set expandtab to ~/.vimrc.
    • Emacs: add (setq-default indent-tabs-mode nil) to ~/.emacs.
    • ... google for your favourite editor.

For more information you may google "tabs vs spaces" and visit this links:

P.S. I will add link to this post in the overall feedback field when I see this problem while assessment.

пятница, июля 01, 2011

Странный код

На работе наткнулся вот на такой Java-код:
    boolean flag = false;
    assert flag = true;
    if (flag) {
        // ...
    }
У кого есть идеи, зачем так писать?

четверг, июня 02, 2011

True, yes or sure

Третий вариант записи истинного выражения в строке хорошо поднял настроение с утра:
/*
 * Parse boolean string
 */
public static boolean parseBoolean(String s) {
    if(s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("sure"))
        return true;
    if(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no"))
        return false;
    MSG.error("string cannot be converted to boolean: " + s);
    return false;
}

четверг, мая 19, 2011

Patch для Git Gui под Windows

После установки msysGit (например, отсюда) наблюдается следующий баг-фича в git-gui: он в упор не видит untracked-файлы (их можно увидеть только через git-status). Это может приводить к весьма печальным последствиям, так как можно легко забыть включить новые файлы в коммит.

Вот тут народ также озаботился этой проблемой, и изготовил решение, правда для оригинального git'а (в данный момент в основном репозитории git'а фикс уже есть, но до msysGit'а еще не дошло).

В итоге для msysGit'а нужно накатить на файл
...\Git\libexec\git-core\git-gui.tcl
патч вот такой:
1454,1461c1454
<  set ls_others [list --exclude-per-directory=.gitignore]
<  if {[have_info_exclude]} {
<   lappend ls_others "--exclude-from=[gitdir info exclude]"
<  }
<  set user_exclude [get_config core.excludesfile]
<  if {$user_exclude ne {} && [file readable $user_exclude]} {
<   lappend ls_others "--exclude-from=$user_exclude"
<  }
---
>  set ls_others [list --exclude-standard]