LusoRobótica - Robótica em Português

Software => Software e Programação => Tópico iniciado por: Njay em 24 de Março de 2015, 20:45

Título: TCL ("ticle")
Enviado por: Njay em 24 de Março de 2015, 20:45
Embora pouco conhecida, TCL é uma das minhas linguagens favoritas; é o meu canivete suíço do software.
Como tal venho mostrar-vos algumas linhas de código nesta linguagem. Quem usar linux já tem o interpretador de TCL instalado e é só usar o comando tclsh para entrar numa linha de comando do interpretador (exit é o comando para sair, ou CTRL+C).

Eu gosto de TCL (e Tk, a biblioteca gráfica que nasceu com o TCL, também) por várias razões, entre as quais a simplicidade da linguagem. Em TCL cada linha do script (programa) corresponde a um comando e respectivos argumentos. O interpretador de TCL parte cada linha em palavras, pelos espaços, e interpreta a 1ª palavra da linha como o nome do comando e as restantes como argumentos desse comando. Quando é preciso que uma palavra tenha espaços (mesmo que sejam fins de linha!), envolve-se essa palavra em aspas "".
Por exemplo o comando puts serve para escrever em canais e adiciona automaticamente um fim de linha; por omissão o puts escreve para o canal stdout (tipicamente é o "ecrã"):

puts olá

Se quisermos escrever uma string com espaços, então temos que o envolver em aspas:

puts "olá mundo"

E isto também funciona:

puts "Olá mundo.
Agora uma nova linha.
E outra."


Um comentário é uma linha começada por #. Em TCL só existem 3 tipos de dados: string, lista e array. As listas só podem conter strings e outras listas, e os arrays em TCL são associativos (tabelas de hash). Uma variável pode conter um valor de qualquer um destes tipos, e o comando set é forma mais habitual de criar ou alterar variáveis:

# set <nome-da-variável> <valor>
set nick Njay

Se a variável não existia previamente, o set cria-a. Podemos apagar uma variável com

# unset <nome-da-variável>
unset nick

Usar o valor da variável faz-se prefixando-a com um dólar, $ . Para mostrar no ecrã o valor da variável nick,

puts $nick

e para copiá-la para outra

set nick2 $nick

Se quisermos misturar variáveis com texto basta enfiar as variáveis no meio de uma string:

puts "O meu nick é $nick"

Depois de separar a linha em palavras, o interpretador de TCL pega em cada palavra e faz as chamadas substituições, sendo que uma delas é procurar instâncias de variáveis e substituí-las pelo valor da variável. Assim, o comando puts acima não recebe como argumento "O meu nick é $nick" mas sim "O meu nick é Njay" . Parte da simplicidade do TCL é que ele limita-se a passar "strings" aos comandos, e os comandos depois é que decidem o que fazer com essas string. Isto é muito poderoso.

Para passar um argumento a um comando sem que sejam feitas substituições, envolve-se o argumento em chavetas {}. Se no exemplo acima quiséssemos mesmo imprimir no ecrã a string "O meu nick é $nick", sem que a variável fosse substituída pelo seu valor, poderiamos fazer assim:

puts {O meu nick é $nick}

Outra coisa muito poderosa em TCL é que é muito fácil lidar com ficheiros e com sockets. Abrir e carregar o conteúdo de um ficheiro de texto para uma variável é tão simples como

set fd [open data.txt r]
set data [read $fd]
close $fd


Aqui usei 4 comandos: open, set, read e close. Além das variáveis, outra das substituições que o interpretador de TCL faz quando está a parsar uma linha, é a "substituição de comandos", quando estes aparecem em parentesis rectos []. Ao fazer as substituições nos argumentos do comando set na 1ª linha do script acima, o interpretador vê os [] e pega em todo o texto que contém, parsa-o e executa-o como se fosse uma linha isolada no script. Portanto invoca o comando open com os argumentos data.txt (nome do ficheiro) e r (abrir o ficheiro para leitura), e substitui os [] pelo resultado do comando, que é um identificador de ficheiro aberto. Este identificador é então passado ao comando set como 2º argumento, que cria a variável fd para o guardar.
Na 2ª linha o comando read lê todo o conteúdo do ficheiro e coloca-o na variável data. Na 3ª linha o ficheiro é fechado com close.

