Вопросы по языку TCL

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Вопросы по языку TCL

Непрочитанное сообщение Olej » 11 фев 2018, 15:15

Причины непопулярности Tcl/Tk
Для начала огорчу тех, кто с пеной у рта кричит о том, что «Tcl не нужен» или «Tcl мертв». Для опровержения последнего — посмотрите на дату выпуска последней версии интерпретатора Tcl/Tk. Про первое — ненужный язык не станут использовать AOL, BMW, CPU за его создание не станут давать ACM Software System Award. В настоящий момент разработки на Tcl/Tk ведутся в основном в недрах компаний, которые пишут на данном языке программное обеспечение для внутреннего пользования. Поэтому говоря о непопулярности Tcl/Tk мы прежде всего говорим о его непопулярности среди разработчиков настольных пользовательских приложений.
...
Среди разработчиков свободного ПО с открытым кодом популярность Tcl стала меньше благодаря FSF и Ричарду Столлману в частности. В сентябре 1994 году RMS надолго «утопил» продуктивные идеи Tcl/Tk своей рекомендацией «Почему вы не должны использовать Tcl» в котором концентрируется внимание на якобы невозможно сложном синтаксисе Tcl (приводя в качестве контраргумента язык с куда более тяжелым синтаксисом, но четкой семантикой — Lisp) и о «подкупающей хакеров простоте Tcl». Не разобравшись с основными идеями «расширяемости» и «расширения» Тикл, RMS наносит последний удар, утверждая, что Tcl пригоден только для маленьких приложений и выносит вердикт: «Поэтому проект GNU не собирается использовать Tcl в программном обеспечении GNU». Особенно странно это ввиду того, что Lisp и Tcl имеют общие черты и идеи, в частности — та же расширяемость. Несмотря на все старания Столлмана Tcl так и не «потонул», а «лисп» не смог занять ведущую позицию среди языков для разработки настольных приложений.
Tcl действительно сильно недооценивают, и уж особенно в русскоязычной программистской среде (оно и понятно ... в 90-х и первой половине 2000-х, когда Tcl был более-менее на слуху и обсуждался - русскоязычная программистская общественность лежала в руинах, и занималась челночной торговлей дамскими прокладками).

В Tcl очень простыми средствами достигаются такие вещи, как функции высших порядков, анонимные функции и т.д.
См. (это пример, приводимый авторами в документации):

Код: Выделить всё

[olej@dell Tcl]$ cat map.tcl
#!/usr/bin/tclsh
proc map { lambda list } {
   set result {}
   foreach item $list {
      lappend result [ apply $lambda $item ]
   }
   return $result
}

puts [ map { x { return [ string length $x ]:$x } } { a bb ccc dddd } ]
Вот что из этого получается:

Код: Выделить всё

[olej@dell Tcl]$ ./map.tcl
1:a 2:bb 3:ccc 4:dddd
Вложения
map.tcl
(230 байт) 95 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Вопросы по языку TCL

Непрочитанное сообщение Olej » 12 фев 2018, 00:35

Ещё задача, теперь почти в точности соответствующая той тестовой, сравнительной, что вот здесь: сравнение языков программирования

Код: Выделить всё

#!/usr/bin/tclsh

# 2D точки придставляются как списки { x y }

proc pstring { p } {  ;# форматирование 2D точки
   return [ format "\[%.2f,%.2f\]" [ lindex $p 0 ] [ lindex $p 1 ] ]
}

proc minus { f t } {  ;# замыкание 2-х векторов
   set dx [ expr [ lindex $f 0 ] - [ lindex $t 0 ] ]
   set dy [ expr [ lindex $f 1 ] - [ lindex $t 1 ] ]
   return [ list $dx $dy ]
}

proc pabs { p } {     ;# длина вектора
   set x2 [ tcl::mathfunc::pow [ lindex $p 0 ] 2 ]
   set y2 [ tcl::mathfunc::pow [ lindex $p 1 ] 2 ]
   return [ tcl::mathfunc::sqrt [ expr $x2 + $y2 ] ]
}

proc polar { p } {    ;# полярное представление вектора
   return [ list [ pabs $p ] [ tcl::mathfunc::atan2 [ lindex $p 1 ] [ lindex $p 0 ] ] ]
}

proc perimeter { lp } {
   set n [ expr [ llength $lp ] - 1 ]
   set summa 0.0
   for { set i 0 } { $i <= $n } { incr i } {
      set prev [ expr $i == 0 ? $n : [ expr $i - 1 ] ]
      set dist [ pabs [ minus [ lindex $lp $i ] [ lindex $lp $prev ] ] ] 
      set summa [ expr $summa + $dist ] 
   }
   return $summa 
}

proc square { lp } {
   set n [ expr [ llength $lp ] - 2 ]
   set summa 0.0
   for { set i 1 } { $i <= $n } { } {
      set p1 [ polar [ minus [ lindex $lp $i ] [ lindex $lp 0 ] ] ]
      incr i
      set p2 [ polar [ minus [ lindex $lp $i ] [ lindex $lp 0 ] ] ]
      set ampl [ expr ( [ lindex $p1 0 ] * [ lindex $p2 0 ] / 2 ) ]
      set asin [ tcl::mathfunc::sin [ tcl::mathfunc::abs [ expr [ lindex $p1 1 ] - [ lindex $p2 1 ] ] ] ]
      set summa [ expr $summa + $ampl * $asin ] 
   }
   return $summa
}

