객체지향 프로그래밍보다 함수형 프로그래밍이 더 좋은 건가요?

방학때 아직 제대로 알고있지 않은 객체지향을 좀 배워보려고 했는데

함수형 프로그래밍이라는 더 좋은 방식이 있나봐요…

객체지향을 건너뛰고 바로 함수형 프로그래밍으로 넘어가도 괜찮은 건가요?

그리고 함수형 프로그래밍 언어의 조건이 있는데 그중 하나가 반환값으로 함수를 사용할 수 있다는 건데,

이말은 재귀적 프로그래밍을 할 때에 리턴값으로 함수를 지정하는 것과는 다른 건가요?

안녕하세요.

함수형 프로그래밍이 더 좋은거라기 보다는
그냥 프로그래밍을 하는 패러다임이 다르다고 봐주시는게 맞는거 같습니다.

네 이부분은 사실 좀 다르죠, 함수의 값을 리턴하는게 아니고, 함수 자체를 반환할 수 있어요.
이건 함수가 일급 객체냐 아니냐를 보시면 되는데, 간단하게 설명하면, JAVA에서는 메서드(함수)가 일급객체가 아니기 때문에 메서드를 동적으로 생성해서 반환하는건 불가능한 것이죠.
메서드를 컨테이너에 넣을 수 있는가? 그것도 아니죠.

그리고 함수형 언어의 장점은 단순히 함수가 일급객체이냐 아니냐가 아니에요. 함수가 부작용을 갖냐 갖지 않냐이죠. (사실 설명하려면 글이 좀 길어져서… ;; 양해를 ㅎㅎ)

사실 요즘 나오는 언어들은 객체지향적 방식과 함수형 방식을 혼합하고 있어요.
함수형 프로그래밍 패러다임이 주는 이점이 많거든요.
많은 언어들이 클래스와 상속, 다형성을 지원함과 동시에 람다, 익명함수, 클로저 또한 지원하죠.

그리고 이건 제 사견인데, 둘 다 공부하시는것도 좋아요. 특히 객체지향을 심도있게 공부하시는건 큰 도움이 될겁니다.

1 Like

더 나쁜 프로그래밍 스킬/스타일은 있어도, 더 좋은 프로그래밍 패러다임이라는 건 없습니다. 상황에 맞는 방식이 있을 뿐이죠.

C++은 C89 스타일로 절차지향으로 짤 수 있고,
다중 상속 써서 객체지향으로 짤 수 있고,
템플릿/타입트레잇/컨셉 써서 제네릭 지향으로 짤 수 있고,
람다식이랑 펑터 써서 함수형 지향으로 짤 수 있고 뭐 그렇죠.
그리고 실력 좋은 프로그래머라면 하나의 프로그램 내에서 위의 패러다임을 전부 알맞게 활용할 수 있죠…

머신러닝 인퍼런스 프로그램에서 레이어/코스트펑션은 객체지향, 레이어 내 매트릭스는 템플릿 기반 제네릭, 내부 계산과 잡다한 체크는 함수형으로, GPU/멀티코어 활용은 멀티스레딩/병렬화 쓰고 이런 식이죠

4 Likes

조선인이 우물에 람다를 풀었다!!!

2 Likes

잘모르겠으면 그냥 다 공부하십쇼
편식은 나쁩니다

화장실에서 휴지 쓰느냐 비데 쓰느냐 차이 입니다

그럼 리스트 안에 함수들을 담아둔 다음
필요한 함수를 인덱스로 가져와서 인자 넘겨줘서 값 뽑는게 가능한 건가요?
제가 제대로 이해한 건지 모르겠습니다

함수형부터 하세요…
함수형부터 하고 객체지향을 보면
대체 왜 저런 똥꼬 쇼를 하는거지
하는 부분이 이해가 됩니다

특히 디자인 패턴이 진짜 가관인데
함수가 1급 시민(first class)이 되면 안 써도 되는 패턴이 정말 많습니다

그리고 객체지향하면 자바나 씨플플을 공부할텐데
그 언어들 특성 상 interface에 의한 다형성과 상속을 강조하게 될 겁니다.
그거 정말 구린 방법인데 자바를 많이 쓰다보니 무슨 대세가 됬어요. 개병맛임
(모던 C++은 좀 다르긴 하다만 과연 협업하는 사람들이 모던할까요?)

함수가 1급 시민이 되면 클래스 따위보다 더 표현력이 좋습니다
그래서 사실 OOP에서 할 수 있는 모든 것을 함수형으로 할 수 있어요

저는 하나만 배운다면 함수형을 배워야 한다고 생각합니다만
둘 다 배운다면 함수형 먼저 공부하세요

>>> def inc(x): return x + 1
... 
>>> def dec(x): return x - 1
... 
>>> fs = [inc,dec]
>>> fs[0](1)
2
>>> fs[1](1)
0

넹 되요