É igualmente fácil abrir um socket e enviar e receber dados. Em TCL o I/O ocorre em canais e usam-se as mesmas funções para ler, escrever, configurar e fechar. Muda o comando que abre um canal, dependendo do tipo de canal; open para ficheiros e portas série, socket para sockets. Abrir uma ligação TCP para um servidor web e obter uma página é simples:

set sock [socket lusorobotica.com 80]
puts $sock "GET / HTTP/1.0\nHost: lusorobotica.com\nConnection: close\n"
flush $sock
set response [read $sock]
close $sock
puts $response


A 1ª linha abre uma ligação TCP para o servidor lusorobotica.com no porto 80 (o porto por omissão para servidores HTTP) com o comando socket, e guarda o identificador do socket na variável sock. Depois o puts envia ao servidor o pedido HTTP, e o flush "despeja" os buffers do canal, garantindo que o que foi escrito pelo puts foi *mesmo* enviado para a rede. Depois é lida toda a resposta do servidor web para a variável response, o socket é fechado e a resposta é impressa no ecrã. Reparem que o pedido HTTP enviado pelo puts é uma string constante, mas eu usei aspas em vez de chavetas; se eu usasse chavetas, não ocorreria a substituição dos caracteres \n por um real caractere de fim de linha.
A resposta tem no inicio algumas linhas que correspondem os cabeçalhos HTTP de resposta, e depois a página. Mais tarde posso explicar como separar ambos, mas para já não quero complicar mais.

É igualmente simples abrir uma ligação a uma porta série, por exemplo para falar com um Arduino, ou executar outras aplicações. Em TCL "tudo são strings" e isso simplifica muito as interfaces dos comandos e facilita imenso a inter-operabilidade.

Podem executar os comandos 1 a 1 na tcl shell (tclsh) ou metê-los num ficheiro e passar o nome do ficheiro como argumento à tclsh para executar o script todo. Em linux é possível executar o script directamente activando a flag de executável do ficheiro e adicionando isto logo ao inicio do script (espero que esteja certo, não costumo usar Linux):

#! /usr/bin/env tclsh

End of Part I
Título: Re: TCL ("ticle")
Enviado por: Nunito em 25 de Março de 2015, 08:37
Muito bom.
Fácil de interpretar.
Isso dá para windows?
Título: Re: TCL ("ticle")
Enviado por: Njay em 25 de Março de 2015, 12:52
Sim, há para Windows e outras plataformas. Podes sacar o instalador da última ou penúltima versão aqui: http://www.activestate.com/activetcl/downloads (http://www.activestate.com/activetcl/downloads)

Em alternativa, deixo aqui em anexo a minha versão do package para windows, que é o TCL/TK8.3 mas reduzido ao essencial com umas extensões extra para Windows e que não é preciso instalar, basta descomprimir e o interpretador (tclsh) está da directoria bin/ (mais fácil se adicionares essa directoria ao path). A tclsh é uma consola muito básica, eu normalmente uso outra consola mais inteligente que é a TkCon (que está feita em TCL/TK, é um script TCL!); para correr a TkCon há um bat na raíz da directoria. Na directoria doc está o help, que contém *toda* a documentação do TCL/TK (excepto a das extensões que eu juntei, que têm uns html com doc lá dentro); acabei por perder a doc do TCL8.3 e por isso o ficheiro que lá está é a do 8.4, mas as diferenças são muito poucas.
Este zip de ~3MB (~10MB descomprimido) faz maravilhas ;)
Título: Re: TCL ("ticle")
Enviado por: senso em 20 de Abril de 2015, 23:57
Parabéns, para quando mais um petisco em TCL?

Já agora, e a titulo de curiosidade, quem tem o IDE do Arduino já lá tem o TCL enfiado numa pasta.
Título: Re: TCL ("ticle")
Enviado por: TigPT em 21 de Abril de 2015, 12:24
Não conhecia, e é sempre útil ter opções de scripting fáceis de utilizar para simplificar tarefas do dia-a-dia.

