Pergunta semelhante foi encerrada no SO.
Às vezes, quando estamos programando, descobrimos que alguma estrutura de controle específica seria muito útil para nós, mas não está diretamente disponível em nossa linguagem de programação.
Quais estruturas de controle alternativas você acha que são uma maneira útil de organizar a computação?
O objetivo aqui é obter novas formas de pensar sobre a estruturação do código, a fim de melhorar o chunking e o raciocínio.
Você pode criar uma sintaxe / semântica desejada agora não disponível ou citar uma estrutura de controle menos conhecida em uma linguagem de programação existente.
As respostas devem fornecer idéias para uma nova linguagem de programação ou aprimorar uma linguagem real.
Pense nisso como um debate de ideias, então publique algo que você acha que é uma ideia maluca, mas que pode ser viável em alguns cenários.
É sobre programação imperativa.
Respostas:
OK, esta é uma pergunta divertida.
Eu também gostaria de ter um general
else
por enquanto e por loops, para quando a condição não for verdadeira no primeiro teste:Isso evita o recálculo incômodo da condição ou o armazenamento em uma variável.
fonte
while ... else
construção da maneira que Macneil a descreve no PHP. Eu acho que é uma ótima idéia, porque o "aqui estão os resultados / não houve resultados" é um idioma bastante comum nos aplicativos da web.Por que não misturar algumas respostas em uma?
Uma sintaxe de construção de controle de fluxo generalizada e extensível em uma linguagem imperativa seria bastante útil e divertida. Até que isso apareça, acho que vou usar o Lisp ou algo assim.
fonte
seventh { ... }
.Estruturas de controle como funções.
Quero
for
,if
,else
,while
, etc, para ser funções, e não estruturas especiais.Eu quero
return
,try/except
egoto
ser derivado de continuações.É claro que isso tem menos a ver com uma estrutura de controle específica e mais com a forma como você vê as estruturas de controle em geral, a meta das estruturas de controle.
fonte
for
,if
,else
, ewhile
como as funções que me faz inferir que os parâmetros para essas funções precisam ser preguiçosamente executado, a fim de comportar o mesmo que as construções originais. Ter a capacidade de executar preguiçosamente seria bom.return
, exceções, etc. Mas agora o programador especialista possui uma ferramenta adicional poderosa em sua caixa de ferramentas, se necessário. Além disso, as línguas IMHO não devem ser "emburrecidas". Os idiomas devem ter a capacidade de oferecer suporte ao aumento da experiência e ao crescimento do conhecimento em CS.O artigo vinculado definitivamente esclarece os N + 1/2 Loops de Donald Knuth . Expressado em C / C ++ / Java:
Isso é útil para ler linhas ou caracteres de um arquivo, testar se você atingiu o EOF e depois processá-lo. Estou tão acostumado a ver o padrão
for(;;)..if(..)break;
aparecer que é idiomático para mim. (Antes de ler o artigo de Knuth, reimpresso no livro Literate Programming , este costumava ser um "wtf?".)Knuth sugeriu as palavras
loop/while/repeat
- chave :Onde
S
eT
são espaços reservados para uma série de zero ou mais instruções eC
é uma condição booleana. Se não houvesse umaS
instrução, seria um loop while e, se não houvesse umaT
instrução, seria um loop do.Essa construção em si poderia ser generalizada, permitindo zero ou mais
while C
cláusulas, tornando-a perfeita para expressar loops infinitos e, em seguida, algumas condições mais raras que precisariam de duas verificações.No mesmo artigo, Knuth sugeriu um mecanismo de sinalização que seria uma versão local de exceções de lançamento / captura (como uma alternativa ao uso de goto).
Para mim? Desejo que a Java suporte a otimização de chamada de cauda, para que eu possa expressar qualquer estrutura de controle geral, conforme necessário.
Atualização: esqueci de mencionar que muitos programadores de C / C ++ / Java resolvem esse problema usando uma atribuição incorporada na condição de
while
:Usando os termos da construção de Knuth, isso é permitido quando
S
eC
pode ser combinado em uma única expressão. Algumas pessoas odeiam ver a atribuição incorporado acima, enquanto outros odeiam ver obreak
nofor (;;)
acima. Mas quandoS
eC
não pode ser combinado, como quandoS
possui várias instruções,for (;;)
é a única alternativa sem repetir o código. A outra alternativa é simplesmente duplicar oS
código:A
loop/while/repeat
alternativa de Knuth parece muito melhor.fonte
repeat-until
loop Pascal .do while ... loop until
- a pré-condição e a pós-condição são opcionais, e eu (vagamente) lembro de usar as duas em um loop. Para sua condição intermediária, há o Adaexit when ...;
. A principal vantagemif ... break;
é que você pode escreverexit loopname when ...;
para sair de vários loops aninhados (mas não necessariamente todos) ao mesmo tempo. Provavelmente um pouco mais visível do que essa pausa também.A linguagem BCPL tinha uma
valueof
expressão que poderia ser usada para transformar uma sequência de instruções em uma única expressão:Onde
some series of statements
pode haver qualquer coisa e o todo évalueof
avaliadov
.Isso pode ser útil em Java para quando você precisar calcular um argumento para chamar um
this()
ousuper()
(que requer que nada aconteça antes dele). Obviamente, você pode simplesmente escrever um método separado, mas isso pode ser um problema se você precisar passar muitos valores locais para o contexto.Se você puder usar as
final
variáveis necessárias, já poderá fazer umvalueof
em Java usando classes internas anônimas:fonte
({ statement1; statement2; ...; result-expr; })
. Vi outros lugares semelhantes também, mas não me lembro onde. Provavelmente todos copiados do BCPL, no entanto.faz o mesmo que:
faz o mesmo que:
fonte
unless
.Em uma nota diferente, eu gostaria de ver um melhor suporte para iteradores nas linguagens de programação. Em particular, para quando você quiser descer duas coleções em pares :
Algumas linguagens dinâmicas já podem ter isso, ou suportam facilmente via bibliotecas e macros, mas acho que isso está no espírito da sua pergunta.
Se os dois conjuntos não tiverem o mesmo tamanho, isso poderá gerar uma exceção ou um
else
loop após o sinalizar que houve uma diferença nos tamanhos.Naturalmente, você pode generalizar isso ao descer três ou mais listas.
Atualização: Também seria útil fazer o produto cartesiano entre iteráveis:
que seria nada mais que loops aninhados:
Estou um pouco preocupado que, entre as duas notações que forneço aqui, exista uma diferença de O (n) e O (n ^ 2) no número de pares, apenas com a alteração de um único caractere.
fonte
for a, b, c in itertools.product(iter1, iter2, iter3):
dá-lhe o produto cartesiano avaliado preguiçosamente. O que é isso? Você deseja permutações e combinações de um determinado iterador também?itertools.permutations
,itertools.combinations
.Existe o chamado "Dijkstra's Loop" (também chamado "Dijkstra's Guarded Loop"). Foi definido na The Guarded Command Language (GCL) . Você pode encontrar algumas informações sobre a sintaxe e a semântica no artigo da Wikipedia acima, na seção 6 Repetição: do .
Atualmente, conheço uma linguagem de programação que suporta diretamente essa estrutura de controle. É Oberon-07 (PDF, 70 KB). E suporta "Loop de Dijkstra" na sua forma de declaração while. Veja a seção 9.6. Declarações While no PDF acima.
PS Esta é uma cópia da minha resposta SO .
fonte
Expressões em estilo de ícone com retorno interno.
O Python obtém muitos dos benefícios do gerador de ícones - e faz um trabalho melhor deles em geral, a IMO. E, em princípio, o retorno era apenas um tipo de exceção, mas era a simplicidade das expressões o equivalente aproximado de ...
para lidar com casos de falha, como divisão por zero.
Onde Icon ficou louco - não há operadores de comparação com retorno booleano. As comparações sempre foram bem-sucedidas ou desencadearam o retorno, e havia outra questão semântica que agora estou tentando desesperadamente lembrar que ... bem, digamos que provavelmente seja mais reprimida do que esquecida.
Eu sempre pensei que eles deveriam ter uma
if
expressão sem outra parte -if (condition, success-value)
tipo de coisa, voltando atrás se a condição retornar falsa - e descartar as comparações estranhas.EDIT Lembro-me - óbvio realmente. Uma comparação com dois argumentos é bem-sucedida ou falha - ela não calcula um novo valor para retornar. Então, quando for bem-sucedido, o que ele retornará? Resposta - um dos argumentos. Mas se você escrever
a > b
, qual é o argumento lógico para retornar -a
oub
? E se você escreverb < a
? Eu acho que sempre retornou o argumento certo, o que faz tanto sentido quanto qualquer outra coisa, mas ainda assim normalmente parecia o argumento errado para mim.fonte
Esta é apenas uma ideia e sintaxe gerais:
A condição TAMBÉM é sempre avaliada. ELSE funciona como de costume.
Também funciona para o caso. Provavelmente, é uma boa maneira de eliminar a declaração de quebra:
pode ser lido como:
Não sei se isso é útil ou simples de ler, mas é um exemplo.
fonte
O estilo de passagem de continuação vem à mente. Então, é claro, você também gostaria de ter a Otimização de chamada de cauda .
fonte
goto return ...;
declaração, tornando explícita a intenção de chamar a cauda, portanto, se o compilador não puder torná-lo iterativo, será um erro.Ramificação de encadeamento sem costura, possui sintaxe como uma função, mas é executada em um encadeamento separado e não pode acessar dados que não foram passados inicialmente para ele.
Quando um ramo é chamado, ele retornará imediatamente um identificador.
O identificador pode ser usado para verificar se a tarefa está concluída.
Se o resultado for solicitado antes que a execução seja concluída, o encadeamento principal simplesmente aguardará.
Isso não cobriria os cenários de multithreading mais avançados, mas forneceria uma maneira facilmente acessível de começar a utilizar vários núcleos.
fonte
handle.finished()
teste, masspawn
esync
tudo o que você precisa para 90% das tarefas de programação paralela.O PRIMEIRO e o THEN são executados se qualquer um dos três condicionais for avaliado como verdadeiro. O PRIMEIRO bloco é executado antes do bloco condicional e, em seguida, depois do bloco condicional.
A gravação condicional ou final ELSE após a instrução FIRST e THEN é independente desses blocos.
Pode ler-se como:
Essas funções são apenas um formulário para ler. Eles não criariam escopo. É mais como um gosub / return do Basic.
Utilidade e legibilidade como assunto de discussão.
fonte
Às vezes me pego escrevendo um loop que precisa fazer algo diferente durante a primeira iteração. Por exemplo, exibindo tags <th> em vez de <td>.
Eu lido com essa situação com uma bandeira booleana. Algo assim:
Parece bobagem verificar o valor de
first
todas as iterações quando elas serão falsas na maioria das vezes.Eu gostaria de ter uma opção de loop para especificar um corpo de loop diferente na primeira iteração. Não haveria necessidade de uma variável separada. O código compilado também não precisaria de um, porque o código gerado teria dois corpos, um para a primeira iteração e outro para o restante.
fonte
print(out, first "<th>" then "<td>")
if (!first) gimme-a-comma ();
, mas praticamente a mesma coisa. Uma objeção que eu teria, no entanto - se você o encerrar adequadamente, acabará com coisas como o método de junção de strings Python - por mais que precise do padrão básico, o loop subjacente não precisará ser reescrito com tanta frequência.if (!first)
, mas os micro-otimizadores podem levantar objeções de previsão de ramificação.if (!first)
e deixar um compilador otimizador decidir se o corpo do loop é pequeno o suficiente para que se desenrolar e se livrarfirst
seja uma vitória líquida.[copiado da minha própria resposta no stackoverflow]
ignoring
- Ignorar exceções que ocorrem em um determinado bloco de código.Com uma construção de controle de ignorância, você pode escrevê-la de forma mais concisa e mais fácil como:
[Scala fornece isso (e muitas outras construções de controle de manipulação de exceção) em sua biblioteca padrão, no pacote util.control. ]
fonte
try..catch
bloco vazio é uma coisa; obriga a reconhecer o erro e ignorá-lo deliberadamente; ao jogar pedaços de código sob uma ignição global, podem ocorrer problemas quando essas exceções são lançadas, além de levar a maus hábitos de programação.try
bloco, exceto que lista as exceções que captura e ignora na frente, em vez de mais tarde. Isso pode até ser uma vantagem de legibilidade - por exemplo, permitir que o leitor saiba que um arquivo ausente não é um erro antes mesmo de ler a chamada em aberto.Ao invés de:
Faça o Python, ou agora também o C #:
Scala tem muitos novos recursos.
Finalmente, idiomas como o Clojure podem ser estendidos para fornecer a funcionalidade extra.
fonte
Eu tenho duas idéias
Muitas vezes, acho que estou me repetindo em
catch
blocos. Isso pode ser um pouco ajudado através da extração de métodos, mas isso pode causar confusão desnecessária se os métodos forem muito curtos ou não forem dignos de um método. Então, seria bom aninharcatch
blocos:Na programação da web, também me vejo frequentemente fazendo algo assim (este não é um exemplo real, portanto não analise casos de ficção):
Em Javascript (bem, ECMAScript e talvez outros que eu não conheça), já que qualquer valor pode ser avaliado como uma condição,
||
pode ajudar.Eu realmente gosto da aparência e desejo que mais idiomas, especialmente alguns do lado do servidor, tenham suporte para isso. (O PHP pode avaliar qualquer coisa como uma condição, mas converte toda a expressão condicional em um booleano em vez de preservar o valor. Não sei sobre Python ou Ruby.) Ele pode ficar complicado depois de três casos, mas se você tiver mais Em três casos, você também pode ter um design de software ruim.
fonte
x if c else y
sintaxe de expressão condicional , um dos principais motivos que aconteceu foi o fato de muitas expressões usarem essa semântica||
e&&
serem sutilmente problemáticas. Um caso comum do IIRC era um valor (como zero) válido para o aplicativo que estava sendo tratadofalse
, sendo descartado para que um substituto inválido fosse usado. No entanto - veja minha resposta WRT, a linguagem de programação Icon, que pode ter expressões comoget1() else get2() else default
.O interruptor generalizado disse acima:
Em Haskell:
fonte
Em C #, eu gostaria de usar simples
switch () { ... }
, mas extensível com essas expressões:E assim por diante. O mesmo com números ou outros tipos (que suportes
IComparable
,IConvertible
...)Isso pode tornar meu código mais lacônico e legível.
fonte
É uma pergunta divertida, como @Macneil disse.
Minha estrutura de controle incomum favorita, que eu (tosse humilde) descobri, é a execução diferencial .
Tem certos usos. Para mim, o uso predominante está na programação de interfaces de usuário, que é uma instância do problema mais geral de manter dados redundantes em correspondência. Por um lado, existem dados do aplicativo e, por outro, há controles da interface do usuário que precisam ser mantidos em concordância. Isso soa como "vinculativo", mas na verdade há muito mais.
Geralmente eu o implico por macros em C ou C ++. Em C #, eu tenho que fazer isso com instruções de expansão manual. Isso é uma dor, mas funciona.
Uma vez eu o implementei em termos de macros Lisp e ficou muito limpo. Não exigiu cuidado por parte do programador. Eu poderia ter feito a mesma coisa em qualquer outra linguagem estruturada se tivesse o cuidado de escrever um analisador completo e depois gerar as coisas certas. Esse é um grande projeto, e eu não o fiz.
fonte
Estruturas de controle "tradicionais", como
for
o controle do trabalhador, o mantêm subserviente às ideologias corruptas da elite capitalista dominante. É por isso que eu uso estruturas de controle alternativasph0r
. É comofor
, mas mais radical: você não vai pegarph0r
terno e gravata, jorrando alguns BS corporativos.ph0r
mantém real, cara.Combate o Poder!
fonte
for
Loop mais simplesfonte