Nas entrelinhas (Parte 1)

Se você começou a estudar Scala há um tempo, certamente já encontrou em algum código o famigerado _ (chamado de sublinhado, placeholder, underscore, underbar…). Se ficou meio confuso, a confunsão é justificada pelo fato desse símbolo ter quatro usos (pelo menos que eu saiba) em Scala. Podemos encará-lo como uma espécie de caractere coringa, com comportamento distinto dependendo de uma das quatro situações.

O uso mais simples do _ é como coringa para importação de classes em diferentes pacotes. Funciona da mesma forma que o * (asterisco) em Java.


package br.com.verde
import java.util._

class Lab {
 val today = new Date
}

Isso porque o asterisco tem outra finalidade na linguagem de programação criada por  Martin Odersky. Para Scala o asterisco é o operador de indireção, usado para declarar ponteiros. Calma, calma! É só brincadeira! Passou, passou! O asterisco em Scala é usado como “operador” (método/função) para multiplicações e para declarar varargs.

O _ também pode ser um coringa em um “casamento” de padrões (pattern matching). Representando um valor qualquer:


object Fatorial {
  def f(n: Int): Int = n match {
    case 0 = 1
    case _ = n * f(n - 1)
  }
}

No código acima quando o n for igual a (”casar com”) 0, a função retornará 1. Para qualquer outro valor, retornará o resultado da expressão n * f(n -1).

O terceiro uso do _ já é um pouco mais capcioso. Podemos usá-lo para “iniciar” vars com um valor padrão.


class Lab {
  var numero: Int = _ //zero
  var booleano: Boolean = _ //falso
  var caracter: Char = _ //vazio
  var texto: String = _ //null
  var dinheiro: BigDecimal = _ //null
}

Para cada “tipo” de variável o _ assumirá um valor. Apesar de tudo em Scala ser um objeto, Int, Boolean e Char não receberam  null como valor.

Bem, como diria o suicida otimista ao passar caindo pelo quinto andar do prédio de onde pulou: “Até aqui tudo bem”. Na segunda parte veremos os usos mais complicados do _.

Édson Rocha Patrício

Actors locais ou remotos ? Tanto faz !

Quem já trabalhou com RMI em Java sabe que hoje em dia é um processo altamente burocrático. Muitos desistem quando seguem um tutorial passo-a-passo e no final não funciona. Eu já havia feito programas que usavam RMI nos primórdios do Java e já achava, por um lado difícil de implementar, por outro lado, mais simples que a alternativa da época que era Corba. Quando precisei usar novamente, há uns dois anos atrás, descobri que estava ainda mais complicado. Quem quiser se aventurar, pode ler o Tutorial sobre RMI da Sun.

Dentre as burocracias, temos que rodar o rmiregistry para ser o registro de objetos distribuídos ou criar um programaticamente. Depois, temos que criar um stub dinamicamente, usar este stub para fazer o bind no registro, criar um SecurityManager, configurar um arquivo policy, criar uma interface e implementá-la, fazer lookup no cliente, parâmetros na execução, etc…

Seguindo a descoberta de Scala, passei pela seção de Actors e achei muito interessante, porém, a implementação que vi era local. Pensei então: Se eu fosse projetar em Scala uma solução de comunicação remota, iria usar o modelo de Actors para tal. Será que não pensaram assim ? Sim ! Exatamente ! E a burocracia ? Menor que essa, só adivinhando !

Para transformar a comunicação local dos Actors em remota, basta apenas colocar a porta TCP a ser usada pelo servidor, registrar-se e no cliente, fazer o lookup. Pronto ! Vejamos um hello world remoto:

Servidor:


package scalademo

import scala.actors.Actor._
import scala.actors.remote.RemoteActor._

