Tcl

Tcl (від англ. Tool Command Language - "Командний мова інструментів", читається "Тікл" або "ти-сі-ель") - скриптова мова високого рівня.

Tcl часто застосовується спільно з графічної бібліотекою Tk (Tool Kit). В'язку Tcl / Tk по-російськи іноді називають "Так-Тікл" (англійський варіант - "Тікл-ток").

Області застосування мови - швидке прототипування, створення графічних інтерфейсів для консольних програм (пакетів програм), вбудовування в прикладні програми, тестування. Також Tcl застосовується в веб-розробці.

Tcl, поряд з Perl і Python, став одним з трьох класичних скриптових мов загального призначення. Ця трійця фігурує не тільки в якості списку вільних дистрибутивів, зібраних в ActiveState, але і, наприклад, як мови, на яких (крім діалекту PL / pgSQL) можна писати тригери і збережені процедури популярного сервера БД PostgreSQL.

Tcl, як вбудовувана мова, знайшов застосування і в сфері САПР ( CAD | CAM | CAE) [1] [2]. Він, наприклад, використовується як засіб налаштування баз даних, в постпроцесора Unigraphics. Крім того, він де-факто є мовою автоматизації та інтеграції у всіх провідних програмних пакетах розробки мікросхем ( ПЛІС і ASIC).


1. Особливості

У Tcl даними всіх типів, включаючи код програми, можна маніпулювати як рядками. Це робить його мовою з природною підтримкою метапрограмування. Ця парадигма програмування враховувалася в ході розробки та еволюції мови.

Програма на Tcl складається з команд, розділених символами нового рядка або крапками з комою. Кожна команда складається з набору полів, розділених пробілами. Перше поле повинно бути ім'ям команди, а необов'язкові інші поля - передані цій команді аргументи. Команда повертає значення, іноді порожнє. Тобто, як і в Ліспі, в Tcl використовується префіксная нотація.

Ключових слів як таких немає - поняття команди в Tcl аналогічно поняттю процедури або функції поширених мов програмування. Це відноситься і до керуючих конструкцій мови. У поєднанні з елементарним синтаксисом це забезпечує гарну розширюваність мови, в тому числі і бібліотеками, написаними на інших мовах, таких як C / C + + або Java.

У Tcl також якісно реалізована модель управління програмою на основі подій. Події можуть генеруватися таймером, при появі даних в каналі, зміні значення змінної, при завершенні якої зовнішньої програми, або просто при роботі користувача з інтерфейсом Tk. Можна задавати свої події та керувати ними.

Як і більшість сучасних скриптових мов Tcl містить розвинені засоби роботи з регулярними виразами, працює з асоціативними масивами та іншими динамічними структурами даних.

У базовому Tcl немає підтримки ООП, однак існує безліч розширень Tcl об'єктно-орієнтованими механізмами, реалізованих у вигляді підключаються бібліотек на Сі, чи самому Tcl. Ось найпоширеніші з них [3] :

розширення реалізовано на особливості використовуваної моделі
XOTcl C потужна об'єктна система з динамічним визначенням класів і методів, близька до CLOS
incr Tcl C ООП в стилі, близькому до C + +, розширеному введенням Конфігуратор
Snit Tcl реалізація об'єктної моделі на основі делегування, а не спадкування
STOOOP Tcl ООП в стилі, максимально близькому до C + +, також запроваджено механізм перемикання класів
TclOO [4] C Компактна, але потужна об'єктно-орієнтована система, яку можна використовувати як безпосередньо, так і як фреймвок для побудови розширених моделей ООП.

Простори імен підтримуються на рівні ядра мови. При реалізації механізмів ООП на Tcl використовується підтримка ієрархії вкладеності просторів імен у цій мові [5].

На Tcl легко програмувати в функціональному стилі : він забезпечує такі механізми, як функції вищого порядку і абстракції функцій [6], хоча Tcl рідко використовують таким чином. Ось приклад того, як можна здійснити композицію двох функцій :

 proc  o  {  fgx  }  {  $ F  [  $ G  $ X  ]  } 

У версії 8.5 в Tcl також введена команда apply, значно полегшує програмування в цьому стилі.