Obrigado Nuno por este cheirinho do TCL.
Título: Re: TCL ("ticle")
Enviado por: Njay em 16 de Maio de 2015, 21:48
"Petisco de TCL", lol... É verdade tens razão senso, o TCL vem "embebido" no pacote do arduino. TCL/Tk é um bocado "low-profile" mas quando vamos cavar encontra-se por aí em vários sítios.

Vou fazer um twist a este "tutorial". Perguntem como se faz qualquer-coisa em TCL/Tk. Coisas relativamente simples claro, tipo como se ordena uma lista, como se processa um ficheiro de texto linha-a-linha, etc; não aceito perguntas do género "como se faz um editor com sintaxe highlight" (embora na verdade não seja mto dificil :o ).
Título: Re: TCL ("ticle")
Enviado por: jm_araujo em 16 de Maio de 2015, 22:29
Se me permites uma proposta: abrir um ficheiro de texto, correr uma regex, e retornar (para um ficheiro ou consola) todos os matches.

É uma das tarefas que já me poupou muitas horas de trabalho, e que atualmente executo em python por ser rápido e fácil. Em python:
Código: [Seleccione]
import re

f = open ("exemplo.txt")
texto = f.read()
f.close()

for result in re.findall("\d{3}",texto): #encontra numeros de 3 digitos
   print result
Título: Re: TCL ("ticle")
Enviado por: Hugu em 16 de Maio de 2015, 22:49
@off-topic: precisava dum script podia ser em python que me pegasse em um txt, com mails pra lá atirados e que me faça ordenação em grupos de x mails por ficheiro txt separado, com respectiva exclusao de mails repetidos... tinha um script que fazia quase isto, mas deixou de dar porque aquilo tinha um deadtimmer e nao houve mais upgrades ou novas versoes do autor :(
Título: Re: TCL ("ticle")
Enviado por: Njay em 16 de Maio de 2015, 23:29
Se me permites uma proposta: abrir um ficheiro de texto, correr uma regex, e retornar (para um ficheiro ou consola) todos os matches.

É uma das tarefas que já me poupou muitas horas de trabalho, e que atualmente executo em python por ser rápido e fácil. Em python:
Código: [Seleccione]
import re

f = open ("exemplo.txt")
texto = f.read()
f.close()

for result in re.findall("\d{3}",texto): #encontra numeros de 3 digitos
   print result

Em TCL seria muito parecido:

Código: [Seleccione]
set fd  [open "exemplo.txt" r]
set data  [read $fd]
close $fd

foreach line [split $data \n]  {
    if [regexp -- "\\d{3}" $line match]  {
        puts $line
    }
}

A sintaxe das expressões regulares é basicamente a mesma que em python (é usada a mesma lib de re em C lá por baixo de certeza), as diferenças são apenas por causa da forma como representas certos caracteres.

split é um comando que retorna uma lista de strings, gerada partindo em bocados a string indicada como 1º argumento, sempre que encontra um dos caracteres indicados no 2º argumento. Assim, o comando split $data \n retorna uma lista em que cada elemento é uma linha do ficheiro.

Depois o comando foreach serve para percorrer listas elemento a elemento e fazer alguma coisa com eles; o nome diz tudo, "for each" -> "para cada" (para cada elemento da lista, faz ...). O 1º argumento é o nome de uma variável onde a cada iteração do foreach é colocado o elemento. O 2º argumento do foreach é a lista a percorrer e o 3º é o script a executar para cada elemento.

Finalmente há um if que verifica se houve um match da linha com a expressão regular e em caso afirmativo envia a linha para o stdout (vulgo, "imprime a linha" :) ).

O comando regexp tem um parâmetro não usado neste exemplo, que é o "match". Este é o nome de uma variável que o regexp cria com o texto que fez o 1º match da string. O argumento está no exemplo porque é obrigatório no comando, mas estou a ignorá-lo (não faço nada com ele). Mas podia usar-se para ter mais informação no output, se relevante para a aplicação.
Título: Re: TCL ("ticle")
Enviado por: dropes em 16 de Maio de 2015, 23:45
Na era do DOS tudo o que eram scripts eram à base de batchs, até foi assim que comecei a interessar-me por programação e ainda fiz uns jogos, à base de linhas de comandos como é óbvio.

