LINUX.ORG.RU

а вам кажется странным поведение двойных кавычек в tcl?

 , ,


2

6

Принимая во внимание следующее:

  • списки в tcl не построены из консов
  • списки в tcl на печати изображаются с помощью фигурных скобок
  • при этом внешняя пара фигурных скобок при печати опускается
  • слова можно считать символами
  • {*} по смыслу есть ,@ (см. Википедию)

Получаем следующее:

# присвоим переменной v список из двух символов b и с
> set v {b c} 
b c 
; то же в лиспе
> (setq v '(b c))
(b c)

# построим двухэтажный список
> list a $v
a {b c}
; то же в лиспе 
> (list 'a v)
; то же в лиспе с помощью квазицитирования
> `(a ,v)

# вклеим содержимое v в список
> list a {*}$v
a b c
; то же в лиспе с помощью квазицитирования
> `(a ,@v)

# А вот это что и зачем? 
> puts "a $v"
a b c

# А так не работает:
> puts "a {*}$v"
a {*}b c

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

> "a $v"
a {b c}
> "a {*}$v"
a b c

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

★★★★★

Последнее исправление: den73 (всего исправлений: 2)

Я столько лет писал тебе «делом займись», а ты несгибаем и даже прогрессируешь. Я в смятении.

t184256 ★★★★★
()

# А вот это что и зачем?

потому что двойные кавычки осуществляют подстановку значения переменной

puts "a {b c}"
a {b c}

Опять ты хочешь странного

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

Я не спрашиваю, _как_ оно работает - это понятно. Я спрашиваю, _для чего_ было сделано именно так. В лиспе квазицитирование чёткое, ясное и простое. У него есть понятная область применения - построение объектов данных по шаблону. А в тикле выглядит сложно и нелогично. И для построения объектов по шаблону не годится. Чтобы получить «a {b c}», при том, что «b c» - в переменной, нужно писать лишнее:

> puts "a {$v}"
a {b c}
При этом, если подставляемое значение - не список, получится фигня:
> set vv 4
> puts "a {$vv}"
a {4}
Что здесь значат эти скобки? Список, вложенный в список? Нет. Вообще слабо прослеживается разница между единичным значением и списком из одного элемента:
> lindex "a {4}" 1
4
> lindex "a 4" 1
4
Т.е. мы видим, что если что-то заключено в фигурные скобки, то это не значит, что мы имеем дело со списком! Во, наконец-то я начал вспоминать, в чём суть проблемы. Именно в этом :) В том, что нет разницы между списком из одного элемента и собственно элементом. Поэтому у меня были трудности передавать данные из лиспа в tcl - вложенные лисповые списки вообще не получается просто так выразить в тикле.

> lindex "{4}" 0
4
> lindex "4" 0
4

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

А передавать списки мне нужно было, когда я писал на tcl/tk клиента для SWANK. Клиента я написал, но мне пришлось разрабатывать свой формат представления лиспового списка в виде строки и свой API для работы с этим представлением. Притом получилось весьма неудобно. А казалось бы, tcl/tk - тоже лисп.

Но я оставляю возможность, что я что-то просто не догнал :) Потому я и тут.

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

Т.е. если бы я разрабатывал тикль, я бы не стал вот так вот смешивать списки из одного элемента с символами. Правда, в самом лиспе nil является одновременно и списком. Не факт, что это хорошо.

Но допустим, мы будем отличать списки из одного элемента от символов. Что потеряем? Я вижу уже сразу, что нельзя будет делать так:

> puts {a b c}
a b c
А придётся
> puts {a b c}
{a b c}
При этом встаёт под вопрос и то, правомерно ли вообще писать
> puts a
> myProc
Ведь это же в тикле неявный список. В т.ч. myProc - это список из одного элемента. Если мы говорим, что список помнит о своих скобках, то понадобится писать
> {puts a}
> {myProc}
И внезапно тикль становится таким же тяжеловесным, как лисп. Но! Можно принять соглашение, что при вводе ридер домысливает один уровень скобок, если первый элемент - атом. Так сделано в листенере Lispworks, там можно написать
> + 2 2
4
Правда, с тем исключением, что для списка из одного элемента скобки не домысливаются. Это исключение тиклю вряд ли нужно.

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

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

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

Хорошо, тогда следующий вопрос: а зачем в тикле нет списков? И на самом деле они там почти есть:

> lindex [lindex {a b {c d}} 2] 0
c
Возможно, это иллюзия, но довольно стойкая и я всё время пытался ей пользоваться и всё время получал по рукам. За что? В чём был смысл так делать? Я гляжу, как там толково сделано многое, и не готов поверить, что автор просто тупанул.

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

Т.е. если бы я разрабатывал тикль

То он бы, наверное, никогда не увидел бы белый свет.

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

а зачем в тикле нет списков?

Затем же, зачем в bash в основном строки(массивы и то появились не сразу) - потому что так захотели авторы языка

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

В лиспе квазицитирование чёткое, ясное и простое. У него есть понятная область применения - построение объектов данных по шаблону. А в тикле выглядит сложно и нелогично.

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

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

Ну ладно, читаем и видим, что на тикль оказали влияние lisp и shell. Ты говоришь, что ген shella выиграл лотерею в этом скрещивании. Как версию это вполне можно принять. Но есть ли более рациональные объяснения?

den73 ★★★★★
() автор топика
Ответ на: комментарий от t184256
>"a $v"
a {b c}
>"a {*}$v"
a b c

А вот это непохоже на строковую интерполяцию? Если абстрагироваться от способа, которым происходит подстановка. И заодно такая полезная абстракция, как вложенный список, перестаёт быть сломанной (наверное).

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

зачем в тикле нет списков?

Так там ничего нет кроме строк. Гомоиконность панимашь. Для скриптования строки удобнее, а со списками лишп получился бы. Но зачем человекам еще один лишп?

anonymous
()

Кремень человек!

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

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

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

Конечно, списки в тикле есть:

tclsh8.6 [~]set x [list a b c]
a b c
tclsh8.6 [~]::tcl::unsupported::representation $x
value is a list with a refcount of 3, object pointer at 0x55e0cfec0f40, internal representation 0x55e0cff32700:(nil), string representation "a b c"
tclsh8.6 [~]set y "z $x"
z a b c
tclsh8.6 [~]::tcl::unsupported::representation $y
value is a pure string with a refcount of 2, object pointer at 0x55e0cfea4250, string representation "z a b c"

Другое дело, что у каждого объекта есть строковое представление, и именно оно используется внутри кавычек (кроме тривиального случая типа "$x". Ну и альтернативное представление может меняться, превращая список во что-нибудь другое, скажем в словарь:

tclsh8.6 [~]set z [list a b c d]
a b c d
tclsh8.6 [~]::tcl::unsupported::representation $z
value is a list with a refcount of 3, object pointer at 0x55e0cfe9f960, internal representation 0x55e0d00e0af0:(nil), string representation "a b c d"
tclsh8.6 [~]dict get $z a
b
tclsh8.6 [~]::tcl::unsupported::representation $z
value is a dict with a refcount of 3, object pointer at 0x55e0cfe9f960, internal representation 0x55e0d008a970:(nil), string representation "a b c d"

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

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

У Айка получилось. Учи JS, забудь эту недоскобкоту. Объективно, JS - самый мощный из всех языков программирования когда-либо созданных. Можно много кукарекать насчёт неприменимости JS в крупных проектах (овер 10^6 строк. хотя таких проектов никто из кукарекающих никогда в жизни не сопровождал. максимум - пробовали распаковать zip с такого проекта, полазить, почитать readme и rf -rf с глаз долой). На самом деле, JS давно и далеко уделал все известные лиспо-тикли-куллязычки. Зря ты пыхтишь по лиспо-ностальгии. Лисп хорошо знаешь где? В AST для компилятора цепепе :-) Смехота, но это правда :-)

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

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

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

ЖоЭс выйграл потому, что 💩 и идёт с каждым браузером. А говноделы любят 💩 и работодателям дешевле нанять 💩. Вот и весь расклад.

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

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

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

ЖоЭс выйграл потому, что 💩 и идёт с каждым браузером. А говноделы любят 💩 и работодателям дешевле нанять 💩. Вот и весь расклад.

Да всем плевать на эти значки с кофе. Факт то в том, что толку от JS больше чем от всех тиклей с лиспами вместе взятых. Пока ты тешишь себя токсичными мыслишками на предмет «JS - говно», прямо сейчас вот кто-то другой творит софт на JS. Конечно же самодовольные ламерки разных мастей вскукарекнут тут наряду со своей скептикой, что этот софт неправильный, потому что, оказывается «JS - говно». Но кто же вам виноват, что вы - ламерки, и что ваша участь - смотреть как прямо на ваших глазах создаётся объективная реальность, к созданию которой вы не имеете никакого отношения? Ну это ваше личное, это такое.

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