파이썬이 함수형 언어라서 이게 된다기보다는
파이썬의 함수가 1급 시민(first class)이라서 됩니다.

파이썬은 함수형 언어는 아닙니다.

오… 검색해보니 c++11부터 함수가 일급객체라는데
C는 지원이 아예 안되나요?

C는 포기하시는게 정신 건강에 이로웁니다…

C를 포기하라는게 함수형 패러다임을 말씀하시는 건가요 아니면 언어가 노답이란 의미인가요 ?

C에서는 함수형을 포기하라는 뜻입니다. 그러라고 만든 언어가 아니니까…

근데 함수형에서 함수가 1급 시민인 거 말고
값이 불변한다는 점만을 이용해서 C에서 함수형 프로그래밍(비스므리한게…) 가능한지는 모르겠습니다.

대부분의 함수형 언어는 값이 변하지 않는 자료구조를 쓰는데요.
값이 변하지 않으면서도 성능이 좋은 특수한 자료구조를 만들어서 씁니다.


그런 자료구조를 C로 구현한 라이브러리가 있는지는 모르겠습니다.

예로 드신 방법은 C에서도 되지 않나요? 함수 포인터로 같은 방법을 사용한 적이 있어요

저건 그냥

그럼 리스트 안에 함수들을 담아둔 다음
필요한 함수를 인덱스로 가져와서 인자 넘겨줘서 값 뽑는게 가능한 건가요?

물어보셔서 답해드린거구요.

함수형으로 가능한 거는 뭐 이런게 있겠네요
예를 들어서 벡터 [x1, x2, … xn]의 길이를 계산한다고 해봅시다
수학적인 답은
sqrt(x1^2 + x2^2 + x3^2 + ... xn^2) 이렇겠네요

C면 이렇게 짜겠죠

double vlen(double* v, int n){
    double sum = 0.0;
    for(int i = 0; i < n; i++){
        sum += v[i] * v[i];
    return sqrt(sum)
...
double[] vec = {1,2,3,4};
vlen(vec,4);
double[] vec2 = {1,1};
vlen(vec,2);

함수형 언어라면 아마 이렇게 짤겁니당

lmap = lambda f: lambda xs: list(map(f,xs))
vlen = compose(sqrt,sum,lmap(lambda x: x**2))

>>> vlen([1,2,3,4])
5.477225575051661
>>> vlen([1,1])
1.4142135623730951

map은 함수 f와 시퀀스(리스트) seq를 받아서 seq의 원소에 f를 적용해서 반환합니다.
map(f,[1,2,3,4]) => [f(1), f(2), f(3), f(4)]
compose는 함수를 합성하는 함수입니다. 보통 수학에서는 . 연산자로 표기합니다.
f.g = f(g(x)) 임다

C는 일반적인 함수 합성이 불가능합니다. 만들려고 해보시면 알겠지만… 못해요…
하려면 함수를 일일이 만들어야 되는데 그러면 의미가 없습니다…

함수형 프로그래밍을 하는데 함수합성을 못하는 것은 굉장히 치명적입니다.
그래서 C에서 일반적인 함수형은 포기하시는게…

1 Like

강려크한 클로져로 모든걸 구현하는 뽀터프리터 구경하고 가십쇼

리스트? 함수형? OOP? 클래스? 와서 구현하십쇼 :wink:

C는 명령형 언어라 함수형으로 구현하기 어렵죠.

말씀대로 C는 별로 추천을 드리는 않구요.

제가 객체지향을 말씀드린건 사실 구현보다도 프로그램을 설계하는 눈을 기르라는 의미였습니다.

그리고 함수형 언어라는것이 위와 같은 특징을 갖는것이지 위에 언급한 특징을 구현가능하다고 해서 함수형 프로그래밍을 할 수 있는건 아니에요. 함수형 프로그래밍 패러다임은 기존의 명령형 언어의 방식과는 많이 달라요.

정 함수형 언어를 맛보고 싶으시면 lisp나 haskell의 소스코드를 찾아보세요.

모던 씨플플에서 인터페이스 없이 상속하고 다형성 하는게 머에염?

템플릿을 이용한 의존성 주입을 사용하면 됩니당
템플릿 인자로 인터페이스의 구현체를 넣으면, 템플릿 특수화시 구현이 없을 경우 에러를 띄웁니다

template<class T>
int func(T && t)
{
    return t.foo();
}

위와 같이 짜면, T는 반드시 foo() 메소드를 구현해야 빌드시 에러가 안 나겠죠?

정확히는 위의 코드는 단순 덕타이핑이고,

template<class Foo>
struct Bar
{
    explicit Bar(Foo && foo);

    int f()
    {
        return _foo.g();
    }

    Foo & _foo;
};

이런식으로 필요한 클래스에 주입 하면 됩니당

주입할 클래스가 많아서 객체 생성하는게 귀찮다면, Boost::DI를 쓰시면 해결