파이썬으로 함수형 프로그래밍을 할 수 있다면 특정한 함수형 프로그래밍 언어가 필요합니까? [닫은]


22

생성기와 람다를 사용하여 Python으로 함수형 프로그래밍을 수행 할 수 있습니다. 루비에서도 같은 결과를 얻을 수 있습니다.

문제는 왜 Erlang, Haskell, Scheme과 같은 특정 기능 프로그래밍 언어가 필요한가? 이 특정 기능 프로그래밍 언어가 제공하는 것과 다른 점이 있습니까? 함수형 프로그래밍에 파이썬을 사용할 수없는 이유는 무엇입니까?


30
그 모든 파이썬이 생성되기도 전에 주변에 있었다
마흐무드 호삼

51
포드 핀토는 자동차입니다. 왜 우리는 페라리 스와 같은 특정 고속 자동차가 필요합니까?
Martin York

11
클래스와 템플릿을 사용하면 C ++에서 OO를 수행 할 수 있습니다. 왜 Java와 Python이 만들어 졌습니까? 그들은 무엇을 추가합니까?
9000

19
모든 프로그래밍 언어 (순수하게 학술 연구 언어로 사용)는 Turing과 동일하므로 언어 ​​A에서 수행 할 수있는 작업 다른 언어로 수행 할 수 있습니다. 따라서이 사고에 따라, 우리는 하나의 Turing 완전한 언어 만 필요합니다-sendmail.cf와 같이 말하십시오.) okmij.org/ftp/Computation/#sendmail-Turing
Maglob

17
이 언어를 알고 있다면 파이썬이 함수형 프로그래밍을 잘한다고 주장하지는 않을 것입니다. 그렇지 않습니다. 그것은 FP-ish 것들의 일부를 통합하기에 충분하지만 더 나아지지는 않습니다.

답변:


20

개인적으로 파이썬과 기능적 스타일의 프로그래밍 모두에 대한 열렬한 팬이기 때문에 질문에 감사드립니다. 저는 Python에 대한 오랜 경력을 가지고 있으며 최근 Haskell을 배우기 시작했습니다. 따라서 기능적 관점에서 이러한 언어 간의 차이점에 대한 개인적인 경험을 바탕으로 한 몇 가지 사항이 있습니다.

청정

기능의 순도 (예 : 부작용 없음)에 대해 신경 쓰지 않아도 코드를 읽는 것이 얼마나 쉬운 지, 그에 대한 추론에 실질적인 영향을 미칩니다. 자신의 파이썬 함수에서 순도를 유지하더라도 컴파일러가 순도를 시행하고, 순도 및 불변의 데이터 구조 측면에서 표준 라이브러리를 구축하는 데 큰 차이가 있습니다.

공연

응용 프로그램 도메인에 따라 성능에 신경 쓰거나 신경 쓰지 않을 수도 있지만 정적 타이핑 및 순도 보장은 컴파일러를 파이썬 및 기타 동적 언어와 비교하여 더 많은 작업을 제공합니다 (PyPy가 훌륭하다는 것을 인정해야하지만) 예를 들어 LuaJIT는 기적적으로 접하고 있습니다).

테일 콜 최적화

성능과 관련이 있지만 약간 다릅니다. 런타임 성능에 신경 쓰지 않아도 테일 콜 최적화 (특히 테일 재귀)를 사용하지 않으면 스택 제한에 도달하지 않고 Python에서 알고리즘을 구현할 수있는 방법이 제한됩니다.

통사론

이것이 바로 함수형 스타일로 파이썬을 사용하는 대신 "실제"기능 언어를보기 시작한 가장 큰 이유입니다. 파이썬은 일반적으로 표현력이 매우 뛰어나다 고 생각하지만 기능적 코딩과 관련된 약점이 있습니다. 예를 들면 다음과 같습니다.

  • 람다 함수의 구문은 다소 장황하며 포함 할 수있는 내용이 제한됩니다.
  • 기능 구성에 대한 구문 설탕 없음, 즉 f = g . hvs.f = lambda *arg: g(h(*arg))
  • 부분적 적용, 즉 f = map gvs.f = functools.partial(map, g)
  • 즉, 고차 기능에 중위 연산자를 사용에 대한 문법 설탕없는 sum = reduce (+) lstsum = reduce(operator.add, lst)
  • 함수 인수에 대한 패턴 일치 또는 가드가 없으므로 재귀 끝 조건과 읽기 쉬운 구문으로 일부 경계 사례를 쉽게 표현할 수 있습니다.
  • 대괄호는 함수 호출에 대해 선택 사항이 아니며 중첩 된 호출에 대한 구문 설탕이 없습니다. 나는 이것이 맛의 문제라고 생각하지만, 특히 함수 코드에서는 함수 호출을 연결하는 것이 일반적 이며 그 표기법에 익숙해지면 y = func1 $ func2 $ func3 x보다 읽기 쉽습니다 y = func1(func2(func3(x))).

