L'autore di quel post sembra ignorare che la maggior parte delle lingue con tipi generici e sottotipi hanno un qualche modo di esprimere la varianza nei loro parametri generici. Scrivono:
So here's the issue: if we have a function that accepts arguments of type Tuple, and we want to pass it a tuple of arguments of type Tuple, we can only do this when A = X, and B = Y. If X is a subtype of A or Y is a subtype of B, we will get a type error. Subsumption is broken. Suddenly, you can't pass a String as an argument to a function that accepts Objects.
In realtà, una tupla può essere definita come qualcosa di simile:
case class Tuple2[+T1, +T2]
in Scala e in altre lingue simili (C # o Java) anche se non è sempre definito così, che gli dà la varianza corretta.
Anche se questo non è un problema, ci sono alcuni compromessi tra i due:
Pro argomenti multipli:
- Rende gli argomenti opzionali, denominati e variadici abbastanza semplici.
- Leggero vantaggio in termini di prestazioni (non è necessario creare tuple).
- Può avere tutti gli argomenti che vuoi, senza che il linguaggio debba fornire fino a
Tuple20
di dire.
Tuple Pro:
- Le tuple sono esse stesse valori che possono essere passati e trasformati.
- Richiede la lingua per supportare una sintassi di tuple piacevole da usare.
Come hanno sottolineato David Arno, entrambe le tuple come argomenti singoli e argomenti multipli hanno lo stesso svantaggio rispetto agli argomenti completamente elaborati: non possono essere parzialmente applicati.
Modifica :
Quindi potrei aver interpretato male la domanda, anche se penso che sia vaga su questo punto. Per chiarezza, ci sono tre modi in cui una funzione potrebbe "prendere più argomenti". Il primo è che prende effettivamente più argomenti , che è quello che fa la maggior parte dei linguaggi di programmazione. Ad esempio, in Scala,
def concatenateMulti(left: String, right: String): String = left + right
il secondo è di prendere un singolo argomento che sia una tupla o un record, per esempio
def concatenateTuple(args: Tuple2[String, String]): String = args._1 + args._2
e il terzo è di prendere una funzione che restituisce una funzione parzialmente applicata
def concatenateSingle(left: String): (String => String) = (right: String) => left + right
Ho pensato che l'autore stesse chiedendo dopo il primo contro il secondo mentre sembra che fossero più interessati al secondo contro il terzo