O DOS também tinha incluído uma versão BASIC que achei uma maravilha, muito simples passando mais tarde para o Pascal em paralelo com o C.

Em Pascal fazia de tudo, desde de crackar jogos, scripts para tudo e mais alguma coisa, criar jogos, efeitos gráficos mesmo tridimensionais, acesso directo à memória gráfica, não haviam limites...
Infelizmente perdeu continuidade quando se entrou em modo windows e passou a ser uma linguagem ultrapassada, entretanto o C permaneceu até hoje.

No presente não entendo mesmo nada de C, entretanto ainda dou uns toques em VB no que toca a linguagem informática, o mesmo se passa com os microcontroladores, 0 em C, programando sempre em Basic (BascomAVR), tirando os casos em que tenho de recorrer ao assemby 8051 ou AVR.

Sei que devia aprender C, até os arduinos o têm mas há algo que me desagrada desde a época do DOS, por isso fujo um pouco a esta linguagem, o que hoje em dia é essencial entende-la...

No que toca a opiniões, prefiro saber trabalhar bem com uma linguagem do que saber várias assim por alto, com os micros passa-se o mesmo, não vario muito do Atmega 8b e nunca me deixou ficar mal para o que tenho feito  :)

TCL nunca tinha ouvido falar, é como quando me iniciei em ladder para PLCs, que porcaria, é que nem linguagem pode ser considerada, foi sem dúvida a pior experiência que já tive em "programação", tudo muito visual com uma apresentação confusa de ser interpretada, bonequinhos por tudo o que é sitio, podendo ser visto o código gerado em assembly, é que até em texto corrido seria muito mais rápido de se programar do que neste tipo de interface, enfim... são gostos.

Boa iniciativa aqui do Njay apresentado uma solução simples para pequenos scipts que nos vão ajudando nas rotinas especificas do dia a dia   ::)
Título: Re: TCL (&quot;ticle&quot;)
Enviado por: artur36 em 17 de Maio de 2015, 10:05


Citação de: dropes

TCL nunca tinha ouvido falar, é como quando me iniciei em ladder para PLCs, que porcaria, é que nem linguagem pode ser considerada, foi sem dúvida a pior experiência que já tive em "programação", tudo muito visual com uma apresentação confusa de ser interpretada, bonequinhos por tudo o que é sitio, podendo ser visto o código gerado em assembly, é que até em texto corrido seria muito mais rápido de se programar do que neste tipo de interface, enfim... são gostos.

O ladder tem de ser entendido no contexto em que foi criado, quando appareceram os primeiros autómatos os técnicos de automação que existiam não eram programadores mas sim electricistas/projectistas que a única linguagem que conheciam era lógica com relés e daí surgiu o ladder como linguagem perfeita para autómatos, mesmo hoje em dia um bom electricista é capaz de interpretar um programa de ladder sem nunca ter estudado programação.
Para mim a dificuldade inicial do ladder prende-se com a estruturação inicial do programa, quando se compreende o conceito de máquina de estados e se parte de um Grafcet a programação é relativamente simples. Mas para quem quiser uma linguagem de programação em texto e conhecida pelo menos a siemens já disponibiliza uma linguagem de programação de alto nível derivada do C.
Título: Re: TCL ("ticle")
Enviado por: Njay em 17 de Maio de 2015, 14:40
Pensava que programavas os AVR em C, dropes. Tens que aprender C, até é uma vergonha um gajo do baixo nível não saber C  :o :P, hehehe

Bom, voltando ao tópico, podemos agarrar no código que procura expressões regulares em linhas dum ficheiro e fazer dele um comando para ser mais útil. Em TCL criam-se comandos com o comando proc (e chamamos-lhes "proc" para não estar sempre a dizer "comando"), que aceita 3 argumentos: o nome do novo comando, a lista de argumentos do comando e o código. Portanto ficaria assim:

proc ScanFileLines {file_name regular_expression}  {
    set fd  [open $file_name r]
    set data  [read $fd]
    close $fd

    foreach line [split $data \n]  {
        if [regexp -- $regular_expression $line match]  {
            puts $line
        }
    }
}