Ось приклад її використання з офіційної документації:

 proc  map  {  lambda  list  }  {  set  result  {  }  foreach  item  $ List  {  lappend  result  [  apply  $ Lambda  $ Item  ]  }  return  $ Result  }  map  {  x  {  return  [  string  length  $ X  ]  :  $ X  }  }  {  a bb ccc dddd  } 

результатом роботи цього прикладу буде

 1: a 2: bb 3: ccc 4: dddd 

2. Історія

Мова розроблений Джоном Оустерхаутом (John Ousterhout) в той час, коли він працював в університеті Каліфорнії в Берклі. Первинною метою було створення універсальної мови для вбудовування в консольні додатки. Слідом за цим Оустерхаут розширив свою мову засобами створення графічних інтерфейсів - так з'явився Tcl / Tk. [7]

За 4 роки розвитку в університетських стінах Тікл-спільнота зросла до кількох сотень тисяч програмістів. У 1993 році було розроблена перша об'єктно-орієнтоване розширення - incr Tcl.

У 1994 р. Оустерхаут стає провідним інженером проекту SunScript. Протягом наступних 4 років, ставши одним з проектів корпорації Sun, Тікл не тільки залишився вільно поширюваної системою, але і значно вдосконалився, став крос-платформних.

Помітний удар по популярності мови завдав Річард Столлман, опублікувавши у вересні 1994 р. в ряді новинних груп рекомендацію "Чому ви не повинні використовувати Tcl" [8]. У ній він на підставі тверджень, що "Tcl розроблений не як серйозний мову програмування" та "Tcl має особливий синтаксис, притягальний для хакерів через свою простоту. Але синтаксис Tcl здається дивним для більшості користувачів. ", А також у зв'язку з просуванням Emacs Lisp виніс вердикт: "проект GNU не збирається використовувати Tcl в програмному забезпеченні GNU ". Крім суб'єктивних претензій до дизайну мови, Столлман вказав на об'єктивний на той момент недолік - низька швидкодія.

Тим не менш, зростання кількості розробників, що активно використовують Тікл, склав за цей період 600%.

У 1998 р. у зв'язку з Java -бумом і пов'язаної з ним гострою конкурентною боротьбою корпорація вже не могла приділяти Тікл колишнього уваги. Джон Остераут покидає Sun і створює (за підтримки Sun) компанію Scriptics, продовжуючи розвиток технології Tcl / Tk [9] [10]. Це була одна з перших комерційних програмних фірм, чия діяльність будувалася навколо безкоштовного вільного ПЗ.

Колірне рішення логотипу, прийняте у 90-х рр.. XX століття

У березні 1998 року Оустерхаут пише стала класичною статтю "Сценарії: високорівневе програмування для XXI століття" [11], в якій назвав скриптові мови мовами системної інтеграції, тому що вони орієнтовані насамперед на роботу з об'єктами операційного середовища, а не з елементарними даними. Це дозволяє без написання тисяч рядків коду двома-трьома командами "склеювати" такі об'єкти в одне ціле.

У тому ж році він виграв за розробку мови Tcl дві великих нагороди. Перша - це ACM Software System Award, що вручається за "найбільш значуще програмне забезпечення". Цією нагородою до цього були відзначені такі основоположні системи, як стек протоколів TCP / IP, перша електронна таблиця, перша реляційна база даних, World Wide Web, Unix, PostScript і Smalltalk. Друга - це щорічна USENIX Software Tools User Group (STUG) Award, на знак визнання видатного програмного забезпечення.

У 1999 році виходить Tcl 8.0 - в цій реалізація вперше з'явилася компіляція в байткод, що дозволило в 6 разів підняти швидкодію [12]. В следующую модификация Tcl 8.1 введена полноценная поддержка юникода, в ней впервые реализована многопоточность. В связи c этим релизом Остераут заявил:

"В целом 8.1 переводит Tcl в новую категорию, поскольку теперь его можно использовать для серверных приложений. Си, Си++ и Java можно по-прежнему использовать для создания частей приложений, критических с точки зрения производительности, а Tcl - для интеграции и создания интерфейсных компонентов". [13]

В 2000 году фирма Scriptics была переименована в Ajuba Solutions, а затем куплена фирмой Interwoven, не заинтересованной в работе со свободным ПО. В связи с этим разработка Tcl была передана сообществу программистов. Так была сформирована Tcl Core Team.

