Resposta do Desafio do dia / 2

20 04 2007

Resposta do Desafio do dia / 2

Vamos por partes:

Um dos objetivos deste desafio era demonstrar que blocos de códigos podem ser utilizados em qualquer parte, e não apenas em estruturas de controle, decisão, etc. O seguinte trecho de código é perfeitamente válido e funcional (apesar de “estranho”)

<?php
  
{
      
$foo ‘foo’;
      echo 
$foo;
  }

Como pode se observar no desafio, coloquei o código em diversos blocos, mas apenas para isso: Demonstrar que é possível utilizar em qualquer lugar. Para resolução do desafio, é indispensável conhecimento de operações bit-a-bit. Como não é todo mundo que tem esse conhecimento, um outro objetivo do desafio era despertar a curiosidade de quem não soubesse e quisesse resolver e também falar um pouco sobre isso (na resposta). Segue agora então o mesmo código, comentado, com a resposta do desafio:


<?php
  
// desafio2.php

  // para acompanhar, segue alguns numeros binarios:
  //
  // 000 0
  // 001 1
  // 010 2
  // 011 3
  // 100 4
  // 101 5
  // 110 6
  // 111 7
  // iniciamos $x com valor 2
  $x 2;
  {
    
// aqui temos também um pequeno truque:
    // print é utilizado para exibir uma mensagem,
    // e sempre retorna 1. Logo, sera exibida a
    // mensagem ‘Iniciando ‘ e $x sera incrementado
    // em 1. Neste momento temos:
    // $x = 3
    
$x += print(‘Iniciando ‘);
    {
        
// aqui sera exibido ‘desafio 2’
        
echo ‘desafio 2’;
        
        
// aqui temos a primeira operacão bit-a-bit,
        // um ‘left shift’ de $x em 1 passo. Vejamos
        // o que tinhamos e o que sera retornado para $y
        // 
        // $x = 011 (3)
        //
        // deslocando 1 bit a esquerda teremos 110 (6)
        //
        // nesse momento temos:
        //
        // $x = 3 (nao modificamos $x)
        // $y = 6
        
$y $x << 1;
    }
    
// aqui são feitas várias operações. Vamos começar
    // pelas mais internas e com maior prioridade:
    //
    // $y^$x
    //
    // Aqui temos um $y xor $x. XOR – exclusive or – retornará
    // os bits que estão ativos em $y e os que estão ativos
    // em $x,  mas não os que estão ativos em ambos: veja:
    //
    // $x = 011
    // $y = 110
    // —- 101
    //
    // observe que como o segundo bit estava ativo em ambos,
    // ele nao estara ativo na saída. Entao após esta operação, 
    // o retorno será 5 (101)
    //
    // logo após esta operação, temos um “not”:
    //
    // ~($y^$x), ou seja ~(5) ou ~5.
    //
    // aqui ocorre uma inversão de cada bit: Os que estão ativos
    // serão desativados e os que estão desativados serão ativados:
    //
    // 5 – 101
    // — 010
    //
    // o resultado desta operação então seria 2 (010)
    //
    // Mas tem um pequeno “problema”: A operacao deve ser feita em
    // todos os bits. Logo, ~5 = 11111111111111111111111111111010 e
    // 11111111111111111111111111111010 = -6
    //
    // temos entao que o resultado da operacao ~($y^$x) = -6
    // o resultado disso tudo é retornado por sprintf.
    // 
    // Aproxima operação, por ordem dos operadores, é $y + (-6), ou 
    // seja $y + sprintf(‘%d’,~($y^$x)). Isso porque o operador ‘+’ tem
    // precedência ante ao ‘|’. Então temos
    //
    // $6 + (-6) = 0
    //
    // apos isto, temos “$x | 0”. Aqui o os bits que estão ativos ou 
    // em $x ou em 0 (ou ambos, diferentemente do xor) estarão ativos na
    // saída. Como 0 não tem bits ativos, o resultado da operação sera o
    // própio valor de $x:
    //
    // $x = 011
    // 0  = 000
    // —- 011 (3)
    //
    // finalmente, temos que $y = 3
    //
    // ao final disso entao:
    //
    // $x = 3
    // $y = 3
    
$y $x $y sprintf(‘%d’,~($y^$x));

    // apenas exibimos um “\n”. O $z não é utilizado mais
    
$z = print(“\n”);
    
    
// verificamos se $x é menor do que $y (não é)
    
if ($x $y) {
        
$x ^= $x;
    
// observe que aqui não temos um else. Então esse trecho
    // será executado de qualquer forma (mesmo que o if anterior
    // fosse verdadeiro. Foi utilizado apenas para “confundir” : )
    
} {
        
// Fazemos um xor de $y em $y. Lembre-se que no xor, o retorno
        // são os bits que estão ativos ou em um ou em outro número, mas
        // não em ambos. Como o xor está sendo feito no mesmo número, o que
        // estiver ativo em um também estará ativo em outro. Logo, o retorno
        // será 0 (este tipo de operação é bastante utilizada em assembly, 
        // quando se deseja zerar o valor de algum registrador: “xor eax, eax”
        // “xor ebx, ebx”, …)
        //
        // $y = 011
        // $y = 011
        // —- 000
        //
        //
        
$y ^= $y;
    
// novamente utilizamos um bloco, que será executado de qualquer forma
    
} {
        
// verificamos se $x (3) é maior do que $y (0). Como sabemos que é,
        // será exibido ‘$y menor do que $x’
        
if ($x $y) {
            echo 
‘$y menor do que $x’;
        
// e este trecho será ignorado : )
        
} else {
            echo 
‘$y maior do que $x’;
        }
    }
  }
  
