LINUX.ORG.RU

Функциональный tcl

 , ,


2

4

Точнее библиотека just-for-fun зарелижена вашим покорным слугой на https://www.assembla.com/spaces/tclamba

наличиствуют map, filter, fold, chain, compose, zip а также некоторые другие, полезные и не очень. Интеграция в стиль Тикля на мой взгляд получилась неплохая и даже удобная.

А вот примерчик:

## Можно использовать процедуры tcl как lambda
map { expr 2+$$ } [ f::range 1 10 ]
# =3 4 5 6 7 8 9 10 11 12

## Анонимные функции по прежнему используются
map { apply {{a b} { expr $a + $b }} } {{2 3} {4 5}}
# =5 9

## lambda можно выстраивать в цепочку
map { expr 2+} { expr 2*} [ f::range 1 10 ]
# =6 8 10 12 14 16 18 20 22 24

## Можно применять фильтры c break и continue
map {
	if { {$$} =={} } {  break } else { continue }
} {{a b} {expr $a + $b}} {{ 1 2} {0 7} {} {3 4}}
# =3 7

## fold lambda+ init list
fold {{{a b} {expr $a+$b}}} 0 { 1 2 3 4 }
# =10

map { fold {::tcl::mathop::+} 2 } { { 1 2 3 } { 4 5 6 } }
# =8 17

## filter lambda+ list
filter {expr $$ % 2} [f::range 1 10 ]
# =1 3 5 7 9

## chain lambda+ list - просто цепь исполнения без обработки сигналов
chain { concat "WORD" } { concat "hello" } { string totitle "$$" 0 end } "!!"
# =Hello word !!

## Можно строить композиции (конвееры),использовать внешние переменные
##  и много-много разного
set charClass "upper"
set numberOfUpperChar {
   {split {$$} {}}
   {isolate { if {$charClass == "lower"} { set charClass "upper"} }}
   {filter {string is $charClass -strict} }
   {collapse}
   {llength}
}
set lorem "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"

chain {*}$numberOfUpperChar $lorem
# =4

## в частности делать вот такую композицию:
set func [ compose2 {string range $$ 1 end-1} {lindex $$ end} ]
invoke [ list $func ] {one two three}
# =hre

## теперь можно считать факториалы "по взрослому" :)
proc fasum { n } {
	set s [ zip [ map {{ a {
		list "*(1+$a" ")"
	} }} [ range 2 $n ] ] ]
	set s [ string map { " " {} \{ {} \} {} } $s ]
	return [ string range $s 2 end-1 ]
}
fasum 10
# =1+2*(1+3*(1+4*(1+5*(1+6*(1+7*(1+8*(1+9*(1+10))))))))

в дальних планах - lazy, благо что свой-же код надо только слегка переделать и (если осилю NRE) lazylist

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

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

Это ты прямо в точку попал. Как правило, хаскелисты не любят лисп, а лисперы терпеть не могут хаскель. Хотя бывают исключения.

jtootf известен как хаскелист.

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

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

лисп не любят из-за скобочек.

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

потому что tk страшный как ядерная печь холокоста.

Шучу. Фанаты хаскелла не любят из-за нарушения парадигм и отсутствия чистоты. А лисперы - потому что столлман так сказал.

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

А если без шуток, то с чем это связано?

Наверное с тем же, почему питоноводы, рубисты и перловщики недолюбливают друг друга, как и дельфисты и плюсисты друг друга. Следствие конкуренции. Конкуренции за умы, подходы и идеи.

А, вообще, среди нового поколения лисперов много тех, кто просто «не осилил» хаскель. Впрочем, я думаю, что и среди хаскелистов много тех, кто не понял или не захотел понять лисп. А так, несмотря на существенные внешние различия, я нахожу, что эти два языка наиболее близки друг к другу по духу, культуре и традициям по сравнению с другими языками.

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

А разве на tcl нельзя писать чисто функционально? (сам таким не занимался, поэтому и спрашиваю)

iMushroom ()

Бессмысленно, но очень прикольно.

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

Тогда почему не любят Tcl и лисперы и хаскелисты?)))

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

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

Дельфисты? Они живы еще что ле? Эх, старые добрые времена клепания говногуяпрограмм на коленках...

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

Это когда это Дельфи было конкурентом С++? Оно под оффтопик нормально работает только и ни на что, кроме GUI не годно.

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

Субъективно все, на самом деле. Мне проще его читать и на нем писать. Быстрее выходит при том же качестве.

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

Так а для счастья больше ничего не надо. ЯЗык гибкий, позволяет использовать любую парадигму, меттапрограммирование на высоте. Синтаксис удобный и читаемый. Если что-то уж сильно завязаное на производительность - то можно кусок переписать на Си. Хотя я, пока, таких задач не встречал

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

А ты другие-то знаешь?

да

для скриптов даже питон лучше tcl

для моих задач Tcl на практике оказался удобней Python и Scheme, с которыми сравнивался результат

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

Для скриптов и ещё много чего питон хуже tcl именно «вырвиглазным наркоманским синтаксисом !!!!1111АдыАдын»

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

почему не любят Tcl и лисперы

Могу про себя сказать. За кошмар с upvar и uplevel. Хотя может просто не умею их готовить.

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

среди нового поколения лисперов много тех, кто просто «не осилил» хаскель

Я замечательно писал на Ocaml. А хаскель меня добил после такого примера:

Prelude> let test = either (+ 5) length
Prelude> test (Left 3)
8
Prelude> let y = Left 3
Prelude> test y

<interactive>:45:6:
    Couldn't match expected type `Int' with actual type `Integer'
    Expected type: Either Int [a0]
      Actual type: Either Integer b0
    In the first argument of `test', namely `y'
    In the expression: test y
То есть, если значению даю имя, я обязан ему ещё и тип явно указать?

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

Тут ты мог нарваться на особенности обработки во время сеанса REPL, когда Integer насильно сводится к Int. Кстати, похожим образом поступает F#, когда есть неопределенность по типу. Попробуй то же самое написать в текстовом файле, и просто его откомпилировать. Я не проверял, но, может быть, сработает.

dave ★★★★★ ()

Когда доберутся руки до тикля — потыкаю обязательно.

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

Тут разница в подходах. Если в лиспе REPL - вездесущий царь и бог, то в хаскеле REPL - лишь небольшой придаток, хотя и весьма полезный иногда :)

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

То есть, если значению даю имя, я обязан ему ещё и тип явно указать?

Числовая константа - вещь полиморфная, её тип (Num a) => a. В строчке с определением y ghci не может вывести тип, поскольку y нигде не используется, поэтому использует тип по умолчанию - Integer. Ф-я length возвращает Int, поэтому для test тип был выведен как Either Int [a] -> Int. Тип функции (+) :: Num a => a->a->a. Поэтому и ругань.

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

Поэтому и ругань

Понять-то это можно. Но из-за таких «особенностей» проще писать на Scala, указывая типы, чем надеяться на type inference Haskell'а.

А лаконично и быстро получается только в «лабораторных условиях», когда программист в уме прикинул как будет работать типизатор, где произойдёт полное копирование объекта, а где можно сделать Zip... в итоге, результат на HAskell'е короче, чем на Lisp'е и красивее, но придумывать его намного дольше (а если писать в лоб, то будет на порядок медленнее и придётся явно указывать типы).

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