software-development
April 26, 2023

Неочевидное но вероятное: TCL

Рассказываю про один редкий и необычный язык программирования, который часто считают эзотерическим.

Как-то так по мнению остальных программистов выглядит процесс обучения этому языку

Он такой один

Tcl (от англ. Tool Command Language — «командный язык инструментов», читается «тикль» или «ти-си-эль») — скриптовый язык высокого уровня.

И практически все в нем является командой с аргументами.

Чтобы оценить сей подход, вот для примера как выглядит простейшее вычисление на Tcl:

Давайте разберем что тут и зачем.

puts — команда вывода на экран

expr — команда обработки выражений

Теперь самое интересное, как это работает:

при вызове команды puts сначала вычисляется выражение в скобках — результат выполнения команды expr, которая вызывается с параметром в котором указано выражение «2 + 2»

Да да, это то самое чистое функциональное программирование, как в Lisp но по-другому :)

Едем дальше, как вы думаете с таким «все есть команда» подходом может выглядеть объявление переменных?

Как-то так:

set test "да это строка"

Правда весело? Разработка сразу заиграла новыми красками.

А что насчет конкатенации?

Легко:

set test "это строка"
set test "$test и дополнение к строке"

Чем-то напоминает шелл-скрипты и не зря, поскольку TCL часто используется для их написания:

#!/usr/bin/tclsh
puts $tcl_version

Высокоуровневые структуры

Вот тут начинаются глобальные отличия как от Си так и от шелл-скриптов.

В Tcl есть списки:

set x "a b c d e f g h"
puts "Элемент номер 2 из списка {$x} : [lindex $x 2]\n"

И ассоциативные массивы:

set name(first) "Василий"
set name(middle) "Иванович"
set name(last)  "Петренко"

puts "ФИО: $name(last) $name(first) $name(middle)"

А ведь тот же JavaScript до сих пор не дошел до такой логичности и простоты.

Дата и время

Tcl создавался как прикладной язык, как «tool» — инструмент, а не как адская «wunderwaffe» или «наш ответ Голливуду», видимо именно по-этому он удивительно удобен для решения повседневных прикладных инженерных задач.

Вот например как выглядит получение даты в плюс 10 дней и 2 часа от текущей:

set today [clock seconds]
set 10daysFromNow [clock add $today 10 days 2 hours]
puts [clock format $10daysFromNow]

Вот и сравните это с вариантом на современном Javascript:

var dateNow = new Date();  
var twoWeeksFutureDate = new Date(dateNow.setDate(dateNow.getDate() + 14)).toISOString();

Обработка ошибок

Конечно же она есть и все с ней красиво, просто и очевидно:

proc myBadProc {param1} {
        error "Ехай лесом" "Ехай лесом далеко" $param1    
}

catch {myBadProc}
puts "результат вызова: $errorCode"
puts "Информация об ошибке:\n$errorInfo\n"

Напоминаю, что все это успешно работало еще в 90х, когда сишники страдали от кодов возврата.

Работа с файлами

Естественно тут все тоже очень элегантно и красиво, умели раньше писать со вкусом.

Построчное чтение текстового файла:

  set infile [open "test.txt"]
  while { [gets $infile line] >= 0 } {
       puts "строка: $line"
  }

Запись:

set outfile [open "out.txt" w]
puts $outfile "Эта строка записана из скрипта на Tcl!"
close $outfile

ООП и объекты

С 8.6 версии в базу Tcl добавили «стандартное» ООП. Хотя и до этого момента были реализации ООП в виде внешних библиотек — настолько Tcl оказался гибок.

Вот так выглядит описание класса:

  ::oo::class create range {
        variable max 
        variable current

        constructor {upto} {
            my max $upto
        }

        method max {upto} {
            variable max 
            variable current
            set max     $upto
            set current -1
        }

        method next {varName} {
            upvar $varName var
            incr current
            set var $current
            if { $var < $max } {
                return 1
            } else {
                return 0
            }
        }
    }

Пример использования:

set xrange [range new 10]
set yrange [range new 10]

while { [$xrange next x] } {
        while { [$yrange next y] } {
            puts [expr {$x + $y}]
        }
        $yrange max 10 ;# We need to reset the y-range
    }

Какое же ООП без наследования?

Вот:

::oo::class create newrange {
        superclass range
        method reset {} {set current -1}
}

При этом есть и method rewrite в стиле Javascript:

 ::oo::define range method reset {} {set current -1}

Причем это сработает на все инстансы класса, даже уже созданные. Ну разве не круто?

Краткий итог

Tcl — уникальный язык, c одной стороны его синтаксис обычные современные программисты считают неадекватным и непонятным, поскольку он достаточно сильно отличается от «фигурных скобочек Си-стиля», победившего во всех остальных языках.

Одновременно, Tcl обходят стороной всевозможные радикалы от разработки и проповедники «чистоты», поскольку этот язык создавался и всегда использовался только в прикладных целях, а не ради завоевания мира или каких-то революций.

Я сам же считаю что Tcl это пример хорошей и продуманной инженерной работы, редкий пример софта, который делает именно то ради чего его и создавали, не вы#бываясь и не прикидываясь непонятно чем.

Стоит ли целенаправленно его изучать и использовать в реальных проектах - на ваш выбор, есть определенные минусы и риски, главный из которых - его редкость на территории РФ.

Но посмотреть именно как пример хорошей инженерной работы - абсолютно точно стоит.