LINUX.ORG.RU

Самый лучший язык для скриптов: Tcl?

 , , , ,


7

5

Кратко: Я немного сравнивал разные языки и выбрал Tcl, при дальнейшем изучении не разочаровался.

А какие языки вы используете для задач средней сложности — тех что не требуют эпохальных тяжеловесных программ, но и не решаются тривиально пайпом из трёх-пяти команд в баше? Средняя сложность — это что-то порядка от 3-5 до 3-5 тысяч строк кода (смотря какой язык). Такие где разбиение программы на отдельные модули, хранимые в разных файлах ещё не требуется.

Длинно. Почему я выбрал Tcl.

Долгое время я писал на bash. Это неплохой язык, к тому же он достаточно выразительный, чтоб делать что угодно без вызова внешних программ и в таком случае производительность получается вполне на уровне.

Но у bash есть проблемы. Основная из которых — многие выражения (в частности пайпы) выполняются в субшелле, а из субшелла почти невозможно передать информацию в материнский иначе через stdout. Ещё одной проблемой является постоянная сериализация-десериализация объектов. Это уже не настолько важно, но всё-таки хотелось бы от этого по возможности избавиться.

То же самое касается других стандартных языков UNIX: dc, bc, sed, m4, awk, ... На последнем, впрочем, наверное, можно писать и нормальные программы, но синтаксис у него не очень красивый и возможностей не так уж много. Это хорошие языки, очень хорошие в своей области, но имеют ограниченную область применения.

Я уже знаю C и несколько других императивных языков, но если нужно что-то быстро посчитать или сделать, эти языки малопригодны — в том же C даже сравнить строки просто так нельзя, нужна специальная функция, кроме того нужно вручную рулить памятью. Pascal крайне беден в экспрессивном плане, а begin / end — это уродливо, так что лучше уж C. Basic уже мёртвый, да к тому же ещё более убог чем паскаль. C++ крайне сложен для изучения, а профита по сравнению с C почти никакого.

Таким образом, стало ясно, что мне нужно изучить какой-то другой язык. Так как язык требуется для того, чтоб быстро решить какую-то задачу, а не писать оптимизированное решение на века, стало ясно, что нужен один из динамических языков общего назначения: Perl, Python, PHP, Ruby, Tcl, Lua или какой-то другой.

Я выбрал Tcl.

1. PHP не подходит сразу, на нём только веб-странички хорошо писать, а всё остальное лучше в Perl (да и про страницы можно поспорить, если нужно чёткое разделение контента, стилей и логики).

1. На Perl, Python и Ruby множество сложных синтаксических конструкций, которые без поллитра не разберёшь, например (python):

_='_=%r;print _%%_';print _%_

2. Lua: простой язык, код на нём быстрый, изучить тоже можно довольно быстро. Но однако на каждый чих нужна либа. Даже работы с юникодом изкоробки нет (в смысле строку можно прочитать и вывести, но нельзя посчитать кол-во символ или заменить подстроку и тд).

3. Tcl: крайне простой синтаксис: 12 правил и man-ы по всем используемым командам достаточно для для понимания любого кода. При этом богатая стандартная библиотека, хорошая интеграция с Tk и кроссплатформенность.

То есть на Tcl можно решить любую задачу почти так же просто как на баше (да в крайнем случае даже пайпы есть), но при этом синтаксис гораздо более предсказуем.

Плюс на Tcl можно писать графические приложения так же легко как и консольные, например вот такой код в 10 строк — это уже целая работающая игра! Правда автор явно экономил строки, и читаемость кода из-за этого несколько страдает. Кроме того, Tcl поддерживает (особенно с 8.6) функциональное программирование и длинные числа изкоробки. Так что переход с bc, который только их и использует будет проще. Ещё мне очень нравится, что ключевых слов в этом языке нет. Вообще. Те же for / if и другие — это просто такие команды, которые берут условие и фрагмент и его исполняют. Можно запросто объявить процедуру for, которая будет использовать другой синтаксис итератора и далее использовать её, если так удобней. Язык динамически типизированный, как и другие скриптовые, но проблем из за этого не возникает. Если переменная используется внутри expr, то она интерпретируется как число. Если в команде string ... на месте строки — строка и тд. Никаких сомнительных x=«10»+10 Работа с переменными похожа на такую в bash, что тоже плюс: при присваивании переменной знак $ не ставится, а при извлечении из неё значения ставится:

set i 10 # i:=10
puts $i ;# будет выведено 10
incr i ;# i теперь 11
puts [expr [set i]+3] ;# set можно использовать вместо $i или ${i}\
так как при отсутствии третьего аргумента он просто возвращает значение.\
Ещё это один из немногих способов двойной подстановки.

4. Что-то другое. А что собственно? Пока только идёт в голову что-то лиспоподобное (например: clisp (scheme (или racket guile))), APL-подобное: J, K (есть свободная Kona), APL и тд или конкатенативное (dc-подобное): forth, factor...

Из 2, 3, 4 выбрал всё-таки Tcl, потому что синтаксис у него хоть и не стандартный для императивных языков, но похож на привычный шелловский и он есть в GNU/Linux изкоробки или в репозитории, так что не придётся заморачиваться ручной сборкой.

Уже начал изучать, почти всё нравится, кроме необходимости писать всё время expr и set, всё-таки такие частые операции можно было бы и сделать частью синтаксиса, хоть и немного в ущерб единообразию.

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

Учить его действительно легко, так как базовый синтаксис простой, а команды можно изучать по мере надобности, к тому же man к командам Tcl снабжен сносками на команды с похожим назначением, так что поняв, что команда — это не то, что надо, можно посмотреть все остальные и найти наиболее подходящую.

Таким образом, язык сочетает достоинства лиспа — гибкость, функциональщину и простоту базового синтаксиса и достоинства других скриптовых языков — более привычную инфиксную нотацию для арифметики и читаемый код.

★★★★★

Последнее исправление: Xenius (всего исправлений: 5)
Ответ на: комментарий от Xenius

Да, это квайн. Другой вопрос - зачем ты это писал копипастил? На любом языке можно нечитаемого говна навалить если сильно захотеть.

Kalashnikov ★★★
()
Ответ на: комментарий от Kalashnikov

А ты сравни с квайном на Tcl:

set quine {puts "set quine {$quine}; eval \$quine"}; eval $quine

У Tcl синтаксис простейший — команда, после которой аргументы. Почти как в шелле, но только правила развёртывания проще.

У других языков дофига синтаксических конструкций.

Xenius ★★★★★
() автор топика
Последнее исправление: Xenius (всего исправлений: 2)
Ответ на: комментарий от Xenius

Причём тут гуманитарии?

При том, что использование слов вместо арифметических знаков отдаёт гуманитарщиной.

csh — шелл для гуманитариев?

Наверное.

it-nativa
()
Ответ на: комментарий от it-nativa

При том, что использование слов вместо арифметических знаков отдаёт гуманитарщиной.

Можешь заалиасить set на =, будет = a 2 или [= a] для подстановки.

Xenius ★★★★★
() автор топика
Ответ на: комментарий от Xenius

У меня для тебя плохие новости если ты всерьёз так пытаешься что-то доказать.

quine = 'quine = %r; print quine %% quine'; print quine % quine

С поправкой на синтаксис строки абсолютно идентичны.

Kalashnikov ★★★
()
Ответ на: комментарий от Kalashnikov

С поправкой на синтаксис строки абсолютно идентичны.

Не идентичны. у тебя используется аналог printf, а у меня eval

Xenius ★★★★★
() автор топика

Единственная причина (для меня) проявлять хоть какой-то интерес к TCL — его поддержка на цисках.

frob ★★★★★
()

А какие языки вы используете для задач средней сложности

Tcl

jtootf ★★★★★
()

кроме необходимости писать всё время expr и set,всё-таки такие частые операции можно было бы и сделать частью синтаксиса, хоть и немного в ущерб единообразию.

ну дык сделай - Tcl это позволяет

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

ну дык сделай - Tcl это позволяет

Тогда код будет несовместимый. Или если ты про proc / alias, тогда можно просто сократить expr и set до одного символа, но это всё равно не то. Разве что если извернуться с препроцессором.

В общем, проще смириться, не настолько уж это и плохо.

Xenius ★★★★★
() автор топика
Последнее исправление: Xenius (всего исправлений: 1)
Ответ на: комментарий от Xenius

Вот кстати eval без кучи предварительных проверок - отличное начало для дырявого софта.

router ★★★★★
()
Ответ на: комментарий от Xenius

Тогда код будет несовместимый

несовместимый с кем/чем?

p.s. Tcl настолько позволяет менять свой синтаксис, что даже программы на GW-basic или Intel ASM являются корректными tcl-скриптами :)

