Pergunta

Depois de me convencer de que pausas/continuações rotuladas são um total "não-não" aqui, preciso de ajuda para remover o rótulo do meu código.

Eu tenho uma matriz quadrada e um vetor de mesmo comprimento.O vetor já contém alguns valores e dependendo dos valores da matriz o vetor é alterado no loop.

Espero que o fragmento de código seja basicamente compreensível…

vectorLoop:
for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) ) continue vectorLoop;

    matrixLoop:
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue matrixLoop;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) continue vectorLoop;
    }
    setValueInVector( v, idx );
}     

Por favor, me convença de que existe uma versão mais legível/melhor sem os rótulos.

Foi útil?

Solução

Olhando para as soluções apresentadas até agora:

  • Todos eles parecem menos legíveis que o original, pois envolvem gastar mais código no mecanismo do código do que no próprio algoritmo

  • Alguns deles estão quebrados ou estavam antes de serem editados.O mais contundente é o fato de que as pessoas estão tendo que pensar muito sobre como escrever o código sem rótulos e sem quebrar nada.

  • Alguns vêm com uma penalidade de desempenho ao executar o mesmo teste duas vezes, o que nem sempre é trivial.A alternativa para isso é armazenar e passar booleanos, o que fica feio.

  • Refatorar a parte relevante do código em um método é efetivamente uma operação autônoma:ele reorganiza a forma como o código é apresentado no arquivo, mas não afeta a forma como ele é executado.

Tudo isso me faz acreditar que, pelo menos no caso desta questão formulada, o rótulo é a solução correta e não precisa ser refatorado.Certamente há casos em que os rótulos são usados ​​incorretamente e devem ser refatorados.Só não acho que isso deva ser tratado como uma regra inquebrável.

Outras dicas

@Patrick, você está assumindo que está chamando setValueInVector( v, idx );no final do segundo loop está OK.Se o código for idêntico, logicamente, ele deverá ser reescrito para algo assim:

for( int idx = 0; idx 

Facilmente, meu bom homem.

for( int idx = 0; idx < vectorLength; idx++) {
  if( conditionAtVectorPosition( v, idx ) ) continue;

  for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
    if( anotherConditionAtVector( v, rowIdx ) ) continue;
    if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) break;
  }
  if( !conditionAtMatrixRowCol( m, rowIdx, idx ) )
    setValueInVector( v, idx );
}

EDITAR:Muito correto, você é Anders.Editei minha solução para levar isso em consideração também.

Da leitura do seu código.

  • Percebi que você eliminou as posições inválidas do vetor em ConditionAtVectorPosition e depois removeu as linhas inválidas em anotherConditionAtVector.
  • Parece que verificar linhas em anotherConditionAtVector é redundante, pois qualquer que seja o valor de idx, anotherConditionAtVector depende apenas do índice de linha (assumindo que anotherConditionAtVector não tenha efeitos colaterais).

Então você pode fazer isso:

  • Obtenha primeiro as posições válidas usando condiçãoAtVectorPosition (estas são as colunas válidas).
  • Em seguida, obtenha as linhas válidas usando anotherConditionAtVector.
  • Finalmente, use conditionAtMatrixRowCol usando as colunas e linhas válidas.

Eu espero que isso ajude.

@Nicolas

Alguns deles estão quebrados ou estavam antes de serem editados.O mais condenatório é o fato de as pessoas estarem tendo que pensar muito sobre como escrever o código sem rótulos e não quebrar nada.

Eu tenho um ponto de vista diferente:Alguns deles estão quebrados porque é difícil descobrir o comportamento do algoritmo original.

Sei que é subjetivo, mas não tenho problemas para ler o algoritmo original.É mais curto e claro do que as substituições propostas.

O que todas as refatorações neste tópico fazem é emular o comportamento de um rótulo usando outros recursos de linguagem - como se você estivesse portando o código para uma linguagem que não possui rótulos.

Alguns vêm com uma penalidade de desempenho ao executar o mesmo teste duas vezes, o que nem sempre é trivial.A alternativa para isso é armazenar e passar booleanos, o que fica feio.
A penalidade de desempenho é menor.No entanto, concordo que executar um teste duas vezes não é uma boa solução.

Acredito que a questão era como remover os rótulos, e não como otimizar o algoritmo.Pareceu-me que o autor da postagem original não sabia como usar as palavras-chave 'continuar' e 'quebrar' sem rótulos, mas é claro que minhas suposições podem estar erradas.

Quando se trata de desempenho, o post não fornece nenhuma informação sobre a implementação das outras funções, então, pelo que sei, eles poderiam muito bem estar baixando os resultados via FTP, em vez de cálculos simples embutidos pelo compilador.

Dito isto, fazer o mesmo teste duas vezes não é o ideal – em teoria.

