Meu workflow em Clojure

Há algum tempo postei sobre LightTable e Clojure, e embora minha opinião sobre essa nova forma de programar não tenha mudado, algumas coisas infelizmente mudaram bastante. A primeira foi o esquema de plug-ins do LightTable. Ele tem poucos plug-ins úteis, e alguns dos que existem não funcionam com as versões Read more…

Clojure, gentilmente

Nos últimos posts eu percebi que me empolguei um pouco no assunto Clojure. Então, esse é um post para tentar começar com a linguagem, ao invés de tentar entender detalhes. Vou atualizar os outros posts para indicar que esse é o primeiro da série, apesar de estar por último…

Clojure é uma linguagem baseada em LISP. Isso, pra muita gente, significa parênteses intermináveis e sintaxe horripilante. Mas não é bem assim.

Os parênteses são um desafio, um degrau. Então ignore-os por enquanto. Use um editor com suporte ao parinfer – Atom ou LightTable. Acho que o vim também. Isso vai tratar de manter os parênteses em sincronia, baseado na indentação, e também de forçar você a entender a indentação de Clojure. A partir daí, é entender por que esses parênteses existem. Então vamos lá:

Em LISPs, ou seja, em Clojure, parênteses nunca são opcionais. Nunca. Então nem tente resolver seu código com “vou tentar colocar um parênteses aqui” porque não vai funcionar. Você sempre abre um parênteses quando você vai chamar uma função ou special form, ou macro. A soma, multiplicação, divisão e subtração (+ * / e -, respectivamente) são funções. Concatenação de strings (str) também, bem como map, reduce, split e join. Já o if não é uma função – é uma special form, bem como fn* (retorna uma nova função) e def (define novas variáveis, que os LISPs gostam se chamar de símbolos). E o or, o and, e o defn são macros. Para poder usar todos eles, sem exceção, você tem que abrir um parêntese.

Primeiros passos

Para somar 4 números, abrimos um parêntese e o primeiro elemento é a função da soma. Ou seja:

(+ 5 3 9 7)

Isso vai somar os quatro números. Normalmente deixamos grudado ao parêntese a função que vamos rodar.
(more…)

Clojure e simplicidade

AVISO – me empolguei um pouco nessa postagem, para uma introdução mais gentil, verifique o post após esse.

Qualquer linguagem baseada em LISP, como Clojure, tem o mesmo problema: as pessoas falam de como a linguagem é fantástica, como ela revoluciona como você programa, até o momento em que você resolve entender por que. Aí você estuda a linguagem, aprende uma ou outra coisa, e não entende porque as pessoas falam tão bem dela.

Esse ciclo se repete várias vezes, e várias vezes, e você nunca entende o motivo das pessoas falarem tão bem. Até um dia em que você finalmente entende – e é aí que você vira uma dessas pessoas que falam bem, mas ninguém mais entende por que.

Clojure é, basicamente, um LISP que roda sobre a JVM. Porém, diferente de common LISP, Clojure possui duck typing – LISP não. É essa foi a primeira realização – tipagem dinâmica não implica em duck typing.