object ServerActor {
  def main(args: Array[String]) {
    actor {
      alive(5000)
      register('Server, self)
      println("Server running..." )
      loop {
        react {
          case text => sender ! "Message |"
                          + text + "| was received ok"
        }
      }
    }
  }
}

Cliente:


package scalademo

import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._

object ClientActor {
  def main(args: Array[String]) {
    actor {
      val server = select(Node("localhost", 5000), 'Server)
      println("Sending hello..." )
      server ! "Hello"
      receive {
        case text => println(text)
      }
    }
  }
}

Caso queiram ver um exemplo mais completo, recomendo este artigo. Para simplificar, usei objetos da classe String como transporte. Em uma aplicação mais completa, é conveniente usarmos case classes.

Assim como em Java, evito usar um repositório público de classes via HTTP para o classloader. A complicação adicional, que está presente em ambas linguagens, só se justifica quando o lado servidor pode receber objetos de classes não previstas originalmente. Normalmente as aplicações são fechadas, isto é, todas as classes já são conhecidas. Assim, é somente uma questão de empacotar as classes necessárias nos jars do servidor e do cliente.

Abaixo a burocracia ! Escalabilidade é fazer o simples fácil, e o complicado possível.

Alexei Barbosa de Aguiar

SED, DCOP e outras coisas que só o Linux faz para você

Não costumo fazer guerra religiosa com sistemas operacionais. Sempre ouço falar das facilidades que certos sistemas operacionais oferecem, e tenho que admitir que o Linux às vezes peca na usabilidade. Mesmo me considerando um usuário de Linux avançado, a instalação e configuração de um modem pode se tornar uma tarefas tortuosa. Mesmo assim, usar uma das principais distribuições Linux, para a grande maioria dos casos é fácil e agradável. Muitas coisas no Linux não são mais difíceis, só diferentes. O problema é que tolerar diferenças nunca foi uma das maiores virtudes naturais dos seres humanos.

Difícil ou fácil, o que faz o Linux assunto obrigatório para um profissional de Informática é tornar possível tarefas muito difíceis. A meu pedido recebo alguns boletos bancários em PDF (para evitar gasto de papel desnecesário), pago-os pelo sítio na Internet do banco que sou cliente. O código do boleto é algo como:

23792.37205 66281.169319 11011.260004 1 00000000000000

Não posso simplesmente copiar do boleto e cola no sítio do banco, por causa dos espaço e ponto. Preciso que quando o código for colado no sítio do banco vá sem pontos nem espaço, como:

23792372056628116931911011260004100000000000000

Em Shell posso fazer: echo ‘23792.37205 66281.169319 11011.260004 1 00000000000000‘ | sed ’s/[\.|[:space:]]//g’

A sintaxe do comando de substituição do sed é: s/RegexProcurada/ValorSubstitutivo/

O /g no final do comando faz com que todas as ocorrências que casam com a regex sejam substituída, não só a primeira. Podemos ler a regex usada como: casa com ponto ou espaço. Percebam que o campo referente ao valor a ser substituído está vázio, i.e. o que casar com o padrão será substituído por nada (vazio). Sobre regex, vale apena ler o Expressões Regulares – Guia de Consulta Rápida do Aurélio Marinho Jargas. Entre outras coisa é bem divertido.

Agora, como gravar na área de transferência, depois ler da área de transferência, modificar o conteúdo e gravar o resultado na área de transferência. É hora do milagre chamado DCOP. Com o uso desse protocolo do KDE podemos executar essa tarefa, através de um comando com o mesmo nome do protocolo. O primeiro passo é criar um script shell com os comandos requeridos.


#!/bin/bash
parselessString=`/opt/kde3/bin/dcop klipper klipper getClipboardContents`
result=`echo $parselessString | sed 's/[\.|[:space:]]//g'`
/opt/kde3/bin/dcop klipper klipper setClipboardContents $result

Na primeira linha salvamos o conteúdo da área de transferência em uma variável chamada parselessString. Na segunda, usamos a variável para que o sed possa agir no conteúdo e guardar o resultado em uma variável chamada result. Na terceira, gravamos o conteúdo de volta à área de transferência.

Se dermos mais uma olhada na primeira linha, podemos ver que através do comando dcop, chamamos do módulos klipper do aplicativo klipper, um método chamado getClipboardContents. Esse método retorna o conteúdo da área de transferência. Para gravar o resultado foi usada uma mecânica similar.

Falta ainda vencer um desafio. Como criar atalhos de teclado que de uma só vez copie o texto selecionado à área de transferência e acione o script. A resposta está nas Ações de entrada do KDE, que podem ser acessadas chamando kcontrol. Em geral podemos chegar até elas via o menu do botão principal, ou digitando kcontrol no console ou no Executar Comando (alt+f2). Uma vez no kcontrol (Configurações Pessoais), vá até Regional & Acessibilidade e depois Ações de Entrada. Basicamente temos que criar uma nova ação, dar um nome para ela, designar seu tipo como genérico, escolher o conjunto de teclas que serão gatinho para ação e finalmente acrescentar as duas ações propriamente ditas, que serão executadas ao pressionar-se as teclas gatilho. O acréscismo das ações propriamente ditas é feito com o botão Novo. Precisamos de uma entrada de teclado (ctrl+c) e uma chamada a comando (executa o script). A entrada de teclado funciona como se o usuário tivesse digitado aquela seqüência de teclas, tendo o mesmo efeito da ação real.

No exemplo que fiz com o atalho win+crtl+c, cópio para área de transfência o texto já modificado e com o crtl+v normal colo o resultado.

Publicado em Linux. Tags: , , . Deixar um comentário »

Comparação em Scala: equals, == e eq

“Tudo que sei é que nada sei e até disso tenho dúvida.”

http://www.verde.com.br/img/BrokenCup.jpg

Essa frase faz muito sentido quando estamos aprendendo algo novo e muito diferente do já conhecido. Quebrar o paradigma das linguagens imperativas (como Java, C, C++) e entrar no paradigma funcional é uma verdadeira lição de humildade e resignação. De repente descobrimos que não sabemos fazer coisas, que eram triviais. Como a dúvida suscitada por Alexei:

Para comparar um objeto com null em Scala, que operador devemos usar ? equals, ==, eq ?

Para começar, por natureza o == do Scala tenta comparar conteúdo e não referência como no Java. O == é tão somente um “atalho” para a função equals. Os idealizadores entenderam que é mais comum comparações de conteúdo do que de referência. O jeito Java de compararmos objetos vem do C++, onde as “variáveis” que representam os objetos são ponteiros. Dessa forma, nada mais justo que o valor que elas guardam (endereço para algo) seja seu principal característica. Já em uma linguagem de orientação a objetos mais fiel, a referência pode não ser a principal identificação de um objeto.

“Sou melhor identificado pelo meu nome do que pelo meu número telefônico.”

Em contra partida, precisamos ter o hábito de sobrescrição da função equals para regularmos a coerência da identificação de objetos.

“Um automóvel é melhor identificado pela placa dele, do que pelo nome do modelo.”

Sendo assim, para fazer comparações de referência, que no Java seria com ==, em Scala usa-se a função eq.

A coisa complica quando analisamos as classes encapsuladoras de tipos primitos em Scala (wrappers). A função eq vem de scala.AnyRef, da qual todas as classes Java tornan-se filhas quando em ambiente Scala.

Contudo, scala.Int, por exemplo, não é filha de scala.AnyRef e sim de scala.AnyVal que não tem eq. Porém, tanto a função equals, quanto seu “atalho” == estão em scala.Any (uma classe mais abrangente que java.lang.Object. É quase uma classe tropadeelite.CapitãoNascimento).

Vejamos um exemplo de comparação em Scala:


object ComparingObject extends Application{