Todos os comandos em TCL retornam alguma coisa, nem que seja uma string vazia. Se um proc não retornar com o comando return (por exemplo return "sucesso"), ele retorna o resultado do último comando executado no proc. Neste caso não retornamos nada explicitamente no proc ScanFileLines, que é como quem diz que não queremos retornar nada de especial. O proc criado leva 2 argumentos, o nome do ficheiro a inspeccionar e a expressão regular. Invocar este proc para fazer o trabalho do exemplo original é assim:

ScanFileLines "exemplo.txt" "\\d{3}"

Agora tendo este proc fica mais fácil fazer uma ferramenta de linha de comando para esta tarefa. O TCL cria automaticamente uma lista com os argumentos passados ao script na linha de comando, colocando essa lista na variável argv . Se enfiarmos o nosso script num ficheiro chamado scanfilelines.tcl, e o invocarmos assim

tclsh scanfilelines.tcl arg1 arg2 arg3

a variável argv terá uma lista com 3 elementos, os 3 argumentos da linha de comando: {arg1 arg2 arg3} . Vamos agora convencionar que passamos ao nosso script no 1º argumento o nome do ficheiro e no 2º a expressão regular, para usar assim

tclsh scanfilelines.tcl exemplo.txt \d{3}   (*)

Dentro do script temos que extrair esses argumentos para variáveis separadas para passarmos ao proc ScanFileLines. Há 2 ou 3 maneiras de fazer isto, mas vamos começar pela mais explicita (mas não a mais compacta), que é usar o comando lindex (list index), que retorna o elemento de índice X de uma lista, sendo que X começa em 0, ou seja, o 1º elemento de uma lista é o que está no índice 0. Ficaria então assim:

set file_name  [lindex $argv 0]
set regular_expression  [lindex $argv 1]


O comando lindex aceita 2 argumentos, a lista e o índice a extrair. Agora já podemos invocar o nosso proc:

ScanFileLines $file_name $regular_expression

E fica em anexo o script completo (em .zip que o fórum não aceita .tcl).

Venham de lá mais pedidos de "como é que se faz X" em TCL...


(*) isto é em windows, \d{3} pode ter que ser passado de forma ligeiramente diferente noutras shells
Título: Re: TCL ("ticle")
Enviado por: Njay em 17 de Maio de 2015, 14:49
@off-topic: precisava dum script podia ser em python que me pegasse em um txt, com mails pra lá atirados e que me faça ordenação em grupos de x mails por ficheiro txt separado, com respectiva exclusao de mails repetidos... (...)

Com esses requisitos tão esparsos eu nem arrisco uma estimativa de preço ;)
Título: Re: TCL ("ticle")
Enviado por: dropes em 18 de Maio de 2015, 11:30
Pensava que programavas os AVR em C, dropes. Tens que aprender C, até é uma vergonha um gajo do baixo nível não saber C  :o :P, hehehe

Shame on me, é que nem um arduino sei programar  :-[ :P

Quanto ao ladder também me foi explicado que um electricista conseguia entender mesmo sem saber programar, já ao contrário... é frustrante (omron, siemens ou schneider, 3 programas lindos que foram desinstalados mal acabei a formação).
Título: Re: TCL ("ticle")
Enviado por: Njay em 22 de Maio de 2015, 13:57
Então, e mais desafios para fazer em TCL?

Olha um contador de palavras num ficheiro:

# Obter o nome do ficheiro da linha de comando (1º argumento)
set file_name  [lindex $argv 0]
# Abrir e ler o ficheiro todo para a variável txt
set fd  [open $file_name r]
set txt  [read $fd]
close $fd
# Substituir múltiplos espaços, tabs e fins de linha por 1 único espaço
regsub -all "\\s\\s+" $txt " " txt
# Partir o texto pelos espaços, guardando o resultado (uma lista, de palavras) na variável words
set words  [split $txt " "]
# E escrever no ecran o número de palavras
puts "[llenght $words] palavras"


Ainda não testei, mas deve funcionar :)

Já fazíamos era uma função para abrir um ficheiro de texto e retornar o conteúdo:

proc LoadTextFile {file_name}  {
    set fd  [open $file_name r]
    set txt  [read $fd]
    close $fd
    return $txt
}


