나는 주로 OOP 관점에서 프로그래밍하는 방법을 배웠지 만 (우리 대부분과 마찬가지로) 나는 문제를 기능적으로 해결하는 방법을 배우려고 많은 시간을 보냈습니다. FP로 계산 문제를 해결하는 방법을 잘 알고 있지만 더 복잡한 문제가 발생하면 항상 변경 가능한 객체가 필요한 것으로 되돌아갑니다. 예를 들어, 입자 시뮬레이터를 작성하는 경우 변경 가능한 위치의 입자 “개체”를 업데이트하려고합니다. 기능적 프로그래밍 기술을 사용하여 본질적으로 “상태 저장”문제를 해결하는 방법은 무엇입니까?
답변
기능적 프로그램은 상태를 매우 잘 처리하지만 다른 방식으로 볼 필요가 있습니다. 위치 예를 들어, 고려해야 할 사항은 위치가 고정 된 값 대신 시간의 함수가되도록하는 것입니다 . 고정 된 수학적 경로를 따르는 입자에는 효과적이지만 충돌 후와 같이 경로의 변화를 처리하기위한 다른 전략이 필요합니다.
여기서 기본 전략은 상태를 가져 와서 새로운 상태를 반환하는 함수를 만드는 것입니다 . 따라서 입자 시뮬레이터는 Set
입자를 입력으로 받아 Set
시간 단계 후에 새로운 입자를 반환하는 함수입니다 . 그런 다음 입력을 이전 결과로 설정하여 해당 함수를 반복적으로 호출합니다.
답변
@KarlBielefeldt가 지적한 것처럼, 이러한 문제에 대한 기능적 접근 방식은 이전 상태에서 새로운 상태를 반환하는 것으로 보는 것입니다. 함수 자체는 정보를 보유하지 않으므로 항상 상태 m 을 상태 n으로 업데이트 합니다.
새 상태를 계산하는 동안 이전 상태 를 메모리에 유지 해야한다고 가정하기 때문에이 비효율적이라고 생각합니다 . 완전히 새로운 상태를 작성하거나 이전 상태를 다시 작성하는 것 중에서 선택 하는 것은 기능적 언어의 관점에서 구현 세부 사항 입니다.
예를 들어, 백만 개의 정수 목록이 있고 10 분의 1을 증가시키고 싶다고 가정하십시오. 10 번째 위치에 새로운 번호로 전체 목록을 복사하는 것은 낭비입니다. 그러나 이는 언어 컴파일러 또는 인터프리터에게 작업을 설명하는 개념적 방법 일뿐입니다. 컴파일러 또는 인터프리터는 첫 번째 목록을 자유롭게 가져 와서 열 번째 위치를 덮어 씁니다.
이러한 방식으로 작업을 설명하는 이점은 많은 스레드가 다른 위치에서 동일한 목록을 업데이트하려고 할 때 컴파일러가 상황에 대해 추론 할 수 있다는 것입니다. 작업이 “이 위치로 이동하여 찾은 내용을 덮어 씁니다”로 설명 된 경우 덮어 쓰기가 충돌하지 않도록하는 것은 컴파일러가 아닌 프로그래머입니다.
그러나 Haskell에도 “상태 유지”가 문제에 대한보다 직관적 인 솔루션 인 상황을 모델링하는 데 도움 이되는 State 모나드 가 있습니다. 그러나 ” 데이터베이스에 쓰는 것과 같이 본질적으로 상태 가 양호하다 “는 Datomic과 같은 불변의 솔루션 이 있다는 몇 가지 문제에 주목하십시오 . 개념이라는 것을 알기 전까지는 반드시 실현 될 필요는 없습니다.
답변
올바른 정신 모델을 구독하면 상태를 더 잘 생각하고 관리하는 데 도움이됩니다. 내 마음에, 최고의 정신 모델은 플립 북 입니다. 클릭하면 FP가 세계 상태를 캡처하는 영구적 인 데이터 구조에 크게 의존하고 있으며 함수가 돌연변이없이 해당 상태를 전환하는 데 사용된다는 것을 이해할 수 있습니다.
Rich Hickey는 다음 아이디어를 밝힙니다.
이 다른 이야기입니다 그러나 이것은 옳은 방향으로 당신을 보내야합니다.
답변
크고 중간 규모의 응용 프로그램을 작성할 때 종종 상태 기반 응용 프로그램과 상태 비 저장 응용 프로그램 섹션을 구분하는 것이 유용하다는 것을 알았습니다.
상태 저장 섹션의 클래스 / 데이터 구조는 응용 프로그램 데이터를 저장하며이 섹션의 기능은 응용 프로그램 데이터에 대한 암시 적 지식으로 작동합니다.
상태 비 저장 섹션의 클래스 / 데이터 구조 / 함수는 애플리케이션의 순전히 알고리즘 측면을 지원하기 위해 존재합니다. 그들은 응용 프로그램의 데이터에 대한 암시 적 지식이 없습니다. 그것들은 순전히 기능적인 성격으로 작동합니다. 응용 프로그램의 상태 저장 부분은 응용 프로그램의 상태 비 저장 섹션에서 함수 실행의 부작용으로 상태 변경을 경험할 수 있습니다.
가장 어려운 부분은 stateless 섹션에 넣을 클래스 / 함수와 stateful 섹션에 넣을 클래스 / 함수를 파악하고 별도의 파일 / 라이브러리에 넣는 규칙을 갖는 것입니다.