함수형 프로그래밍 - 일급 함수, 고차함수, Iterable, Generator

jiseong·2022년 6월 27일
0

T I Learned

목록 보기
277/291
post-custom-banner

일급 함수

컴퓨터 과학에서, 함수를 변수와 동일하게 다루는 프로그래밍 언어를 일급 함수를 가졌다고 언급한다. 이것은 언어가 함수를 다른 함수에 인자로 전달하고, 다른 함수의 값으로 반환하고, 변수에 할당하거나 데이터 구조에 저장하는 것을 지원한다는 것을 의미한다.

다른 함수에 인자로 전달

function sayHello() {
   return "Hello, ";
}
function greeting(helloMessage, name) {
  console.log(helloMessage() + name);
}
// `sayHello`를 `greeting` 함수에 인자로 전달
greeting(sayHello, "JavaScript!");

다른 함수의 값으로 반환

function sayHello() {
   return function() {
      console.log("Hello!");
   }
}

변수에 할당하거나 데이터 구조에 저장

const add10 = a => a + 10;
console.log(add1) 
// 함수의 내용이 나온다 즉, 변수에 함수가 담겼다로 생각할 수 있다.

고차 함수

함수를 인자로 받는 함수

const times = (f, n) => {
  let i = 0;

  while(i < n) {
    f(i++);
  }
}

times(console.log, 3);

함수를 반환하는 함수

const addMaker = a => b => a + b; // 커링??

const add10 = addMaker(10);
console.log(add10);

iterable

이전 Iterable, Iterator 관련 포스팅

iterable인 것은 어떻게 순회할지에 대해 구체적, 명령적으로 정의하기 보다는 보다 선언적으로 정의하여 순회할 수 있다.

const str = 'abc';
// 어떻게 순회할지에 대해 구체적, 명령적으로 정의하기 보다는 
for(let i = 0; i < str.length; i+=1) {
  // console.log(str[i]);
}

// 보다 선언적으로 가능해짐
for(const i of str) {
  // console.log(i);
}

새롭게 알게 된 점

map 의 경우에는 for... of문 내부에서 keys(), values() 메서드로 호출하여도 다시 iterable한 객체를 반환해줌.

아래와 같은 코드가 가능해짐

const map = new Map([['a', 1], ['b', 2]]);

for(const a of map.keys()) console.log(a);

DOM과 관련된 값들도 Iterable 값을 가짐

for(const a of document.querySelectorAll('*')) console.log(a);

Well-formed iterable의 추가적인 조건

iterator 객체 또한 Symbol.iterator 메소드가 존재하며, iterator 객체인 자기 자신을 반환하는 것

직접 만들어보기

const countObj = {
  from: 1,
  to: 5,
}

Object.defineProperty(countObj, Symbol.iterator, {
  value() {
    let {from, to} = this;

    return {
      next() {
        if(from <= to) return iteratorProtocol(from++);
        
        return iteratorProtocol();
      },
      [Symbol.iterator]() {return this}
    }

  }
})

function iteratorProtocol(value) {
  if(!value) return { done: true };

  return {
    done: false,
    value
  }
}

for(const a of countObj) {
  console.log(a);
}

Generator

이전 Generator 관련 포스팅

제네레이터 함수에 의해 반환되며 이전 시간에 배운 Iterable Protocol과 Iterator Protocol을 준수하는 객체

그렇기 때문에 아래와 같이 반복이 가능

function *gen() {
  yield 1;
  yield 2;
  yield 3;
}

for(const a of gen()) console.log(a);

새롭게 알게 된 점

제네레이터 함수에 의해 반환되는 Generator가 Iterable Protocol을 준수하는 객체라고 했던 이유Generator가 Iterator 객체이기도 하지만 잘 만들어진 Iterator는 또 다시 자신을 반환하는 Well-formed iterable이기 때문이다.

const wellFormedIterable = {
  [Symbol.iterator](){
    return {
      next() { }, // 생략
      [Symbol.iterator]() { return this; } // 이 부분!!!
    }
  }
}

Reference

post-custom-banner

0개의 댓글