E mais?
Título: Re: TCL ("ticle")
Enviado por: KammutierSpule em 22 de Maio de 2015, 14:48
E se quiseres eliminar as palavras repetidas?
Título: Re: TCL ("ticle")
Enviado por: Njay em 22 de Maio de 2015, 20:14
A 1ª coisa que me veio à cabeça foi usar um array de TCL, que é uma tabela de dispersão (hashtable). Varria a lista de palavras e criava elementos dummy em que os nomes (como em TCL se chamam às chaves) são as palavras. Ao inserir no array uma palavra que já existe, esta vai sobrepôr a palavra já existente. No final, é obter uma lista só com os nomes do array (subcomando names do comando array) e contar o número de elementos dessa lista. Ficaria então assim:

...
# Partir o texto pelos espaços, guardando o resultado (uma lista, de palavras) na variável words
set words  [split $txt " "]
# Percorrer a lista de palavras, criando no array word_table entradas em que os nomes são as
# palavras. Palavras repetidas sobrepõem-se, ficando apenas uma ocorrência da palavra no array.
foreach word $words  {
    # Criar a entrada de nome $word no array word_table (quando a variável não existe,
    # o set cria-a). Como neste caso não interessa o que guardamos no array, metemos
    # strings vazias (não ocupa mem)
    set word_table($word)  ""
}
# Obter a lista dos nomes do array
set words  [array names word_table]
# E escrever no ecran o número de palavras únicas
puts "[llenght $words] palavras"


Mas depois lembrei-me que o comando para ordenar listas tem um parâmetro para deitar fora os elementos repetidos :) . Então aí ficaria assim:

...
# Partir o texto pelos espaços, guardando o resultado (uma lista, de palavras) na variável words
set words  [split $txt " "]
# Ordenar a lista de palavras deitando fora as repetidas
# (lsort recebe uma lista e retorna uma nova lista)
set words  [lsort -unique $words]
# E escrever no ecran o número de palavras únicas
puts "[llenght $words] palavras"


No final ainda ficamos com a lista de palavras ordenada. Se quisermos imprimi-la no ecran, uma palavra por linha, podemos usar o comando join. Esta comando aceita uma lista e uma string separadora, e cria uma string com todos os elementos da lista separados pela string separadora. Para meter uma palavra por linha, temos que as separar por um fim de linha, daí:

# Escrever no ecran a lista de palavras únicas, uma palavra por linha
puts [join $words "\n"]


É comum escrever-se de uma forma um pouco mais compacta, juntando na mesma linha até 2 ou 3 comandos (agora completo e usando a função que criámos lá atrás, para carregar um ficheiro de texto):

# Carregar um ficheiro e escrever no ecran o número de palavras únicas
set txt  [LoadTextFile [lindex $argv 0]]
regsub -all "\\s\\s+" $txt " " txt
set words  [lsort -unique [split $txt " "]]
puts "[llenght $words] palavras"


Aqui adicionei uma linha extra, com o comando regsub, uma expressão regular para substituir conjuntos de 2 ou mais espaços consecutivos por apenas um espaço. Isto é para evitar criar palavras vazias, pois se o split apanhar por exemplo 2 espaços consecutivos, ele parte a string entre os espaços e cria uma entrada vazia (string vazia, "") a representar o que se encontra entre esses espaços. Há outras formas de eliminar estas palavras vazias, que até são bastante mais eficientes; mas eu gosto de expressões regulares :)

Então, e mais desafios para fazer em TCL?
Título: Re: TCL ("ticle")
Enviado por: KammutierSpule em 23 de Maio de 2015, 20:58
Alright, sinceramente, nao consigo perceber nada da linguagem :), sou mau em linguagens, so sei C/C++

Ha ai uma coisa que nao entendo, se estas a usar hashtable, porque precisas de ordenar e eleminar, se e' so para saber quantas palavras existem, entao era so retornar o tamanho da tabela.

A ideia de usar uma hashtable 'e boa, em C++ podia-se usar map para isso, e dessa maneira ate dava para contar as ocorrencias de cada palavra.
Neste caso nao importa a ordem.
Título: Re: TCL ("ticle")
Enviado por: Njay em 24 de Maio de 2015, 01:25
Apresentei 2 métodos diferentes. O 1º usa uma tabela de dispersão (hash), que em TCL é um array (o nome formal deste tipo de dados é "array associativo"). De facto há um subcomando, "size", do comando array, que retorna o número de elementos do array, não sei porquê não me lembrei na altura, e podemos assim poupar uma linha, substituindo

