sexta-feira, 12 de junho de 2009

Microsoft pronta para lançar seu antivírus gratuito

De acordo com a Reuters, a Microsoft já tem uma versão Beta de seu antivírus pronta para ser liberada para testes. A idéia é lançar um produto sem custo para os usuários, batendo de frente com os tradicionais antivírus existentes no mercado.

Acionistas de fornecedoras de antivírus, tais como Symantec e McAfee já estão preocupados com o impacto deste lançamento da Microsoft. No longo prazo, esta nova o oferta pode causar um impacto significante na concorrência. No entanto, um porta-voz da Symantec diz estar tranqüilo, pois a empresa já vem se saindo bem contra ofertas gratuitas de softwares antivírus existentes no Mercado.

[]'s

Leonardo X. T. Cardoso

quinta-feira, 4 de junho de 2009

teste

teste

terça-feira, 2 de junho de 2009

Lista de inicialização no C++ 0x


A maioria dos desenvolvedores C++ sonham com a possibilidade das declarações abaixo:



std::vector< std::string > peoples = { “joao”, “pedro", “maria" };


ou


std::list< std::pair< std::string, int> > peoples = {
{"joao",12}, {"maria", 15}, {"pedro", 20}
};


Agora o sonho se tornará realidade, pois é isto que a lista de inicialização irá possibilitar no C++ 0x. Desenvolvedores C++ não ficarão mais restritos a utilização de lista de inicialização apenas em arrays.

Para a construção da lista de inicialização o C++ 0x irá associa-la a um novo tipo chamado std::initializer_list. Isto permitirá que construtores e as tradicionais funções recebam uma lista de inicialização como parâmetro. A lista de inicialização pode ter tamanho arbitrário, mas os elementos devem ser homogêneos (todos do mesmo tipo T ou conversíveis para T).

Por exemplo:


class List
{
public:
List(std::initializer_list< int > list);
};


Esta declaração permite que a classe List seja construída a partir de uma sequência de inteiros como mostrado no exemplo abaixo:


List my_list = {1, 4, 5, 6};



O construtor da classe List é chamado construtor de lista de inicialização.

A classe std::initializer_list, apesar de ser um tipo de primeira classe no C++ 0x, somente pode ser inicializada estaticamente pelo compilador. A lista de inicialização sempre é constante e não pode ser modificada depois de criada.

Vejamos abaixo a implementação do construtor de lista de inicialização da classe std::vector da biblioteca padrão de gabarito – (Standard Template Library). Este exemplo foi retirado daqui.



template< class E> class vector {
public:
vector (std::initializer_list s) // novo construtor da lista de inicialização
{
// reserva o espaço de memoria apropriado
reserve(s.size());

// inicializa elementos com o da lista de inicializacao
uninitialized_copy(s.begin(), s.end(), elem);

// seta o tamanho do vector
sz = s.size();
}

// ...... ...
};



Observe que não existe almoço grátis. O programador deve implementar o suporte para a lista de inicialização para todas as suas classes.

Por hoje é isso. Em breve posto outra feature do C++ 0x.

[]'s
Leonardo X. T. Cardoso

domingo, 31 de maio de 2009

Funções e expressões Lambda no C++ 0x - Parte 2


Todas as funções lambdas apresentadas no post anterior não possuiam membro de dados. A utilização de membro de dados pode ser feita por meio da captura de variáveis locais que é realizada pelo introdutor lambda ([]). Neste introdutor é possível especificar uma lista de captura (capture-list) como demonstrado no Código 1.

Código 1

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 0;
int y = 0;

cout << "Input: ";
cin >> x >> y;

v.erase(remove_if(v.begin(), v.end(), [x, y](int n) { return x < n && n < y; }), v.end());

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
}



Um exemplo da execução do programa do Código 1 seria
Input: 4 7
0 1 2 3 4 7 8 9



É importante salientar que apesar do corpo da função lambda estar lexicamente no escopo de main() , ela esta conceitualmente fora do escopo de main(). Sendo assim, não é possível usar variáveis locais declaradas em main() sem “captura-las”.



Todas as capturas são feitas por valor e apenas cópias das variáveis são armazenadas na função. Isso implica em algumas conseqüências importantes: (a) não é possível modificar as cópias capturadas, pois por default a chamada da função objeto é const, (b) atualizações nas variáveis locais não serão refletidas nas cópias capturadas. Mais a frente neste post irei explicar como capturar variáveis por referência.