// finalmente, exibimos um último “\n”
  
echo “\n”;
?>

Ao final disso, temos então:

Iniciando desafio 2
$y menor do que $x

É isso, espero que tenha aprendido um pouco sobre bitwise operations neste desafio.





Desafio do dia / 2

18 04 2007

Depois de ter sido explicado o primeiro desafio, vamos partir para o segundo.
Que tal algumas operações bit-a-bit ?


<?php
  
// desafio2.php
  
$x 2;
  {
    
$x += print(‘Iniciando ‘);
    {
        echo 
‘desafio 2’;
        
$y $x << 1;
    }
    
$y $x $y sprintf(‘%d’,~($y^$x));

    $z = print(“\n”);
    
    if (
$x $y) {
        
$x ^= $x;
    } {
        
$y ^= $y;
    } {
        if (
$x $y) {
            echo 
‘$y menor do que $x’;
        } else {
            echo 
‘$y maior do que $x’;
        }
    }
  }
  echo 
“\n”;

A pergunta é: O que será exibido na execução do script ?
Resposta e explicação em breve.
Nota: Não vale executar para saber : )





Resposta Desafio do Dia

18 04 2007

Fala galerinha : )
Bom, existem certas pessoas ai que propoem desafios, não sabem resolver, e ai ficam me implorando no msn para que eu resolva.
Vamos então dar uma explicação aí sobre o funcionamento desse código, e demonstrar o resultado.


<?php
// desafio1.php

$n  'X';
$
$n 'N';
$m  'Y';
$
$m 'M';
$c  = (int)($n == $$n);

echo $
    {
        $c == 
    
$n:
    
$m
    
};
?>

Como todos sabem, o símbolo de $, indica a declaração de uma variável, mas muitos não conhecem a utilização do $$
O símbolo $$, significa que estamos utilizando o valor definido na váriavel, para transforma-la em variável. Hein?
Vejamos esse exemplo:


<?php

$x 'var1';

// Essa linha é o mesmo que $var1 = 'Oi, sou a variavel 1';
$$x 'Oi, sou a variavel 1';

echo $var1;

?>

Acho que esse exemplo deixa tudo bem claro né?
Acredito que outra parte que pode confundir no código, é o cast que o nosso amiguinho faz:
$c = (int)($n == $$n);
Isso ai nada mais é do que o retorno de um if. Ele verifica se $n == $$n, ou seja, está verificando se $n == $X. Caso seja, isso ai deve retornar true, caso não seja deve retornar false. Aquele (int) na frente, converte o tipo bool para o tipo int. True será convertido para 1, false será convertido para 0.
Como sabemos que $n não é igual a $X, essa sentença irá retornar 0.

Agora vem a pegadinha da coisa, a função echo. Irei escreve-la em uma só linha para ficar mais claro:

echo ${ $c == 1 ? $n : $m };

O que o rapazinho faz ai, é basicamente um if também, perguntando se $c é igual a 1 (que nós já sabemos que não é). Caso $c fosse igual a 1, essa sentença retornaria o valor de $n, mas como não é, o que ela faz é retornar o valor de $m. Sabemos que $m vale ‘Y’, logo, reescrevendo essa linha após o resultado do if, teriamos:

echo $Y;

$Y nós sabemos que vale ‘M’. Tadam! Respondido o desafio do menino E. Silva ; D
Espero que tenham achado interessante ; D

[]s





Desafio do dia

17 04 2007

O que será exibido durante a execução do seguinte script (se funcionar):


