2009-12-04 10 views
9

El siguiente código está en Haskell. ¿Cómo escribiría una función similar en C#?Learning Haskell: enumera las comprensiones en C#

squareArea xs = [pi * r^2 | r <- xs] 

Solo para aclarar ... el código anterior es una función que toma como entrada una lista que contiene el radio de los círculos. La expresión calcula el área de cada uno del círculo en la lista de entrada.

Sé que en C#, puedo lograr el mismo resultado, al recorrer una lista y calcular el área de cada círculo en la lista y devolver una lista que contiene el área de círculos. Mi pregunta es ... ¿Se puede escribir el código anterior de manera similar en C#, quizás usando expresiones lambda o LINQ?

+0

Espera, que tienen una función que inicia con un capital? Eso es ilegal? – codebliss

+0

¿Por qué calcula el área con 2 * pi * r? ¿No es pi * r^2 o pi * r ** 2 el camino a seguir? – Long

+1

'2 * pi * r' calculará la circunferencia de un círculo, no su área. –

Respuesta

22

Usando Enumerable:

IEnumerable<double> SquareArea(IEnumerable<int> xs) 
{ 
    return from r in xs select Math.PI * r * r; 
} 

o

IEnumerable<double> SquareArea(IEnumerable<int> xs) 
{ 
    return xs.Select(r => Math.PI * r * r); 
} 

que está muy cerca de

squareArea xs = map (\r -> pi * r * r) xs 
+1

¿No sería más simple no usar expresiones Lambda? 'squareArea xs = map (2 * pi *) xs' –

+0

Sure. Incluso puedes acortarla 'squareArea = map (2 * pi *)' Pero eso ya no es muy cercano a C#. – dtb

+2

o 'squareArea = map ((* pi). (^ 2))' con la fórmula correcta – dtb

6
xs.Select(r => 2 * Math.PI * r * r) 

es el lado derecho, creo (código de escritura en mi navegador, no compilado).

En general, una lista por comprensión de la forma Haskell

[e | x1 <- x1s, x2 <- x2s, p] 

es probablemente algo así como

x1s.SelectMany(x1 => 
x2s.SelectMany(x2 => 
if p then return Enumerable.Singleton(e) else return Enumerable.Empty)) 

o

from x1 in x1s 
from x2 in x2s 
where p 
select e 

o algo así. Maldición, no tengo tiempo para arreglarlo ahora, alguien más por favor hazlo (marcado Community Wiki).

4

DTB de Haskell tiene probablemente la mejor versión hasta ahora, pero si se toma una un poco más allá y poner los métodos en una clase estática y agregó este operador como el siguiente podría cal l los métodos como si fueran una parte de su lista:

public static class MyMathFunctions 
{ 
    IEnumerable<double> SquareArea(this IEnumerable<int> xs) 
    { 
     return from r in xs select 2 * Math.PI * r * r; 
    } 

    IEnumerable<double> SquareAreaWithLambda(this IEnumerable<int> xs) 
    { 
     return xs.Select(r => 2 * Math.PI * r * r); 
    } 

} 

que podría ser ejecutado como esto:

var myList = new List<int> { 1,2,3,4,5 }; 

var mySquareArea = myList.SquareArea(); 
+0

¿Son los dos métodos de SquareArea iguales? Mi ojo no puede ver la diferencia :( – chollida

+1

Sí, quise incluir: de r en xs seleccionar 2 * Math.PI * r * r; en el primer método, edité mi publicación en reflejarlo –

2
Func<IEnumerable<Double>, IEnumerable<Double>> 
    squareArea = xs => xs.Select(r => Math.PI*r*r);