28

가장 중요한 차이점은 다음과 같습니다.

하스켈

  • 게으른 평가
  • 머신 코드로 컴파일
  • 정적 타이핑으로 기능이 순수함
  • 타입 추론

하스켈과 얼랑

  • 패턴 매칭

에를 랑

  • 동시성, 경량 프로세스의 액터 모델

계획

  • 매크로

모든 언어

  • 실제 클로저 (루비에는 클로저가 있습니다. 파이썬이 토론 할 수 있는지 여부는 주석을 참조하십시오)
  • 기능적 프로그래밍 스타일 (불변 콜렉션, 맵, 필터, 접기 등)에 적합한 표준 라이브러리
  • 꼬리 재귀 (이것은 일부 비 기능 언어에서도 찾을 수 있습니다)

또한 ML과 기능 프로그래밍을 새로운 방식으로 융합하는 SML, Ocaml 및 F # 및 Scala와 같은 ML 제품군의 언어를 살펴 봐야합니다. 이 모든 언어에는 고유하고 흥미로운 기능이 있습니다.


3
좋은 소식 +1 Erlang의 Haskell 및 Lightweight 프로세스에 유형 유추를 추가 할 수 있습니다.
조나스

1
파이썬에는 맵, 필터링 및 접기 (감소) 기능이 있습니다. "실제 클로저"와 관련하여 : 단일 클로저가 아닌 다른 것을 포함 할 수있는 클로저로 실제 클로저를 정의하면 Haskell에는 실제 클로저도 없습니다 (물론 Haskell은 표현식이 아닌 것들이 거의 없습니다 ...) . 그러나 불변 데이터 구조에 대한 요점은 좋은 것이므로 +1입니다. 또한 : 꼬리 재귀 (및 일반적으로 덜 비싼 재귀).
sepp2k

2
"정적 타이핑은 기능이 순수함을 보장합니다"+1 순수 기능과 비 순수 기능을 구분하는 유형 시스템을 사용하는 것이 매우 좋습니다. (C ++의 const doe snot count. :)
Macke February

1
@btilly : 범위에있는 변수에 할당 할 수 없다면 클로저로 간주하지 않습니다. 그렇지 않으면 우리는 Java가 클로저를 가지고 있다고 말할 것입니다.
Kim

3
클로저에서는 일반적으로 할 수있는 것과 같은 방식으로 변수에 액세스 할 수 있습니다. 이것은 Haskell과 Ruby의 클로저에 해당하지만 파이썬이나 Java의 가난한 대체물에는 해당되지 않습니다. 다른 사람이 얼랭에 대해 우리를 깨우칠 수도있을 것입니다. 잘 모르겠습니다.
Kim

19

나열한 언어 중에서 "기능적 언어"가 무엇인지 정확히 정의하기는 어렵습니다. Haskell 만 순전히 기능적입니다 (다른 모든 것들은 일종의 하이브리드 방식을 채택합니다). 함수형 프로그래밍에 매우 유용한 특정 언어 기능이 있지만 Ruby와 Python에는 FP를위한 매우 좋은 환경이 될 수 없습니다. 중요한 순서대로 내 개인 체크리스트는 다음과 같습니다.

  1. 일류 함수클로저 (Ruby, Python 및 나열된 모든 기타 기능).
  2. 테일 콜 최적화 보장 (Erlang, Haskell, Scala 및 Scheme에는 Python, Ruby 또는 Clojure (아직)이 없음)
  3. 언어 및 표준 라이브러리에서 불변성 을 지원합니다 (이것은 나열된 모든 "기능적 언어"(구성표 제외)이지만 루비와 파이썬은 그렇지 않은 큰 언어입니다).
  4. 참조 적으로 투명한 (또는 순수한) 기능에 대한 언어 수준의 지원 (내가 아는 한, Haskell만이 현재 이것을 가지고 있습니다).