MKuznetsov ★★★★★
()

А живой пример «чего угодно» на bash-е «без вызова внешних программ» увидеть можно?

ananas ★★★★★
()
Ответ на: комментарий от ugoday
return $1, map { s/\s+/ /; $_ } split /\s*,\s*/, $_ if /^$itemRe(?:\s*,\s*$itemRe)*(.*)$/;

Кроме как на перле и еще, как подсказали, рубях, такое пишется только в виде костыльного УГ в 100500 строк. Текст процессинг это вовсе не уникодно-позиционный substr, поддержкой которого так гордятся т.н. «unicode-aware» языки.

arturpub ★★
()

Кстати, коли такая пьянка. Как в tcl получить отдельно вывод stdout и stderr: помню сталкивался, а ничего приемлимого не нашел.

anonymous
()
Ответ на: комментарий от Xenius

У других языков дофига синтаксических конструкций.

То есть когда вместо синтаксиса - сплошной сахар, то код получается «послаще»?

anonymous
()

Да.

Ты все правильно сделал. Только не слушай советов юзать 8.6. Если тебе не нужны его плюшки типа dict, то он нафиг не нужен - он медленнее. Ну и аккуратнее с русскими строками особенно - можешь сильно удивится особенно при смене регистра ;)

Suntechnic ★★★★★
()

он есть в GNU/Linux изкоробки или в репозитории, так что не придётся заморачиваться ручной сборкой.

В Ubutnu с 12.04 кажется изкоробки его нет. Я даже легкий шок испытал...

Suntechnic ★★★★★
()
Ответ на: комментарий от Suntechnic

Более вероятно, что ты ничего не понял из того, что мною имелось ввиду.

anonymous
()
Ответ на: комментарий от arturpub

Кроме как на перле и еще, как подсказали, рубях, такое пишется только в виде костыльного УГ в 100500 строк.

Ну зато твой код не понятен без знания перла. Скажи, что он должен делать, может попробую на Tcl?

Xenius ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Кстати, коли такая пьянка. Как в tcl получить отдельно вывод stdout и stderr: помню сталкивался, а ничего приемлимого не нашел.

puts stderr «error!»

Или ты про программу, вызванную через open/exec? Это я ещё не изучал.

Xenius ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

можешь сильно удивится особенно при смене регистра ;)

УМВР:

% set x строка\ на\ русском
строка на русском
% string toupper $x
СТРОКА НА РУССКОМ

Если тебе не нужны его плюшки типа dict, то он нафиг не нужен - он медленнее.

dict есть и в 8.5, вообще-то. В 8.6 зато есть string is entier, lmap и tailcall

Xenius ★★★★★
() автор топика

Хорошее дело, одобряю начинание TC.

Tcl швейцарский ножик, верой и правдой меня выручает более 10 лет.)) Забыть bash и забить быстро на bash можно подключив расширение Tclx и используя оттуда удачную команду system. Например:

package require Tclx

proc apt-install str {
 global distr
 system chroot ./$distr-chroot env LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get -y install $str \
--no-install-recommends --force-yes }

apt-install "mc gedt gdm3"

в принципе, вся система ваша теперь )

bedcasus
()
Ответ на: комментарий от Xenius

УМВР

Теперь тоже самое в скрипте...

dict есть и в 8.5, вообще-то

Да? А я перепрыгнул с 8.4 на 8.6 и не обратил внимания...

Suntechnic ★★★★★
()
Ответ на: комментарий от annulen

Если нужно делать нетривиальный парсинг текста, то здесь однозачно рулит Perl

Для lua есть lpeg, так что и он не так уж плох в этом деле.

quantum-troll ★★★★★
()

Ах ты тостячок

Вообще за популяризацию тикля большой и жирный плюс. Но в обзоре очень много бреда разной степени упоротости. Давай по пунктам:

Я уже знаю C и несколько других императивных языков, но если нужно что-то быстро посчитать или сделать, эти языки малопригодны — в том же C даже сравнить строки просто так нельзя, нужна специальная функция, кроме того нужно вручную рулить памятью.

А ты что ожидал от языка низкого уровня?! Ты бы еще на FASM этому поудивлялся. А так - Си. В качестве скриптового языка. Чистый Си. Голый Си...В качестве скриптового...Санитары - поциента забирайте...

Pascal крайне беден в экспрессивном плане, а begin / end — это уродливо, так что лучше уж C.

