방금 함수형 프로그래밍에 대해 들었고 몇 가지 질문이 있을 수 있습니다.
좋아요...
- 함수형 프로그래밍이란 정확히 무엇인가요?
- 객체 지향 프로그래밍과 비교하면 어떤가요?
- Ruby에서 함수형 프로그래밍을 사용해야 합니까?
어떻게 작동하는지 더 잘 이해할 수 있도록 이 질문에 답변해 드리겠습니다.
함수형 프로그래밍이란 무엇입니까?
단순한 유행어나 멋진 단어가 아니라 오래전부터 존재했지만 최근 다시 인기를 얻고 있는 실제 프로그래밍 패러다임입니다.
그리고 이 패러다임의 이면에 있는 기본 아이디어는 생각보다 이해하기 쉽습니다.
함수형 프로그래밍에서 우리는 상태 변경을 피합니다 &"순수한" 함수를 작성하려고 합니다. .
상태 변경을 피한다는 것은 이러한 함수가 함수 외부에서 아무 것도 변경하지 않고, 인스턴스 변수도 변경하지 않으며, 전달된 일부 개체를 변경하지 않는다는 것을 의미합니다...
그런 건 없어요!
Haskell과 같은 함수형 프로그래밍 언어에서 모든 데이터는 IMMUTABLE입니다.
변수와 같은 것이 있지만 수학적 세계에서처럼 행동합니다. 변수에 값이 주어지면 컴파일러는 이 변수를 다른 값으로 재정의하는 것을 허용하지 않습니다.
함수형 프로그래밍의 이점
변경 가능한 데이터는 추적하기 어려운 미묘한 오류로 이어질 수 있기 때문에 불변성은 함수형 프로그래밍의 주요 이점입니다.
예 :
def all_different_from_first?(arr) first = arr.shift arr.all? { |n| n != first } end arr = [1,3,5,7,9] p all_different_from_first?(arr) # true
이 예에서는 배열의 모든 요소가 첫 번째 요소와 다른지 확인하고 싶습니다.
이 작업을 수행하려면 배열에서 첫 번째 요소를 제거하고 동시에 나머지 요소와 비교할 수 있도록 이 요소를 저장해야 합니다.
어떻게 하면 될까요?
우리는 배열로 작업하고 있으며 사용 가능한 방법 목록을 보면 Array#shift 방법이 우리가 원하는 것과 정확히 일치한다는 것을 알 수 있습니다.
다음까지는 잘 작동합니다...
... arr
의 값을 봅니다. 메서드를 한 번 호출한 후:
all_different_from_first?(arr) # true arr # [3,5,7,9]
깜짝!
배열에서 하나의 요소가 손실되었습니다(1
) &우리는 눈치채지 못했습니다.
이것이 이러한 종류의 가변성 버그가 얼마나 교활할 수 있는지입니다.
고정 버전 :
def all_different_from_first?(arr) arr[1..-1].all? { |n| n != arr.first } end
기능 대 OOP
우리 모두 함수형 프로그래밍을 채택해야 합니까?
이 모든 불변 상태가 함수형 프로그래밍을 OOP와 완전히 반대되는 것처럼 보일 수 있으며 어떤 의미에서는 그렇습니다. 그러나 두 프로그래밍 패러다임이 함께 작동할 수 있는 방법이 여전히 있습니다. .
따라서 서두르거나 완전한 기능적 프로그래밍을 시작할 필요가 없습니다. Ruby는 어쨌든 OOP용으로 설계되었으므로 곡물에 맞서 싸울 것입니다.
좋은 소식 :
여전히 함수형 프로그래밍에서 최고의 아이디어를 사용하고 이를 Ruby 코드에 적용할 수 있습니다.
그 방법에 대해 이야기해 보겠습니다.
변동성을 최대한 줄이십시오
이를 수행하는 한 가지 방법은 attr_accessor
를 사용하여 중지하는 것입니다. , attr_reader
에만 충실 .
그런 다음 문자열, 배열 및 해시를 주시해야 합니다.
이러한 개체를 변경하는 메서드가 있습니다.
!
로 끝나는 대부분의 메소드 (예:gsub!
)- 삭제
- 업데이트
- 맑음
- 시프트/시프트 해제/팝/푸시
첫 번째 단계는 이러한 방법을 인식하는 것입니다.
이러한 방법 중 하나를 사용해야 하는 경우 복제 개체에 대해 작업할 수 있습니다.
특정 문자열 및 해당 문자열의 복제본 :
str = "abcd" dup = str.dup
clear
하면 이러한 결과가 나타납니다. 중복된 문자열:
dup.clear # str => "abcd" # dup => ""
이렇게 하면 원래 문자열이 안전하게 유지됩니다.
부분 적용
함수형 프로그래밍에는 불변 데이터와 순수 함수보다 더 많은 것이 있습니다.
"커링"이라고도 하는 기능의 부분적 적용과 같습니다.
예 :
def add(a,b) a + b end add_five = method(:add).curry[5] add_five.call(5) # 10 add_five.call(20) # 25
add
하는 방법을 확인하세요. 메서드는 두 개의 인수를 사용하지만 curry
를 사용하여 메서드는 인수 중 하나를 "미리 로드"할 수 있습니다.
그런 다음 두 번째 인수만으로 호출할 수 있는 람다를 얻습니다.
다음은 또 다른 예입니다. :
list = (1..10) greater_than = ->(x,y) { y > x }.curry list.select(&greater_than.(5)) # [6, 7, 8, 9, 10] list.select(&greater_than.(8)) # [9, 10]
예시 하나 더 :
divisible_by = ->(x,y) { y % x == 0 }.curry list.select(&divisible_by.(5)) # [5, 10] list.select(&divisible_by.(2)) # [2, 4, 6, 8, 10]
요약
함수형 프로그래밍에 대해 배웠습니다. 그 핵심은 순수 함수와 불변 데이터입니다. 이것은 OOP와 완전히 호환되지 않는 코드에 대해 생각하는 방법일 뿐입니다.
읽어주셔서 감사합니다. 아직 뉴스레터를 구독하지 않았다면 구독하는 것을 잊지 마세요! 🙂