    val scalaInteger1 = 7
    val scalaInteger2 = 7
    scalaInteger1 == scalaInteger2 //true: chama equals
    scalaInteger1 equals scalaInteger2 //true: contéudo igual
    scalaInteger1 eq scalaInteger2 //erro: scala.Int não é um scala.AnyRef
}

Em Java:


...
        Integer int1 = 7;
        Integer int2 = 7;
        int1 == int2; //true: Só existe um objeto 7
	int1.equals(int2)); //true: Mesmo objeto, mesmo conteúdo
...

Porém se fizermos também em Java:


...
        Integer int1 = new Integer(7);
        Integer int2 = new Integer(7);
        int1 == int2; //false: São objetos diferentes
        int1.equals(int2); //true: o conteúdo deles é o mesmo
...

Esse comportamento se repete para todas as classes encapsuladoras do Java. Se criarmos nossa própria classe Int no Java, só teremos o segundo comportamento. A comparação através do == será referencial, e devemos sobrescrever o método equals para termos uma comparação por conteúdo.

Em Scala o comportamento torna-se uniforme entre as classe encapsuladoras da linguagem e as suas classes:


object ComparingObject extends Application{
    val scalaObject1 = new MyObject(7)
    val scalaObject2 = new MyObject(7)
    val int1: Integer = 7
    val int2: Integer = 7

    scalaObject1 == scalaObject2 //true: conteúdo igual
    scalaObject1 eq scalaObject2 //false: referências diferentes

    int1 == int2 //true: conteúdo igual
    int1 eq int2 //false: referências diferentes
}

class MyObject(val id: Int) {
    override def equals(that: Any): Boolean = if(that.isInstanceOf[MyObject])
                                                hasSameId(that.asInstanceOf[MyObject])
                                                  else false

