Die Idee ist von der Tatsache inspiriert, dass Operatoren wie +, -,% usw. als Funktionen mit einem oder zwei übergebenen Argumenten und ohne Nebenwirkungen angesehen werden können. Angenommen, ich oder jemand anderes schreibt eine Sprache, die die Übergabe von mehr als zwei Argumenten verhindert und auch nur über den Rückgabewert funktioniert:
a) Würde eine solche Sprache zu einem einfacheren Verständnis von Code führen?
b) Wäre der Ablauf des Codes klarer? (In mehrere Schritte gezwungen, mit möglicherweise weniger versteckten Interaktionen)
c) Würden die Einschränkungen die Sprache für komplexere Programme übermäßig sperrig machen?
d) (Bonus) sonstige Kommentare zu Vor- / Nachteilen
Hinweis:
Es müssten noch zwei Entscheidungen getroffen werden - die erste ist, ob Benutzereingaben außerhalb von main () oder dessen Äquivalent zulässig sind und welche Regeln für die Übergabe von Arrays / Strukturen gelten. Wenn beispielsweise eine einzelne Funktion mehrere Werte hinzufügen soll, kann die Einschränkung umgangen werden, indem sie in einem Array zusammengefasst wird. Dies könnte gestoppt werden, indem nicht zugelassen wird, dass ein Array oder eine Struktur mit sich selbst interagiert. Auf diese Weise können Sie beispielsweise jede Zahl abhängig von ihrer Position durch einen anderen Betrag dividieren.
result = f(a)(b)…(z)
. Dies ist in der ML-Sprachfamilie wie Haskell der Fall, aber auch konzeptionell in anderen Sprachen wie Lisp, JavaScript oder Perl.Antworten:
Robert C. Martin empfiehlt in seinem Buch "Clean Code" nachdrücklich die Verwendung von Funktionen mit maximal 0, 1 oder 2 Parametern, sodass es zumindest einen erfahrenen Buchautor gibt, der der Meinung ist, dass Code durch diesen Stil sauberer wird (was er jedoch ist) sicherlich nicht die ultimative Autorität, und seine Meinungen sind umstritten).
Wo Bob Martin ist IMHO richtig ist: Funktionen mit 3 oder mehr Parametern sind oft Indikatoren für einen Code-Geruch. In vielen Fällen können die Parameter zu einem kombinierten Datentyp zusammengefasst werden, in anderen Fällen kann dies ein Indikator dafür sein, dass die Funktion einfach zu viel bewirkt.
Ich halte es jedoch nicht für eine gute Idee, eine neue Sprache dafür zu erfinden:
Wenn Sie eine solche Regel wirklich im gesamten Code durchsetzen möchten, benötigen Sie lediglich ein Codeanalyse-Tool für eine vorhandene Sprache. Sie müssen hierfür keine komplett neue Sprache erfinden (beispielsweise könnte für C # wahrscheinlich so etwas wie 'fxcop' verwendet werden ).
Manchmal ist das Kombinieren von Parametern zu einem neuen Typ einfach nicht der Mühe wert, oder es wird zu einer rein künstlichen Kombination. Siehe zum Beispiel diese
File.Open
Methode aus dem .Net-Framework. Es werden vier Parameter benötigt, und ich bin mir ziemlich sicher, dass die Designer dieser API dies absichtlich getan haben, da sie dachten, dass dies der praktischste Weg wäre, die verschiedenen Parameter für die Funktion bereitzustellen.Es gibt manchmal reale Szenarien, in denen mehr als zwei Parameter die Dinge aus technischen Gründen vereinfachen (z. B. wenn Sie eine 1: 1-Zuordnung zu einer vorhandenen API benötigen, bei der Sie an die Verwendung einfacher Datentypen gebunden sind und unterschiedliche nicht kombinieren können Parameter in ein benutzerdefiniertes Objekt)
quelle
Es gibt viele Sprachen, die bereits so funktionieren, z. B. Haskell. In Haskell verwendet jede Funktion genau ein Argument und gibt genau einen Wert zurück.
Es ist immer möglich, eine Funktion, die n Argumente akzeptiert, durch eine Funktion zu ersetzen, die n-1 Argumente akzeptiert und eine Funktion zurückgibt, die das letzte Argument akzeptiert. Wenn Sie dies rekursiv anwenden, ist es immer möglich, eine Funktion, die eine beliebige Anzahl von Argumenten akzeptiert, durch eine Funktion zu ersetzen, die genau ein Argument akzeptiert. Und diese Transformation kann mechanisch durch einen Algorithmus durchgeführt werden.
Dies nennt man Frege-Schönfinkeling, Schönfinkeling, Schönfinkel-Currying oder Currying, nach Haskell Curry, der es in den 1950er Jahren ausgiebig erforschte, Moses Schönfinkel, der es 1924 beschrieb, und Gottlob Frege, der es 1893 ankündigte.
Mit anderen Worten, die Beschränkung der Anzahl der Argumente hat genau keine Auswirkung.
quelle
f *(call_with: a,b,c,d,e)
Überladencall_with :
, um eine Kette zu beginnen, die Kette,
zu verlängern und*
auf der LHS aufzurufen,f
indem jeder Inhalt der Kette einzeln übergeben wird. Ein ausreichend schwaches System zum Überladen von Operatoren macht die Syntax nur umständlich, aber das liegt vor allem am System zum Überladen von Operatoren.Ich habe in den letzten Wochen einige Zeit damit verbracht, die Computersprache J zu lernen. In J ist so ziemlich alles ein Operator, so dass Sie nur "Monaden" (Funktionen mit nur einem Argument) und "Dyaden" (Funktionen mit genau zwei Argumenten) erhalten. Wenn Sie weitere Argumente benötigen, müssen Sie diese entweder in einem Array oder in "Feldern" angeben.
J kann sehr prägnant sein, aber wie sein Vorgänger APL kann es auch sehr kryptisch sein - dies ist jedoch hauptsächlich das Ergebnis des Ziels des Entwicklers, mathematische Prägnanz zu emulieren. Es ist möglich, ein J-Programm lesbarer zu machen, indem Namen anstelle von Zeichen zum Erstellen von Operatoren verwendet werden.
quelle
Eine Sprache, die darauf basiert, wie sie den Entwickler einschränkt, hängt von der Annahme ab, dass der Sprachentwickler die Bedürfnisse jedes Programmierers besser versteht als der Programmierer diese Bedürfnisse selbst. Es gibt Fälle, in denen dies tatsächlich gültig ist. Beispielsweise werden die Einschränkungen für die Multithread-Programmierung, die eine Synchronisation unter Verwendung von Mutexen und Semaphoren erfordern, von vielen als "gut" angesehen, da die meisten Programmierer die zugrunde liegenden maschinenspezifischen Komplexitäten, die diese Einschränkungen vor ihnen verbergen, überhaupt nicht kennen. Ebenso möchten nur wenige die Nuancen von Multithread-Garbage-Collection-Algorithmen vollständig erfassen. Eine Sprache, mit der Sie den GC-Algorithmus einfach nicht brechen können, wird einer vorgezogen, die einen Programmierer zwingt, sich zu vieler Nuancen bewusst zu werden.
Sie müssten ein gültiges Argument dafür vorbringen, warum Sie als Sprachentwickler das Weitergeben von Argumenten so viel besser verstehen als die Programmierer, die Ihre Sprache verwenden. Ich denke, das wäre ein schwieriges Argument.
Sie müssen auch wissen , dass Programmierer wird Ihre Einschränkungen umgehen. Wenn sie drei oder mehr Argumente benötigen, verwenden sie Techniken wie das Currying, um sie in Aufrufe mit weniger Argumenten umzuwandeln. Dies geht jedoch oft zu Lasten der Lesbarkeit, anstatt sie zu verbessern.
Die meisten Sprachen, die ich mit dieser Art von Regel kenne, sind Esolangs, Sprachen, die demonstrieren sollen, dass Sie tatsächlich mit einem begrenzten Satz von Funktionen arbeiten können. Insbesondere die Esolangs, bei denen jedes Zeichen ein Opcode ist, neigen dazu, die Anzahl der Argumente zu begrenzen, einfach weil sie die Liste der Opcodes kurz halten müssen.
quelle
Sie benötigen zwei Dinge:
Ich werde ein mathematisches Beispiel hinzufügen, um die Antwort von Jörg W. Mittag zu erklären .
Betrachten Sie die Gaußsche Funktion .
Eine Gaußsche Funktion hat zwei Parameter für ihre Form, nämlich den Mittelwert (Mittelpunkt der Kurve) und die Varianz (bezogen auf die Impulsbreite der Kurve). Zusätzlich zu den beiden Parametern muss der Wert der freien Variablen angegeben
x
werden, um diese auszuwerten.Im ersten Schritt werden wir eine Gaußsche Funktion entwerfen, die alle drei Parameter verwendet, nämlich den Mittelwert, die Varianz und die freie Variable.
Im zweiten Schritt erstellen wir einen zusammengesetzten Datentyp, der den Mittelwert und die Varianz in einer Sache kombiniert.
Im dritten Schritt erstellen wir eine Parametrisierung der Gauß-Funktion, indem wir einen Abschluss der Gauß-Funktion erstellen, die an den zusammengesetzten Datentyp gebunden ist, den wir im zweiten Schritt erstellt haben.
Schließlich bewerten wir den im dritten Schritt erstellten Abschluss, indem wir den Wert der freien Variablen
x
an ihn übergeben.Die Struktur ist daher:
quelle
In nahezu jeder Programmiersprache können Sie einen Typ von Liste, Array, Tupel, Datensatz oder Objekt als einziges Argument übergeben. Es ist nur der Zweck, andere Elemente zu halten, anstatt sie einzeln an eine Funktion zu übergeben. Einige Java-IDEs haben sogar die Funktion " Parameterobjekt extrahieren ", um genau das zu tun. Intern implementiert Java eine variable Anzahl von Argumenten, indem es ein Array erstellt und übergibt.
Wenn Sie wirklich das tun möchten, wovon Sie sprechen, müssen Sie sich die Lambda-Rechnung ansehen. Es ist genau das, was Sie beschreiben. Sie können im Web danach suchen, aber die Beschreibung, die für mich Sinn machte, war in Typen und Programmiersprachen .
Schauen Sie sich die Programmiersprachen Haskell und ML an (ML ist einfacher). Sie basieren beide auf der Lambda-Rechnung und haben konzeptionell nur einen Parameter pro Funktion (wenn Sie ein wenig schielen).
Josh Blochs Punkt 2 lautet: "Betrachten Sie einen Builder, wenn Sie mit vielen Konstruktorparametern konfrontiert werden." Sie können sehen, wie ausführlich dies ist , aber es ist eine Freude, mit einer API zu arbeiten, die auf diese Weise geschrieben wurde.
Einige Sprachen haben benannte Parameter. Dies ist ein weiterer Ansatz, um die Navigation in umfangreichen Methodensignaturen zu vereinfachen. Kotlin hat zum Beispiel Argumente genannt .
quelle