Ao invés de informar todas as variáveis que deseja capturar, é possível especificar a captura de todas as variáveis locais. A syntax para isso é o introdutor lambda [=]. Usando o exemplo do código 1, bastaria substituir a linha 14 para:


v.erase(remove_if(v.begin(), v.end(), [=](int n) { return x < n && n < y; }), v.end());


Usando este recurso, o compilador irá fazer a captura por valor de todas as variáveis de main() (no exemplo x e y)


Caso seja necessário modificar as variáveis capturadas, pode-se modificar a chamada da função lambda de const para non-const. Para isso deve-se usar o já conhecido modificador mutable. O Código 2 mostra um exemplo deste recurso.

Código 2

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 1;
int y = 1;

for_each(v.begin(), v.end(), [=](int& r) mutable {
const int old = r;
r *= x * y;
x = y;
y = old;

});

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
cout << x << ", " << y << endl;
}


O exemplo mostrado no Código 2 multiplica cada elemento de v com os 2 elementos anteriores.
Sua execução mostraria
0 0 0 6 24 60 120 210 336 504
1, 1


É importante ressaltar que modificações nas variáveis capturadas não são refletidas nas variáveis locais. Caso seja necessário refletir as modificações das variáveis capturadas sobre suas correspondentes locais, isso é alcançado por meio da captura por referência. A syntax para a captura por referência é o introdutor lambda [&x, &y, &z]. A declaração anterior deve ser lida como referência para x, y e z e não endereço de x, y e z. O Código 3 mostra o Código 2 modificado para usar variáveis capturadas por referência.

Código 3

int main() {

vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 1;
int y = 1;

for_each(v.begin(), v.end(), [&x, &y](int& r) {
const int old = r;
r *= x * y;
x = y;
y = old;
});

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
cout << x << ", " << y << endl;

}


O exemplo mostrado no Código 3 multiplica cada elemento de v com os 2 elementos anteriores.
A execução do Código 3 mostraria
0 0 0 6 24 60 120 210 336 504
8, 9


Observe as diferenças do Código 3 com o Código 2: (i) O introdutor lambda [&x, &y], (ii) a retirada do modificador mutable e (iii) as variáveis locais tendo valores 8 e 9 ao final da execução, refletindo as modificações dentro da função lambda. Também é possível capturar todas as variáveis locais por referência. usando o introdutor lambda [&]

Finaliza aqui o papo sobre funções lambdas. Acho que para um post introdutório o que já foi dito ate aqui é suficiente. Tem muito mais coisas interessantes sobre funções lambdas que não abordei aqui. Para um estudo mais extensivo sobre esta funcionalidade recomendo a leitura da última versão da especificação que pode ser encontrado aqui.

Irei continuar postando sobre o C++ 0x. Percebi que a quantidade de material na língua portuguesa é mínima e irei tentar dar minha contribuição.

[]’s

Leonardo X. T. Cardoso

quarta-feira, 27 de maio de 2009

Funções e expressões Lambda no C++ 0x


Um dos recursos mais importantes do próximo padrão C++ que ainda esta em desenvolvimento é a chamada função lambda.Expressões lambdas definem e constroem implicitamente funções objetos sem nome que na prática se comportam como as já conhecidas funções objetos. Como um trecho de código vale mais do que mil palavras, no Código 1 abaixo pode-se ver a utilização básica de uma função lambda.


Código 1

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
}



O [] é chamado introdutor lambda (lambda-introducer) e informa o início de uma função lambda. A declaração do parâmetro lambda é representado por int n e o corpo da função lambda é { cout << n << “ “;. Por default uma função lambda retorna void. Segue abaixo no Código 2 como seria este mesmo código escrito no padrão atual do C++ usando o tradicional funtor.


Código 2


struct Functor {
void operator()(int n) const
{
cout << n << " ";
}

};

int main()
{
vector v;
for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), Functor());

cout << endl;
}


Alguns de vocês já devem estar se perguntando se é permitido colocar vários comandos dentro de uma função lambda. A resposta é sim e um exemplo é mostrado no Código 3:


Código 3


int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), [](int n) {
cout << n;
if (n % 2 == 0)
cout << " even ";
else
cout << " odd ";
});

cout << endl;
}



