diale.org
Fotografias com efeito Lomo
2010/02/08-14:20:01
|
|
||||
|
|
||||
|
|
Tenho uma Lomo (uma LC-A) já há alguns 9 anos. Gosto dos efeitos descontraídos que se obtêm quando se usam as regras
- Take your camera everywhere you go
- Use it any time – day and night
- Lomography is not an interference in your life, but part of it
- Try the shot from the hip
- Approach the objects of your lomographic desire as close as possible
- Don’t think (william firebrace)
- Be fast
- You don’t have to know beforehand what you captured on film
- Afterwards either 10. Don't worry about any rules
mas tinha pena em não obter o mesmo efeito usando um máquina digital. Ora, para variar, a função em Emacs Lisp usando o ImageMagick que produz esse efeito é este
(defun lomo (source-dir img-file) (let ((img-file-lomo (concat source-dir "lomo-" img-file ))) (shell-command (format "cp %s %s" (concat source-dir img-file) (concat source-dir (concat "lomo-"img-file)))) (shell-command (format "convert -resize 1024x768 %s %s" img-file-lomo img-file-lomo)) (shell-command (format "convert -unsharp 1 %s %s" img-file-lomo img-file-lomo)) (shell-command (format "cp %s %s" img-file-lomo (concat img-file-lomo "-resized"))) (shell-command (format "convert -contrast -contrast %s %s" img-file-lomo img-file-lomo)) (shell-command (format "convert -modulate 100,150 %s %s" img-file-lomo img-file-lomo)) (shell-command (format "composite -compose overlay %s %s %s" (concat source-dir "mask.png") img-file-lomo img-file-lomo)) (shell-command (format "composite -compose multiply %s-resized %s %s" img-file-lomo img-file-lomo img-file-lomo)) (shell-command (format "rm %s-resized" img-file-lomo))))
baseado neste.
Etiquetas: Lomo, Lisp, Emacs, ImageMagick
Script em ELisp para fotos
2010/02/07-08:50:39
Já há muito tempo que andava para fazer este script em ELisp para gerar uma lista de imagens em html.
(let ((img-file-list (directory-files source-dir () "\\.\\(jpg\\|JPG\\|png\\|gif\\)$"))) (while img-file-list (shell-command (format "convert -geometry %sx%s %s %s" 200 200 (concat source-dir (car img-file-list)) (concat source-dir "thumb." (car img-file-list)))) (insert "<literal>") (insert "<a href=\""(concat "./photos/" (car img-file-list))"\">" "<img class=\"photo-album\" src=\"" (concat "./photos/" "thumb." (car img-file-list)) "\"></a>\n") (insert "</literal>") (setq img-file-list (cdr img-file-list))))
Claro que pode ser bastante melhorado, mas para começo não está mal.
Etiquetas: Lisp, Emacs, fotografias, html
Pipes law
2010/02/07-00:19:00
Os modelos de modelação de tráfego mais simples são os chamados
modelos follow-the-leader.

O mais simples corresponde a tomar o valor da aceleração do i-ésimo carro com
sendo proporcional à diferença de velocidades do carro seguinte e a sua
Este modelo não inclui o tempo de reacção do condutor, para o incluir basta
introduzir um tempo de reacção
que reflecte o tempo de reacção, finito, de cada condutor. Obtém-se assim um
modelo de estímulo-resposta (Pipes law) dado pelas equações
A quantidade
mede a sensibilidade ao estímulo. Estas equações pertencem à classe de equações
diferenciais ordinária com atraso cujas soluções para
se tornam instáveis. Prova-se que (Chandler et al., 1958) as variações das
velocidades individuais de cada carro são amplificadas quando
,
dando origem a ondas de pára-arranca e a acidentes.
Etiquetas: tráfego, modelos, matemática, follow-the-leader, Pipes law
Trabalhos práticos de física
2010/02/05-14:40:08



