Sua tarefa é aplicar um recurso a uma linguagem de programação, implementando uma biblioteca muito inteligente ou processando o texto de entrada e / ou aprimorando o processo de compilação.
Idéias:
- Adicione apresentação em estilo PHP intercalada em C (por exemplo
<?c printf("Hello,"); ?> world!
). - Adicione um operador coalescente nulo a um desses idiomas que não é C #.
- Adicione macros ao PHP.
- Adicionar
goto
ao JavaScript. - Adicione um padrão correspondente ao idioma X.
- Adicione suporte ao namespace a um idioma que não o possui.
- Faça C parecer PHP.
- Faça Haskell parecer Pascal.
- ... (fique à vontade para postar ideias na seção de comentários)
Regras:
- Traga algo para a mesa. Não basta dizer "Template Haskell" para adicionar recursos de metaprogramação ao Haskell. Isso não é StackOverflow.
- Toda a implementação deve caber em uma tela (sem contar o exemplo).
- Não hospede o código em um site externo especificamente para esta tarefa.
- O recurso mais impressionante ou surpreendente vence.
Não se preocupe em implementar o recurso 100% corretamente. Longe disso! O principal desafio é descobrir o que você deseja fazer e cortar com crueldade os detalhes até que sua tarefa planejada se torne viável.
Exemplo:
Adicione um operador lambda à linguagem de programação C.
Abordagem inicial:
Ok, eu sei que gostaria de usar a libgc para que minhas lambdas resolvam os problemas de funarg para cima e para baixo. Eu acho que a primeira coisa que eu preciso fazer é escrever / encontrar um analisador para a linguagem de programação C, então eu precisaria aprender tudo sobre o sistema de tipos de C. Eu teria que descobrir como fazer sentido disso, tanto quanto os tipos. Eu precisaria implementar a inferência de tipo ou simplesmente exigiria que o parâmetro formal fosse digitado conforme fornecido? E todos esses recursos malucos no CI ainda não sabem?
Está bem claro que implementar corretamente o lambda em C seria uma tarefa enorme. Esqueça a correção! Simplifique, simplifique.
Melhor:
Dane-se funargs para cima, quem precisa deles? Eu poderia ser capaz de fazer algo complicado com o GNU C funções aninhadas e expressões declaração . Eu queria mostrar uma incrível transformação sintática em C com código hacker conciso, mas nem precisarei de um analisador para isso. Isso pode esperar por outro dia.
Resultado (requer GCC):
#include <stdio.h>
#include <stdlib.h>
#define lambda(d,e)({d;typeof(e)f(d){return(e);};f;})
#define map(F,A)({typeof(F)f=(F);typeof(*(A))*a=(A);({int i,l=((int*)(a))[-1]; \
typeof(f(*a))*r=(void*)((char*)malloc(sizeof(int)+l*sizeof(*r))+sizeof(int)); \
((int*)r)[-1]=l;for(i=0;i<l;i++)r[i]=f(a[i]);r;});})
#define convert_to(T) lambda(T x, x)
#define print(T, fmt) lambda(T x, printf(fmt "\n", x))
int main(void)
{
int *array = 1 + (int[]){10, 1,2,3,4,5,6,7,8,9,10};
map(print(int, "%d"), array);
double *array2 = map(lambda(int x, (double)x * 0.5), array);
map(print(double, "%.1f"), array2);
long *array3 = map(convert_to(long), array2);
map(print(long, "%ld"), array3);
long product = 1;
map(lambda(int x, product *= x), array);
printf("product: %ld\n", product);
return 0;
}
Isso foi fácil, não foi? Até joguei uma map
macro para torná-la útil e bonita.
fonte
Respostas:
Sintaxe OOP em Haskell
Objetos podem ter propriedades:
... e métodos:
fonte
&
e definido assim(&) = flip ($)
.&
porque é o operador unário de 'endereço de' (a implementação de ponteiros em Haskell é deixada como um exercício para o leitor).flip id
goto
em JavaScript?Meu primeiro pensamento foi uma abordagem funcional - adicionar um parâmetro à função para indicar onde a execução deveria começar, usando isso com uma
switch
instrução e um loop externo chamando repetidamente a função em seu próprio valor de retorno . Infelizmente, isso impediria o uso de variáveis locais, pois elas perderiam seus valores a cada goto.Eu poderia usar uma
with
instrução e mover todas as declarações de variáveis para o início da função, mas tinha que haver uma maneira melhor. Eventualmente, veio a mim usar o tratamento de exceções do JavaScript . De fato, Joel Spolsky disse: "Considero que as exceções não são melhores do que as" goto's ... " - obviamente um ajuste perfeito.A idéia era colocar um loop infinito dentro de uma função, finalizada apenas por uma
return
declaração ou uma exceção não capturada. Todos os gotos, tratados como exceções, seriam capturados dentro do loop para impedir seu término. Aqui está o resultado dessa abordagem:Você pode usá-lo assim - mesmo no modo estrito do ES5 - exceto no Internet Explorer ( demo ):
[O Internet Explorer, por algum motivo, falha na avaliação do código de uma função anônima; portanto, seria necessário dar um nome à função (antes de reescrever) e chamá-la usando esse nome. Obviamente, isso provavelmente violaria as regras do modo estrito.]
Isso não permite pular para uma instrução localizada dentro de um bloco (até que construções como o dispositivo de Duff se tornem legais), mas podemos lidar com isso (outra função reescrita auto-executável), certo?
fonte
goto
fosse implementado completamente em JavaScript (para onde você poderia usargoto
para pular de qualquer escopo, até mesmo uma função ), isso implicaria suporte para continuações.#define em Java
Eu pensei que seria divertido implementar macros em Java.
Uso de amostra (converte para código publicado anteriormente; vamos torná-lo estranho):
fonte
Foreach em C
Iterar matrizes (funciona para matrizes estáticas, não aquelas, recebidas pelo ponteiro)
Para testá-lo:
resultado:
fonte
Propriedades em C
Tomasz Wegrzanowski implementou propriedades em C simples, segmentando intencionalmente o programa quando a propriedade é acessada.
Um objeto com uma "propriedade" é configurado criando um
struct
que atravessa várias páginas, garantindo que o endereço de memória da propriedade esteja em uma página diferente dos membros reais dos dados. A página da propriedade está marcada como sem acesso, garantindo que a tentativa de acessar a propriedade causará um segfault. Um manipulador de falhas descobre qual acesso à propriedade causou o segfault e chama a função apropriada para calcular o valor da propriedade, que é armazenado no endereço de memória da propriedade.O manipulador de falhas também marca a página de dados como somente leitura para garantir que o valor calculado permaneça consistente; na próxima tentativa de gravar em um membro de dados, que dispara um segfault, cujo manipulador define a página de dados como leitura-gravação e a página de propriedades como sem acesso (indicando que ela precisa ser recalculada).
fonte
Origem computada no Common Lisp
Inicialmente, implementei o proveniente. Mas isso não foi bom o suficiente.
Inspirado pelo goto computado, decidi implementar o derivado computado.
Exemplos de uso
Para cada declaração proveniente do corpo da tag, ele verifica em cada rótulo se a variável proveniente é igual ao rótulo atual e, nesse caso, salta para a declaração proveniente correspondente.
Greeter
FizzBuzz
fonte
"Auto-strings" em Ruby
O código é bastante simples:
Agora você pode fazer
fonte
Adicionar macros ao PHP
Podemos apenas usar o pré-processador C para esta tarefa.
Um script php:
Canalize-o através do cpp:
Resultado:
fonte
<<<HEREDOC
nada mais é do que três turnos inferiores ou à esquerda e um identificador :-) Isso fará uma substituição macro em cadeias de caracteres heredoc, no entanto.grep -v ^#
conserto disso. Eu acho que isso é suficiente para esta pergunta :-)Guardas decorrespondência de padrõesem PythonO corpo da função tem 288 caracteres.
Osprotetores decorrespondência de padrõespermitem usar funções completamente diferentes, dependendo dos valores do argumento. Embora possa ser facilmente emulado com uma série deif
instruções,osprotetores decorrespondência de padrõespodem ajudar a separar seções do código, e é uma ótima desculpa para fazer uma metaprogramação maluca.pattern_match
é um decorador que cria uma nova função que implementa guardas decorrespondência de padrões. As condições para cada "sub-função" dada em cada docstring nas linhas começando com um pipe (|
). Se todas as condições forem avaliadas com sinceridade, essa versão da função será executada. As funções são testadas em ordem até que uma correspondência seja encontrada. Caso contrário,None
é retornado.Um exemplo ajudará a esclarecer:
fonte
f [a,b,c] = ...
, que não apenas testa o argumento em relação a um predicado, mas vincula as respectivas variáveis após uma correspondência bem-sucedida. Isso ainda é bem legal, no entanto.f (x:xs) = ...
ef [] = ...
). De alguma forma, convoquei guardas para lá, mas foi para lá que tirei|
.Coroutine
Eu não posso ter crédito por isso, então eu marquei CW.
Corotinas em C por Simon Tatham
fonte
Operadores personalizados em Lua
O Pogs abusou habilmente da sobrecarga de operadores em Lua para permitir a definição de operadores de infix personalizados. Expandi isso para dar suporte ao seccionamento do operador (aplicar parcialmente um operador com qualquer um dos operandos) e chamar o objeto resultante como se fosse uma função.
fonte
Cadeias de linhas múltiplas em javascript
nessa sintaxe elaborada para cadeias de
(function(){/*
linhas múltiplas, todas as cadeias de linhas múltiplas serão precedidas por uma nova linha e seguidas por uma nova linha e*/}+'').split('\n').slice(1,-1).join('\n')
.usando essa sintaxe incrível e intuitiva, podemos finalmente usar cadeias de linhas múltiplas:
para pessoas que não gostam da nossa sintaxe simples, temos um compilador para a nossa fabulosa nova linguagem:
o mesmo exemplo, na versão em idioma compilado:
fonte
*/
minhas strings de múltiplas linhas. Isso é super irritante ao incluir regexps nas strings!Lista Sliceable em C # (como Python)
Eu sempre gostei da notação de fatia do python e gostaria que ela estivesse disponível em C #
Uso:
Código, longe de ser à prova de erros:
fonte
Simplifique C
Esse código permite que você escreva programas em C que mais se assemelham a uma linguagem de script. Possui palavras-chave como 'var', 'is', 'string', 'plus', 'equal' e várias outras. Ele funciona através de várias instruções de definição.
Isso permite que você escreva códigos como:
O exposto acima é expandido para:
Provavelmente não é muito útil, mas achei bastante interessante que você pudesse criar essencialmente uma linguagem de programação inteira por meio de vários
#define
s.fonte
#define
s suficientemente complexos , você pode até dar ao seu idioma coisas como manipulação de exceção e coleta de lixo , mantendo a camada C fundamental por baixo.Tcl
Tcl não tem mais
do ... while
oudo ... until
menos ...Exemplo:
uplevel
executa um script no escopo dos chamadores.fonte
Saltar em PostScript
Meu primeiro pensamento foi que eu teria que mexer com a pilha exec, portanto, esse falso início desenterra o operador de continuação para parar o ghostscript (ou xpost).
Mas, é mais simples que isso. Como a posição do arquivo é a mesma para todas as duplicatas do identificador de arquivo (
setfileposition
consome seu argumento, essa é a única semântica útil para essa função).Imprime
5
.Existem algumas limitações com o acima exposto. O salto não é imediato, mas acontece quando o corpo if retorna ao nível superior e o intérprete está novamente lendo o arquivo (em vez de ler a matriz que contém o corpo if). Nesse ponto, o arquivo foi reposicionado e o 'goto' entra em vigor.
fonte
currentfile <pos> setfileposition
contagem de bytes desde o início do arquivo.Symbol#to_proc
com argumentos em RubySymbol#to_proc
é provavelmente um dos meus truques favoritos para escrever um código Ruby realmente sucinto. Suponha que você tenhae você deseja converter o conteúdo de
nums
etext
para flutuadores e palavras em maiúsculas, respectivamente.Symbol#to_proc
permite que você reduza o código assim:para isso:
Impressionante! Mas e se quisermos elevar todos os elementos
nums
ài
potência th ou substituir cada ocorrência des
por*
intext
? Existe alguma maneira de reduzir o código como este?Infelizmente, não há maneira fácil de passar argumentos ao usar
Symbol#to_proc
. Eu já vi isso de várias maneiras, mas provavelmente duas das mais inteligentes e úteis envolvem a correção de macacos naSymbol
classe [ 1 , 2 ]. Ilustrarei o primeiro caminho abaixo.Agora você pode fazer coisas como:
fonte
JavaScript foreach
Resultado
Sintaxe alternativa, mais parecida com Tcl.
fonte
Gotos em Haskell
a idéia básica é que os gotos podem ser parcialmente simulados usando a última declaração em
do
-notations. por exemplo:é equivalente a
como a execução pulará para a última instrução, é ideal expressar gotos.
porque da maneira que é feito, o gotos apenas salta quando está
do
diretamente no bloco de uma definição de nível superior. na verdade, é "chame x e ignore o restante das instruções lexicamente vistas " em vez de "todo x e ignore o restante das instruções", como um verdadeiro goto.o maior problema é que, quando não há como deixar a execução no meio de uma ação de IO - nem
return
isso acontece;return
não faz nada quando não é a última afirmação.isso supera isso capturando o restante das instruções por outro
do
bloco.torna-se
a
print 3
instrução é capturada pelodo
bloco eloop
se torna a última instrução.essa transformação também suporta variáveis presentes no escopo das ações. isso é feito lembrando as variáveis que estão no escopo e passando-as para as ações. por exemplo:
isso simplesmente se traduz em:
algumas notas:
Além disso, uma
return undefined
instrução é adicionada para garantir que odo
bloco de captura não esteja vazio.porque às vezes há ambiguidade de tipo no
do
bloco de captura , em vez deconst
usarmosasTypeOf
, que é o mesmo,const
mas requer que ambos os parâmetros tenham o mesmo tipo.a implementação real (em javascript):
um exemplo:
torna-se:
resultado:
fonte
return
em Haskell é uma função regular e não relacionada à palavra-chave em C / etc.Python Goto
goto.py
Uso
Exemplo de Caso de Teste
Saída de exemplo de caso de teste
Um pouco de diversão com exec (). Pode gerar um erro máximo de profundidade de recursão se não for usado corretamente.
fonte
// importa javascript sem usar especificamente a tag de script em uma página HTML
É coxo, sim, eu sei. Comprimento: 99
fonte
script
marcação. Então, onde exatamente está o novo recurso?