А вот мне как раз си-подобный синтаксис кажется редкостным уродством. И что? При чем тут возможности языка и синтаксис? Да и на паскале...в качестве скриптоты...

Basic уже мёртвый, да к тому же ещё более убог чем паскаль.

А пацаны то не знают...Передам, поржем.

C++ крайне сложен для изучения, а профита по сравнению с C почти никакого.

С++ просто не нужен. Вообще.

1. PHP не подходит сразу, на нём только веб-странички хорошо писать, а всё остальное лучше в Perl (да и про страницы можно поспорить, если нужно чёткое разделение контента, стилей и логики).

Да ну. Такой же скриптовый язык. В системном администрировании может так же спокойно применяться. В студию пруфы на то, что не умеет PHP и умеет Bash.

1. На Perl, Python и Ruby множество сложных синтаксических конструкций, которые без поллитра не разберёшь, например (python): _='_=%r;print _%%_';print _%_

Ок. Тогда привожу код на тикле, который ты мне объяснишь по операторно:

set a 118;set b -399;set c 467;set d -128;set e -229;set f 260;set g -111;set h 18;set q [scan "жопажопа" %c%c%c%c%c%c%c%c];set r {};foreach x $q {append r [format %c [incr x [incr a [incr b [incr c [incr d [incr e [incr f [incr g $h]]]]]]]]]};puts $r

Еще один пример:

proc < 1\ 0\ {l\ ""} {foreach O [split $0 $l] {append l [format %c [expr {[scan $O %c]+$1}]]};set l};return [< -1 {зпрб}]

2. Lua: простой язык, код на нём быстрый, изучить тоже можно довольно быстро. Но однако на каждый чих нужна либа. Даже работы с юникодом изкоробки нет (в смысле строку можно прочитать и вывести, но нельзя посчитать кол-во символ или заменить подстроку и тд).

А в чем минус?

3. Tcl: крайне простой синтаксис: 12 правил и man-ы по всем используемым командам достаточно для для понимания любого кода. При этом богатая стандартная библиотека, хорошая интеграция с Tk и кроссплатформенность.

Код привел выше. Объясняй.

То есть на Tcl можно решить любую задачу почти так же просто как на баше (да в крайнем случае даже пайпы есть), но при этом синтаксис гораздо более предсказуем.

Ok, bro. Напиши мне дрова на баше и тикле для видеокарты. (задача же любая) А так -какой к чертовой матери предсказуемый синтаксис в языке, где любое слово можно перегрузить и балом правят макры?!

Плюс на Tcl можно писать графические приложения так же легко как и консольные, например вот такой код в 10 строк — это уже целая работающая игра! Правда автор явно экономил строки, и читаемость кода из-за этого несколько страдает. Кроме того, Tcl поддерживает (особенно с 8.6) функциональное программирование и длинные числа изкоробки.

Tcl изначально был с элементами функционального языка. Далее - про игру в 10 строк. Это как раз нормальный стиль программирования для Tcl.

4. Что-то другое. А что собственно? Пока только идёт в голову что-то лиспоподобное (например: clisp (scheme (или racket guile))), APL-подобное: J, K (есть свободная Kona), APL и тд или конкатенативное (dc-подобное): forth, factor...

Использовать вместо скриптового языка Racket, Factor, J или K - да, мсье знает толк в извращениях....

Уже начал изучать, почти всё нравится, кроме необходимости писать всё время expr и set, всё-таки такие частые операции можно было бы и сделать частью синтаксиса, хоть и немного в ущерб единообразию.

В дизайн языка это все вписывается как раз прекрасно. В tcl нет ни одного слова, которое нельзя было бы перегрузить. Все операторы - функции, которые можно перегрузить.

Таким образом, язык сочетает достоинства лиспа — гибкость, функциональщину и простоту базового синтаксиса и достоинства других скриптовых языков — более привычную инфиксную нотацию для арифметики и читаемый код.

Вообоще Tcl давно уже стал языком общего назначения. Так же как и Python. Да и он уже компилируемый давно как (в байткод своей же виртуальном машины). Я ничего не имею против Tcl/Tk (это, наоброт, мой любимый язык). Но почему не тот же Io?

silver-bullet-bfg ★★
()

Lua: простой язык, код на нём быстрый, изучить тоже можно довольно быстро. Но однако на каждый чих нужна либа. Даже работы с юникодом изкоробки нет (в смысле строку можно прочитать и вывести, но нельзя посчитать кол-во символ или заменить подстроку и тд).