Ruby, JS, e Clojure possuem métodos (ou keywords, ou funções) que rodam sobre qualquer tipo que atenda aquele protocolo. for element in array, por exemplo, roda em Ruby e JS da mesma maneira para Arrays, ou para Objects (em JS) ou Hash, Set, para Ruby. Em Ruby, é porque todos implementam o método .to_a. Já em Clojure, o nth serve para pegar um elemento de uma coleção qualquer, seja ela uma List ou Vector, usando (nth ["some" "elements"] 1). E como é isso em Common LISP? Bom, se for uma List, usa-se: (nth 1 '("some" "elements")). Se for um Vector, com (aref (vector "some" "elements") 1). E assim por diante (o que quer que isso signifique nessa situação, já que nem posicionamento dos parâmetros nem nome das funções é consistente).

A segunda coisa interessante de Clojure é a sua “sintaxe”, ou na verdade, ausência de sintaxe. Na prática, a sintaxe não existe – você programa definido diretamente as S-Expressions, como se fosse uma lista de comandos. Por exemplo:

; uma definição de uma função
(defn sum-ages [people]
  (reduce + (map :age people)))

; uma definição de uma lista
`(defn sum-ages [people]
   (reduce + (map :age people)))

A segunda expressão, apenas pela presença de um “quote”, torna-se uma lista. O primeiro e segundo elementos são Symbol, o terceiro elemento é um Vector que contém outro Symbol, e o quarto elemento é outra List: (reduce + (map :age people)), e assim as coisas continuam. Symbols, em Clojure, serão convertidos em sintaxe mais cedo ou mais tarde, então defn será clojure.core/defn, e chamará a função, símbolo, ou special-form desse nome mais cedo ou mais tarde. E isso é uma coisa fantástica pelos motivos que veremos a seguir. Mas o primeiro deles é bem óbvio: você não tem códigos – apenas dados. E como a linguagem é composta de dados, podemos manipulá-la, moldá-la, e alterá-la com macros. Além disso, Clojure é uma linguagem muito simples – ao contrário por exemplo, de Ruby, aonde a linguagem é complexa, mas programar nela é simples, em Clojure a linguagem é simples, mas programar nela é um pouco mais complicado.

E o motivo, por mais absurdo que pareça, é que nós, programadores, aprendemos a programar de forma errada
(more…)

Programação funcional, imutabilidade, e previsibilidade

O post de hoje é uma introdução à programação funcional, para podermos entrar finalmente em Clojure. Mas antes disso, vamos falar sobre como aprendemos a programar na faculdade, em cursos, e em todos os lugares. Vamos falar de “orientação a objetos”, principalmente, e vamos falar sobre “abstração”. A programação, como sabemos, é um exercício total de abstração – ao fazer um software, temos apenas um objetivo – fazer com que um trabalho, que provavelmente seria realizado de forma ineficaz ou manual, torne-se automático. Parece uma super-simplificação, mas é verdade. Processadores de texto substituem máquinas de escrever, editores de imagem automatizam vários trabalhos de restauradores, pintores, e desenhistas, e sistemas de folha de pagamento substituem o trabalho de vários matemáticos, contadores, etc. A profissão de todos continua válida – apenas simplificamos um pouco (ou MUITO!) o trabalho deles. E o nosso trabalho, de programadores, é simplificado com linguagens mais modernas, nas quais se escreve menos e se sub-entende mais. E para isso, precisamos aprender a escrever nessas linguagens. E aí entram os cursos, ou a faculdade.

Basicamente, aprendemos a programar nesses cursos, ou na faculdade, pensando em orientação a objetos. Para muita gente, essa é a única maneira sadia de se programar – afinal, orientação a objetos é o paradigma que representa melhor o mundo real, uma frase que muito se ouve. E essa frase é verdadeira, mas com uma pegadinha muito difícil de encontrar: o mundo real é um lugar complicado.

Esse será um post grande, portanto, está dividido em partes. Falaremos sobre a imprevisibilidade, depois mutabilidade e imutabilidade, e na última parte teremos exemplos em Ruby e Clojure sobre trabalhar com dados mutáveis e imutáveis.
(more…)

Clojure, LightTable, e uma nova forma de programar

Esses últimos meses tenho estudado Clojure, ClojureScript, e me entendendo com o ecosistema de tudo isso. Mas sobre a linguagem fica para outro post. Por hora, vamos a uma frase famosa: A language that doesn’t affect the way you think about programming, is not worth knowing, ou Uma linguagem que não afeta a forma que você pensa sobre programar, não vale a pena aprender. Essa frase, de Alan Perlis, mostra muita coisa do que eu penso antes de aprender uma nova linguagem, e vai explicar muito ao aprender sobre Clojure.

Antes de mais nada, vejamos como as linguagens evoluíram – C++ e Java são linguagens orientadas a objeto. Ruby, Python, e Scala também. Mas vejamos como usar uma lista em Java: abrimos o Java, numa IDE lenta como o Eclipse (que precisa de instalação, etc), importamos a lib…. qual lib mesmo? Bom, entramos num Javadoc, procurarmos a lib…. isso em C++ é pior ainda, já que em Java, pelo menos a IDE completa automaticamente os métodos (e algumas vezes, até os imports) pra nós.

Em Scala e Ruby? Abrimos o console, criamos uma lista, atribuímos a uma variável e digitamos: variable., seguido de alguns tabs e o console completa para a gente. Esse é o poder de um REPL (Read-Eval-Print-Loop, ou console, IRB, etc), e o REPL muda completamente a forma de escrever, explorar, entender e até mesmo de pensar em programação. Precisamos um dado no banco de dados? Entramos no REPL, digitamos User.create!(login: “foobar”), e voilá – temos um objeto criado. Não precisamos criar uma tela de cadastro para criar esse dado, não precisamos abrir o gerenciador do banco, etc.

Isso, com Clojure, é elevado ao limite.

(more…)

Alguns meses com CoffeeScript

Recentemente, resolvi testar o editor Atom… Mas isso eu já falei em outro post.

O que eu vim falar agora é sobre CoffeeScript, e a forma como eu tenho programado recentemente envolvendo Javascript.

Estando no mundo Rails, é bem comum a gente acabar usando as ferramentas que o Rails nos disponibiliza. Embora seja uma boa idéia no começo, há uma tendência a ficarmos meio “engessados” numa única tecnologia. Então, resolvi começar um projeto meio ousado de fazer uma UI inteira em HTML + CoffeeScript, sem a intervenção do Rails, e por hora, nem sequer com backend. Talvez eu fale sobre isso num post futuro, mas especificamente agora quero falar de Coffee.

Eu nunca gostei de CoffeeScript, na verdade, por causa da idéia de “indentation-based”. Outra coisa do Coffee é que ele basicamente não faz milagres – tudo no fim das contas é Javascript, e é essa a parte difícil e chata de entender.

(more…)

Interface Gráfica com Ruby

Quando se pensa em Ruby, logo se imagina usando Rails. Na verdade, Ruby é uma linguagem completa com suporte a praticamente qualquer coisa. Todo programador Ruby sabe disso, mas esquecemos isso em nosso dia-a-dia.

Muitas pessoas usam várias GEMs para tentar automatizar qualquer coisa – e isso é bem errado. Por exemplo, há várias gems que tentam trazer o ActiveRecord para Sinatra, enquanto que na verdade, tudo o que temos que fazer é o código abaixo:

ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: 'some_database.sqlite3'
)

E é a mesma coisa com GUI (Graphical User Interface). Há uma série de gems que tentam trazer uma interface gráfica “fácil” para nós, que na verdade só acabam complicando tudo. Por isso, temos às vezes que simplificar o processo – que no caso de interfaces gráficas, para mim significa usar a gem qtbindings
(more…)

Evitando o null-driven-development

Quando a programação em C estava em alta, havia uma série de alocações e liberações de memória. Depois disso, a alocação/liberação passou para C++, e a partir daí tínhamos código como o seguinte:

Person *person = new Person();
delete person;

Algumas vezes, queríamos criar um objeto mas não tínhamos todas as informações dele. Era comum usarmos o ponteiro e só atribuir ele quando tivessemos a informação:

Person *person = null;
//do something in-between
person = new Person(name);

Isso causava um efeito estranho que, eventualmente, o objeto seria “nulo”, ou “não existente”. Isso era uma novidade até o momento, já que nas linguagens mais antigas (VB, QuickBasic, Pascal, etc) ou não havia esse conceito de “nulo” ou não era comum usar.

Quando as linguagens orientadas a objeto dominaram o mercado, esse “null-pattern” acabou também entrando no mercado. Em Java (e Scala), por exemplo, qualquer operação que envolva um null lança um “Null-pointer exception” (que muitos programadores simplesmente capturam com um try-catch, mandam imprimir no console o stacktrace, e continuam o programa, que normalmente para de funcionar). Em Ruby, as coisas são mais complexas…

Ruby é a primeira linguagem que eu conheço que meio que “institucionalizou” o uso de nulos.
(more…)

SQL Orientado a Objetos

O nome parece estranho, mas um ORM, dependendo de como ele for implementado, pode ser usado exatamente para isso.

Estou trabalhando numa lib em Scala chamada relational, na qual eu pretendo fazer um SQL inteiro virar um objeto Scala. Mais ou menos o que o Arel tenta fazer, porém de forma esquisita (meio compatível com Rails, meio compatível com álgebra relacional, e não 100% nada). Mas isso fica pra um outro momento…

No post anterior, eu falei bastante sobre SQL, e sobre todas as coisas que podemos fazer ao saber montar uma query. A idéia agora é tentar montar, de fato, uma query, mas com mais do que apenas fragmentos SQL, mas com o próprio ORM.

Vamos pensar que temos uma tabela de usuários, e uma de números de telefones. O número pertence a um usuário, um usuário tem muitos números de telefone (nada de “join-tables” e coisas mais complexas por agora). Digamos que eu queira saber números de telefone possuem o mesmo prefixo (os primeiros quatro números-vamos ignorar, por hora, os nono dígito para deixar o código mais fácil) de um determinado número.

A idéia, num primeiro momento, é fazer o código para um único número. Vamos, por simplicidade, deixar isso na classe de Telephone mesmo:

class User < ActiveRecord::Base
  has_many :telephones
end

class Telephone < ActiveRecord::Base
  belongs_to :user
  
  def self.same_prefix_of(telephone)
    where('SUBSTR(telephones.number, 0, 5) = ?', telephone.number[0...4])
  end
end

#Para usar:
Telephone.same_prefix_of(Telephone.first)

Por hora, tudo bem. Um código simples, porém é agora que a coisa começa a ficar divertida: generalização
(more…)

Resourceful Web

Todos sabem que, com o tempo, os frameworks web evoluem. Porém, o que poucas pessoas percebem é que além das mudanças nas APIs e na estrutura dos programas feitos com o framework, há uma mudança também nas idéias dos desenvolvedores e até mesmo nas metáforas que o sistema usou para definir-se. E o Rails não é exceção.

Por exemplo, no Ruby on Rails versão 1.x, a idéia do framework era a construção de aplicações web. Para tal, a idéia era que a aplicação fosse simples e divertida de desenvolver. Além disso, havia a idéia de web-services, XML-RPC e SOAP que nunca pegaram direito no mundo Rails (mas que estavam presentes na versão 1.x). Depois, na versão 2.x, surgiu o conceito de RESTful (em contraponto aos web-services do Rails 1) e, junto com ele, o conceito de “resource” ou “recurso”. Já no Rails 3, surgiu a idéia de separar o Javascript do HTML usando o conceito de Unobtrusive Javascript (Javascript não-intrusivo), e junto com essa idéia, veio a substituição do prototype pelo jQuery (que torna certas operações envolvendo AJAX mais fáceis). Junto também com a substituição por jQuery, o scaffold passou a fazer os controllers responderem por HTML e JSON, ao invés de HTML e XML como no rails 2.x.

E é essa a mudança mais importante.

Vamos começar pensando: qual seria o motivo de renderizar um JSON? A resposta é simples: JSON é mais fácil de ser entendido pelo browser, por Javascript, e por aplicativos de terceiros tais como em iOS ou Android. Antes, responder por XML não tinha aplicação real nenhuma nos próprios aplicativos Rails, e ficavam apenas como forma de comunicação com sistemas de terceiros (o velho “big design up front“) que nem sempre ocorriam. E hoje, renderizar JSON está muito pouco utilizado mesmo no mundo Rails, e há um motivo para isso:

Não sabemos o que é um “resource”.
(more…)