<?php
// desafio1.php

$n  ‘X’;
$
$n ‘N’;
$m  ‘Y’;
$
$m ‘M’;
$c  = (int)($n == $$n);

echo $
    {
      $c == 
        
$n:
        
$m
    
};
?>

Explicação no próximo post (junto com mais um desafio) : )





PHP / refactoring: Como ?

15 04 2007

Refatorar código em PHP normalmente não é simples.

As IDEs que mais utilizei até hoje, como pdt (aka eclipse + plugins), zend studio e quanta plus não oferecem (ou não ofereciam na época) suporte a nenhum tipo de refatoração. Nada de renomear variável, função, classe, método.

Talvez a maior dificuldade em se trabalhar com com isso seja a tipagem fraca do PHP (somente talvez). Mas alguns trabalhos encontrados na internet, como por exemplo o phc – php compiler (não se deixe enganar pelo nome), podem ajudar: Há aqui um exemplo de como modificar chamadas de uma função para outra. Bastante trabalho para uma tarefa relativamente simples; O phc transforma o código php em uma AST – Abstract Syntax Tree e o exemplo atravessa essa árvore efetuando as modificações.

Algumas classes implementadas em PHP mesmo também são encontradas no PEAR. Mas também não há nada que seja muito utilizável.

Acredito que o que se tenha de mais “útil” no momento são as funções da extensão tokenizer (que é compilada por padrão). Com ela podemos trabalhar mais facilmente com um script, para criarmos algum tipo de ferramenta útil para refatoração. Vejamos por exemplo, como criar uma função para modificar o nome de uma variável:


<?php
// arquivo sample.php

$foo   ‘foo’;
$hello “Ola $foo\n”;

// variavel $foo no comentario nao sera modificada

function foo()
{
    
// variavel $foo neste contexto sera modificada
    
$foo ‘1’;
    echo 
$foo;
}
    
echo 
$hello;
?>


<?php
// arquivo change_var_name.php

/**
 * Funcao que ira modificar o nome de uma variavel
 *
 * @param  array  $tokens  Array com os tokens a serem analisados
 * @param  string $oldName Nome da variavel que sera modificada
 * @param  string $newName Novo nome da variavel
 * @return string Codigo-fonte referente aos tokens fornecidos, com a 
 * variavel devidamente modificada
 */
function changeVarName($tokens$oldName$newName)
{
    
// variavel que ira conter o codigo-fonte a ser retornado
    
$ret ;
    
    
// como $tokens e’ um array, utilizamos foreach para
    // passar por todos os seus itens
    
foreach ($tokens as $token) {
    
        
// quando se obtem os tokens de um arquivo, eles vem em um 
        // array contendo o numero do token e o valor ou em uma string,
        // contendo apenas o valor. Entao verificamos qual o caso.
        
if (!is_array($token)) {
            
$tokenName  false;
            
$tokenValue $token;
        } else {
            
$tokenName  token_name($token[0]);
            
$tokenValue $token[1];
        }

        // se nao ha o nome/numero do token, siginifica que ele nao e’ uma variavel,
        // pois elas contem o numero e o valor. Entao podemos adicionar o token ao
        // codigo-fonte que sera retornado e passar para o proximo token
        
if (!$tokenName) {
            
$ret .= $tokenValue;
            continue;
        }        
        
        
// verificamos se o token e’ uma variavel – T_VARIABLE. Se nao for, adicionamos
        // o valor do token ao codigo-fonte que sera retornado e passar para o proximo token
        
if ($tokenName != ‘T_VARIABLE’) {
            
$ret .= $tokenValue;
            continue;
        }

        // verificamos se o valor do token, ou seja, o nome da variavel, e’ o mesmo
        // que queremos modificar. Se nao for, o processo e’ o mesmo do anterior, adicionamos
        // o valor ao codigo-fonte e passamos para o proximo token
        
if ($tokenValue != $oldName) {
            
$ret .= $tokenValue;
            continue;
        }

        // se chegou ate aqui, significa que o token e’ uma variavel e tem o nome que
        // precisa ser modificado. Entao modificamos o valor do token e o adicionamos ao
        // codigo-fonte que sera retornado
        
        
$tokenValue $newName;
        
$ret .= $tokenValue;
    }
    
    
// retornamos o fonte
    
return $ret;
}

// exemplo de uso da funcao

// obtemos o conteudo do arquivo que iremos modificar
$arquivo file_get_contents(‘sample.php’);

// e utilizamos a funcao token_get_all para obter todos
// os tokens do arquivo. Observe que tudo no script e’
// tratado como sendo um token
$tokens  token_get_all($arquivo);

