Ihre Aufgabe ist es, ein Feature in eine Programmiersprache zu integrieren, indem Sie entweder eine sehr clevere Bibliothek implementieren oder den eingegebenen Text verarbeiten und / oder den Kompilierungsprozess optimieren.
Ideen:
- Fügen Sie C eine PHP-artige Präsentationsverschachtelung hinzu (zB
<?c printf("Hello,"); ?> world!
). - Fügen Sie einer der Sprachen, die nicht C # sind, einen Null-Vereinigungsoperator hinzu .
- Fügen Sie PHP Makros hinzu.
- Fügen Sie
goto
JavaScript hinzu. - Füge die Musterübereinstimmung zu Sprache X hinzu.
- Hinzufügen von Namespace-Unterstützung zu einer Sprache, in der dies nicht der Fall ist.
- Stellen Sie sicher, dass C wie PHP aussieht.
- Lass Haskell wie Pascal aussehen.
- ... (zögern Sie nicht, Ideen im Kommentarbereich zu posten)
Regeln:
- Bring etwas zum Tisch. Sagen Sie nicht einfach "Template Haskell", um Haskell Metaprogrammierfunktionen hinzuzufügen. Dies ist kein StackOverflow.
- Die gesamte Implementierung sollte in einen Bildschirm passen (ohne das Beispiel zu zählen).
- Hosten Sie Code nicht speziell für diese Aufgabe auf einer externen Site.
- Das beeindruckendste oder überraschendste Feature gewinnt.
Machen Sie sich keine Sorgen, wenn Sie die Funktion zu 100% korrekt implementieren. Weit davon entfernt! Die größte Herausforderung besteht darin, herauszufinden, was Sie tun möchten, und Details bösartig auszuschneiden, bis Ihr geplantes Unternehmen durchführbar wird.
Beispiel:
Fügen Sie der Programmiersprache C einen Lambda-Operator hinzu .
Anfänglicher Ansatz:
Okay, ich weiß, dass ich libgc verwenden möchte, damit meine Lambdas die Aufwärts- und Abwärts-Funarg-Probleme lösen. Ich denke, das erste, was ich tun müsste, ist, einen Parser für die Programmiersprache C zu schreiben / zu finden. Dann müsste ich alles über das Typensystem von C lernen. Ich müsste herausfinden, wie ich es verstehen kann, wenn es um Typen geht. Muss ich eine Typinferenz implementieren oder muss ich einfach nur den formalen Parameter wie angegeben eingeben? Was ist mit all den verrückten Funktionen in CI, von denen ich noch nichts weiß?
Es ist ziemlich klar, dass die korrekte Implementierung von Lambda in C ein großes Unterfangen wäre. Vergiss die Korrektheit! Vereinfachen, vereinfachen.
Besser:
Wer braucht sie? Ich könnte in der Lage sein, mit den verschachtelten Funktionen und Anweisungsausdrücken von GNU C etwas heikles zu machen . Ich wollte eine erstaunliche syntaktische Transformation in C mit knappem, hackigem Code demonstrieren, aber ich brauche dafür nicht einmal einen Parser. Das kann auf einen anderen Tag warten.
Ergebnis (erfordert 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;
}
Das war doch einfach, oder? Ich habe sogar ein map
Makro eingefügt, um es nützlich und hübsch zu machen.
quelle
Antworten:
OOP-Syntax in Haskell
Objekte können Eigenschaften haben:
... und Methoden:
quelle
&
und definiert(&) = flip ($)
.&
da es sich um den unären Operator 'address-of' handelt (die Implementierung von Zeigern in Haskell bleibt als Übung für den Leser).flip id
goto
in JavaScript?Mein erster Gedanke war ein funktionaler Ansatz - der Funktion einen Parameter hinzuzufügen, der angibt, wo die Ausführung beginnen soll, wobei dieser Parameter mit einer
switch
Anweisung und einer äußeren Schleife verwendet wird, die die Funktion wiederholt auf ihren eigenen Rückgabewert aufruft . Leider würde dies die Verwendung lokaler Variablen ausschließen, da diese mit jedem Sprung ihre Werte verlieren würden.Ich könnte eine
with
Anweisung verwenden und alle Variablendeklarationen an den Anfang der Funktion verschieben, aber es musste einen besseren Weg geben. Es kam schließlich zu mir, die Ausnahmebehandlung von JavaScript zu verwenden . Tatsächlich sagte Joel Spolsky: "Ich halte Ausnahmen für nicht besser als" goto's ... " - offensichtlich eine perfekte Passform.Die Idee war, eine Endlosschleife in eine Funktion zu setzen, die nur durch eine
return
Anweisung oder eine nicht erfasste Ausnahme beendet wird. Alle GOTOS, die als Ausnahmen behandelt werden, würden in der Schleife abgefangen, um ihre Beendigung zu verhindern. Hier ist das Ergebnis dieses Ansatzes:Sie können es wie folgt verwenden - auch im strengen ES5-Modus - außer im Internet Explorer ( Demo ):
[Aus irgendeinem Grund kann Internet Explorer den Code einer anonymen Funktion nicht auswerten. Daher muss der Funktion ein Name zugewiesen werden (bevor sie neu geschrieben wird), und sie muss unter diesem Namen aufgerufen werden. Natürlich würde das wahrscheinlich gegen die Regeln des strengen Modus verstoßen.]
Dies erlaubt nicht, zu einer Anweisung zu springen, die sich in einem Block befindet (bis Konstrukte wie Duffs Gerät legal sind), aber wir können uns damit befassen (eine andere, selbstausführende, umgeschriebene Funktion), oder?
quelle
goto
es vollständig in JavaScript implementiert (wo Siegoto
aus jedem Bereich herausspringen könnten, sogar aus einer Funktion ), würde dies die Unterstützung von Fortsetzungen implizieren.#define in Java
Ich dachte, es würde Spaß machen, Makros in Java zu implementieren.
Beispielnutzung (wird in zuvor veröffentlichten Code konvertiert; lasst es uns komisch machen):
quelle
Foreach in C
Arrays iterieren (funktioniert für statische Arrays, nicht für solche, die über einen Zeiger empfangen werden)
Um es zu testen:
Ergebnis:
quelle
Eigenschaften in C
Tomasz Wegrzanowski implementierte Eigenschaften in normalem C, indem er das Programm absichtlich in Fehler umwandelte , wenn auf die Eigenschaft zugegriffen wurde.
Ein Objekt mit einer "Eigenschaft" wird eingerichtet, indem ein Objekt erstellt wird,
struct
das sich über mehrere Seiten erstreckt. Dadurch wird sichergestellt, dass die Speicheradresse der Eigenschaft auf einer anderen Seite als die tatsächlichen Datenelemente liegt. Die Seite der Eigenschaft ist als nicht zugänglich markiert, was garantiert, dass der Versuch, auf die Eigenschaft zuzugreifen, zu einem Segfehler führt. Ein Fehlerbehandler ermittelt dann, welcher Eigenschaftszugriff den Segfault verursacht hat, und ruft die entsprechende Funktion auf, um den Wert der Eigenschaft zu berechnen, der unter der Speicheradresse der Eigenschaft gespeichert wird.Der Fehlerbehandler markiert die Datenseite auch als schreibgeschützt, um sicherzustellen, dass der berechnete Wert konsistent bleibt. Wenn Sie das nächste Mal versuchen, in ein Datenelement zu schreiben, wird ein Segfault ausgelöst, dessen Handler die Datenseite als schreibgeschützt und die Eigenschaftsseite als nicht zugreifbar festlegt (was darauf hinweist, dass sie neu berechnet werden muss).
quelle
Berechnet in Common Lisp
Ich habe anfangs come-from implementiert. Aber das war nicht gut genug.
Inspiriert von dem berechneten goto, entschied ich mich für die Implementierung von computed come-from.
Anwendungsbeispiele
Bei jeder Herkunftsdeklaration im Tagbody wird bei jedem Etikett geprüft, ob die Herkunftsvariable mit dem aktuellen Etikett übereinstimmt, und in diesem Fall wird zur entsprechenden Herkunftsdeklaration gesprungen.
Grüße
FizzBuzz
quelle
"Auto-Strings" in Ruby
Der Code ist ganz einfach:
Jetzt kannst du tun
quelle
Fügen Sie PHP Makros hinzu
Wir können nur den C-Präprozessor für diese Aufgabe verwenden.
Ein PHP-Skript:
Pipe es obwohl cpp:
Ergebnis:
quelle
<<<HEREDOC
ist nicht mehr als 3 niedriger als oder linksverschoben und ein Bezeichner :-) Dies führt jedoch eine Makrosubstitution in heredoc-Strings durch.grep -v ^#
könnte man beheben. Ich denke, das ist genug für diese Frage :-)Pattern MatchingGuards in PythonDer Funktionsumfang umfasst 288 Zeichen.
Mit Pattern MatchingGuards können Sie abhängig von den Argumentwerten völlig unterschiedliche Funktionen verwenden. Obwohl es leicht mit einer Reihe vonif
Anweisungen emuliert werden kann, könnenPattern-Matching-Guards helfen, Codeabschnitte zu trennen, und es ist eine gute Ausrede, verrückte Metaprogrammierungen vorzunehmen.pattern_match
ist ein Dekorateur, der eine neue Funktion erstellt, diePattern MatchingGuards implementiert . Die Bedingungen für jede "Unterfunktion", die in jedem Dokumentstring in Zeilen angegeben sind, die mit einer Pipe (|
) beginnen. Wenn alle Bedingungen wahrheitsgemäß ausgewertet werden, wird diese Version der Funktion ausgeführt. Die Funktionen werden der Reihe nach getestet, bis eine Übereinstimmung gefunden wird. AndernfallsNone
wird zurückgegeben.Ein Beispiel soll dazu beitragen, Folgendes zu verdeutlichen:
quelle
f [a,b,c] = ...
, dass das Argument nicht nur mit einem Prädikat verglichen wird, sondern bei erfolgreicher Übereinstimmung auch die entsprechenden Variablen gebunden werden. Das ist aber immer noch ziemlich cool.f (x:xs) = ...
undf [] = ...
) zu definieren. Irgendwie habe ich Wachen hineingezogen, aber von dort habe ich die genommen|
.Coroutine
Ich kann das nicht gutschreiben, deshalb habe ich es als CW markiert.
Coroutinen in C von Simon Tatham
quelle
Benutzerdefinierte Operatoren in Lua
Pogs haben das Überladen von Operatoren in Lua geschickt missbraucht , um die Definition von benutzerdefinierten Infix-Operatoren zu ermöglichen. Ich habe dies erweitert, um das Aufteilen von Operatoren zu unterstützen (teilweise Anwenden eines Operators mit einem der Operanden) und das Aufrufen des resultierenden Objekts, als ob es eine Funktion wäre.
quelle
Mehrzeilige Zeichenfolgen in Javascript
In dieser aufwändigen Syntax für mehrzeilige Zeichenfolgen wird jeder mehrzeiligen Zeichenfolge
(function(){/*
eine neue Zeile vorangestellt, gefolgt von einer neuen Zeile und*/}+'').split('\n').slice(1,-1).join('\n')
.Mit dieser erstaunlichen, intuitiven Syntax können wir endlich mehrzeilige Zeichenfolgen verwenden:
Für Leute, die unsere einfache Syntax nicht mögen, haben wir einen Compiler für unsere fabelhafte neue Sprache:
das gleiche Beispiel in der kompilierten Sprachversion:
quelle
*/
meine mehrzeiligen Zeichenfolgen nicht einfügen. Das ist super nervig, wenn man Regexps in die Saiten einbindet!Aufteilbare Liste in C # (wie Python)
Ich mochte immer die Slice-Notation von Python und wünschte, sie wäre in C # verfügbar.
Verwendungszweck:
Code, alles andere als fehlerfrei:
quelle
Machen Sie C einfacher
Mit diesem Code können Sie C-Programme schreiben, die eher einer Skriptsprache ähneln. Es enthält Schlüsselwörter wie 'var', 'is', 'string', 'plus', 'equal' und mehrere andere. Es funktioniert mit vielen define-Anweisungen.
Auf diese Weise können Sie Code wie folgt schreiben:
Das Obige wird erweitert zu:
Wahrscheinlich nicht übermäßig nützlich, aber ich fand es ziemlich interessant, dass Sie im Wesentlichen eine ganze Programmiersprache durch eine Reihe von
#define
s erstellen können .quelle
#define
s können Sie Ihrer Sprache sogar Dinge wie Ausnahmebehandlung und Garbage Collection zuweisen, während die grundlegende C-Ebene darunter bleibt.Tcl
Tcl hat keine
do ... while
oderdo ... until
so ...Beispiel:
uplevel
Führt ein Skript im Bereich des Aufrufers aus.quelle
Springen in PostScript
Mein erster Gedanke war, dass ich mich mit dem Exec-Stack herumschlagen müsste, so dass dieser Fehlstart den Fortsetzungsoperator ausgräbt, um von Ghostscript (oder Xpost) gestoppt zu werden.
Aber es ist einfacher als das. Da die Dateiposition für alle Duplikate des Datei-Handles gleich ist (
setfileposition
verbraucht sein Argument, daher ist dies die einzige nützliche Semantik für diese Funktion).Es druckt
5
.Es gibt einige Einschränkungen bei den oben genannten. Der Sprung ist nicht unmittelbar, sondern erfolgt, wenn der If-Body zur obersten Ebene zurückkehrt und der Interpreter erneut aus der Datei liest (anstatt aus dem Array zu lesen, das den If-Body enthält). Zu diesem Zeitpunkt wurde die Datei neu positioniert und das 'goto' wird wirksam.
quelle
currentfile <pos> setfileposition
, indem Sie die Bytes vom Dateianfang an zählen.Symbol#to_proc
mit Argumenten in RubySymbol#to_proc
ist wahrscheinlich einer meiner Lieblingstricks, um wirklich prägnanten Ruby-Code zu schreiben. Angenommen, Sie habenund Sie möchten den Inhalt von
nums
undtext
in Floats bzw. Großbuchstaben konvertieren .Symbol#to_proc
ermöglicht es Ihnen, Code wie folgt zu verkürzen:dazu:
Genial! Aber was ist, wenn wir jedes Element in
nums
diei
Macht bringen oder jedes Vorkommen vons
durch*
in ersetzen wollentext
? Gibt es eine Möglichkeit, Code wie diesen zu verkürzen?Leider gibt es keine einfache Möglichkeit, Argumente bei der Verwendung zu übergeben
Symbol#to_proc
. Ich habe es auf mehrere Arten gesehen, aber wahrscheinlich beinhalten zwei der klügsten und nützlichsten das Patchen derSymbol
Klasse mit Affen [ 1 , 2 ]. Ich werde den ersten Weg unten veranschaulichen.Jetzt können Sie Dinge tun wie:
quelle
JavaScript für jeden
Ausgabe
Alternative Syntax, eher wie Tcl.
quelle
Gotos in Haskell
Die Grundidee ist, dass gotos mit der letzten Anweisung in
do
-notations teilweise simuliert werden können. zum Beispiel:ist äquivalent zu
da die Ausführung zur letzten Anweisung springt, ist es optimal, gotos auszudrücken.
gotos springt nur, wenn sie sich
do
direkt im Block einer Toplevel-Definition befinden. Es heißt eigentlich "rufe x auf und ignoriere den Rest der lexikalisch gesehenen Anweisungen" und nicht "alle x und ignoriere den Rest der Anweisungen", wie ein echtes goto.Das größte Problem ist, dass, wenn es keine Möglichkeit gibt, die Ausführung mitten in einer E / A-Aktion zu beenden,
return
dies auch nicht der Fall ist.return
tut nichts, wenn es nicht die letzte Aussage ist.Dies überwindet dies, indem der Rest der Anweisungen von einem anderen
do
Block erfasst wird .wird
Die
print 3
Anweisung wird vomdo
Block erfasst und wird soloop
zur letzten Anweisung.Diese Umwandlung unterstützt auch Variablen, die im Bereich der Aktionen vorhanden sind. Dazu werden die Variablen, die sich im Gültigkeitsbereich befinden, gespeichert und an die Aktionen übergeben. zum Beispiel:
das übersetzt einfach in:
einige Notizen:
Außerdem wird eine
return undefined
Anweisung hinzugefügt, um sicherzustellen, dass der Erfassungsblockdo
nicht leer ist.weil der Erfassungsblock manchmal mehrdeutig ist
do
, anstatt dassconst
wir ihn verwendenasTypeOf
. Dies ist dasselbe wieconst
, erfordert jedoch, dass beide Parameter den gleichen Typ haben.die eigentliche Implementierung (in Javascript):
eine exampe:
wird:
Ausgabe:
quelle
return
bei Haskell um eine reguläre Funktion handelt, die nichts mit dem Schlüsselwort in C / etc zu tun hat.Python Goto
goto.py
Verwendungszweck
Beispiel Testfall
Beispiel für eine Testfallausgabe
Nur ein bisschen Spaß mit exec (). Kann einen maximalen Rekursionstiefenfehler auslösen, wenn er nicht richtig verwendet wird.
quelle
// JavaScript importieren, ohne das Skript-Tag in einer HTML-Seite zu verwenden
Es ist lahm, ja, ich weiß. Länge: 99
quelle
script
Tag versehen werden. Wo genau ist dann die neue Funktion?