(1)의 필요성은 명백해야합니다. 일류 함수가 없으면 고차 함수는 극히 어렵습니다. 사람들이 루비와 파이썬이 FP를위한 좋은 언어라고 이야기 할 때, 그들은 보통 이것에 대해 이야기하고 있습니다. 그러나이 특정 기능이 필요하지만 FP에 적합한 언어를 만들기에는 충분하지 않습니다.

(2) Scheme이 발명 된 이래 FP는 전통적으로 필요했습니다. TCO가 없으면 스택 오버플로가 발생하기 때문에 FP의 초석 중 하나 인 깊은 재귀로 프로그래밍 할 수 없습니다. 이것을 갖지 않는 유일한 "기능적"(일반적으로 정의 된) 언어는 Clojure (JVM의 제한 때문에)이지만 Clojure는 TCO를 시뮬레이션하기위한 다양한 핵을 가지고 있습니다. 참고로, Ruby TCO는 구현별로 다르지만 Python 에서는이를 지원하지 않습니다 . TCO가 보장되어야하는 이유는 구현별로 깊은 재귀 함수가 일부 구현에서 중단되므로 실제로는이를 수행 할 수 없기 때문입니다. 전혀 사용하지 마십시오.

(3)은 현대의 기능적 언어 (특히 Haskell, Erlang, Clojure 및 Scala)가 루비와 파이썬이 가지고 있지 않은 또 다른 큰 것입니다. 너무 자세하게 설명하지 않으면 서, 불변성이 보장되면 특히 동시 상황에서 모든 종류의 버그가 제거되고 지속적인 데이터 구조 와 같은 깔끔한 것들이 가능해 집니다. 언어 수준의 지원 없이는 이러한 이점을 활용하기가 매우 어렵습니다.

(4)는 순수 기능 언어 (하이브리드 언어와 반대)에 관해 가장 흥미로운 것입니다. 다음과 같은 매우 간단한 Ruby 함수를 고려하십시오.

def add(a, b)
  a + b
end

이것은 순수한 기능처럼 보이지만 작업자 과부하로 인해 매개 변수를 변경하거나 콘솔에 인쇄하는 등의 부작용을 일으킬 수 있습니다. 누군가가 +운영자에게 과부하를 가하여 부작용을 일으킬 가능성은 낮지 만 언어는 보장하지 않습니다. (이 특정 예제에서는 그렇지 않지만 Python에도 동일하게 적용됩니다.)

반면 순수하게 기능적인 언어에서는 기능이 참조 적으로 투명하다는 언어 수준의 보장이 있습니다. 이것은 많은 장점을 가지고 있습니다 : 순수한 기능은 쉽게 기억 될 수 있습니다; 어떤 종류의 전역 상태에 의존하지 않고 쉽게 테스트 할 수 있습니다. 그리고 함수 내의 값은 동시성 문제에 대해 걱정하지 않고 느리게 또는 병렬로 평가할 수 있습니다. Haskell은 이것을 최대한 활용하지만 다른 기능 언어에 대해서는 잘 모릅니다.

모든 말로, 거의 모든 언어 (Java까지)에서 FP 기술을 사용할 수 있습니다. 예를 들어 Google의 MapReduce 는 기능적인 아이디어에서 영감을 얻었지만 큰 프로젝트에 "기능적"언어를 사용하지 않는 한 (주로 C ++, Java 및 Python을 사용한다고 생각합니다).


2
철저한 설명을 위해 +1-심지어 FP 외부인으로서도 이해했습니다. 감사! :-)
Péter Török

지금까지이 질문에 대한 가장 귀중한 답변입니다. 사실과 많은 정보를 기반으로합니다. 잘 했어.
wirrbel