На 9-ой конференции по Tcl/Tk, проходившей в Ванкувере, была представлена виртуальная файловая система StarKit, обеспечившая новый, удобный для обычного пользователя способ распространения Tcl программ.


3. Синтаксис Tcl

Скрипт
команды, разделённые переводом строки или точкой с запятой (;).
Команда
слова, разделённые пробелами.
 commandName argument1 argument2 argumentN 

Первое слово - имя команды, остальные - её аргументы. Любой аргумент может быть заменён другой командой, помещённой в квадратные скобки. Любые аргументы в фигурных скобках передаются команде "как есть", в виде единого аргумента.

3.1. Символы, имеющие особое значение

  • $ - вызывает подстановку значения переменной.
  • [] - вызывает подстановку результата выполнения команды внутри скобок.
  • "" - группирует аргументы в один с подстановкой значений переменных.
  • {} - группирует аргументы в один без подстановки значений переменных.
  • \ - экранирует следующий символ или вызывает подстановку управляющего символа.
  • # - начало однострочного комментария, должен быть после неэкранированного символа перевода строки или ";" (точки с запятой).

3.2. Замечания о процессе разборки скрипта

  • Разбивка на слова, подстановка значений переменных и результатов выполнения команд производятся за один проход по команде.
  • Все символы, находящееся внутри скобок {} и кавычек "", рассматривается как одно слово.
  • Первое слово команды рассматривается как встроенная или определённая процедура.

3.3. Примеры команд

  • Присваивание обозначается словом set, а не знаком равенства.

Синтаксис:

 set  переменная значение 

Приклад:

 set  a  2 
 set  b  3 
  • Комментарий обозначается символом #

Синтаксис:

 # текст комментария 

Приклад:

 # это комментарий 
  • Вывод (печать) реализуется командой puts

Синтаксис:

 puts  выражение 

Приклад:

 puts  "Привет! Это я."  puts  123  puts  $a  puts  "b = $b" 
  • Цикл пока реализуется командой while, имеющей два аргумента. Первый - Tcl выражение (выражения фактически пишутся на миниатюрном языке, состоящем из математических операций и операций сравнения в стиле языка C). Второй аргумент - это скрипт, выполняемый при каждой итерации. Его, как правило, помещают в фигурные скобки, чтобы избежать немедленного выполнения.

Синтаксис:

 while  {  Выражение_Tcl_С_Логическим_Значением  }  {  TclКоманда другаяTclКоманда  } 

Приклад:

 while  {  $x  <  10  }  {  puts  $x  incr  x  } 
  • Условная команда

Синтаксис:

 if  {  Выражение_Tcl_С_Логическим_Значением  }  {  КомандаTcl  } 

Приклад:

 if  {  $x  <  0  }  {  set  x  0  } 
  • Команда ветвления

Приклад:

 switch  -  glob  -  $var  {  {  see  }  -  {  saw  }  -  {  seen  }  {  puts  "Все это значит одно и то же!"  }  } 
  • Команда может не иметь аргументов, например
 pwd 

просто возвращает текущий рабочий каталог. А командой

 set  wdir  [  pwd  ] 

вы сохраните имя текущего каталога в переменной wdir.

  • Команда может возвращать список, например
 glob  Образец 

возвратит список имён файлов текущей директории, удовлетворяющих шаблону Образец.


3.4. Процедури

Процедуры определяются следующим образом

 proc  имяПроцедуры  {  списокАргументов  }  {   } 

3.5. Ассоциативные массивы

Следующий фрагмент кода создаст и инициализирует ассоциативный массив (называемый в других языках также карта, словарь, или хеш).

 set  capital  (  France  )  Paris  set  capital  (  Italy  )  Rome  set  capital  (  Germany  )  Berlin  set  capital  (  Poland  )  Warsaw  set  capital  (  Russia  )  Moscow  set  capital  (  Spain  )  Madrid 

Для запроса и вывода одного из значений ассоциативного массива используется

 puts  $capital  (  Italy  ) 

Список всех стран (ключей массива) можно получить командой

 array names capital 

Результат не будет отсортирован, потому что массивы Tcl базируются на хеш-таблицах.

 Poland Spain Russia Germany Italy France 