Подсчет кол-ва символов гуглится на раз-два:

local _, count = string.gsub(unicode_string, "[^\128-\193]", "")

cPunk ★★
()

Уже начал изучать, почти всё нравится, кроме необходимости писать всё время expr и set, всё-таки такие частые операции можно было бы и сделать частью синтаксиса, хоть и немного в ущерб единообразию.

proc let {varName args} {
    uplevel "set $varName \[expr $args\]"
}

let a 10
let b $a * 3
let c $b >> 1

puts "$a $b $c"

Можешь не благодарить.

anonymous
()
Ответ на: комментарий от Xenius

Код понятен абсолютно любому человеку со знанием английского и регэкспов. Для перла специфично только то, что все наглядно и в одну-две строки и интерполяция.

arturpub ★★
()

IMO в озвученной нише питон лучше(тикля): за счёт более сложного синтаксиса, задачи, которые ещё допускают решение в рамках возможностей, под которые этот синтаксис и усложнялся, выглядят приятнее. tcl гибче; следовательно лучше подходит для менее «унылых» случаев.

DonkeyHot ★★★★★
()
Ответ на: Ах ты тостячок от silver-bullet-bfg

silver-bullet-bfg

Ок. Тогда привожу код на тикле, который ты мне объяснишь по операторно:

set a 118;set b -399;set c 467;set d -128;set e -229;set f 260;set g -111;set h 18;set q [scan "жопажопа" %c%c%c%c%c%c%c%c];set r {};foreach x $q {append r [format %c [incr x [incr a [incr b [incr c [incr d [incr e [incr f [incr g $h]]]]]]]]]};puts $r

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

 set a 118;set b -399;set c 467;set d -128;set e -229;set f 260;set g -111;set h 18; 

Переменные инициализируются числовыми значениями.

set q [scan "жопажопа" %c%c%c%c%c%c%c%c]

Жопой чую, что '[]' --- синтаксис для массивов, таким образом в q помещается массив из трёх значений.

set r {};

r --- пустой список.

foreach x $q {append r [format %c [incr x [incr a [incr b [incr c [incr d [incr e [incr f [incr g $h]]]]]]]]]};

Для всех х из q (т.е. для скан «жопажжопа» и форматной строки) соединить r с выводом на печать суммы х и определённых в начале переменных. Каким образом осуществляется приведение типов нужно читать.

puts $r

Напечатать результат предыдущей команды.

Образец простоты и читабельности.

harm
()
Ответ на: комментарий от Xenius

на прожекэйлере мало выбрать быстрый язык программирования. там нужно предже всего думать и находить закономерности и т.п. вещи.

хотя 80% задач из первых двух сотен можно брутфорсить.

ymn ★★★★★
()
Ответ на: комментарий от harm

Ну хотя бы потому, что инкр принимает два аргумента предположу, что так обрамляется вызов во вложенных выражениях. То есть эта лестница скобок не более чем x += (y += ...).

В общем-то глупо определять читабельность по синтаксису, важна выразительность предметной области.

arturpub ★★
()
Ответ на: комментарий от harm

set a 118;set b -399;set c 467;set d -128;set e -229;set f 260;set g -111;set h 18;set q [scan «жопажопа» %c%c%c%c%c%c%c%c];set r {};foreach x $q {append r [format %c [incr x [incr a [incr b [incr c [incr d [incr e [incr f [incr g $h]]]]]]]]]};puts $r

Однажды так Бармин умер.

anonymous
()
Ответ на: комментарий от silver-bullet-bfg

у тебя остались не понятные моменты

Я этот язык впервые вижу. Сравни с ситуацией, когда кто-то впервые видит перл.

harm
()
Ответ на: комментарий от cPunk

Подсчет кол-ва символов гуглится на раз-два:

Предлагаешь вручную парсить юникод? Вот это я и называю «нет поддержки юникода». Если бы была, была бы функция string length как в Tcl.

Xenius ★★★★★
() автор топика
Ответ на: комментарий от harm

Жопой чую, что '[]' --- синтаксис для массивов, таким образом в q помещается массив из трёх значений.

Не угадал, это аналог $() или `` в баше или круглых скобочек в лиспе. Подстановка. А scan — аналог сишного sscanf

А для массивов используется синтаксис $arrayname(keyvalue)

Xenius ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.