// modificamos $foo para $bar
$bla changeVarName($tokens‘$foo’‘$bar’);

echo $bla;

E, executando:

$ php change_var_name.php
<?php
// arquivo sample.php

$bar = ‘foo’;
$hello = "Ola $bar\n";

// variavel $foo no comentario nao sera modificada

function foo()
{
// variavel $foo neste contexto sera modificada
$bar = ‘1’;
echo $bar;
}

echo $hello;
?>

Exemplo bem simples de como poderiamos utilizar tokenizer para refatorar código. Observe que o nome da variável foi modificada tanto no contexto global, quanto no contexto da função “foo”. Alguns outros detalhes poderiam ser observados, mas quem sabe em um post futuro.

É bem possível (e acho que relativamente fácil) trabalhar melhor neste exemplo para se definir onde se deseja modificar a variável. E quem sabe nos próximos dias escrever uma classe para refatorar realmente, permitindo modificar nome funções, classes e outras coisas úteis.

E para quem não sabe o que é refatoração, vale uma lida no artigo da wikipedia e em Refactoring Home Page.





espeak-php / OOP

5 04 2007

Faz uns dias já que modifiquei o espeak-php, deixando a OOP.
O que era espeak_* tornou-se método.

era

espeak_setVoiceByName(‘pt’);

agora:

$esp = new Espeak();
$esp->setVoiceByName(‘pt’);

E as constantes que eram globais, agora fazem parte da classe:
era:

espeak_setParameter(ESPEAK_VOLUME, 90, 0);

agora:

$esp->setParameter(Espeak::VOLUME, 90, 0);

E nesse tempo encontrei uma utilidade maior para o espeak: Debug (sim, pog, eu sei)…
Sabe aquele método daquela classe que é chamado via ajax, e que é difícil de se depurar ? É, coloque ele pra falar… : D





Notícias e links – 05/04

5 04 2007

Sim, há notícias de várias semanas… Fazer o que…

Validating Incoming Data by Using Polymorphism with Objects in PHP 5
Building Interpreter Classes with PHP 5
Building Dynamic Web Pages with Polymorphism in PHP 5
Bons artigos (como normalmente são) no devshed

650 PHP Tutorials
Falando sobre diversos assuntos, desde básicos até mais “avançados”

111 PHP Articles
Com os outros 650, é leitura para o resto do ano : )

Five common PHP design patterns
Mais sobre design patterns (que acho que nunca é o bastante); Fala um pouco sobre factory, singleton, observer, chain-of-command e strategy. Todos com exemplos de código e diagrama descrevendo o funcionamento. Leitura rápida, vale uma passada.

PHP Sessions – Files vs Database Based
Dicas para utilização de mysql como “session handler”.
Notei um dia desses que php 5.2 (não sei se outras versões também) é compilado com suporte a sqlite por padrão e com isso, suporte a sqlite como “session handler”. Verei algum esquema em breve para compartilhar sessão entre servidores futuramente.

CodeGear™ Announces General Availability of Delphi® for PHP
Após muita espera (não minha, mas de muita gente) foi liberado o Delphi4php, com trial de 1 dia 14 dias de funcionamento.
Não consegui testar, não tenho windows instalado (e nem pra instalar) e não funcionou no wine, chegou no segundo ou terceiro passo e dava um erro de uma função não implementada (no wine).
Consta que já há um crack para o delphi4php, para tornar full a versão trial.
Para quem tiver curiosidade, assim como eu tive, foi disponibilizado também o vcl4php que são os componentes utilizados. Lá você encontrará adodb, jscalendar, nusoap, smarty e xajax, para citar apenas os mais conhecidos. Ou seja, é a cola da cola (parafraseando o “php is glue”). Há também código próprio lá, que… bem, prefiro não comentar…

Instant SQL Formatter
Interessante, as vezes encontra-se subqueries super-aninhadas, terriveis de ler… Funciona com diversos dialetos de sql.

Data Generator
O Lorem Ipsum do sql. Conheci hoje, muito legal.

Emulating Analytic (AKA Ranking) Functions with MySQL
Using the New MySQL Query Profiler
Mais dicas sobre mysql. Esta última é bastante interessante, pode ajudar a encontrar gargalos em uma aplicação.

PHP Search Engine Showdown

FPDI Import existing PDF documents into
“FPDI is a collection of PHP classes that allow developers to read pages from existing PDF documents and to use them as templates in FPDF by Olivier Plathey.”

Interessante. Não testei, mas de qualquer forma é interessante.