Сортировку можно выполнить командой

 lsort  [  array names capital  ] 

Чтобы сослаться на массив (передать его как ссылку) используется имя содержащей его переменной:

 proc  demo arrName  {  upvar  1  $arrName  arr  ;  # tie the reference to a local name  #do something with arr  } 

Для доступа к массиву по значению, используется array get или array set. Например, чтобы скопировать один массив в другой:

 array  set  Newarr  [  array get Oldarr  ] 

В Tcl 8.5 введены массивы, передаваемые по значению - словари ( dict).

Для преобразования скалярной переменной в массив и наоборот следует удалить существующую переменную при помощи команды unset.


3.6. Область видимости переменных

По умолчанию внутри процедуры видны только определённые в ней переменные. За пределами определения процедуры её переменные недоступны, иначе чем через механизм передачи параметров. Вы можете иметь переменные в процедуре с таким же именем, как и в основной программе, при этом значения этих переменных будут различаться, по сути это будут разные переменные. Чтобы изменить это поведение используются команды global или upvar.

4. Приклади

Дополнительные примеры с комментариями на русском вы можете найти на wiki-ресурсе Нижегородской Группы Пользователей Linux в разделе Programming Gems::Tcl/Tk. [14]

4.1. Здрастуй, світ!

Програма Hello, world выглядит так

 puts  "Здравствуй, мир!" 

или так

 puts  {  Здравствуй, мир  !  } 

4.2. Масиви

4.2.1. Обращение к элементам массива

Вывод значения элемента массива OldArray(precision), имя которого (массива) задается новой переменной NewArray

 set  NewArray OldArray  puts  [  set  $  {  NewArray  }  (  precision  )  ] 

4.2.2. Сложение чисел массива

Метод (A) - Сложение с использованием цикла 'foreach'

 set  numbers  {  1  2  3  4  5  6  7  8  9  10  }  set  result  0  foreach  number  $numbers  {  set  result  [  expr  {  $result  +  $number  }  ]  }  puts  $result 

Метод (B) - Гораздо более элегантный способ с использованием команды 'join'

 set  numbers  {  1  2  3  4  5  6  7  8  9  10  }  puts  [  expr  [  join  $numbers  +  ]  ] 

4.2.3. Список содержимого массива

В массиве tcl_platform, содержится информация о свойствах платформы, на которой запущен Tcl. Список имён свойств может быть получен с помощью

 array names tcl_platform 

Следующий фрагмент выводит их вместе со значениями:

 foreach  i  [  array names tcl_platform  ]  {  puts  "$i = $tcl_platform($i)"  } 

Если свойства должны быть отсортированы

 foreach  i  [  lsort  [  array names tcl_platform  ]  ]  {  puts  "$i = $tcl_platform($i)"  } 

Здесь демонстрируется вложенность команд. Они могут быть вложены на любую глубину. Подобного же результата можно достичь с помощью команды parray (появившейся в Tcl 8.5).


4.3. Пересечение множеств

Процедура filter возвращает те элементы списка, для которых script принимает значение TRUE:

 proc  filter  {  list  script  }  {  set  res  {  }  foreach  e  $list  {  if  {  [  uplevel  1  $script  $e  ]  }  {  lappend  res  $e  }  }  return  $res  } 

Команда uplevel 1 позволяет вычислить выражение в контексте, в котором вызывается слово filter.

Процедура in - это сокращённая запись для включения (инклюзии) множеств:

 proc  in  {  list  e  }  {  expr  {  [  lsearch  -exact  $list  $e  ]  >  =  0  }  } 

Проверка:

 %  filter  {  abc  }  {  in  {  bcd  }  }  bc 

4.4. Факторіал

 proc  !  x  {  expr  {  $x  <  2  ?  1  :  $x  *  [  !  [  incr  x -  1  ]  ]  }  } 

Здесь демонстрируется, что именем команды могут быть любые строки, а также известный по другим языкам оператор ?:.

5. Реализация, дистрибутивы, инструменты

Tcl - интерпретируемый язык, то есть программы на Tcl готовы к выполнению без компиляции и компоновки.

Интерпретатор Tcl портирован на большинство распространённых платформ. Он распространяется под свободной некопилефтной лицензией, позволяющей использовать его без ограничения в разработке проприетарных приложений, а также создавать проприетарные производные системы. Разработчики относят её к BSD подобным, хотя по сравнению с лицензией BSD лицензия Tcl накладывает меньшее количество запретов.


5.1. Реалізація

В даний час робота над ядром мови Tcl ведеться групою розробників іменованої Tcl Core Team. Найсвіжіші версії Tcl-транслятора та основних бібліотек доступні в репозиторії на SourceForge.net, см. список.

Транслятор Tcl компілює програму в проміжне представлення - байткод, а потім інтерпретує її. На відміну від, наприклад, Python, це проміжне представлення не зберігається на диск, програма може зберігається тільки у вихідних текстах, можливо упакованих в StarKit модуль або за допомогою якого-небудь іншого врапперов. В залежності від параметрів компіляції інтерпретатор Tcl може підтримувати або не підтримувати багатопоточність.

Хоча в більшості підручників з Tcl для початківців говориться щось подібне "в Tcl є всього один тип змінних - рядок", насправді транслятори Tcl вже давно як влаштовані по-іншому. Усередині Tcl використовує систему динамічних типів з автоматичним, прозорим перетворенням до строковому увазі.

Tcl входить практично у всі дистрибутиви Linux. Для Microsoft Windows потрібен окремий інсталяційний пакет.

В даний час поточна стабільна версія Tcl 8.4, її основні відмінності від попередньої - нові функції (оптимізація 64-бітного коду, VFS, доповнення в плані інтроспекції) і деяке підвищення швидкодії за рахунок оптимізації роботи з байткод.

Нові можливості, додані в версії 8.1 (зокрема, підтримка багатопотокового виконання, засоби інтернаціоналізації та робота з символами Unicode), сповільнили роботу Tcl в порівнянні з що дала стрибок швидкості восьмий версією приблизно на 19%. Розробники 8.4 доклали всіх зусиль для того, щоб максимально підвищити швидкість виконання програм, домогтися, щоб вони працювали не тільки не повільніше, але навіть швидше, ніж це було при появі версії 8.0. Ця мета була досягнута практично для всіх засобів Tcl і Tk - версія 8.4 в середньому в 8 разів швидше ніж версія 7.6 [12]. Поточна версія TCL - 8.5.


5.1.1. Альтернативні реалізації та діалекти

Існує альтернативні реалізації Tcl для популярних віртуальних машин загального призначення. Це написаний на Java інтерпретатор - Jacl [15] (остання версія від 2008 року), і проект Eagle [16], який реалізує більшість команд Tcl 8.4 для CLR (Доступні збірки для . NET 4.0 і 2.0). Ведуться експерименти по трансляції Tcl програм в код віртуальної машини Parrot, що розробляється для шостої версії Perl [17].

Для програмування вбудованих систем і вбудовування в додатки розроблений спеціальний діалект Tcl Jim [18]. Це інтерпретатор реалізує велику підмножину Tcl, розширене додатковими механізмами об'єктно-орієнтованого та функціонального програмування і займає в скомпільованому вигляді менше 100 кілобайт.

Ще один діалект Tcl - скриптова мова мобільних пристроїв Hecl [19], реалізований на Java ( J2ME). Що ж стосується платформи Android, підтримку Tcl на ній (поряд з іншими скриптовими мовами) забезпечує скриптова прошарок SL4A [20].


5.2. Використання у веб-розробці

У web-програмуванні Tcl зазвичай використовується разом з веб-сервером AOLServer або одним з "полегшених" веб-серверів, на зразок lighttpd, орієнтованим на FastCGI. Для інтеграції Tcl з Apache існує модуль Rivet [21].

Існують також такі проекти, як TclHttpd [22] і його наступник - Wub [23], є повноцінними Web- фреймворками. На базі нового об'єктного розширення мови TclOO розробляється веб-фреймвок Woof (Web Oriented Object Framework) [24].

Крім використання в якості мови реалізації веб-додатків, TCL може використовуватися як скриптова мова для розширення існуючих додатків. До прикладу на нього пишуть модулі для IRC бота Eggdrop.


5.3. Дистрибутиви

Всі нижчеперелічені дистрибутиви поширюються вільно і зібрані з компонентів, що мають ту чи іншу вільну ліцензію. Більшість з них - кроссплатформени (крім WinTclTk і Tcl / Tk Aqua), хоча в Unix -системах Tcl / Tk зазвичай є частиною дистрибутива ОС.

  • ActiveTcl
    Найпоширеніший дистрибутив TCL. Подібно іншим продуктам компанії ActiveState включає в себе великий набір бібліотек і розширень. У windows-версіях включає в себе засоби інтеграції з WSH. Які або інструментальні засоби, що полегшують життя програміста, відсутні. Фірма продає пакет TclDevKit містить засоби налагодження і створення автономних програм (останнє на базі технології StarKit) і Komodo - універсальне IDE для скриптових мов, що включає засоби візуального програмування Tk -форм.
  • WinTclTk
    Більш компактний, дистрибутив орієнтований на роботу з XOTcl - об'єктно-орієнтованим розширенням Tcl. Список включених в нього бібліотек декілька вужчий, ніж у ActiveTcl, але "джентльменський набір" ви тут знайдете. У цей дистрибутив входять Tloona IDE - Середа розробки традиційного типу і XOTclIde - середа об'єктно-орієнтованого програмування в стилі Smalltalk, обидві - з відладчиком. Також на сайті розробників вільно доступний пакет для створення єдиного запускається файлу TkWrapper заснований на FreeWrap - технології, альтернативної StarKit, заснованої на простому ZIP -стисненні. Остання на сьогоднішній день версія - 8.5.6.
  • TclKit
    Це Tcl / Tk c базовим набором бібліотек в одному компактному виконуваному файлі. Дистрибутив створений з використанням технології StarKit. Містить Бібліотеку MetaKit дозволяє керувати вмістом цього файлу.
  • dqkit
    Альтернативна збірка, відома як "TclKit на стероїдах", є кілька варіантів, що відрізняються складом бібліотек, підтримкою багатопоточності і т. д.
  • MyTcl
    Потужне Tcl IDE, що включає в себе дистрибутив мовного середовища.

6. Переваги і недоліки

Недоліком ранніх версій Tcl / Tk, безсумнівно, була низька швидкодія. Версії нижче 8-ї використовували пряму інтерпретацію вихідного тексту, однак використання байткод дозволив цю проблему. Зараз по швидкодії Tcl не сильно відрізняється від PHP [25], хоча помітно поступається таким скриптовою мовам як, наприклад, Python або Lua. Складні або критичні за часом виконання дільниці коду рекомендується виконувати у вигляді зовнішніх модулів на C / C + +.

Tcl / Tk, відрізняє незвичність синтаксису для програмістів на "традиційних" мовах. Він ближче до стандартного синтаксису оболонки Unix. Цей синтаксис може бути довільно змінений (як і в інших "програмованих мовах програмування", таких як Forth [26] або Common Lisp). Це може бути перевагою для програміста-індивідуала або невеликої групи програмістів, але робить Tcl / Tk навряд чи придатним для використання в якості мови загального призначення при розробці в промисловому масштабі. Хоча наявність стандартизованих розширень знижує гостроту цієї проблеми. Tcl може використовуватися і в крупних проектах в межах своєї "екологічної ніші" (вбудовані скрипти, "склеювання" компонент, WEB-програмування).

Хоча Tcl має всі властивості функціонального мови, його інтерпретатор до версії 8.6 не справляв оптимізацію хвостовій рекурсії, що ускладнювало використання чисто функціонального стилю, зменшувало його ефективність. Втім, гнучкість мови дозволяє обійти цю проблему, реалізувавши подобу такої оптимізації на високому рівні [27]. Нарешті, з'явилася в тестовій версії 8.6 команда tailcall дозволяє без особливих проблем використовувати хвостову рекурсію.

Найбільш тісна інтеграція Tcl з графічної бібліотекою Tk, яка часто використовується і в поєднанні з іншими мовами програмування - безперечна перевага Tcl. Для створення GUI оболонок до для програм або пакетів консольних програм Tcl може виявитися найкращим вибором.

За кількістю розроблених для Tcl бібліотек розширень і інструментальних засобів дещо поступається Пітонові, а тим більше Перлу, але навряд чи ви зіткнетеся з їх браком. Чого, щоправда, не можна сказати про кількість документації і літератури з Tcl, особливо - російськомовною.