Ref: H. Amorim Ferreira, Dr.Sc., "Trabalhos práticos de física", Livraria Sá da Costa, 1931, 2ª ed.
Etiquetas: física, gotas
Gotas
2010/02/05-10:37:48
As equações que modelam a forma de gotas numa superfície (sinal -) ou suspensas (sinal +) são:
As figuras mostram as soluções que se obtém para os perfis de gotas sobre uma superfície hidrófoba e gotas suspensas.
![]() |
| Gotas sobre uma superfície. |
![]() |
| Gotas suspensas. |
Código em LaTeX para a equações
\begin{eqnarray*} \frac{d \varphi}{d s}&=& \mp 2 z-\frac{\sin \varphi}{r}\\ \frac{d r}{d s}&=& \cos \varphi\\ \frac{d z}{d s}&=& \sin \varphi \end{eqnarray*}
Código em GNU/Octave
clf hold on z=-1 x0=[.001 z 0] t=linspace (0,pi*.9,100); y=lsode ("fu",x0,t); plot(y(:,1),y(:,2)) plot(-y(:,1),y(:,2)) z=-1 x0=[.001 z 0] t=linspace (0,pi/2+.1,100); y=lsode ("fl",x0,t); plot(y(:,1),y(:,2)) plot(-y(:,1),y(:,2)) axis("square") grid on xlabel("r") ylabel("z") print -dsvg "drop.svg"
function xdot=fl(x, t) xdot(1)=cos(x(3)); xdot(2)=-sin(x(3)); xdot(3)=-2*x(2)-sin(x(3))/x(1); endfunction
function xdot=fu(x, t) xdot(1)=cos(x(3)); xdot(2)=-sin(x(3)); xdot(3)=2*x(2)-sin(x(3))/x(1); endfunction
Etiquetas: física, matemática, gotas, equações, LaTeX
Bach + catmap
2010/02/03-13:46:23
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
Animação das sucessivas iterações do catmap aplicada a uma imagem de Bach (50x50). O primeiro retorno ocorre na iteração 151.
![]() |
| 151 iterações |
Etiquetas: JSBach, catmap
Monte Carlo Pi
2010/02/03-10:58:54
![]() |
| Distribuição aleatória de pontos. |
Uma das formas mais engraçadas de calcular uma aproximação ao número PI é a de considerar um círculo de raio um inscrito no quadrado de lado dois; gerar um conjunto de pontos aleatoriamente com coordenadas dentro do quadrado, e se o ponto estiver dentro do círculo é contado, no caso de cair fora não se conta. O número de pontos que cai dentro do círculo a dividir pelo número total de pontos vezes quatro é aproximadamente igual a 3.1415926... Como se pode verificar no gráfico seguinte da quantidade referida em função do número de pontos; a linhas vermelha é o valor 3.1415926...
![]() |
| Convergência para o valor de Pi. |
O código seguinte em GNU/Octave faz todo o trabalho:
clf; hold on axis square u=[0:.01:2*pi]; plot(cos(u),sin(u),'r-') n=500; x=2*rand(n,2)-1; px=[]; j=0; for i=1:n if sumsq(x(i,:))<1 plot(x(i,1),x(i,2),'o') j=j+1; px(j)=4*j/i; else endif; endfor; [j i] print -dpng "circPI.png" clf; hold on; plot(px,'-') plot([1:length(px)],pi*ones(1,length(px)),'r-') print -dpng "circPIx.png"
Etiquetas: Pi, Monte Carlo, matemática
Pepper map
2010/02/03-10:20:55
![]() |
| 121 iterações pela aplicação "cat map" de Arnold |
É necessário ter alguma paciência para as ver todas...
A aplicação em GNU/Octave é esta:
function y=catmap(x,n) [nx ny]=size(x); for i=1:nx for j=1:ny y(i,j)=x(1+mod(i+j,n),1+mod(i+2*j,n)); endfor; endfor; endfunction;
Sempre desejei fazer uma figura destas!
P. S.
Já está na Wikipedia em: en.wikipedia.org/wiki/Arnold%27s_cat_map
Etiquetas: cat map, Arnold, matemática
Power tower
2010/02/02-11:31:25
![]() |
| Hiper-superfícies de nível das sucessivas potências de z |
z = x + i y.
Código em GNU/Octave
clf; n=3, m=3; [x y]=meshgrid([-2:.05:2],[-2:.05:2]); z=x+1i*y; w=z.^z; subplot(n,m,1) contour(x,y,real(w),-2:.05:2) axis square subplot(n,m,2) contour(x,y,imag(w),-2:.05:2) axis square subplot(n,m,3) contour(x,y,abs(w),-2:.05:2) axis square subplot(n,m,4) contour(x,y,real(w.^z),-2:.05:2) axis square subplot(n,m,5) contour(x,y,imag(w.^z),-2:.05:2) axis square subplot(n,m,6) contour(x,y,abs(w.^z),-2:.05:2) axis square subplot(n,m,7) contour(x,y,real(w.^w),-2:.05:2) axis square subplot(n,m,8) contour(x,y,imag(w.^w),-2:.05:2) axis square subplot(n,m,9) contour(x,y,abs(w.^w),-2:.05:2) axis square
Etiquetas: matemática, Lambert, power tower
i9 = inove
2010/02/02-11:31:18
Nunca fui um apaixonado pela tecnologia, sempre gostei mais do que estava dentro de um gadget do que do gadget propriamente dito. Isto faz de mim um hacker 1 e não um techie2. Não tenho um iPhone mas gostava de ter um Openmoko pelas capacidades e possibilidades que encerra em si mesmo. Num artigo publicado na sua crónica semanal do Expresso (30/Jan/2010), Nuno Crato (NC) revela: "sou um teckie". Na verdade deveria querer dizer techie.
Se é verdade que não se espera que os alunos aprendam mais só porque o professor gosta de gadgets tecnológicos, é meio caminho andado, para que aprendam, que o professor goste de saber como funcionam esses gadgets. E é esta pequena diferença que faz com que a introdução de tecnologia no funcionamento das aulas resulte, e o ser hacker em vez de teckie faz muita diferença.
Talvez seja esta a diferença entre o sucesso das mesmas experiências de ensino activo feitas por físicos como Mazur e aquelas desenvolvidas por Steenhuis, o SABER como as coisas funcionam. É mais razoável duvidar da universalidade dos matemáticos do que da matemática. Ser hacker ou techie, eis a questão?
1. "A person who enjoys exploring the details of programmable systems and stretching their capabilities, as opposed to most users, who prefer to learn only the minimum necessary." (http://catb.org/jargon/)
2. "A person who displays a great, sometimes even obsessive, interest in technology, high-tech devices, and particularly computers." (http://en.wikipedia.org/wiki/Techie)
Etiquetas: Notícias, tecnologia, Jornal Expresso, Nuno Crato, hacker, techie
As raízes de Lisp
2010/02/02-11:31:09
(revisão da tradução do artigo de Paul Graham de http://www.paulgraham.com/rootsoflisp.html para português e agora em HTML)
Em 1960 John McCarthy publicou um artigo espantoso no qual fez para a programação o mesmo que Euclides fez para a geometria (Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I, Communications of the ACM 3:4, April 1960, pp. 184-195). Mostrou como construir, dado uma mão cheia de operadores simples e uma notação para funções, uma linguagem de programação completa. Denominou-a de Lisp, abreviatura de List Processing, porque a ideia chave era usar uma estrutura simples de dados chamada lista para o código e para os dados propriamente ditos.
O que McCarthy descobriu não foi só aquilo que se tornou um marco para a história dos computadores, e que vale por si só, mas um modelo para o qual convergem, no nosso tempo, as linguagens de programação. Parece-me a mim que existem apenas dois tipos de modelos realmente escorreitos e consistentes: o modelo do C e o de Lisp. Estes dois modelos parecem estar bem alto com baixios pantanosos entre si. Com o aumento da capacidade dos computadores as linguagens de programação que têm surgido convergem para o modelo de Lisp. A receita mais popular para construir uma nova linguagem de programação nos últimos 20 anos consiste em considerar o modelo de C e adicionar partes do modelo de Lisp, tais como runtime typing e garbage collection.
Neste artigo tentarei explicar de uma maneira simples o que McCarthy descobriu. O objectivo não é só o de aprender um resultado teórico importante que alguém descobriu à quarenta anos atrás, mas mostrar para onde tendem as linguagens de programação. A coisa pouco usual do Lisp — de facto, a qualidade que o define — é que se escreve a si mesmo. Para se entender o que McCarthy quer dizer com isto, vamos repetir os seus passos, traduzindo a sua notação matemática em código Common Lisp.
Sete operadores primitivos
Para começar, definimos o que se entende por expressão. Uma expressão
é, alternativamente, um átomo, que é uma sequência de letras (por
exemplo: foo), ou uma lista de zero ou mais expressões,
separadas por espaços em branco e enquadradas por parêntesis. De seguida
mostram-se várias expressões:
foo () (foo) (foo bar) (a b (c) d)A última expressão é uma lista de quatro elementos, o terceiro dos quais é uma lista de um elemento.
Em aritmética a expressão 1+1 tem o valor 2. Uma expressão válida de Lisp
também tem um valor. Se uma expressão e tem o valor v dizemos que
e return v. O passo seguinte é definir que tipo de expressões podem existir e
que tipo de valor têm.
Se uma expressão é uma lista, chamamos ao primeiro elemento da lista
operador, e os restantes elementos argumentos. Vamos, no que
se segue, definir sete operadores primitivos (no sentido de axiomas):
quote, atom, eq, car, cdr, cons, e
cond.
quote
(quote x ) retorna x. Para uma leitura mais simples abreviamos (quote x) por 'x.
> (quote a) a > 'a a > (quote (a b c)) (a b c)
atom
(atom x) retorna o átomo t se o valor de x é um
átomo ou a lista vazia (). Em Lisp convenciona-se usar o átomo t
como representando o valor lógico verdade, e a lista vazia como o valor lógico
falso.
> (atom 'a) t > (atom '(a b c) () > (atom '()) tAgora que temos um operador cujo argumento é avaliado podemos mostrar para que é que
quote serve. Através de quoting (Nota do tradutor: não
vou traduzir quote por citação de modo a que não se perca o sentido em
Inglês da frase) uma lista protegemo-la de ser avaliada. Uma lista
unquoted como argumento de um operador como por exemplo atom é
tratada como código:
> (atom (atom ' a)) > tenquanto uma lista quoted é tratada como uma mera lista, neste caso uma lista de dois elementos
> (atom '(atom 'a)) ()
Isto corresponde à maneira de usar citações em Inglês (Nota do tradutor: ver o que se passa em PT). Cambridge é uma cidade de Massachusetts que contém cerca de 90.000 habitantes. "Cambridge" é uma palavra de nove letras.
quote pode parecer um conceito estranho, não há muitas línguas com coisa
semelhante. Está intimamente ligado a uma das características distintivas de
Lisp: o código e os dados são feitos de uma mesma estrutura, e o operador
quote é uma maneira de distinguir os dois.
eq
(eq x y) retorna t se os valores de x e y
são o mesmo átomo ou ambos uma lista vazia, e
()caso contrário.
> (eq 'a 'a) t > (eq 'a 'b) () > (eq '() '()) t
car
(car x) espera que o valor de x seja uma lista, e
retorna o seu primeiro elemento.
> (car '(a b c)) a
cdr
(cdr x ) espera que o valor de x seja uma lista, e
retorna o resto da lista a seguir do primeiro elemento.
> (cdr '(a b c)) (b c)
cons
(cons x y) espera que o valor de y seja uma lista, e
retorna uma lista contendo o valor de
xseguido dos elementos valor dey.
> (cons 'a '(b c)) (a b c) > (cons 'a (cons 'b (cons 'c '()))) (a b c) > (car (cons 'a '(b c))) a > (cdr (cons 'a '(b c))) (b c)
cond
(cond (p1 e1) ... (pn en)) e avaliado da seguinte forma. As expressões p são
avaliadas até que uma retorna t. Quando uma é encontrada, o valor
correspondente da expressão e é retornado como o valor total da expressão cond.
> (cond ((eq 'a 'b) 'first)
((atom 'a) 'second))
second
Os argumentos de cinco dos sete operadores primitivos anteriores são avaliados quando uma expressão com esse operador é avaliado. Chamaremos a esses operadores funções.
Denotando funções
De seguida definimos a notação para a descrição de funções.
Uma função é representada por
((lambda (p1 ... pn) e) a1 ... an), onde p1 ... pn são átomos (chamados
parâmetros) e e é uma expressão. Uma expressão cujo primeiro elemento
é uma expressão
((lambda (p1 ... pn) e) a1... an)
é chamada de função e o seu valor é calculado da seguinte forma. Cada
expressão ai é avaliada. Depois e é avaliada. Durante a avaliação de e, o
valor de qualquer ocorrência de qualquer um dos pi é o valor do ai
correspondente na mais recente chamada da função.
> ((lambda (x) (cons x '(b))) 'a) (a b) > ((lambda (x y) (cons x (cdr y))) 'z '(a b c)) (z b c)
Se uma expressão tem como primeiro elemento um átomo f que não é um dos
operadores primitivos
(f a1 ... an)
e o valor de f é uma função
(lambda (p1 ... pn)e) então o valor da expressão é o valor de
((lambda( p1 ... pn)e) a1 ... an).
Por outras palavras, os parâmetros podem ser usados com expressões assim como argumentos
> ((lambda (f) (f '(b c))) '(lambda (x) (cons 'a x)))
Existe outra notação para funções que permite que uma função se chame a si
própria, permitindo assim de uma forma conveniente definir funções recursivas
(definidas por recorrência) (não é necessário definir uma nova notação
para isto. Poderia-mos definir funções recursivas com nossa notação através de
do construtor Y. McCarthy poderia não conhecer o Y construtor na altura em
que escreveu o artigo; de qualquer modo, a notação label é de leitura
mais simples).
A notação label f (lambda (p1 ... pn) e)
denota a função que se comporta como
lambda (p1 ... pn) e), com a propriedade adicional que uma ocorrência de f dentro de e
avaliará a expressões label, como se f fosse um parâmetro da função.
Suponhamos que queremos construir uma função subst(x y z), que
toma uma expressão x, um átomo y e uma lista z, e retorna uma lista tipo
z onde cada instância y (em qualquer nível) é substituída em z por x.
> (subst 'm ' b '(a b (a b c) d)) (a m (a m c) d)
Podemos escrever esta função como
(label subst (lambda (x y z) (cond ((atom z) (cond (eq z y) x) ('t z)) ('t (cons (subst x y (car z)) (subst x y (cdr z)))))))
Vamos abreviar f (label f (lambda (p1 ... pn)e)) por
(defun f(p1 ... pn e))
e logo ficamos com
(defun subst (x y z) (cond ((atom z) (cond ((eq z y) x) ('t z))) ('t (cons (subst x y (car z)) (subst x y (cdr z))))))
Acidentalmente, podemos ver que uma condição definida por omissão numa expressão
cond. Uma condição cujo primeiro elemento é 't é sempre
executada. Assim (cond( x y)('t z)) é equivalente
aquilo que se poderia escrever numa outra linguagem com sintaxe if x then y else z.
Algumas funções
Agora que temos uma maneira de expressar funções, podemos definir novas em
termos dos nossos sete operadores primitivos. Em primeiro lugar é conveniente
introduzir algumas abreviaturas. Vamos usar cxr, como uma
sequência de a ou d, correspondendo a composição de car e
cdr. Por exemplo (cadr e) é uma abreviatura de
(car (cdr e)), que retorna o segundo elemento de e.
> (cadr '((a b) (c d) e)) (c d) > (caddr '((a b) (c d) e)) e > (cdar '((a b) (c d) e)) (b)
Vamos também usar (list e1 ... en) para significar
(cons e1 (cons e2 (...(cons en'())))).
> (cons 'a (cons 'b (cons 'c '()))) (a b c) > ( list 'a 'b 'c) (a b c)
Vamos definir novas funções. Alterei os nomes das funções que se seguem introduzindo um ponto o fim. Isto distingue as funções primitivas daquelas definidas à custa delas, e também evita confusões com aquelas que já existem em Commnon Lisp.
null
(null. x) testa se o seu argumento é uma lista vazia.
(defun null. (x) (eq x '())) > (null. 'a) () > (null. '()) t
and
(and. x y) retorna t se ambos os argumentos o são, () caso contrário.
(defun and. (x y) (cond (x (cond (y't) ('t '()))) ('t '()))) > (and. (atom 'a) (eq 'a 'a)) t > (and. (atom 'a) (eq 'a 'b)) ()
not
(not. x) retorna t se o seu argumento é (), e () se o seu argumento é t.
(defun not. (x) (cond (x '()) ('t 't))) > (not. (eq 'a 'a)) () > (not. (eq 'a 'b)) t
append
(append. x y) toma duas listas e retorna a sua concatenação.
(defun append. (x y) (cond ((null. x) y) ('t (cons (car x) (append. (cdr x) y))))) > (append.'(a b) '(c d)) (a b c d) > (append. '() '(c d)) (c d)
pair
(pair. x y) toma duas listas com o mesmo comprimento e retorna uma lista de
listas de dois elementos, com pares de formados com elementos de cada uma das listas iniciais.
(defun pair. (x y) (cond ((and. (null. x) (null. y)) '()) ((and. (not. (atom x)) (not. (atom y))) (cons (list (car x) (car y)) (pair. (cdr x) (cdr y)))))) > (pair. '(x y z) '(a b c)) ((x a) (y b) (z c))
assoc
(assoc. x y) toma um átomo x e uma lista y da forma
criada por pair., e retorna o segundo elemento da primeira lista de y
que contém
xcomo primeiro elemento.
(defun assoc. (x y) (cond ((eq (caar y) x) (cadar y)) ('t (assoc. x (cdr y))))) > (assoc. 'x '((x a) (y b))) a > (assoc. 'x '((x new) (x a) (y b))) new
A surpresa
Assim conseguimos definir funções que concatenam listas, substituem uma expressão por outra, etc. Talvez seja apenas uma notação elegante, e depois? Agora chega a surpresa. Podemos também escrever uma função que funciona como um interpretador da nossa linguagem: uma função que tem como argumento uma expressão de Lisp, retornando o seu valor. Aqui está ela:
(defun eval. (e a) (cond ((atom e) (assoc. e a)) ((atom (car e)) (cond ((eq (car e) 'quote) (cadr e)) ((eq (car e) 'atom) (atom (eval. (cadr e) a))) ((eq (car e) 'eq) (eq (eval. (cadr e) a) (eval. (caddr e) a))) ((eq (car e) ' car) (car (eval. (cadr e) a))) ((eq (car e) 'cdr) (cdr (eval. (cadr e) a))) ((eq (car e) 'cons) (cons (eval. (cadr e) a) (eval. (caddr e) a))) ((eq (car e) 'cond) (evcon. (cdr e) a)) ('t (eval. (cons (assoc. (car e) a) (cdr e)) a)))) ((eq (caar e) 'label) (eval. (cons (caddar e) (cdr e)) (cons (list (cadar e) (car e)) a))) ((eq (caar e) 'lambda) (eval. (caddar e) (append. (pair. (cadar e) (evlis. (cdr e) a)) a))))) (defun evcon. (c a) (cond ((eval. (caar c) a) (eval. (cadar c) a)) ('t (evcon. (cdr c) a)))) (defun evlis. (m a) (cond ((null. m) '()) ('t (cons (eval. (car m) a) (evlis. (cdr m) a)))))
A definição de eval. é bastante maior do que as definições que vimos
anteriormente. Vamos estuda-la em mais detalhe e por partes.
A função tem dois argumentos: e, a expressão a ser avaliada, e
a, uma lista que representa os valores que os átomos que aparecem como
parâmetros das chamadas das funções. Esta última lista é chamada de
ambiente, e é da forma da listas criadas por pair. e
assoc..
A parte principal da função eval. é a expressão cond. que tem
quatro condições (clausulas). A avaliação de uma expressão depende de qual é
usada. A primeira clausula trata de átomos. Se e é um átomo, procuramos o
seu valor no ambiente:
> (eval. 'x '((x a) (y b))) a
A segunda clausula de eval. é um outro cond que trata de
expressões da forma (a ...), onde a é um átomo. Estas incluem todos os
tipos de operadores primitivos, e há uma clausula para cada um deles.
> (eval. '(eq 'a 'a) '())
t
> (eval. '(cons x '(b c))
'((x a ) (y b)))
(a b c)
Todos eles (excepto quote) chamam eval. para determinar o valor
dos seus argumentos.
As duas últimas clausulas são mais complicadas. Para avaliar uma expressão
cond chamamos uma função subsidiária evcon., que percorre as
clausulas de uma forma recursiva, procurando o primeiro elemento que retorna
t. Quando o encontra tal clausula retorna o valor do segundo elemento.
> (eval. '(cond ((atom x) 'atom)
('t 'list))
'((x '(a b))))
list
A parte final da segunda clausula de eval. trata das chamadas das funções
que são passadas como parâmetros. Funciona substituindo o átomo pelos seu valor
(que deverá ser uma expressão lambda ou label)) avaliando o
resultado da expressão. Assim
(eval. '(f '(b c))
'((f lambda (x) (cons 'a x))))
\end{verbatim}
passa a ser
\begin{verbatim}
(eval. '((lambda (x) (cons 'a x)) '(b c))
'((f (lambda (x) (cons 'a x)))))
que retorna (a b c).
As duas últimas clausulas de eval. tratam de chamadas de funções para as
quais o primeiro elemento da lista é uma expressão lambda ou
label. Uma função label é avaliada empurrando o nome da função e a
própria função para o ambiente, e depois chamando eval. numa expressão
onde a expressão lambda interior é substituída pela expressão
label. Isto é,
(eval. '((label firstatom (lambda (x) (cond ((atom x) x) ('t (firstatom (car x)))))) y) '((y ((a b) (c d)))))fica
(eval. '((lambda (x) (cond ((atom x) x) ('t (firstatom (car x))))) y) '((firstatom (label firstatom (lambda (x) (cond ((atom x) x) ('t (firstatom (car x))))))) (y ((a b) (c d)))))
que no fim retorna a.
Finalmente, uma expressão da forma
((lambda (p1 ... pn) e) a_1 ... a_n), é avaliada chamando em primeiro lugar
evlis. de modo a obter uma lista de valores
( v_1 ... v_n) dos argumentos (a_1 ... a_n), avaliando e
com (p1 v1) ... (pn vn) appended ao ambiente.
Assim
(eval. '((lambda (x y) (cons x (cdr y)))
'a
'(b c d))
'())
fica
(eval. '(cons x (cdr y))
'((x a) (y (b c d))))
que no fim retorna (a c d).
Aftermath
Agora que percebemos como é que eval funciona, voltemos atrás para
perceber qual é o seu significado. O que aqui temos é um modelo muito elegante
para computação. Usando apenas quote, atom, car,
cdr, cons e cond, podemos definir a função eval.,
que implementa a nossa linguagem de programação, usando-a depois para construir
qualquer outra função que queiramos.
Como é claro, na altura já existiam modelos de computação — o mais notável exemplo sendo as máquinas de Turing. Mas os programas das máquinas de Turing não são muito edificantes de se ler. Se queremos uma linguagem para descrever algoritmos precisamos de algo mais abstracto, este foi um dos objectivos de McCarthy ao definir Lisp.
A linguagem definida em 1960 tinha muitas omissões. Não tinhas
side-effects, nem execução sequencial (que apenas é útil com o anterior),
sem números (é possível fazer cálculos de aritmética no Lisp de 1960 de
McCarthy, usando, por exemplo, uma lista de n átomos para representar um
número n) e dynamic scope. Todas estas limitações podem ser
remediadas, surpreendentemente, com um pouco de código adicional. Isto mesmo
foi mostrado por Steele e Sussman num famoso artigo intitulado "The Art
of the Interpreter" (Guy Lewis Steele, Jr. and Gerald Jay Sussman,
"The Art of the Interpreter, or the Modularity Complex (Part Zero, One and
Two)", MIT AI Lab Memo 453, May 1978.
O entendimento do eval de McCarthy não é só perceber um patamar da
história das linguagens. Estas ideias são ainda hoje parte do núcleo semântico
do Lisp. Não é tanto o que McCarthy desenhou ou o que descobriu. Não é uma
linguagem intrinsecamente para a IA ou para qualquer outra tarefa. É aquilo que
obtemos quando tentamos axiomatizar a computação.
Com o passar do tempo, a linguagem média de programação (a linguagem usada pelo
programador médio) tem-se aproximado do Lisp. Assim ao perceber eval
estamos a perceber o que poderá ser o modelo principal de computação do futuro.
Etiquetas: Lisp, tradução, Paul Graham
A linguagem como um virus
2010/02/02-11:24:45
Aqui e aqui tratei de parte deste tópico.
O que é esta entidade estranha, a linguagem, e de onde é que veio? O que é ninguém o diz, que evoluiu apenas, de modo a incorporar as propriedades daquilo a que chamamos de linguagem. Coisa atribuída anteriormente, e por engano, ao cérebro. De onde veio? Qual a sua origem? Não interessa porque depois do seu aparecimento o mundo das linguagens evoluiu espontaneamente, através da evolução natural, processada fora do cérebro humano. Tornou-se, por isto, na coisa mais bem adaptada às pessoas; tal qual parasitas e hospedeiros, presas e predadores, num ciclo familiar de co-evolução; ou então vírus, usando uma analogia mais exacta. Mas ninguém acreditaria, ou proporia, que o sistema visual de um insecto ou mamífero se desenvolveria espontaneamente fora de qualquer um deles, por uma mutação rápida, agarrando-se depois a um hospedeiro, providenciando as capacidades visuais de moscas ou ratos.
Etiquetas: linguagem, natureza, Chomsky
Literate programming
2010/02/02-11:24:45
Tenho andado a ler o artigo de D. Knuth intitulado Literate programming. A ideia
principal consiste na percepção de que o acto de construir um programa de
computador e a construção da documentação são duas coisas indissociáveis; Knuth
denominou a relação entre o programa de computador e a documentação de WEB.
O termo WEB foi escolhido porque, diz Knuth, era a única palavra em inglês com
três letras que ainda não tinha sido usada para designar algo relacionado com
computadores. Pode parecer estranho nos tempos que correm porque web é hoje a
palavra que mais gente relaciona com computadores mas em 1980 (?-confirmar data)
não havia ainda sombra de que a WWW alguma vez existisse.
A ideia subjacente a toda a construção do WEB system é a mudança de paradigma do
acto de programar; em vez de imaginar que a principal tarefa inerente ao acto de
programar é produzir um conjunto de instruções para serem executadas por um
computador, passamos a explicar a um ser humano aquilo que queremos que um
computador faça. Isto é conseguido através da construção de uma obra literária
que incluirá num só sítio a documentação e as instruções a serem executadas por
um computador.
O argumento de plausibilidade do sistema WEB de Knuth consiste em mostrar em
como o conceito de programação estruturada levou os programadores a escreverem
bons e melhores programas, fáceis de ler, de explicar e manter durante longos
períodos de tempo, mas que não é inteiramente satisfatório; claro que se
programa para um computador, mas a transmissão do conhecimento que um programa
em si mesmo encerra é mais útil a outro ser humano do que propriamente para um
computador e neste sentido uma obra literária talvez seja a melhor forma de
transmissão de conhecimento entre humanos. Será? Knuth compara o programador a
um ensaísta cujo estilo e excelência na sua exposição permitem a introdução no
texto dos nomes e significado das variáveis usadas no programa de forma a que
seja compreensível para um outro ser humano usando uma cuidada mistura de
métodos formais e informais que se reforçam entre si.
O acto de programar é uma actividade muito pessoal, cada programador tem um estilo próprio e o resultado depende muito do autor. Cada autor escreve um programa da forma que acha que deve ser escrito.
A abordagem de Knuth consiste em tornar a relação entre o código e a
documentação numa dualidade. De um mesmo texto, em texto WEB, o utilizador
poderá extrair dois conteúdos: a primeira linha de processamento consiste no
weaving the web que produz um documento que descreve o programa de uma forma
clara e facilitando a sua manutenção; a segunda corresponde ao tangling the
web, e produz o código-máquina do programa. O código e a sua documentação
derivam assim de uma mesma fonte (source), garantindo a sua consistência.
Knuth afirma mesmo que o termo Literate programming contém alguma maldade. Durante os anos 70 todos os programadores foram forçados a escrever programas de uma forma estruturada, obrigando-se a reescrever os programas moralmente repreensíveis que não estivessem formatados na moral vigente; de modo a que a culpa controlasse os ímpetos menos estruturados. O termo "programação literária" tem exactamente o mesmo objectivo, introduzir uma moral irrepreensível no acto da escrita de programas de computador; certamente ninguém quererá escrever um programa de computador aliterado.
Etiquetas: Linguagem de programação, web, lisp, C, Knuth
Sumatório: imperativo vs funcional
2010/02/02-11:24:45
Duas formas de fazer a mesma coisa em Emacs Lisp, a primeira de uma forma imperativa, a segunda funcional; implementam a soma de um vector.
A primeira: forma imperativa
(defun sum (x) "Sum of elements of X." (let ((i 0) (aux 0)) (while (< i (length x)) (setq aux (+ aux (nth i x)) i (1+ i))) aux))
A segunda: forma funcional
(defun sum (x) "Sum of elements of X." (cond (x (+ (car x) (sum (cdr x)))) (t 0)))
Mais bonita, esta última!
Etiquetas: Emacs, Lisp, matemática, programação funcional, programação imperativa, programação
Revenge of the nerds
2010/02/02-11:24:45
Em 2002 Paul Graham escreveu um artigo intitulado "Revenge of the Nerds" que, entre outras coisas, fala das vantagens do uso de Lisp e o que o torna diferente das outras linguagens de programação. O que me levou até este artigo foi aquilo de que se trata no apêndice, i.e., sobre o poder de uma linguagem de programação.
As an illustration of what I mean about the relative power of programming languages, consider the following problem. We want to write a function that generates accumulators— a function that takes a number n, and returns a function that takes another number i and returns n incremented by i. (That's incremented by, not plus. An accumulator has to accumulate.)
Em Common Lisp a função que faz isto é dada por
(defun foo (n) (lambda (i) (incf n i)))Para ver como funciona põe-se
> (setq a (foo 3))
#<FUNCTION :LAMBDA (I) (INCF N I)>
> (funcall a 1)
4
Fui ver então se a mesma função foo, definida anteriormente, funciona em Emacs
Lisp. Depois de (funcall a 1) o resultado é este:
Debugger entered--Lisp error: (void-variable n) (+ n i) (setq n (+ n i)) (incf n i) (lambda (i) (incf n i))(1) funcall((lambda (i) (incf n i)) 1) eval((funcall a 1)) eval-last-sexp-1(nil) eval-last-sexp(nil) call-interactively(eval-last-sexp
Aparentemente a variável n é considerada como local na definição de foo, mas
isto não faz sentido nenhum. É um
bug acidental ou propositado do dialecto de Lisp que corre no Emacs?
Email enviado para a mailing list do Emacs. Novidades aqui, mais tarde.
Já recebi a resposta da mailing list. Aqui está ela:
Should not the function foo in Common Lisp work with Emacs Lisp?
(defun foo (n) (lambda (i) (incf n i)))
No, that won't work because emacs has no lexical scoping and that code is a closure. See the elisp manual:
,----[ (info "(elisp)Extent") ] | To illustrate this, the function below, `make-add', returns a | function that purports to add N to its own argument M. This would work | in Common Lisp, but it does not do the job in Emacs Lisp, because after | the call to `make-add' exits, the variable `n' is no longer bound to | the actual argument 2. | | (defun make-add (n) | (function (lambda (m) (+ n m)))) ; Return a function. | => make-add | (fset 'add2 (make-add 2)) ; Define function `add2' | ; with `(make-add 2)'. | => (lambda (m) (+ n m)) | (add2 4) ; Try to add 2 to 4. | error--> Symbol's value as variable is void: n | | Some Lisp dialects have "closures," objects that are like functions | but record additional variable bindings. Emacs Lisp does not have | closures. `----
Mais uma resposta da mailing list:
Emacs Lisp has dynamic scoping, not lexical scoping. If you want to emulate lexical scoping, (require 'cl-macs) and use lexical-let:
(defun foo (n) (lexical-let ((lexn n)) (lambda (i) (incf lexn n))))
Etiquetas: Lisp, Emacs, Paul Graham, bug
Citações de "O homem sem qualidades" de R. Musil
2010/02/02-11:24:45
"E como a posse de qualidades pressupõe uma certa alegria pela sua realidade, é legitimo prever que alguém a quem falte o sentido de realidade até em relação a si próprio possa um belo dia, sem saber como, encarar-se como um homem sem qualidades." R. Musil, HsQ, pg. 43
"... quando andava pelas ruas - muito mais excitante era ainda andar de eléctrico!- costumava contar, e isto já levava anos, os segmentos de recta nas grandes letras das tabuletas das lojas (o A, por exemplo, tinha três, o M quatro), dividindo o seu número pelo número de letras. Até agora, a média mantinha-se invarialvelmente nos dois e meio.É claro que este número não era definitivo, e podia mudar com cada nova rua; assim, cada divergência trazia grandes preocupações, e cada coincidência grandes alegrias, o que correspondia aos efeitos catárticos atribuídos à tragédia. Mas quando somos nós a contar as letras, constataremos... que a divisibilidade por três é um caso raro, pelo que a maior parte das tabuletas deixam em nós uma sensação de clara insatisfação, à excepção daquelas que apresentam várias letras de grande intensidade, por exemplo WEM, e que em qualquer circunstância nos deixam particularmente felizes. E que consequências é que isto tem?... Nada mais nada menos do que isto: o Ministério da Saúde Pública deveria editar uma portaria com a finalidade de bonificar, na escolhas dos nomes das firmas, sequências de letras com quatro segmentos de recta, reprimindo na medida do possível as que só têm uma linha, como o O, o I e o C, já que a sua pobreza de traços é causadora de grande tristeza!" R. Musil, HsQ, pg. 465
Implementei então esta última actividade, em Emacs Lisp, para a contagem do número médio de traços das letras em palavra ou frases.
Implementação em Emacs Lisp
Aqui ficam as funções em Lisp que calculam ao número médio de segmentos de uma frase/texto.
(setq list-n (list '(" " . 0.0) '("A" . 3.0) '("B" . 3.0) '("C" . 1.0) '("D" . 2.0) '("E" . 4.0) '("F" . 3.0) '("G" . 2.0) '("H" . 3.0) '("I" . 1.0) '("J" . 1.0) '("K" . 3.0) '("L" . 2.0) '("M" . 4.0) '("N" . 3.0) '("O" . 1.0) '("P" . 2.0) '("Q" . 2.0) '("R" . 3.0) '("S" . 1.0) '("T" . 2.0) '("U" . 1.0) '("V" . 2.0) '("W" . 4.0) '("X" . 4.0) '("Y" . 3.0) '("Z" . 3.0) '("a" . 3.0) '("b" . 3.0) '("c" . 1.0) '("d" . 2.0) '("e" . 4.0) '("f" . 3.0) '("g" . 2.0) '("h" . 3.0) '("i" . 1.0) '("j" . 1.0) '("k" . 3.0) '("l" . 2.0) '("m" . 4.0) '("n" . 3.0) '("o" . 1.0) '("p" . 2.0) '("q" . 2.0) '("r" . 3.0) '("s" . 1.0) '("t" . 2.0) '("u" . 1.0) '("v" . 2.0) '("w" . 4.0) '("x" . 4.0) '("y" . 3.0) '("z" . 3.0) '("á" . 4.0) '("á" . 4.0) '("à" . 4.0) '("é" . 5.0) '("í" . 2.0) '("ó" . 2.0) '("ú" . 2.0) '("â" . 5.0) '("ã" . 5.0) '("ê" . 6.0) '("ô" . 3.0) '("Á" . 4.0) '("Â" . 4.0) '("À" . 4.0) '("É" . 5.0) '("Í" . 2.0) '("Ó" . 2.0) '("Ú" . 2.0) '("Â" . 5.0) '("Ã" . 5.0) '("Ê" . 6.0) '("Ô" . 3.0) '("." . 0.0) '("," . 0.0) '(":" . 0.0) '(";" . 0.0) '("-" . 1.0) '("ç" . 2.0))) (defun string-to-strings (s) "Convert a string into a list of strings." (let ((i (- (length s) 1)) (l '())) (while (<= 0 i) (setq l (cons (aref s i) l) i (- i 1))) (mapcar (lambda (x) (char-to-string x)) l))) (defun get-number-straight-lines-letter (s) (cdr (assoc (car s) list-n))) (defun get-number-straight-lines-list-of-letters (s) (if (not s) 0 (if (stringp (car s)) (+ (get-number-straight-lines-letter s) (get-number-straight-lines-list-of-letters (cdr s))) (get-number-straight-lines-list-of-letters (cdr s))))) (defun number-straight-lines-sentence (s) (/ (get-number-straight-lines-list-of-letters (string-to-strings s)) (length s)))
Alguns exemplos
A expressão "Esta última sugestão" tem 2.05 segmentos, enquanto o meu nome "Tiago" tem 1.8. Segue uma pequena tabela (sugestões para mais palavras são bem vindas):
| Palavra | Nº |
|---|---|
| Musil | 1.8 |
| Bach | 2.5 |
| diale | 2.4 |
| qualidades | 2.1 |
| Sócrates | 2.125 |
Etiquetas: Musil, homem sem qualidades, citações
Quadricas
2010/02/02-11:24:45
![]() |
| Parabolóide hiperbolico. |
Etiquetas: matemática, quadricas
QR code
2010/02/02-11:24:45
Isto é o QR code

para o diale.org
Etiquetas: QR, code, diale.org
Preferências
2010/02/02-11:24:45
A construção de poemas aleatórios tem, ao contrário da prosa, uma boa aceitação. Uma das razões está relacionada com o facto de os algoritmos que os geram produzirem textos com uma fraca conectividade semântica. Como é atribuída ao poeta a autorização de quebrar algumas regras somos naturalmente levados a interpretar o texto como se as regras quebradas fossem poesia e não a outra coisa que são. Aceitamos melhor a metáfora como alternativa ao sem-sentido. Ainda bem.
P. S.
Acreditem ou não, isto foi escrito ao som do Concerto Suite para guitarra eléctrica e orquestra em Mi menor op. 1 de Yngwie Malmsteen. Lembra qualquer coisa de JSBach, mas ainda não descobri o quê!?
Etiquetas: poemas aleatórios, Lisp, Bach, Malmsteen
Mais alguns exemplos de poemas concretos
2010/02/02-11:24:45
Indefinido de Liberto Cruz
Despossuindo de Liberto Cruz
Pouca-terra
Etiquetas: Poesia concreta, Liberto Cruz
Palavras chave: página pessoal, blog, vida-exacta

![Validate my RSS feed [Valid RSS]](valid-rss.png)
