    def hasSameId(that: MyObject): Boolean = this.id == that.id

}

Usando scala.Int o comportamento é diferente, como vimos no primeiro trecho de código. Vimos um comportamento que favorece a performance. A JVM cria um repositórios de objetos String. Classes de encapsulamento de tipos primitivos melhoram a performance através autoboxing.

E quanto a comparação de objetos com null ? Lembrando que em Scala null é um objeto da classe scala.Null.

A comparação pode ser feita com eq, mas para mantermos uma uniformidade de código devemos usar ==, que na classe scala.Null é um atalho para eq. Não faria sentido existir uma equals. Em scala.Null não há comparações de conteúdo.

Alguns desenvolvedores reclamam bastante das funções comparativas em Scala, pedem mudanças no comportamento, padronização mais intuitiva.

Outros pedem a migração da função eq para scala.Runtime, ou até mesmo a criação de uma função === como em Groovy. Alegam a possibilidade de fazer:


...
     new Qualquer() == new Qualquer() //true
     new Qualquer() === new Qualquer() //false
...

Acredito que muita coisa ainda vai acontecer até encontrarmos um consenso. Estamos escalando o Everest.

Édson Rocha Patrício

Classes desburocratizadas: Fim dos getters e setters pobres

Para expor o estado interno dos objetos ao mundo exterior, algumas linguagens se valem de um conceito chamado propriedade. Vou começar falando das linguagens que não tem propriedades como o Java. Estas linguagens consideram que as variáveis e constantes tem propósito apenas interno, apesar de poderem ser declaradas como públicas. Caso caiamos na tentação de usá-las como membros públicos para simplificar e desburocratizar a programação, compramos uma dor-de-cabeça futura.

O problema nesta abordagem é que quebrarmos o encapsulamento, expondo o interior do objeto como ele realmente é. Assim, se a representação interna mudar, obrigatoriamente, os clientes externos vão ser afetados. Isso é o indesejado alto acomplamento que propaga as alterações e amarra os objetos, reduzindo o reuso. Também temos o problema de não podermos controlar a atribuição, fazendo validações. Assim, podemos ter aluno.nota = 11 ! Outra possibilidade é engessar a classe. A própria Sun cometeu uma gafe ao criar a classe java.awt.Rectangle com campos públicos. Daí, depois não pôde evitar que façamos um rect.height = -100, que é bastante esquisito ! O retângulo é tão baixo que o topo está abaixo da base ?!?! E se ela os transformasse em campos privados quebrando a compatibilidade ? Já pensou ter que pedir para os usuários não fazerem upgrade de jvm porque senão o programa não vai mais rodar ? Por causa disso, espalhamos uma porção de getters e setters pelo código da classe por pura burocracia. O Java herdou essa filosofia do C++.

O conceito de propriedades não é nada novo, nem revolucionário. O velho Delphi já tinha propriedades. Para não mexer com a poeira do fundo do baú, vamos deixar o Delphi de lado e ver como o Scala expõe o estado interno sem burocracia e com escalabilidade: “Tornar o simples fácil e o difícil possível”.

Suponha o mesmo caso da classe Rectangle. Vejamos como ficaria a classe com a suposta quebra de encapsulamento:


class Rectangle {
   var x, y, width, height: Int
}

val rect = new Rectangle
rect.height = -100

Então, percebido o erro depois de esta classe estar sendo usada em vários programas, precisamos corrigi-lo. Felizmente, Scala tem um mecanismo sofisticado para permitirmos interferir na leitura e gravação da variável, sem alterar o uso externo da mesma. Vejamos como ficaria:


Class Rectangle {
    var x = 0
    var y = 0
    private var pwidth = 0
    private var pheight = 0

    def width_=(arg: Int) {
      if (arg < 0) throw new IllegalStateException("width não pode ser menor que zero" )
      pwidth = arg
    }
    def width = pwidth

    def height_=(arg: Int) {
      if (arg < 0) throw new IllegalStateException("height não pode ser menor que zero" )
      pheight = arg
    }
    def height = pheight
  }

val rect = new Rectangle
rect.height = -100  // Causa uma IllegalArgumentException

Assim, ganhamos o controle quando precisarmos, garantindo a manutenção da interface externa da classe para os clientes dela. É admissível que x e y possam receber valores negativos por estarem à esquerda do eixo y ou abaixo do eixo x. Assim, não precisamos da burocracia e poluição de getters e setters pobres desnecessários mas requeridos nas linguagens que não tem propriedades.

Bonus track

Por baixo dos panos, no bytecode, na verdade todos os campos ficam privados e têm os métodos de leitura e escrita.Vejam como ficou a classe Rectangle “descompilada” (sem implementação) para Java:


public class scalaintegration.Rectangle
   extends java.lang.Object implements scala.ScalaObject{
 private int pheight;
 private int pwidth;
 private int y;
 private int x;
 public scalaintegration.Rectangle();
 public int height();
 public void height_$eq(int);
 public int width();
 public void width_$eq(int);
 private void pheight_$eq(int);
 private int pheight();
 private void pwidth_$eq(int);
 private int pwidth();
 public void y_$eq(int);
 public int y();
 public void x_$eq(int);
 public int x();
 public int $tag();
 }

Alexei Barbosa de Aguiar