Programing

기능적 프로그래밍 및 비 기능적 프로그래밍

crosscheck 2020. 11. 8. 09:18
반응형

기능적 프로그래밍 및 비 기능적 프로그래밍


대학 2 학년 때 우리는 Haskell을 "배웠습니다". 저는 그것에 대해 거의 알지 못하며 함수형 프로그래밍에 대해서도 알지 못합니다.

함수형 프로그래밍이란 무엇이며, 왜 그리고 / 또는 비 기능적 프로그래밍 대신에 그것을 사용하고 싶어하며 C가 비 기능적 프로그래밍 언어라고 생각하는 것이 맞습니까?


기능적 언어의 핵심 기능 중 하나는 일류 기능의 개념입니다. 아이디어는 다른 함수에 매개 변수로 함수를 전달하고 값으로 반환 할 수 있다는 것입니다.

함수형 프로그래밍에는 상태를 변경하지 않는 코드 작성이 포함됩니다. 이렇게하는 주된 이유는 함수에 대한 연속 호출이 동일한 결과를 산출하기 위해서입니다. 일류 기능을 지원하는 모든 언어로 기능 코드를 작성할 수 있지만 Haskell과 같은 일부 언어는 상태 변경을 허용하지 않습니다. 사실, 전혀 쓸모없는 것처럼 들리는 부작용 (텍스트 인쇄와 같은)을 전혀 만들어서는 안됩니다.

대신 Haskell은 IO에 대해 다른 접근 방식 인 모나드를 사용합니다. 이들은 인터프리터의 최상위 수준에서 실행할 원하는 IO 작업을 포함하는 객체입니다. 다른 수준에서는 단순히 시스템의 개체입니다.

함수형 프로그래밍은 어떤 이점을 제공합니까? 함수형 프로그래밍을 사용하면 각 구성 요소가 완전히 분리되어 있기 때문에 버그 가능성이 적은 코딩이 가능합니다. 또한 재귀 및 일급 함수를 사용하면 일반적으로 코드 구조를 반영하는 간단한 정확성 증명이 가능합니다.


함수형 프로그래밍이란?

오늘날 일반적으로 사용되는 "기능적 프로그래밍"에는 두 가지 다른 정의가 있습니다.

이전 정의 (Lisp에서 시작됨)는 함수형 프로그래밍이 일류 함수를 사용하는 프로그래밍에 관한 것입니다. 즉, 함수가 다른 값처럼 처리되므로 함수를 다른 함수에 인수로 전달할 수 있고 함수는 반환 값 중에서 함수를 반환 할 수 있습니다. 이는 mapreduce( mapReduceGoogle에서 많이 사용하는 단일 작업으로 들었을 수 있으며 당연히 가까운 친척입니다!) 같은 고차 함수의 사용으로 이어집니다 . 닷넷 유형 System.FuncSystem.ActionC #에서 고차원의 기능을 사용할 수 있도록. C #에서는 커링이 실용적이지 않지만 다른 함수를 인수로 받아들이는 Parallel.For함수 ( 예 : 함수) 가 일반적 입니다.

더 젊은 정의 (Haskell에 의해 대중화 됨)는 함수형 프로그래밍이 돌연변이를 포함한 부작용을 최소화하고 제어하는 ​​것, 즉 표현을 구성하여 문제를 해결하는 프로그램을 작성하는 것에 관한 것입니다. 이것은 일반적으로 "순수 함수형 프로그래밍"이라고합니다. 이것은 "순수 기능적 데이터 구조"라고하는 데이터 구조에 대한 매우 다른 접근 방식에 의해 가능해졌습니다. 한 가지 문제는 순전히 기능적인 데이터 구조를 사용하기 위해 전통적인 명령형 알고리즘을 번역하면 일반적으로 성능이 10 배 더 나빠진다는 것입니다. Haskell은 순수하게 기능하는 유일한 프로그래밍 언어이지만 개념은 Linq.NET 과 같은 라이브러리를 사용하여 주류 프로그래밍에 침투했습니다 .

비 기능적 프로그래밍 대신 어디에 사용하고 싶습니까?

어디에나. C #의 Lambda는 이제 주요 이점을 입증했습니다. C ++ 11에는 람다가 있습니다. 이제 고차 함수를 사용하지 않을 변명의 여지가 없습니다. F #과 같은 언어를 사용할 수 있다면 유형 추론, 자동 일반화, 커링 및 부분적 적용 (다른 많은 언어 기능 포함)의 이점도 누릴 수 있습니다.

C가 비 기능적 프로그래밍 언어라고 생각하는 것이 맞습니까?

예. C는 절차 적 언어입니다. 그러나 함수 포인터와 void *C를 사용하면 함수형 프로그래밍의 이점을 얻을 수 있습니다 .


최근에 게시 된 CoDe Mag의 F # "101"대한이 기사를 확인하는 것이 좋습니다.

또한 Dustin Campbell은 F #에 익숙해지는 것에 대한 그의 모험에 대한 많은 기사를 게시 한 훌륭한 블로그 를 가지고 있습니다.

이 정보가 유용하기를 바랍니다. :)

편집하다:

또한 함수형 프로그래밍에 대한 나의 이해는 모든 것이 인스턴스 / 상태 저장 개체가 아닌 함수 또는 함수에 대한 매개 변수라는 것입니다.하지만 제가 틀릴 수 있습니다. 시간을 보내세요! :)


John the Statistician의 예제 코드는 함수형 프로그래밍을 보여주지 않습니다. 왜냐하면 함수형 프로그래밍을 할 때 핵심은 코드가 할당 ( record = thingConstructor(t)할당)을 하지 localMap.put(record)않고 부작용 이 없다는 것입니다 ( 부작용이있는 문장). . 이 두 가지 제약의 결과로 함수 가 수행 하는 모든 작업 은 인수와 반환 값에 의해 완전히 캡처됩니다. C ++를 사용하여 기능적 언어를 에뮬레이트하려는 경우 통계학 자의 코드를 보이는 방식으로 다시 작성합니다.

RT getOrCreate (const T thing, 
                  const Function <RT <T >> thingConstructor, 
                  const Map <T, RT <T >> localMap) {
    return localMap.contains (t)?
        localMap.get (t) :
        localMap.put (t, thingConstructor (t));
}

부작용 없음 규칙의 결과로 모든 문은 반환 값의 일부이며 (따라서 먼저return 옵니다 ) 모든 문은 표현식입니다. 함수형 프로그래밍을 적용하는 언어에서는 키워드가 암시되며 if 문은 C ++의 연산자 처럼 작동합니다.return?:

또한 모든 것이 불변이므로 원래 localMap 을 수정하는 대신 일반적인 C ++ 또는 Java 프로그램 과 같이 localMaplocalMap.put 의 새 복사본을 만들고 반환해야합니다 . localMap의 구조에 따라 복사본은 원본에 대한 포인터를 재사용하여 복사해야하는 데이터의 양을 줄일 수 있습니다.

함수형 프로그래밍의 장점 중 일부는 함수형 프로그램이 더 짧고 함수형 프로그램을 수정하는 것이 더 쉬우 며 (고려할 숨겨진 전역 효과가 없기 때문에) 프로그램을 바로 잡는 것이 더 쉽다는 점입니다. 처음.

그러나 기능적 프로그램은 느리게 실행되는 경향이 있으며 (해야하는 모든 복사로 인해), 메모리 주소, little-endian을 처리하는 다른 프로그램, 운영 체제 프로세스 또는 운영 체제와 잘 상호 작용하지 않는 경향이 있습니다. 바이트 블록 및 기타 기계 별, 비 기능적 비트. 비 상호 운용성의 정도는 기능적 순도의 정도 및 유형 시스템의 엄격함과 반비례하는 경향이 있습니다.

더 많이 사용되는 함수형 언어에는 정말 엄격한 유형 시스템이 있습니다. OCAML에서는 정수와 부동 소수점 수학을 혼합하거나 동일한 연산자를 사용할 수 없습니다 (+는 정수 추가, +.는 부동 소수점 추가). 이것은 특정 종류의 버그를 잡을 수있는 유형 검사기의 능력을 얼마나 높게 평가 하느냐에 따라 장점 또는 단점이 될 수 있습니다.

기능적 언어는 또한 매우 큰 런타임 환경을 갖는 경향이 있습니다. Haskell은 예외입니다 (GHC 실행 파일은 컴파일 타임과 런타임 모두에서 C 프로그램만큼 작습니다).하지만 SML, Common Lisp 및 Scheme 프로그램에는 항상 많은 양의 메모리가 필요합니다.


예, C가 비 기능적 언어라고 생각하는 것이 맞습니다. C는 절차 적 언어입니다.


저는 함수형 프로그래밍을 사용하여 반복적 인 작업을 절약하고 더 추상적 인 버전을 만든 다음 대신 사용하는 것을 선호합니다. 예를 들어 보겠습니다. Java에서는 구조를 기록하기위한 맵을 작성하여 getOrCreate 구조를 작성하는 경우가 많습니다.

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

이것은 매우 자주 발생합니다. 이제 기능적 언어로 다음과 같이 작성할 수 있습니다.

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

다시는 새로 쓸 필요가 없었습니다. 상속 할 수 있습니다. 그러나 나는 상속하는 것보다 더 잘 할 수 있습니다.이 일의 생성자에서 말할 수 있습니다.

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(*는 일종의 "이 매개 변수를 열어 두는"표기법이며 일종의 카레입니다)

그리고 로컬 getOrCreate는 상속 종속성없이 전체 내용을 한 줄로 작성했을 때와 똑같습니다.


F #에 대한 좋은 텍스트를 찾고 있다면

Expert F# is co-written by Don Syme. Creator of F#. He worked on generics in .NET specifically so he could create F#.

F# is modeled after OCaml so any OCaml text would help you learn F# as well.


I find What Is Functional Programming? to be useful

Functional programming is about writing pure functions, about removing hidden inputs and outputs as far as we can, so that as much of our code as possible just describes a relationship between inputs and outputs.

Prefer explicit when param

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

over

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

A functional language is actively hostile to side-effects. Side-effects are complexity and complexity is bugs and bugs are the devil. A functional language will help you be hostile to side-effects too.

참고URL : https://stackoverflow.com/questions/24279/functional-programming-and-non-functional-programming

반응형