기능 프로그래머가 되길 원합니다 (4 부)

기능 프로그래밍 개념을 이해하기위한 첫 번째 단계를 취하는 것이 가장 중요하고 때로는 가장 어려운 단계입니다. 하지만 꼭 그럴 필요는 없습니다. 올바른 관점이 아닙니다.

이전 부품 : 1 부, 2 부, 3 부

카레

Part 3을 기억한다면, mult5를 구성하고 add (in)하는 데 문제가 있었던 이유는 mult5가 1 개의 매개 변수를 취하고 add가 2를 취하기 때문입니다.

모든 함수를 하나의 매개 변수 만 사용하도록 제한하면이 문제를 쉽게 해결할 수 있습니다.

날 믿어. 소리만큼 나쁘지 않습니다.

우리는 단순히 2 개의 매개 변수를 사용하지만 한 번에 1 개의 매개 변수 만 취하는 add 함수를 작성합니다. 카레 기능을 통해이를 수행 할 수 있습니다.

Curried Function은 한 번에 하나의 매개 변수 만 취하는 기능입니다.

이를 통해 mult5로 작성하기 전에 첫 번째 매개 변수를 추가 할 수 있습니다. 그런 다음 mult5AfterAdd10이 호출되면 add는 두 번째 매개 변수를 얻습니다.

Javascript에서는 add를 다시 작성하여이를 수행 할 수 있습니다.

var add = x => y => x + y

이 버전의 add는 현재 하나의 매개 변수를 사용하고 나중에 다른 매개 변수를 사용하는 함수입니다.

구체적으로 add 함수는 단일 매개 변수 x를 사용하고 단일 매개 변수 y를 사용하는 함수를 반환하며, 결과적으로 x와 y를 더한 결과를 반환합니다.

이제이 버전의 add를 사용하여 mult5AfterAdd10의 작동 버전을 빌드 할 수 있습니다.

var compose = (f, g) => x => f (g (x));
var mult5AfterAdd10 = 작성 (mult5, 추가 (10));

작성 기능은 두 개의 매개 변수 f와 g를 취합니다. 그런 다음 1 개의 매개 변수 x를 사용하는 함수를 반환합니다.이 함수를 호출하면 x 뒤에 g 뒤에 f가 적용됩니다.

그래서 우리는 정확히 무엇을 했습니까? 음, 우리는 평범한 이전 add 함수를 카레 버전으로 변환했습니다. 이것은 첫 번째 매개 변수 10이 앞에 전달 될 수 있고 mult5AfterAdd10이 호출 될 때 최종 매개 변수가 전달되므로 더 유연 해졌습니다.

이 시점에서 Elm에서 add 함수를 다시 작성하는 방법이 궁금 할 것입니다. 그럴 필요는 없습니다. Elm 및 기타 기능 언어에서는 모든 기능이 자동으로 커리됩니다.

추가 기능은 동일하게 보입니다.

x y = 추가
    x + y

이것이 mult5AfterAdd10이 Part 3에서 다시 쓰여진 방법입니다.

mult5AfterAdd10 =
    (mult5 << 10 추가)

문법적으로 말하면, Elm은 커리 및 구성과 같은 기능적인 것들에 최적화되어 있기 때문에 Javascript와 같은 명령형 언어를 능가합니다.

카레와 리팩토링

또 다른 시간 카레 링은 많은 매개 변수가있는 함수의 일반화 된 버전을 만든 다음이를 사용하여 더 적은 매개 변수로 특수한 버전을 만드는 경우 리팩토링 중에 발생합니다.

예를 들어, 문자열 주위에 대괄호와 이중 대괄호를 넣는 다음 함수가있는 경우 :

대괄호 str =
    "{"++ str ++ "}"
doubleBracket str =
    "{{"++ str ++ "}}"

사용 방법은 다음과 같습니다.

bracketedJoe =
    괄호 "조"
doubleBracketedJoe =
    doubleBracket "조"

브라켓과 더블 브라켓을 일반화 할 수 있습니다 :

generalBracket 접두사 str 접미사 =
    접두사 ++ str ++ 접미사

그러나 이제 우리는 generalBracket을 사용할 때마다 대괄호를 전달해야합니다.

bracketedJoe =
    generalBracket "{" "Joe" "}"
doubleBracketedJoe =
    generalBracket "{{" "Joe" "}}"

우리가 정말로 원하는 것은 두 세계의 최고입니다.

generalBracket의 매개 변수를 재정렬하면 함수가 커리된다는 사실을 활용하여 브래킷과 doubleBracket을 작성할 수 있습니다.

generalBracket 접두사 접미사 str =
    접두사 ++ str ++ 접미사
대괄호 =
    일반 브래킷 "{" "}"
doubleBracket =
    일반 브래킷 "{{" "}}"

접두사와 접미사가 가장 정적 일 가능성이 가장 높은 매개 변수를 먼저 배치하고 가장 마지막에 변경 될 가능성이 가장 높은 매개 변수 (예 : str)를 넣으면 일반 버전의 일반 버전을 쉽게 만들 수 있습니다.

커리를 완전히 활용하려면 매개 변수 순서가 중요합니다.

또한 브래킷과 doubleBracket은 포인트 프리 표기법으로 작성됩니다 (즉, str 매개 변수가 암시 됨). 대괄호와 doubleBracket은 최종 매개 변수를 기다리는 함수입니다.

이제 이전처럼 사용할 수 있습니다.

bracketedJoe =
    괄호 "조"
doubleBracketedJoe =
    doubleBracket "조"

그러나 이번에는 일반화 된 커리 기능인 generalBracket을 사용하고 있습니다.