...
# Obter a lista dos nomes do array
set words  [array names word_table]
# E escrever no ecran o número de palavras únicas
puts "[llenght $words] palavras"


por

...
# E escrever no ecran o número de palavras únicas
puts "[array size word_table] palavras"


No código original eu estava a obter uma lista com todas as chaves do array e depois imprimia o tamanho dessa lista, mas de facto, é estúpido :) .

O 2º usa o comando de ordenação de listas, que tem um parâmetro para eliminar os repetidos; ao ordenar a lista de palavras com eliminação de repetidos, fico com uma lista sem palavras repetidas (o que é retornado do comando lsort, list sort):

set words  [lsort -unique $words]

Isto ordena a lista e elimina os repetidos; a lista de entrada está na variável words e o resultado é atribuído à mesma variável words. Não estamos interessados na ordenação, aqui estamos apenas a aproveitar o facto do comando de ordenação de listas também eliminar os repetidos.

TCL é um bocado como lisp (na verdade acho-os conceptualmente parecidos), muda a tua maneira de ver o mundo ;) .

O que é que te faz mais confusão?

Uma variável array de TCL, que é na prática uma tabela de dispersão, acede-se tendo o nome do array sufixado pela chave entre parentesis. Daí que word_table(TCL) é o nome do elemento de chave "TCL" do array word_table. Repara que eu disse "o nome"; se quiseres aceder ao valor é preciso usar o $ tal como no acesso às restantes variáveis, como em $word_table(TCL).
Se quisermos usar a chave que está numa variável, é só passar o valor dessa variável como chave. Exemplos:

set array(TCL)  "FIXE"   ;# cria a chave "TCL" no array "array"
set key  "TCL"           ;# cria a variável "key" com o valor "TCL"
puts "array($key)"       ;# imprime "array(TCL)"
puts "$array($key) é o mesmo que $array(TCL)"   ;# imprime "FIXE é o mesmo que FIXE"


Nota: Para se colocar um comentário a seguir a um comando na mesma linha é necessário colocar um ;

Repara como eu usei "array" como nome de uma variável, apesar de ser também o nome de um comando. Em TCL podes fazer isso, porque para o TCL, comandos são a 1ª palavra da linha ou a 1ª palavra a seguir ao [ , daí que não há ambiguidade.
Título: Re: TCL ("ticle")
Enviado por: KammutierSpule em 24 de Maio de 2015, 10:16
ok nice.

Essa linguagem, 'e dificil de seguir sem conhecer a syntax.
Ai torna-se complicado a cena dos $, porque estas a aceder ao conteudo das variaveis dentro da propria string que vais imprimir.
Por exemplo
"puts "[llenght $words] palavras"

e' dificil entender o que desses caracteres sao para imprimir e o que sao comandos ai pelo meio sem conhecer a syntax.

...Se calhar vou antes aprender um pouco da linguagem: http://en.wikipedia.org/wiki/Brainfuck (http://en.wikipedia.org/wiki/Brainfuck)
:P
Título: Re: TCL ("ticle")
Enviado por: Njay em 24 de Maio de 2015, 11:02
A substituições. Muito bom :) . Quando tens algo dentro de [] isso é visto pelo TCL como um comando. Se olhares bem vais ver que uma linha onde tens vários [], inclusivé uns dentro de outros, tem como que uma hierarquia/árvore bem definida, e é preciso executar 1º os comandos que são mais "interiores", trabalhando "de dentro para fora", pois os comandos "de fora" dependem dos de "dentro", que são ou contribuem para o seus argumentos. No exemplo que deste,

puts "[llenght $words] palavras"

é preciso 1º invocar o comando llenght (mais "interior"), pois o argumento para o comando puts (o mais "exterior") depende dele. E para invocar o comando llenght é preciso ir buscar o valor da variável words, portanto é, nesta linha toda, aquilo que o interpretador de TCL faz 1º
Assumindo que a variável words tem a lista {um dois três} (uma lista em TCL define-se separando os elementos por espaço e envolvendo tudo em {}), o interpretador de TCL faz o seguinte para executar a linha:

puts "[llenght $words] palavras"
   (vai substituir, na linha, $words pelo valor da variável)
puts "[llenght {um dois três}] palavras"
   (vai substituir, na linha, a chamada ao comando llenght pelo seu retorno)
puts "3 palavras"


Acredito que te faça confusão ver chamadas a funções no meio duma string, especialmente se só conheces linguagens "duras" como o C. É uma questão de hábito. Se isto for bem usado é até pode ser mais fácil de entender, estás a "ir buscar" o que é para imprimir no sitio exacto onde é para imprimir. Mas se quiseres muito, também tens o comando format que gera uma string usando a mesma sintaxe de "format specifiers" do C ;)

puts [format "%d palavras" [llenght $words]]

Quanto ao brainfuck, bom, gostos não se discutem, lol . É uma espécie de assembly, não me parece muito dificil construir um CPU com esse instruction set.
Título: Re: TCL ("ticle")
Enviado por: KammutierSpule em 24 de Maio de 2015, 17:01
Quanto ao brainfuck, bom, gostos não se discutem, lol . É uma espécie de assembly, não me parece muito dificil construir um CPU com esse instruction set.

Era uma piada!
Título: Re: TCL ("ticle")
Enviado por: dropes em 24 de Maio de 2015, 20:04
Quanto ao brainfuck, bom, gostos não se discutem, lol . É uma espécie de assembly, não me parece muito dificil construir um CPU com esse instruction set.

Era uma piada!

Programar só com 8 comandos, então os comentários são lindos, 1000 x assembly  :o
Título: Re: TCL ("ticle")
Enviado por: Njay em 24 de Maio de 2015, 21:37
LOL... eu sei que era uma piada. brainfuck é uma "curiosidade cientifica".
Título: Re: TCL ("ticle")
Enviado por: Njay em 02 de Setembro de 2015, 14:34
Tb dá para brainfluckar um bocado em TCL, por exemplo :) :

set \  \ \ \ \
puts ${ }indentado\ a\ 4 espaços


ou

proc \  n { string repeat \  $n }
puts "[\  8]indentado a 8 espaços"

proc \" * { return \"${*}\" }
puts [\" entreaspas]


TCL é tão "básico" que podemos criar funções (procs) ou variáveis com o nome que quisermos, inclusive com o nome "1 espaço" ou " (1 aspa) como nos casos acima, ou mesmo com o nome de "keywords" da linguagem pois não há ambiguidade na utilização. A \ serve para fazer escape ou para indicar que o caracter branco que se segue não é da categoria "espaços separadores" mas é para ser interpretado como um "item sólido".
Mas vamos desligar o complicador e esquecer estes casos patológicos que ninguém usa :) (os fãs de Perl é que devem gostar :) )

E expressões regulares, quem conhece e usa que levante o braço. Não são uma exclusividade do TCL, existem noutras linguagens, mas é onde mais as uso. Expressões regulares são a 2ª coisa mais útil logo a seguir a saber programar, :D :D
Título: Re: TCL ("ticle")
Enviado por: dropes em 02 de Setembro de 2015, 15:17
Também acredito que quem não saiba programar não vá pegar em TCL (na de conceito).
Pela lógica, o que acho reduzido após as limitações, até que tem alguma piada.
Usado pelos fãs dos PLDs para criar uCs, seria possível criar um que interprete TLC apenas com portas lógicas.
Ainda este mês estive com um PLC só com TTLs + um GAL pelo meio, aquilo fez-me uma confusão desgraçada da imensidão de ICs, estava avariado e o técnico perguntou-me se sabia diagnosticar aquilo... LOL pistas queimadas e tal é para esquecer.
Título: Re: TCL ("ticle")
Enviado por: StarRider em 03 de Setembro de 2015, 22:35

Hum ... pois expressões regulares e p-code não obrigado  ;D

Sou daqueles que ainda nos dias de hoje faz contas de cabeça ao numero
de ciclos por cada llinha/rotina que programo, e mesmo em sistemas não
embebed não sou nada adepto de linguagens interpretadas ou semi complidas
que correm em interpretadores de p-code.

Abraços,
PA