스칼라는 꼬리 재귀를 가지고 있으며, Scheme과 마찬가지로 재귀 호출이 꼬리 위치에 있으면 자동으로 수행됩니다 (명시 적으로 요청 해야하는 Clojure와 달리). 심지어 주석이있어서 컴파일러 꼬리 재귀 코드를 생성 하는지 확인할 수 있습니다 . 그것이 가지고 있지 않은 것은 Scheme의보다 일반적인 TCO입니다. 나는 당신이 알고 있다고 가정하지만, 당신이 대부분의 다른 것들에 대해 너무 자세히 설명했기 때문에 이상한 해고 / 누락으로 보였습니다.
itsbruce

@itsbruce이 게시물은 꽤 오래되었습니다. IIRC Scala는 당시에 없었습니다 (또는 방금 잘못되었을 수도 있습니다). 업데이트되었습니다.
shosti

나는 처음부터 스칼라를 사용하지 않았지만 2008 년에 관심이 생겼을 때 꼬리 재귀가있었습니다 .-) 나는이 주제에 대해 묻는 사람들 에게이 특정 SO 질문에 대한 좋은 답변이 있기 때문에 그 이상한 점을 알았으므로 완전성에 대해 논평했습니다.
itsbruce

11

언급 한 언어는 매우 다릅니다.

Python과 Ruby는 동적으로 입력되는 언어이지만 Haskell은 정적으로 입력됩니다. Erlang은 동시 언어이며 액터 모델을 사용하며 언급 한 다른 모든 언어와는 매우 다릅니다.

파이썬과 루비에는 많은 명령 구조가 있지만 Haskell과 같은 더 순수한 기능 언어에서는 모든 것이 무언가를 반환합니다. 즉, 모든 것이 함수입니다.


@kRON : 글쎄, 타입 시스템은 언어의 중요한 속성이며 "특정 기능 프로그래밍 언어와 다른 점이 있습니까?"라고 물었습니다. 물론 다른 언어와 함께 액터 모델을 사용할 수 있지만 Erlang에는 언어가 내장되어 있습니다. Erlang은 간단한 프로세스를 사용하며 분산 프로그래밍을위한 내장 언어 구조 (이후 "동시"언어)를 갖추고 있습니다.
Jonas

8

평소와 같이 파티에 늦었지만 어쨌든 말할 것입니다.

함수형 프로그래밍 언어는 함수형 프로그래밍을 허용 하는 언어가 아닙니다 . 우리가 그 정의에 따라 가면, 거의 모든 언어가 기능적 프로그래밍 언어입니다. (동시에 OOP에도 동일하게 적용됩니다. 원하는 경우 C에서 OOP 스타일로 작성할 수 있습니다. 따라서 논리에 따라 C는 OOP 언어입니다.)

함수형 프로그래밍 언어를 만드는 것은 프로그래밍을 허용 하는 것이 아니라 쉽게 프로그래밍 할 수있게하는 것 입니다. 이것이 핵심입니다.

따라서 파이썬에는 람다 (놀랍게도 빈약 한 폐쇄와 같은 사건)가 있으며 "map"및 "fold"와 같이 기능 라이브러리에서 볼 수있는 몇 가지 라이브러리 함수를 제공합니다. 그러나 함수형 프로그래밍 언어로 만들기에는 충분하지 않습니다. 적절한 함수형 스타일 로 일관되게 프로그래밍하기가 어렵 기 때문입니다 (언어가 확실히이 스타일을 강요하지는 않습니다!). 핵심 파이썬은 상태 및 상태 조작 연산과 관련된 명령형 언어이며 이는 단순히 기능 언어의 표현 및 표현 평가 의미와 상충됩니다.

파이썬 (또는 루비 (또는 원하는 언어를 삽입))이 "기능적 프로그래밍"을 할 수있을 때 왜 기능적 프로그래밍 언어를 사용합니까? 파이썬 등은 적절한 함수형 프로그래밍을 할 수 없기 때문입니다. 그 이유입니다.


6