EDITAR:Pensando bem, o exemplo não é, na verdade, um uso horrível de rótulos.Eu concordo que "goto é proibido", mas não por causa de um código como este.O uso de rótulos aqui não afeta de forma significativa a legibilidade do código.É claro que eles não são obrigatórios e podem ser facilmente omitidos, mas não usá-los simplesmente porque “usar rótulos é ruim” não é um bom argumento neste caso.Afinal, retirar os rótulos não torna o código muito mais fácil de ler, como outros já comentaram.

Esta questão não era sobre como otimizar o algoritmo - mas obrigado de qualquer maneira ;-)

Na época em que o escrevi, considerei o rotulado continue como uma solução legível.

Eu perguntei SO um pergunta sobre a convenção (ter o rótulo em letras maiúsculas ou não) para rótulos em Java.

Basicamente, todas as respostas me disseram "não as use - sempre há uma maneira melhor!refatorar!".Então postei esta pergunta para pedir uma solução mais legível (e, portanto, melhor?).

Até agora, não estou completamente convencido pelas alternativas apresentadas até agora.

Por favor, não me entenda mal.Os rótulos são maus na maioria das vezes.

Mas no meu caso, os testes condicionais são bastante simples e o algoritmo foi retirado de um artigo matemático e, portanto, muito provavelmente não mudará no futuro próximo.Portanto, prefiro ter todas as partes relevantes visíveis de uma só vez, em vez de rolar para outro método chamado algo como checkMatrixAtRow(x).

Especialmente em algoritmos matemáticos mais complexos, acho muito difícil encontrar nomes de funções "bons" - mas acho que essa é outra questão

Eu acho que os loops rotulados são tão incomuns que você pode escolher qualquer método de rotulagem que funcione para você - o que você tem deixa perfeitamente claras suas intenções com os contínuos.


Depois de liderar a sugestão de refatorar os loops na pergunta original e agora ver o código em questão, acho que você tem um loop muito legível aí.

O que eu imaginei era um pedaço de código muito diferente - colocando o exemplo real, posso ver que é muito mais limpo do que eu pensava.

Minhas desculpas pelo mal-entendido.

Isso funciona para você?Extraí o loop interno em um método CheckedEntireMatrix (você pode nomeá-lo melhor do que eu) - Além disso, meu java está um pouco enferrujado.mas acho que isso transmite a mensagem

for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) 
    || !CheckedEntireMatrix(v)) continue;

    setValueInVector( v, idx );
}

private bool CheckedEntireMatrix(Vector v)
{
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }   
    return true;
}

Gishu tem a ideia certa:

for( int idx = 0; idx < vectorLength; idx++) {
    if (!conditionAtVectorPosition( v, idx ) 
        && checkedRow(v, idx))
         setValueInVector( v, idx );
}

private boolean checkedRow(Vector v, int idx) {
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }  
    return true;
}

Não tenho muita certeza de entender a primeira continuação.Eu copiaria Gishu e escreveria algo como (desculpe se houver alguns erros):

for( int idx = 0; idx < vectorLength; idx++) {
    if( !conditionAtVectorPosition( v, idx ) && CheckedEntireMatrix(v))
        setValueInVector( v, idx );
}

inline bool CheckedEntireMatrix(Vector v) {
    for(rowIdx = 0; rowIdx < n; rowIdx++)
        if ( !anotherConditionAtVector(v,rowIdx) && conditionAtMatrixRowCol(m,rowIdx,idx) ) 
            return false;
    return true;
}

@Sadie:

Todos eles parecem menos legíveis que o original, pois envolvem gastar mais código no mecanismo do código do que no próprio algoritmo

Exteriorizar o segundo loop fora do algoritmo não é necessariamente menos legível.Se o nome do método for bem escolhido, poderá melhorar a legibilidade.

Alguns deles estão quebrados ou estavam antes de serem editados.O mais contundente é o fato de que as pessoas estão tendo que pensar muito sobre como escrever o código sem rótulos e sem quebrar nada.

Eu tenho um ponto de vista diferente:alguns deles estão quebrados porque é difícil descobrir o comportamento do algoritmo original.

Alguns vêm com uma penalidade de desempenho ao executar o mesmo teste duas vezes, o que nem sempre é trivial.A alternativa para isso é armazenar e passar booleanos, o que fica feio.

A penalidade de desempenho é menor.No entanto, concordo que executar um teste duas vezes não é uma boa solução.

Refatorar a parte relevante do código em um método é efetivamente uma operação autônoma:ele reorganiza a forma como o código é apresentado no arquivo, mas não afeta a forma como ele é executado.

Eu não vejo sentido.Sim, isso não muda o comportamento, tipo...reestruturação?

Certamente há casos em que os rótulos são usados ​​incorretamente e devem ser refatorados.Só não acho que isso deva ser tratado como uma regra inquebrável.

Eu concordo totalmente.Mas, como você apontou, alguns de nós temos dificuldades ao refatorar este exemplo.Mesmo que o exemplo inicial seja legível, é difícil mantê-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top