set pattern {^[\s\t]*[-+]?(\d+|\.\d+|\d+\.\d*)\s+(\d+|\.\d+|\d+\.\d*)\s*$}
while { true } {
   set polygon [ list ]
   puts "координаты вершин в формате: X Y (^D конец ввода)"
   while { true } {
      set number 1
      puts "вершина № $number : "
      if { [ gets stdin line ] <= 0 } break
      set result [ regexp $pattern $line match x y ]
      if { $result != 1 } {
         puts "ошибка ввода"
         continue
      }
      incr number 
      set point [ list $x $y ]
      lappend polygon $point ;# многоугольник: {{} {} ... {}}
   }  
   set number [ llength $polygon ]
   if { $number <= 2 } break
   set msg "вершин $number : "
   foreach p $polygon {
      set msg [ concat $msg [ pstring $p ] " " ]
   }
   puts "$msg"
   puts "периметр = [ format {%.4f} [ perimeter $polygon ] ]"
   puts "площадь = [ format {%.4f} [ square $polygon ] ]"
}
Конечно, язык Tcl не ориентирован на математические вычисления ... только поэтому код преувеличен, потому что везде приходится вычисление обрамлять [ argv ... ]. Но с учётом этого - код вовсе не так и громоздок.
Выполнение:

Код: Выделить всё

[olej@dell Tcl]$ ./triangle.tcl 
координаты вершин в формате: X Y (^D конец ввода)
вершина № 1 : 
0 0
вершина № 1 : 
0 1
вершина № 1 : 
1 0
вершина № 1 : 
вершин 3 : [0.00,0.00] [0.00,1.00] [1.00,0.00]
периметр = 3.4142
площадь = 0.5000
координаты вершин в формате: X Y (^D конец ввода)
вершина № 1 : 
Единственно что я не могу понять (найти) - как в Tcl сделать puts без перевода строки ... для того чтобы организовывать диалог - запрос-подсказка ... ответ.
Не может быть чтоб такого не было!
Вложения
triangle.tcl
(2.54 КБ) 76 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Вопросы по языку TCL

Непрочитанное сообщение Olej » 12 фев 2018, 00:38

Olej писал(а):Ещё задача, теперь почти в точности соответствующая той тестовой, сравнительной, что вот здесь: сравнение языков программирования
А ещё интересно (и проще, лаконичнее) функцию вычисления периметра perimeter можно записать и так, рекурсивно:

Код: Выделить всё

proc perimeter { lp { i 0 } } {
   set n [ expr [ llength $lp ] - 1 ]
   set next [ expr { $i < $n } ? [ expr $i + 1 ] : 0 ]
   set dist [ pabs [ minus [ lindex $lp $i ] [ lindex $lp $next ] ] ]
   if { $i < $n } {
      return [ expr $dist + [ perimeter $lp $next ] ]
   } else {
      return $dist
   }
}
Вложения
triangle_r.tcl
(2.53 КБ) 72 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Вопросы по языку TCL

Непрочитанное сообщение Olej » 12 фев 2018, 01:28

Olej писал(а): Единственно что я не могу понять (найти) - как в Tcl сделать puts без перевода строки ... для того чтобы организовывать диалог - запрос-подсказка ... ответ.
Не может быть чтоб такого не было!
Нашёл!
Это должно быть так (как и следовало ожидать):

Код: Выделить всё

      puts -nonewline "вершина № $number : "
      flush stdout
      if { [ gets stdin line ] <= 0 } break

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Вопросы по языку TCL

Непрочитанное сообщение Olej » 12 фев 2018, 01:39

Olej писал(а): Нашёл!
Это должно быть так (как и следовало ожидать):
Подправленные варианты прилагаются ;-) (там ещё мелкие правки).
Выглядит это теперь так:

Код: Выделить всё

[olej@dell Tcl]$ ./triangle.tcl 
координаты вершин в формате: X Y (^D конец ввода)
вершина № 1 : 0 0
вершина № 2 : 0 1
вершина № 3 : 1 1
вершина № 4 : 1 0
вершин 4 : [0.00,0.00] [0.00,1.00] [1.00,1.00] [1.00,0.00]
периметр = 4.0000
площадь = 1.0000
координаты вершин в формате: X Y (^D конец ввода)

Код: Выделить всё

[olej@dell Tcl]$ ./triangle.tcl 
координаты вершин в формате: X Y (^D конец ввода)
вершина № 1 : 0 0
вершина № 2 : 0 .1
вершина № 3 : .1 .1
вершина № 4 : .1 0
вершин 4 : [0.00,0.00] [0.00,0.10] [0.10,0.10] [0.10,0.00]
периметр = 0.4000
площадь = 0.0100
координаты вершин в формате: X Y (^D конец ввода)
Это ровно то, что и хотелось получить.
Вложения
triangle.tcl
(2.65 КБ) 84 скачивания
triangle_r.tcl
(2.64 КБ) 84 скачивания

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей