Variadische Funktion
# Variadische Funktion

Als variadische Funktion bezeichnet man in Programmiersprachen Funktionen, Prozeduren oder Methoden mit unbestimmter Arität, also solche, deren Parameteranzahl nicht bereits in ihrer Deklaration festgelegt ist.

In einigen Sprachen wie C, C++, Java und Lua wird dies in der Funktionsdeklaration mit Auslassungspunkten angezeigt, der sogenannten Ellipse. An Stelle der Ellipse können beliebig viele Argumente (oder auch keine) übergeben werden. Nützlich sind variadische Funktionen beispielsweise bei der Verknüpfung mehrerer Zeichenketten oder beim Aufsummieren von Zahlenreihen und generell bei Operationen, die prinzipiell auf eine beliebige Anzahl Operanden angewandt werden können.

In Abhängigkeit von den Konventionen der Programmiersprache können die Argumente unterschiedliche Datentypen haben (z. B. in JavaScript) oder müssen denselben Datentyp haben (z. B. in Java).

## Umsetzung in verschiedenen Programmiersprachen

### C

Der Zugriff auf variadische Parameter erfolgt hier über spezielle Makros. Einige Bibliotheksfunktionen von C sind mit Ellipse deklariert, da es in C keine Möglichkeit der Funktionsüberladung gibt, Beispiele sind die Bibliotheksfunktionen printf und scanf zur formatierten Aus- beziehungsweise Eingabe. Ein grundlegendes Problem bei diesem Mechanismus ist, dass der aufgerufenen Funktion keine Information über Anzahl und Typ der übergebenen Argumente zur Verfügung steht. Der Programmierer muss also durch zusätzliche Maßnahmen (wie etwa mit dem format string bei printf) sicherstellen, dass die Argumente richtig interpretiert werden und nicht mehr Argumente verarbeitet werden, als tatsächlich vorhanden waren. Außerdem muss mindestens ein fester Parameter vor der Ellipse angegeben werden.

Die Funktionsparameter werden, bevor sie an die Funktion übergeben werden, automatisch nach folgendem Schema in größere Typen umgewandelt:

| Ausgangstyp | Zieltyp |
| - | - |
| char, signed char, short | int |
| unsigned char, unsigned short | unsigned int |
| float | double |

Alle anderen Typen bleiben erhalten.

Beispielsweise könnte man in C den Mittelwert von beliebig vielen Ganzzahlen über folgende Funktion errechnen lassen:

### C++

In C++ sind Ellipsen im C-Stil zwar weiterhin möglich, aber sie gelten als überholt, da C++ elegantere Möglichkeiten zur Funktionsüberladung und das Konzept der Defaultargumente bietet. Ellipsen gelten zudem als schlechter Stil, da sie keine Typsicherheit bieten. Außerdem lassen sich nicht alle Datentypen als Teil einer Ellipse übergeben.

In C++ gibt es zusätzlich noch die Möglichkeit, variadische Funktionstemplates zu benutzen. Diese sind typsicher, aber aufwändiger zu benutzen, da man die sogenannten „template parameter packs“ rekursiv auflösen muss:

In C++17 werden sogenannte „fold expressions“ eingeführt, mit denen sich variadische Funktionen wie im obigen Beispiel stark vereinfachen lassen:

Des Weiteren lassen sich Ellipsen oft durch eine std::initializer_list ersetzen, wobei die Syntax beim Aufruf leicht abweicht, da die Argumente in geschweifte Klammern gefasst werden müssen:

### C#

In C# wird in der Deklaration das Schlüsselwort params verwendet. Auch der Typ wird mit angegeben. Einer solchen Methode kann eine durch Kommas getrennte Liste übergeben werden (diese Liste kann auch leer sein). Nach dem Schlüsselwort params sind keine weiteren Parameter mehr zulässig. Zudem darf es nur einmal in der Methodendeklaration vorkommen.

### Go

Die Sprache Go erlaubt die Deklaration variadischer Funktionen über den Anhang einer Ellipse ... an den Namen des letzten Parameters. Es können dann beliebig viele Parameter des angegebenen Types übergeben werden, diese sind dann über ein Slice in der aufgerufenen Funktion verfügbar. Ferner ist es möglich, durch Anhängen einer Ellipse an den letzten Parameter im Aufruf einer variadischen Funktion, direkt ein Slice an Stelle einzelner Parameter zu übergeben. Es folgt ein Beispiel analog zu obigem C#-Beispiel.

### Java

Auch in Java verwendet man in der Deklaration die Ellipse. Hier spricht man von Methoden mit variabler Argumentanzahl, oder kurz Varargs. Im Gegensatz zu C wird aber der Typ mit angegeben. Im Hintergrund wird die Parameterliste in ein Array übersetzt, so dass auch innerhalb des Funktionsrumpfes der Parameter wie ein Array behandelt werden muss.

### JavaScript

In JavaScript werden die beliebig vielen Funktionsargumente dem arguments-Objekt übergeben, das ein Array-artiges Objekt mit den zusätzlichen Eigenschaften arguments.length und arguments.callee ist. Mit dem arguments-Objekt können sogar die Funktionsparameter überschrieben werden, wie das nachfolgende Beispiel zeigt:

Seit ECMAScript 2015 ist es möglich Funktionsargumente mittels rest-Parameter in Form einer Ellipse ... zu sammeln.

### Lua

In Lua kann in der Parameterdeklaration einer Funktion als letztes (auch einziges) Argument die Ellipse ... angegeben werden. Diese kann dann an andere Funktionen weitergereicht werden, wodurch sie sich nach Länge (Anzahl) und einzelnen Elementen analysieren lässt, namentlich mittels select.

### Perl

Da in Perl 5 die Argumente ohne Rücksicht auf ihren Typ im Spezialarray @_ landen, sind alle Subroutinen immer variadisch, solange es kein Prototyp explizit verhindert. Die mit 5.20 eingeführten, optionalen Signaturen prüfen die Arität. Damit sind nur solche Routinen variadisch, deren letzter Parameter ein Array oder Hash (verlangt gerade Anzahl von Werten) ist.

In Perl 6 kann man als letzten Parameter ein slurpy Array angeben, welches mit dem Präfix * gekennzeichnet ist und alle zusätzlichen Argumente „aufsaugt“.

### PHP

PHP unterstützt erst ab Version 4 variadische Funktionen. Bis Version 5.5 wird kein besonderes Kennzeichen in der Funktionsdeklaration verwendet; die Argumente können mit Hilfe spezieller Funktionen ausgewertet werden. Ab Version 5.6 stehen variadische Funktionen als natives Sprachfeature über die Ellipse zur Verfügung. In Versionen vor 5.6 kann eine variadische Funktion bspw. wie folgt definiert werden:

Ab PHP 5.6.0 kann dieselbe Funktion wie folgt umgesetzt werden:

Die Ausgabe beim Aufruf von sum ist dieselbe wie beim Beispiel für Versionen vor 5.6.0. Der Vorteil bei der Umsetzung von variadischen Funktionen ab Version 5.6.0 ist, dass hierbei auch das sogenannte Type Hinting eingesetzt werden kann, wodurch innerhalb der Funktion eine Überprüfung auf einen korrekt übergebenen Objekttyp entfallen kann. So besteht in den oben genannten Beispielen das Problem, dass ein Nutzer der Funktion sum dieser auch einen String, anstelle eines Integers übergeben könnte, was ggf. zu einer falschen Ausgabe oder einer Exception führen könnte (wenn die Funktion Objekte eines bestimmten Typs erwartet). Mit variadischen Funktionen ab PHP 5.6.0 kann die obere Funktion bspw. wie folgt mit Type Hinting umgesetzt werden:

Aufgrund der Tatsache, dass PHP's Type Hinting erst ab Version 7.0 skalaren Typen wie Integer oder String unterstützt, wurde für dieses Beispiel die simple Klasse IntObject definiert, welche einen Wert speichern kann (der bspw. auch eine Zeichenkette sein kann). Für die schematische Darstellung genügt dieses Beispiel, auch wenn es trotz allem keine Typensicherheit umsetzt.

### Ruby

In Ruby werden variable Argumentanzahlen durch einen Stern vor dem Parameternamen gekennzeichnet. Auch hier wird dieser Parameter als ein Array behandelt, in dem alle Argumente gesammelt werden, die der vorgegebenen Anzahl an Argumenten folgen.

### Python

Python bietet dieselbe Funktionalität wie Ruby. Darüber hinaus kann man überzählige Argumente benennen und deren Namen zusammen mit dem Wert in einer Tabelle („Wörterbuch“ im Python-Jargon) speichern, wenn Parameternamen zwei Sterne vorangestellt sind.

### Swift

In Swift wird eine variable Parameteranzahl mit drei Punkten hinter der Deklaration des Parameters gekennzeichnet. Innerhalb der Funktion stehen alle übergebenen Werte als Array zur Verfügung:

### Tool Command Language

In Tcl wird eine variable Parameteranzahl mit dem Wort args als letztes Element der Parameterliste gekennzeichnet. Innerhalb der Funktion stehen alle übergebenen Werte als Liste mit diesem Namen zur Verfügung:

### Haskell

Haskell erlaubt es nicht direkt, variable Argumentanzahlen zu verwenden, allerdings kann man dies über trickreiche Verwendung von Typklassen nahezu beliebig nachbilden. (So sind mit einer entsprechenden Implementation z. B. auch typsichere variadische Funktionen mit verschiedenen Argumenttypen möglich).