Ao avaliar o Código 3 você já pode estar imaginando a “macarronada” que um programador pode fazer no código ao usar expressões lambda. Se já era fácil fazer códigos ilegíveis agora ficará ainda mais simples. Acredito que em breve vão lançar o Obfuscated C++ 0x Code Contest. Pode ser que criem coisas mais assustadoras do que o já conhecido International Obfuscated C Code Contest (http://www.ioccc.org/).

Antes que você me pergunte, expressões lambdas podem retornar qualquer tipo de dados. Se o corpo de sua função é do tipo { return expr; }, o tipo de retorno será automaticamente deduzido para o tipo de expr. No Código 4 é mostrado um exemplo:


Código 4


int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

deque d;

transform(v.begin(), v.end(), front_inserter(d), [](int n) { return n * n * n; });

for_each(d.begin(), d.end(), [](int n) { cout << n << " "; });

cout << endl;
}



No Código 4 o tipo de n*n*n é int e por isso a função lambda retorna int. Lambdas com expressões mais complexas não são capazes de deduzir o tipo de retorno e por isso o programador deve informar explicitamente. O Código 5 ilustra como isso é feito:

Código 5

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

deque d;

transform(v.begin(), v.end(), front_inserter(d), [](int n) -> double {
if (n % 2 == 0)
return n * n * n;
else
return n / 2.0;
});

for_each(d.begin(), d.end(), [](double x) { cout << x << " "; });

cout << endl;
}


O trecho “>- double” é a cláusula opcional de tipo de retorno lambda. O motivo da cláusula não ficar mais a esquerda como acontece com todos os tipos de funções C é que [ ] deve ficar antes para informar ao compilador o início da função lambda. Se o programador não escrever a clausula de tipo de retorno, o compilador provavelmente vai gerar um warning para cada return.

Hoje termino a primeira parte do estudo de expressões lambda. No próximo post irei mostrar expressões lambdas que contem membros de dados.

Referência


O artigo original fonte de inspiração deste post e origem dos código de exemplo pertence ao blog do Visual C++.


[]’s


Leonardo X. T. Cardoso

terça-feira, 26 de maio de 2009

Placa "Live Free or Die" UNIX completa 20 anos

Quem do mundo Unix nunca viu a famosa placa Live Free or Die UNIX em canto pela internet ? Se você nunca viu, segue uma das versões abaixo.


Pois bem, esta placa completou 20 anos em 2009 e foi criada pelo não menos famoso John “Maddog” Hall. Alguns dizem que esta é a placa de carro mais celebrada do estado americano de New Hampshire. Pelo menos no mundo nerd eu não duvido. :)

Segue abaixo uma foto do Maddog ao lado de seu Jeep Wrangler e a placa original.




PS: New Hampshire é um dos poucos estados americanos onde não é cobrado tax. Parece que ele também gosta de fazer suas compras livre de tax. ☺


[]'s

Leonardo X. T. Cardoso

Sun Microsystems anuncia maior App Store do Mundo

De acordo com o CEO da Sun Jonathan Schwarts, a próxima tacada da Sun será a construção de uma App Store que será a maior do mundo deixando a App Store da Apple no chinelo. Esta App Store venderá aplicativos Java com o foco em usuários domésticos. A meta é que o número de usuários ultrapasse 1 bilhão.

Os desenvolvedores vão submeter seus aplicativos no website da App Store e a Sun vai avaliar o conteúdo e segurança antes que seja apresentado ao público. Os ganhos da Sun serão provenientes das taxas de distribuição que serão cobradas de cada aplicativo vendido. Funcionamento parecido com o da App Store da Apple.

O potencial de mercado da Sun é enorme e leva em conta os 4.5 bilhões de computadores, telefones celulares e outros dispositivos que tem suporte Java. Comparando com a App Store da Apple, esta já teve cerca de 1 bilhão de downloads sendo que existem “apenas” cerca de 21 milhões de Iphones em utilização.

Levando em conta estes números, pode ser que a App Store da Sun realmente deixe a da Apple no chinelo em termos de número de usuários e faturamento. Mas isso não será simples e precisará da utilização em massa do serviço pelos usuários de computadores domésticos e smartphones.

Minha opinião é que a Sun pode se dar muito bem se conseguirem construir um bom serviço para downloads de aplicativos para celulares. Lembrando que isso não vai ser fácil dada a variedade de marcas e modelos de aparelhos disponíveis no mercado. Quem já tentou instalar aplicativos escritos em J2ME no celular já percebeu que a idéia de “write once, run anyhwere” não se aplica muito bem. Para usuários de PC eu já acho que o serviço não deve fazer muito sucesso.

E você, o que acha ?

[]’s

Leonardo X. T. Cardoso