JS это убогонький нерасширяемый недоалгол. Адепты таких язычков сидят и веками ждут пока добренькие хозяева не снизойдут капнуть им в клювик новых кейвордов. А пока ждут приходится в сишка-стайл говнокодить мегабайты портянок.

Да знаю я эту лабуду. Один известных ламерок лапши на уши навешал и поржал. Теперь все кому не лень твердят про расширяемый сахар, макры, мощь лиспа, независимость от вендоров, ко-ко-ко. Никаких мегабайтов портянок в JS говнокодить не надо. Нет, ну если кто-то совсем прям лох, то он, обречён. Но это не из-за JS, а из-за лох.

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

Не, пока остановил ученье, хотя в любой день готов возобновить, если вдруг лишп перестанет кормить. C JS всё более-менее норм, поскольку он image-based и в нём есть eval, нет удушающих объятий ООП, а также умеренно хороший JIT. Т.е. как платформа он вполне сойдёт. Как конечный язык - вряд ли.

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

Когда ты был рядовым анонимом со смайлами, ты был интереснее. А сейчас ты стал унылым регистрантом с пониженым IQ.

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

Вот это, да. Я аж до конца первого комента не мог понять, что это за кадр пишет. Но

Лисп хорошо знаешь где? В AST для компилятора цепепе :-) Смехота, но это правда :-)

раскрыло всю интригу. Так даже не интересно.

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

Когда ты был рядовым анонимом со смайлами, ты был интереснее. А сейчас ты стал унылым регистрантом с пониженым IQ.

Знаешь сколько подобных реплик мне доводилось слышать? Ты вряд ли досчитаешь. Но эти реплики как-то до лампочки.

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

раскрыло всю интригу. Так даже не интересно.

Лол :-) А что это за вещество на аватаре?

azelipupenko
()

{*} по смыслу есть ,@

# А так не работает:
> puts «a {*}$v»

Нет, {*} - по смыслу не есть ,@. ,@ разворачивает список при квазицитировании, {*} разворачивает список при вызове функции.

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

Нет, двойные кавычки - интерполированная строка.

Короче, чтобы понять Tcl после лиспа нужно перестать мыслить списками и начать мыслить строками.

Gentooshnik ★★★★★
()
Последнее исправление: Gentooshnik (всего исправлений: 1)

списки в tcl на печати изображаются с помощью фигурных скобок
при этом внешняя пара фигурных скобок при печати опускается

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

В Tcl фигурные скобки означают просто строку без интерполяции. Если в ней есть пробелы, то такую строку можно считать одновременно списком. Да, немного ломает мозг после лисповой динамической но строгой типизации. В Tcl её практически нет. Концептуально в большинстве случаев можно считать, что всё - строка, а всё что не строка (число, список, словарь и т.д.) - это всё-равно строка, но специальным образом сформатированная.

Gentooshnik ★★★★★
()

Насколько я плохо помню, {} это не список, а всего лишь строка, внутри которой тикль ничего не заменяет. А в «» кое что заменяет.

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

а всё что не строка (число, список, словарь и т.д.) - это всё-равно строка, но специальным образом сформатированная

Ага, все зависит от интерпретации. Списковые команды думают, что это список, другие команды могут иметь другое мнение. Тикль гениально прост, но не всем заходит, особенно у типолюбов подгорает.

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

Я аж до конца первого комента не мог понять, что это за кадр пишет.

Смайлик прочитал стандарт борщелиспа и окончательно свихнулся.

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

Концептуально ясно. Как работать - неясно. Я могу перестать мыслить списками, но что, если мне нужны вложенные списки. Скажем, я хочу представить json. В лиспе есть способ это сделать, с помощью s-выражений. Есть элементы, они вкладываются друг в друга, наглядны при печати, не ломаются при операциях сборки из них агрегатов и есть квазицитирование.

Я несколько месяцев кодил на tcl, но мне как-то не попалось такого же удобного способа работы с вложенными данными. Можно так сказать: среди всех строк, есть множество строк, представляющих списки. Есть набор операций над строками, который также является операциями над списками, представляющими эти строки. Например, lindex, list, linsert. В т.ч. и операция «» может принимать и выдавать списки. И вот эта операция, если её рассматривать как операцию над списками, выглядит сломанной, хотя она могла бы быть квазицитированием. А квазицитирования при этом мне как-то не попалось.

Т.е. можно сказать, что «» - это сломанное квазицитирование. Где нормальное квазицитирование?

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

Ты не заметил разве, что в тикле нет полиморфизма. Даже если кавычки рассматривать как команду, то это строковая команда. Проще говоря тебе нужны другие кавычки для квазицитирования.

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

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

Т.е. кавычки сразу делают две вещи: 1. Подстановку строк. 2. Конкатенация списков.

Что они делают, зависит от того, как мы воспринимаем результат. Такая вот философия.

Теперь такой вопрос: а если бы кавычки были определены как

>set v {b c}
>"a $v"
a {b c}
>"a {*}$v"
a b c

то что было бы в этом плохого, кроме того, что это не так как в shell? Shell вообще, на мой взгляд, отнюдь не образец для подражания.

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

любая операция над строками в то же время является также операцией над списками, которые эти строки представляют.

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

Т.е. можно сказать, что «» - это сломанное квазицитирование. Где нормальное квазицитирование?

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

что было бы в этом плохого, кроме того, что это не так как в shell?

То, что кавычки - это интерполяция строки (которая есть ещё в 100500 языков кроме shell и везде работает одинаково), а строковое представление списка - это элементы разделённые пробелом. Без скобок. Если «определить строку» так, как вы предлагаете, то она стала бы одновременно и сломанным квазицитированием, и сломанной интерполяцией.

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

Кстати, как в лиспе можно сделать интерполяцию строк (которой в языке нет, как и квазицитирования в Tcl) макросом (cl-interpol, например), так и в Tcl можно сделать квазицитирование процедурой. Это намного сложнее, правда, и общепринятого решения нет.

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

любая операция над строками в то же время является также операцией над списками, которые эти строки представляют

set ab "{a b"
set c "} c"
puts [lindex "$ab$c" 1]

- какая будет списковая операция?

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

Во, наконец-то я начал вспоминать, в чём суть проблемы. Именно в этом :) В том, что нет разницы между списком из одного элемента и собственно элементом.

Кстати, это не только в TCL.

Powershell:

PS > $a=1,2
PS > $a[0]
1
PS > $b=1
PS > $b[0]
1

sh

> a="1 2"
> for i in $i; echo $i; done
1
2
> a=1
> for i in $i; echo $i; done
1

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

Очевидно и я не стал упоминать, что операция может быть не определена как списковая, если аргументы не представляют списки.

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

В Tcl нет квазицитирования для списков, которое ведёт себя как квазицитирование.

Спасибо, я боялся, что она есть, но ускользнула от меня. Теперь всё Ок.

Есть интерполяция строк, которая ведёт себя как интерполяция строк.

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

которая есть ещё в 100500 языков кроме shell и везде работает одинаково

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

Более правильно было бы определить строковое представление списка с обязательными фигурными скобками

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

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

Кстати, это не только в TCL.

Ну вот это может быть одним из вариантов объяснения, почему именно так сделано - протиражировали чужое кривое и популярное решение, чтобы было всем понятно.

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

чужое кривое и популярное решение

Оно не кривое. Оно удобное для shell'а. Для командной строки пользователя не нужны вложенные списки. Зато нужен удобный способ получать через grep и подобные конструкции один элемент не вешая car на каждую конструкцию.

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

когда долбаёбу не жалко нескольких лет, он тратит их на вразумление сетевых сумасшедших

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

Вообще, с таким же успехом можно предъявлять претензию лиспу, что не различаются пара, список и дерево. И из-за этого нельзя сделать нормальный обобщённый copy и equal.

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

Честно сказать, я усомнюсь в том, что они «не нужны», скорее, «люди адаптировались к их отсутствию».

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

Но в целом тема проясняется, кажется мне.

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

Зато нужен удобный способ получать через grep и подобные конструкции один элемент не вешая car на каждую конструкцию.

Можешь привести пример? Я не понял что-то.

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

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

Не, это у тебя неадекватные ожидания. Tcl не проектировался как язык общего назначения. Фигачить в нем структуры данных это такое... Можно в принципе, но больно и зачем? Ты вроде опытный кодер, должен уже чувствовать границы применимости инструментов.

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

Ну, пример крайне хрупкий, и как раз из-за идеологии «всё есть строка». Сразу три проблемы:

  • my-atopacctd
  • my\ atopacctd
  • запущено более одного экземпляра

Если их начать чинить в рамках bash, то преимущество от отсутствия разделителей быстро съестся, код станет огромным и write-only. Т.е. я продолжаю считать идеологию «всё есть строка» кривой, сериализацию структур данных а-ля лисп необходимой, а такой выбор в tcl вдвойне ошибочным, поскольку человек мог сделать правильно, но не стал.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.