Java로 기능 프로그래밍을 수행 있습니다 (예 : http://functionaljava.org/ 참조 ). C에서 객체 지향 프로그래밍을 수행 할 수도 있습니다 . 그것은 관용적이지 않습니다.

따라서 Erlang, Haskell, Scheme 또는 특정 프로그래밍 언어가 절대적으로 필요 하지는 않지만 , 각각 다른 접근 방식과 다른 절충점을 나타내므로 일부 작업을 쉽고 어렵게 만듭니다. 사용해야 할 것은 달성하려는 것에 달려 있습니다.


4

이 질문은 무한한 언어와 패러다임에 적용될 수 있습니다.

  • 모두가 C ++을 사용하기 때문에 왜 다른 범용 언어가 필요한가?
  • 자바는 훌륭한 OO 언어이기 때문에 왜 다른 OO 언어가 존재합니까?
  • 펄은 놀라운 스크립팅 언어이기 때문에 왜 파이썬이 필요한가?
  • 야타, 야타, 야타

대부분의 언어가 특정 이유로 존재하는 것은 아닙니다. 그것들은 누군가 현재 언어를 채우지 않거나 빈약하게 채울 필요가 없기 때문에 존재합니다. (물론 이것은 모든 언어에 적용되는 것은 아니지만 잘 알려진 대부분의 언어에 적용된다고 생각합니다.) 예를 들어, 파이썬은 원래 Amoeba OS [ 1 , 2 ]와 인터페이스하기 위해 개발 되었으며 Erlang은 전화 응용 프로그램의 개발에서 [ 3 ]. "왜 다른 기능적 언어가 필요한가?"라는 질문에 대한 답변 [insert-name-of-someone-who-know-how-to-design-languages]는 파이썬이하는 방식을 좋아하지 않았기 때문에 간단 할 수 있습니다.

그것은 내가 생각하는 답을 요약합니다. 함수형 언어로 할 수있는 파이썬으로 무엇이든 할 수 있지만 정말로하고 싶습니까? C에서 할 수있는 모든 일, 어셈블리에서 할 수있는 일을 원하십니까? 다른 언어는 항상 다른 일을하는 데 가장 좋을 것이며, 그렇게해야합니다.


2

함수형 프로그래밍은 특정 언어 기능과 마찬가지로 디자인 패러다임에 관한 것입니다. 또는 달리 말하면, 람다와 맵 함수는 함수형 프로그래밍 언어가 아닙니다. 파이썬과 루비는 함수형 프로그래밍 언어에서 영감을 얻은 일부 기능을 가지고 있지만 일반적으로 매우 필수적인 방식으로 코드를 작성합니다. (C와 비슷합니다. C로 OO와 유사한 코드를 작성할 수 있지만 C를 OO 언어로 진지하게 고려하는 사람은 없습니다.)

살펴보기 : 함수형 프로그래밍은 단순한 람다 map또는 고차 함수가 아닙니다 . 디자인 에 관한 것 입니다 . "진정한"기능 프로그래밍 언어로 작성된 프로그램은 기능 구성을 통해 문제를 해결합니다. Ruby 또는 Python으로 작성된 프로그램은 FP와 유사한 기능을 사용할 수 있지만 일반적으로 구성된 기능 세트처럼 읽지는 않습니다.


0

언급 한 각 기능 언어는 특정 틈새 시장에 잘 맞으며 각각 권장하는 관용적 패턴은 거대한 도우미 모듈 라이브러리를 작성하지 않으면 Python에서 수행 할 수없는 특정 작업에 매우 적합합니다. 이러한 틈새 우수성 중 가장 확실한 것은 Erlang의 동시성 모델입니다. 다른 것들도 비슷한 강점을 가지고 있습니다.


0

lambda-calculus, LISP 및 Scheme에서 사용 가능한 모든 개념은 Python에서 사용할 수 있으므로 기능 프로그래밍을 수행 할 수 있습니다. 편리하거나 그렇지 않은 경우 상황과 취향의 문제입니다.

파이썬 (Ruby, Scala)으로 LISP (또는 다른 기능적 언어) 인터프리터를 쉽게 작성할 수 있습니다 (무엇을 의미합니까?). 순수한 기능을 사용하여 Python에 대한 인터프리터를 작성할 수 있지만 많은 작업이 필요합니다. 오늘날 "기능적" 언어 조차도 다중 패러다임입니다.

이 낡고 아름다운 책 은 함수형 프로그래밍의 본질이 무엇인지에 대한 답을 대부분은 아니지만 대부분 가지고 있습니다.


@Arkaaito 그러나 람다 미적분학, LISP 및 체계에서 사용 가능한 모든 개념 이 Python에서 사용 가능 하다는 데 동의 하십니까?
Mark C

당신은 확실하다 모든 혀짤배기 개념 파이썬에서 사용할 수 있습니까? 매크로, 코드 데이터인가?
SK-logic

@ SK-logic Macros는 lambda-calculus가 아니지만 Python에서는 사용할 수 있지만 이름은 아닙니다. 파이썬은 코드가 dataeval()함수를 제공 하지만 더 나아가 LISP에서와 같이 대부분의 런타임 환경을 수정할 수 있습니다.
Apalala

@Apalala, 동적 언어 eval()는 런타임 메타 프로그래밍입니다. 때로는 유용하지만 매우 비쌉니다. Lisp 매크로는 다릅니다. 컴파일 시간 메타 프로그래밍입니다. 파이썬에서는 어떤 형태로든 사용할 수 없습니다.
SK-logic

@ SK-logic 프로그램이 매크로를 변경할 수 없거나 심지어 그 존재를 알 수 없기 때문에 이러한 종류의 매크로는 코드 데이터 전제를 깨뜨 립니다. Python에서 프로그램은 필요할 때 런타임에 자체 구문 분석 트리에 액세스 할 수 있습니다. 매크로 (정적 전처리)는 전혀 작동하지 않습니다.
Apalala

-5

파이썬은 또한 비 기능적인 스타일로 프로그래밍 할 수 있기 때문에 FP 순수 주의자에게는 충분하지 않습니다. 그러나 실용적인 실용적인 코더는 기능적인 스타일의 이점을 독단적으로 즐기지 않아도됩니다.

“기능적 프로그래머는 중세 스님처럼 들리며, 자신을 덕으로 만들 겠다는 희망으로 인생의 즐거움을 거부합니다. 물질적 이점에 더 관심이있는 사람들에게는 이러한“장점”이 설득력이 없습니다. 기능적인 프로그래머들은 큰 물질적 이점이 있다고 주장하지만… 할당 문을 생략하면 엄청난 이점이 생기면 FORTRAN 프로그래머는 20 년 동안 그렇게했을 것입니다. 아무리 나쁜 기능이라도 기능을 생략하여 언어를 더 강력하게 만드는 것은 논리적으로 불가능합니다.”

-John Hughes, 함수형 프로그래밍이 중요한 이유


6
동의한다. 없는 언어 goto는 끔찍합니다.
아논.

2
@Anon : 또는 큰 형제 call-with-current-continuation.
Chris Jester-Young

4
메이슨, 당신이 인용 한 논문은 정반대라고 말하고 있습니다. 인용문은 다른 이야기를 들려주는 논문의 두 단락의 일부일뿐입니다. 실제로 두 단락을 전체적으로 인용하면 다른 의미를 분명히 나타냅니다.
Marco Mustapic

2
@Mason : 그렇습니다. 저자는 모듈화와 게으른 평가가 진정한 이점이라고 주장합니다. 그러나 원래의 인용문이 문맥에 어긋나 있다는 점에 주목하십시오. 실제로 저자가 FP가 위대하다는 이유가 아니라 FP가 크다는 결론을 내리고 논문에서 단락을 인용했을 때 저자가 FP에 대해 무언가를 주장하고 있다고 생각하는 것 같습니다. 더 적을수록 " 이 논문의 제목은 저자의 의도를 "명확한 프로그래밍이 중요한 이유";-) 명확하게 보여줍니다. 순수한 FP 언어가 "불쾌"하다는 주장을 확실히지지하지는 않습니다.
Andres F.

6
@Mason Wheeler : 하이브리드 언어는 파이썬보다 한 단계 앞서 있습니다. 예를 들어, Lisp는 1959 년으로 거슬러 올라가며 사실은 다중 패러다임 언어입니다. 기능적 접근 방식, 절차 적 접근 방식 및 프로그래밍에 대한 객체 지향적 접근 방식을 완벽하게 지원합니다. 올바른 매크로 패키지를 사용하면 논리 프로그래밍도 매우 쉽게 수행 할 수 있습니다. Scheme 역시 Python과이 논문보다 우선합니다. 1975 년으로 거슬러 올라갑니다 . 언젠가 프로그래밍 언어의이 타임 라인을 한눈에 살펴볼 수도 있습니다.
저의 정확한 의견
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.