공통 기능 기능

기능적 언어에서 사용되는 3 가지 공통 기능을 살펴 보겠습니다.

먼저 다음 자바 스크립트 코드를 살펴 보겠습니다.

for (var i = 0; i 

이 코드에는 한 가지 중요한 문제가 있습니다. 버그가 아닙니다. 문제는이 코드가 상용구 코드, 즉 반복해서 쓰여지는 코드라는 것입니다.

Java, C #, Javascript, PHP, Python 등과 같은 명령형 언어로 코드를 작성하면이 상용구 코드를 다른 코드보다 많이 작성하게됩니다.

그게 잘못이야

그럼 죽이자 함수 (또는 몇 가지 함수)에 넣고 다시 루프를 쓰지 마십시오. 글쎄, 거의 결코; 적어도 기능 언어로 넘어갈 때까지

사물이라는 배열을 수정하는 것으로 시작하겠습니다.

var things = [1, 2, 3, 4];
for (var i = 0; i 

어이 !! 변이성!

다시 해봅시다. 이번에는 변경하지 않습니다.

var things = [1, 2, 3, 4];
var newThings = [];
for (var i = 0; i 

자, 우리는 사물을 돌연변이시키지 않았지만 기술적으로 새로운 것들을 돌연변이 시켰습니다. 지금 우리는 이것을 간과 할 것입니다. 우리는 결국 Javascript에 있습니다. 기능 언어로 이동하면 변경할 수 없습니다.

여기서 중요한 것은 이러한 함수의 작동 방식을 이해하고 코드에서 노이즈를 줄이는 데 도움이됩니다.

이 코드를 가져와 함수에 넣겠습니다. 이전 배열의 각 값을 새 배열의 새 값에 매핑하므로 첫 번째 공통 함수 맵을 호출합니다.

var map = (f, array) => {
    var newArray = [];
    for (var i = 0; i 

맵 함수가 배열의 각 항목에 대해 원하는 작업을 수행 할 수 있도록 함수 f가 전달됩니다.

이제 이전 코드를 다시 작성하여 map을 사용할 수 있습니다.

var things = [1, 2, 3, 4];
var newThings = map (v => v * 10, 사물);

엄마 봐 루프가 없습니다. 그리고 훨씬 읽기 쉽고 따라서 추론합니다.

기술적으로 맵 함수에는 for 루프가 있습니다. 그러나 최소한 더 이상 상용구 코드를 작성할 필요는 없습니다.

이제 배열에서 사물을 필터링하는 또 다른 일반적인 함수를 작성해 보겠습니다.

var filter = (사전, 배열) => {
    var newArray = [];
for (var i = 0; i 

술어 함수 pred는 항목을 유지하면 TRUE를 반환하고, 던지면 FALSE를 어떻게 반환하는지 주목하십시오.

필터를 사용하여 홀수를 필터링하는 방법은 다음과 같습니다.

var isOdd = x => x % 2! == 0;
var 번호 = [1, 2, 3, 4, 5];
var oddNumbers = 필터 (isOdd, 숫자);
console.log (oddNumbers); // [1, 3, 5]

새로운 필터 기능을 사용하는 것은 for-loop로 수동 코딩하는 것보다 훨씬 간단합니다.

최종 공통 기능을 감소라고합니다. 일반적으로 목록을 작성하여 단일 값으로 줄이는 데 사용되지만 실제로는 훨씬 더 많은 일을 할 수 있습니다.

이 기능은 일반적으로 기능 언어에서 접기라고합니다.

var reduce = (f, 시작, 배열) => {
    var acc = 시작;
    for (var i = 0; i 

감소 함수는 감소 함수 f, 초기 시작 값 및 배열을 사용합니다.

감소 함수 f는 2 개의 매개 변수, 배열의 현재 항목 및 누산기 acc를 갖습니다. 이 매개 변수를 사용하여 각 반복마다 새 누산기를 생성합니다. 최종 반복에서 누산기가 반환됩니다.

예제는 작동 방식을 이해하는 데 도움이됩니다.

var add = (x, y) => x + y;
var 값 = [1, 2, 3, 4, 5];
var sumOfValues ​​= 축소 (추가, 0, 값);
console.log (sumOfValues); // 15

add 함수는 2 개의 매개 변수를 사용하여 추가합니다. 우리의 reduce 함수는 2 개의 매개 변수를 취하는 함수를 필요로합니다.

시작 값 0으로 시작하여 합산 할 배열 값을 전달합니다. 감소 함수 내에서 합은 값을 반복 할 때 누적됩니다. 최종 누적 값은 sumOfValues로 반환됩니다.

이러한 각각의 기능, 맵, 필터 및 감소 기능을 사용하면 상용구 for 루프를 작성하지 않고도 어레이에서 일반적인 조작 작업을 수행 할 수 있습니다.

그러나 함수형 언어에서는 재귀만으로 루프 구문이 없으므로 훨씬 유용합니다. 반복 함수는 그다지 도움이되지 않습니다. 그들은 필요합니다

나의 두뇌!!!!

지금은 충분합니다.

이 기사의 다음 부분에서는 참조 무결성, 실행 순서, 유형 등에 대해 설명하겠습니다.

다음 : 5 부

이것을 좋아한다면 아래의 을 클릭하면 다른 사람들이 이것을 Medium에서 볼 수 있습니다.

Elm에서 Functional Programming을 사용하여 서로 배우고 웹 응용 프로그램을 개발하도록 돕는 웹 개발자 커뮤니티에 참여하려면 Facebook Group, Elm Programming Learn https://www.facebook.com/groups/learnelm/을 확인하십시오.

내 트위터 : @cscalfani