2010-05-06 19 views
6

¿Por qué ...delegados creando con Lambda Expresiones en F #

type IntDelegate = delegate of int -> unit 

type ListHelper = 
    static member ApplyDelegate (l : int list) (d : IntDelegate) = 
     l |> List.iter (fun x -> d.Invoke x) 

ListHelper.ApplyDelegate [1..10] (fun x -> printfn "%d" x) 

no compilan, cuando:

type IntDelegate = delegate of int -> unit 

type ListHelper = 
    static member ApplyDelegate (l : int list, d : IntDelegate) = 
     l |> List.iter (fun x -> d.Invoke x) 

ListHelper.ApplyDelegate ([1..10], (fun x -> printfn "%d" x)) 

hace?

La única diferencia es que en la segunda, ApplyDelegate toma sus parámetros como una tupla.

Esta función tiene demasiados argumentos, o se utiliza en un contexto donde no se espera una función

Respuesta

11

No he mirado en la especificación para confirmar, pero estoy adivinando que la conversión implícita de "lambda" a "tipo de delegado con nombre" solo aparece en "invocaciones de miembro".

Siempre se puede hacer la conversión explícita:

ListHelper.ApplyDelegate [1..10] (IntDelegate(fun x -> printfn "%d" x)) 

(El error de diagnóstico es bastante pobre; Archivaré un error.)

EDIT:

Para los expertos '.. .

Sí, el spec dice

8.13.6 Conversiones dirigidas a tipos en las invocaciones de miembros Como se describe en Resolución de la aplicación de métodos (ver §14.4), se aplican dos conversiones dirigidas por tipo en las invocaciones de métodos.

Si un parámetro formal es de tipo delegado DelegateType, y un argumento actual es sintácticamente un valor de la función (divertido ...), entonces el parámetro se interpretarse como si hubiera sido escrito nueva DelegateType (divertido ...).

que lambdas se convierten automágicamente para delegar tipos solo en "invocaciones de miembros". En el caso del miembro curried, el primer argumento pasado es una invocación de miembro, pero luego devuelve un valor de función para aplicar el segundo argumento, y las invocaciones de función no tienen esta regla de conversión implícita.

+0

Gracias. ¿Qué es exactamente una "invocación de miembro" y por qué tener argumentos agrupados hace una diferencia? ¿Los miembros siempre deben tomar argumentos agrupados? –

+3

"Miembros" son elementos que define con la palabra clave 'member', p. Ej. métodos estáticos o de instancia en algún tipo. Estos contrastan con las "funciones" que se definen a través de 'let f x = ...' o 'fun' y que son comparativamente muy estrictas (por ejemplo, no puede sobrecargar una función, pero puede sobrecargar un miembro). Los miembros probablemente siempre deberían tomar argumentos agrupados, sí; los miembros son más entidades .NET-y, en comparación con las funciones que son específicas de F #. – Brian

+3

Los 'argumentos agrupados' hacen una diferencia porque cuando se acumula, todos los argumentos se pasan 'a la vez' al miembro, por lo que el segundo argumento es un argumento para un miembro. En el caso de los argumentos al curry, el primer argumento es un argumento para el miembro, y eso da como resultado un nuevo valor de función (no miembro), que luego toma el segundo argumento. – Brian