타겟 언어들이 FP 스타일이 주류인 언어들이라서 그런 듯 합니다.
C# 도 fp 스타일이 가능은 하지만, 최근의 업데이트로 완성된 것들이라 널리 퍼지지는 못했습니다.
그러한 발전에도 불구하고, 아직 부족한 면이 있기도 합니다.
클래스 멤버인 함수
함수는 클래스의 멤버로 한정되어 있는데, 이는 OOP의 철학이기도 합니다.
// oop 의 잔재
static class MyTools
{
public static string Romanize(this string text) => // ...
}
이는 전역 함수를 지칭하는 func 같은 키워드를 도입하면 해결이 가능할 것 같기는 합니다.
namespace MyTools;
// 반환 명시
public func string Romanize(string text) => // ...
// 반환 유추
public func Romanize(string text) => // ..., return str;
기본 콜렉션 부재
// 컴파일 에러
// var collection = [1, 2, 3];
예전에 List<T> 로 확정한다는 계획이 있었는데, 흐지부지된 듯하네요.
개인적으로 유추하건데, IEnumerable<T>, Span<T> 같은 것들이 성능 측면에서 더 좋고, fp 스타일에 더 부합하기 때문인 것 같기도 합니다. fp 언어들이 지원하는 기능이라고 다 좋은 것은 아니니까요.
파이프 부재
접근 연산자 . 와 호출 마커(())를 사용해야 해서, 파이프를 지원하는 언어들과는 차이가 있습니다.
Console.WriteLine("가나다".Romanize().ToUpper());
만약, => 를 파이프로 사용할 수 있게 해준다면,
"가나다" => Romanize => ToUpper => Console.WriteLine;
기존 인프라와 결합해도 가독성이 떨어지지는 않을 것 같습니다.
// Func<string, string>
var convert = str => str.Romanize() => ToUpper;
// <-- 람다 --> 파이프
convert = (string str) => Romanize(str) => ToUpper;
// <-- 무명 메서드 --> 파이프
//Action<string>
var print = str => convert => Console.WriteLine => Console.WriteLine;
// void 파이프
이러한 FP 인프라가 강화되면 코드 스타일이 형식적으로 비슷한 언어로 변환하는 작업 자체가 간단해집니다.
일례로, 일전에 TypeScript 컴파일러를 다시 설계할 때, javascript 코드를 거의 1:1 변환이 가능하다는 효율성 이유만로 golang 이 선택되었습니다.
이러한 FP 스타일 인프라들은, 트랜스 파일러 시장을 위해서라기 보다는, C# 사용자를 위해서라도 도입이 필요하기는 합니다.
FP 스타일 코드는 주로 Gen0 힙 할당하는 경우가 많은데, 이 힙은 스택과 같은 방식(스택 범위를 벗어나면 자동으로 clear)으로 관리되기 때문에 GC 성능 병목이 없습니다.
즉,
FP 스타일 강화 => GEN0 할당 코드 빈도 증가 => 성능 향상
이라는 선순환의 고리가 형성된다는 의미가 되는 것이죠.