최근에 .net 3.0 (windows forms, C#)으로 옮겼습니다. 나는 술어와 람다 표현에 대해 더 알고 싶다. 우리는 어디에서 사용해야합니까? 성능을 개선합니까? 내부적으로 어떻게 작동할까요? 감사.술어와 람다 표현
답변
스택 오버플로를 검색하면 해당 항목을 설명하는 1,000 가지 답변을 찾을 수 있습니다. 즉, 람다는 익명 메소드를 다른 메소드에 전달하고자하는 시점에 익명 메소드를 작성하는 방법입니다. 익명 메소드의 경우 delegate
구문과 기술적으로 동일하지만 형식 유추 기능이 추가되었으므로 매개 변수 유형을 명시 할 필요가 없습니다. 술어는 어떤 값을 받아들이고 bool
을 리턴하는 메소드입니다 - 예는 Where
의 인수가됩니다.
외부 변수를 참조하지 않는 람다는 구성된 정적 메서드로 변환됩니다. 포함하는 클래스의 인스턴스 멤버를 참조하면 인스턴스 메서드가됩니다. 로컬 변수를 참조하는 경우 해당 변수는 둘러싼 메서드가 실행되기 시작할 때 할당되는 컴파일러에서 생성 된 클래스의 필드로 "끌어 올리며"람다 본문은 새 클래스의 메서드가됩니다.
성능면에서 그다지 큰 차이는 없습니다. 임시 객체 생성과 관련이 있지만 I find that these are collected extremely efficiently by the GC입니다.
다른 버전의 C#을 연구하고 어떻게 다른지 궁금하다면. 제 제안은 C.Sharp.in.Depth by jon skeet을 읽으십시오. 이렇게하면 새 버전을 더 잘 이해할 수 있습니다.
성능이 향상 되었습니까? 그리고 그들이 내부적으로 어떻게 일하는가는 입니다. 감사.
대부분의 경우 성능이 저하 될 수 있습니다. 그러나 성능을 죽일 수있는 몇 가지 병리학 적 사례, 즉 fixed point combinators의 과도한 사용이 있습니다.
그것의 우리가 재귀 람다 함수를 작성하기 위해 Y-콤비를 사용할 수있는 잘 알려진 트릭 그러나 다음 코드를 고려하십시오
using System;
using System.Diagnostics;
namespace YCombinator
{
class Program
{
static Func<T, U> y<T, U>(Func<Func<T, U>, Func<T, U>> f)
{
return f(x => y<T, U>(f)(x));
}
static int fibIter(int n)
{
int fib0 = 0, fib1 = 1;
for (int i = 1; i <= n; i++)
{
int tmp = fib0;
fib0 = fib1;
fib1 = tmp + fib1;
}
return fib0;
}
static Func<int, int> fibCombinator()
{
return y<int, int>(f => n =>
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return f(n - 1) + f(n - 2);
}
});
}
static int fibRecursive(int n)
{
switch (n)
{
case 0: return 0;
case 1: return 1;
default: return fibRecursive(n - 1) + fibRecursive(n - 2);
}
}
static void Benchmark(string msg, int iterations, Func<int, int> f)
{
int[] testCases = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20 };
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i <= iterations; i++)
{
foreach (int n in testCases)
{
f(n);
}
}
watch.Stop();
Console.WriteLine("{0}: {1}", msg, watch.Elapsed.TotalMilliseconds);
}
static void Main(string[] args)
{
int iterations = 10000;
Benchmark("fibIter", iterations, fibIter);
Benchmark("fibCombinator", iterations, fibCombinator());
Benchmark("fibRecursive", iterations, fibRecursive);
Console.ReadKey(true);
}
}
}
이 프로그램은 인쇄 아웃 :
fibIter: 14.8074 fibCombinator: 61775.1485 fibRecursive: 2591.2444
fibCombinator 및 fibRecursive는 기능적으로 동일하며 계산 복잡도는 동일하지만 fibCombinator는 모든 중간 개체 할당으로 인해 전체 4100x 느립니다.
- 1. Linq 람다 표현
- 2. 람다 표현 기이가
- 3. 람다 표현 예
- 4. 널 병합 연산자와 람다 표현
- 5. 람다 표현 우선 순위를 이해할 수있게 도와주세요.
- 6. 술어와 고유 한 오브젝트
- 7. lisp는 술어와 일치하지 않는 목록의 결과를 필터링합니다.
- 8. 람다, 람다 정의로 전화하기
- 9. C#을 여러 표현
- 10. 면도기에서 람다 식을 지원합니까?
- 11. 어떻게 람다 식으로 계산합니까?
- 12. 람다 튜토리얼 및 람다 함수 문제 해결
- 13. 기존 람다 식에서 동적 람다 만들기
- 14. 람다 식
- 15. 람다 계산식
- 16. 람다 예제
- 17. 재귀 람다
- 18. 비웃음 람다
- 19. 람다 식
- 20. 면도기 : 람다
- 21. 체크! = 람다
- 22. 람다 식
- 23. 람다 함수
- 24. 람다 표현식
- 25. 템플릿이있는 람다
- 26. 두 탐색 속성이있는 람다 식
- 27. 시퀀스에 Guid가 술어와 MySql.Data.Entity를 비교할 때 요소가 없습니다.
- 28. 복합 표현 대 표현식 대 하위 표현
- 29. ASP.NET 대리인 및 표현 - 정보 요청
- 30. 엔티티 표현
빌드되지 않은 언어의 역사에 대해 스스로 가르치고 싶지 않다면 C# 프로그래머 (또는 포스트 Algol 언어의 사용자)는 재귀를 수행하기 위해 Y 결합자를 사용하지 않을 것입니다 - 자신을 참조 할 수있는 명명 된 함수의 개념. –
@Earwicker : 좋은 지적 :) 당신은 C#에서는 이와 같은 코드를 작성하지 않았지만, 결합 자와 point-free 스타일은 모두 F #, OCaml 및 Haskell의 분노입니다. 필자는 F #에서 combinator와 point-free 스타일을 실험했으며, 거의 모든 경우에 combinator 버전이 성능을 저하시킵니다. – Juliet