2014-06-11 16 views
18

Dato questo semplice funzione di accattivarsi:Perché le funzioni al curry richiedono nomi di parametri esterni?

func foo(x:Int)(y:Int)->String{ 
    return "\(x) with \(y)" 
} 

mi aspetto di essere in grado di fare qualcosa del genere:

let bar = foo(1) 
bar(2) //<- error: Missing argument label 'y:' in call 

Se l'etichetta della chiamata a bar (come in bar(y:2)) tutto funziona bene . Ma non capisco perché il nome del parametro sia necessario. C'è un modo per evitarlo?

la cosa più ovvia:

func foo(x:Int)(_ y:Int)->String ...

non sembra funzionare.

+3

Nice! Il problema esiste sia per un func di primo livello che per un metodo di classe – GoZoner

+0

Sì, anche l'esempio di currying nel libro Swift lo mostra (incollalo, elimina la seconda funzione di manuale "manuale", e tu ottieni "label argomento mancante" b: "in chiamata") –

+0

Riportalo come rdar: // 17359591. Per favore, sentiti libero di ingannare. – jemmons

risposta

0

Non sono sicuro di aver compreso appieno il vostro curriculum. Ecco la mia opinione a riguardo. Ho una funzione foo come segue:

func foo(x:Int, y:Int) -> String{ 
    return "\(x) with \(y)" 
} 

let bar = foo(1, 2) // gives "1 with 2" 

desidero curry questa funzione per 'risolvere' il valore per x, in modo da fare così come segue:

func fooCurry(x:Int) -> (Int -> String) { 
    func curry(y:Int) -> String { 
    return foo(x, y) 
    } 
    return curry 
} 

Quanto sopra restituisce una nuova funzione che può essere utilizzato come segue:

let curriedFoo = fooCurry(1) 
let barWithCurry = curriedFoo(2) // gives "1 with 2" 

la funzione restituita da fooCurry ha la firma (Int -> String), il che significa che il parametro non ha un externa l nome.

+3

il fare qui è fondamentalmente curry 'a mano'. 'func foo (x: Int) (y: Int) -> String' dovrebbe funzionare come una funzionalità linguistica, e non lo è. –

1

Credo che sia un bug del compilatore, il tuo esempio dovrebbe funzionare come descritto nel Swift programmazione libro Lingua in cui accennano dichiarando funzioni al curry:

func addTwoNumbers(a: Int)(b: Int) -> Int { 
    return a + b 
} 

addTwoNumbers(4)(5) // Returns 9 

https://bugreport.apple.com

buona trovare!

8

E 'un bug, si dovrebbe presentare un radar a bugreport.apple.com

A conferma, se si inserisce un trattino basso, come questo

func foo(x: Int)(_ y: Int) -> String 

si ottiene un avvertimento

estraneo' _ 'in parametro:' y 'non ha alcun argomento argomento nome

Quindi afferma esplicitamente che non ha un nome esterno, ma ne richiede ancora uno quando viene chiamato, il che è chiaramente contrario alle specifiche della lingua.

0

Non la sintassi migliore, ma se si vuole andare in giro per ora, è possibile utilizzare il seguente per le funzioni di curry di base:

func foo(x:Int) -> Int -> String { 
    return { 
    return "\(x) with \($0)" 
    } 
} 

Poi si può solo fare:

let bar = foo(1) 
bar(2) //-> 1 with 2 

ora, ovviamente, il problema con questo diventa evidente quando si vuole scrivere una funzione curry per tubazioni quattro Int s per esempio:

func makerAdders(a:Int)(b:Int)(c:Int)(d:Int) {...} 

diventa in questo modo:

func add(a:Int) -> Int -> Int -> Int -> Int { 
    return { 
    b in return { 
     c in return { 
     d in return a + b + c + d 
     } 
    } 
    } 
} 

Le chiusure interne rendono un po 'meglio che usare le funzioni interne, ma ancora una volta sconfigge lo scopo della bella func add(a:Int)(b:Int)(c:Int)(d:Int) {return a+b+c+d} sintassi.

0

Sicuramente un bug nel compilatore per quanto posso dire. Finché non è risolto è possibile ottenere una versione correttamente al curry di qualsiasi funzione utilizzando queste funzioni (si noti che ho incluso i casi per due e tre argomenti, estendere a vostro piacimento:

func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C { 
    return { a in { b in return f(a,b) } } 
} 

func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D { 
    return { a in { b in { c in return f(a,b,c) } } } 
} 

Basta usare:

curry(addTwoNumbers)(1)(2) 
Problemi correlati