ios개발/함수형 프로그래밍

<함수형 프로그래밍> 4편 what is functional programming and state!! by mike bopp

studying develop 2020. 4. 18. 16:05

[https://www.rapiddg.com/article/what-functional-programming-and-state] 여기 정말 잘나와있다. 이런식으로 검색하자.

"what is a state in functional programming" 이게 검색어이다.


State

State is one of those terms that is thrown around a lot when discussing modern application development.  And it may not be something we have traditionally talked much about about, at least not referring to it as "state".  Application state is bascially stored memory for the application, which can be in the form of variables, properties, etc.  

스테이트는 우리가 일반적으로 사용하는 의미랑 좀 다르고,  어플리케이션 스테이트는 어플리케이션을 위해 저장된 메모리를 의미한다. 변수나 프로퍼티 같은.

 

The web in nature is inherintly stateless.  Meaning every request made to a server, begins with no state (with the exception of perhaps session related information, etc).  There are no arrays or data structures persisted. Each call may fetch data from a database and essentially starts from scratch. This is true with the traditional web.  Innovation in web development has had a lot to do with how to add state to web applications.

요즘에야 웹에 스테이트가 있지, 원래는 스테이트가 웹상에서는 없다. 세션 같은게 스테이트임.

 

  So state really applies more to native application development.  Think of it this way.  An app on your machine, like Google Chrome, is constantly running, either in the foreground or background, but running nonetheless.  It is in charge of managing how much memory is uses.  Getting rid of information it no longer needs and persisting (saving) data that it will need to reference later.  

그래서 스테이트는 네이티브 어플레케이션에서 잘 사용된다. 크롬같은 프로그램이 돌아가면 메모리 사용을 책임지고 관리한다. 더이상 필요없는 정보를 제거하고 나중에 사용될걸 남겨놓는 식으로.

 

For example, tabs in Chrome are a form of state.  If you open a tab with GMail in it, and then primarily use other tabs for browsing throughout the day, your GMail tabs still exists and doesn't disappear.  Google Chrome knows that it should not trim that information from memory because you may at some point want to click on that tab and resume using GMail.  This is an oversimplified version of "state".

State as we will be referring to it, will be at a much more micro level, and has more to do with storing variables and properties in your code vs. running values through a "stream" of functions that manipulate the data being passed along.  Global variables are the opposite of stateless design.  One large advantage of removing state is simple testability.  If you have methods or functions that are stateless, and only know about what has been passed to them, they are much easier to test.  There are no outside factors that have to be handled, set up, or torn down.  It is solely dependent on what you tell it in your test.  

Stateless design also relates to language paradigms like mutable and immutable variables.  Mutable means changable.  Immutable means the variable is only ever assigned once, and never changes.  In stateless design we begin using Immutable values much, much more.  Which also eases testing, and reduces the risk of other outside factors giving the app unexpected results.  Languages like PHP are more or less always mutable.  Languages like Swift have introduces more convenient ways to work with Immutable data.  If you are changing or manipulating data that is immutable, you are creating a new variable, rather than change the existing one.  This brings us to Functional Programming.

 


[https://stackoverflow.com/questions/2909282/why-are-functional-languages-considered-a-boon-for-multi-threaded-environments]

 

why are functional languages considered a boon for multi threaded environments?

 

It's important to add one word: "there's no shared state".

Any meaningful program (in any language) changes the state of the world. But (some) functional languages make it impossible to access the same resource from multiple threads simultaneously. The absence of shared state makes multithreading safe.

 

질문에 대한 주된 답들을 보니, 스테이트가 없기 때문이라한다. 공유되는 스테이트(영역인가??)을 최소화하게 된다함 fp를 사용하면.

 

그래서 적용 예시를 좀 찾고 싶었는데, 찾는중이다.


 

State as we will be referring to it, will be at a much more micro level, and has more to do with storing variables and properties in your code vs. running values through a "stream" of functions that manipulate the data being passed along.  Global variables are the opposite of stateless design.  One large advantage of removing state is simple testability.  If you have methods or functions that are stateless, and only know about what has been passed to them, they are much easier to test.  There are no outside factors that have to be handled, set up, or torn down.  It is solely dependent on what you tell it in your test.

Stateless design also relates to language paradigms like mutable and immutable variables.  Mutable means changable.

스테이트는 마이크로 레벨에 관련된 것이다, 그리고 스테이트는 코드에서 변수와 프로퍼티 저장과 관련되어 있다 vs 값들을 넘겨지는 데이터들을 조작하는 함수들의 스트림으로 실행시키는 것과 대비된다는듯?. 스테이트 제거의 가장큰 장점중 하나는 테스트 용이성이다. 함수나 메소드가 스테이트리스면 오직 넘어간 값만 알면 된다, 그럼 테스트하기 더 쉽다. 조절할 다른 외부 요인들이 없다, set up 준비하거나, torn down ? 너가 테스트에서 말하는것에 완전히 의존적이다. 스테이트리스 디자인은 변이성과 불변성 변수같은 언어 패러다임과 연관이 있다. 

 

 

 Immutable means the variable is only ever assigned once, and never changes.  

 

In stateless design we begin using Immutable values much, much more.  Which also eases testing, and reduces the risk of other outside factors giving the app unexpected results.  Languages like PHP are more or less always mutable.  Languages like Swift have introduces more convenient ways to work with Immutable data.  If you are changing or manipulating data that is immutable, you are creating a new variable, rather than change the existing one.  This brings us to Functional Programming.

 

스테이트리스 디자인에서는 이뮤터블 값들을 훨씬 더 많이 사용한다. 그것은 테스팅도 쉽고, 앱에 예상 못한 결과를 주는 외부 요인에 의한 위험도 감소 시킨다. php 같은 언어는 뮤터블하다. 스위프트는 이뮤터블 데이터를 다룰수 있는 편리한 방법을 준다. 만약 너가 이뮤터블 데이터를 변화시키거나 조작하면 , 기존 것을 바꾸는게 아니라 우리는 새로운 값을 만든다. 이것은 우리에게 함수형 프로그래밍을 제공한다.

 


Functional Programming

Functional programming is how we more or less implement stateless application design.  This is because we can "chain" functions together and a value or set of values are passed along the chain being manipulated along the way, and eventually returned to what is usually an immutable variable.  This variable can be immutable because all the manipulation that needs to be done is compartmentalized into a series of functions.  Functions that take in a value and return a value.  A chain of functions is basically saying do this, then do this, then do this, and so on and so forth till we have the data we want.  

fp는 우리가 어떻게 스테이트리스 앱을 디자인하는가 이다. 왜냐면 우리는 함수들을 체인처럼 함께 연결하고 값들이 체인을 통해 넘어가며 조작된다, 그리고 결국에는 이뮤터블 변수로 반환된다. 이 변수는 이뮤터블일수 있다 왜냐하면 모든 실행되야 하는 조작들이 일련의 함수들로 구획화된다. 함수들은 값을 받고 리턴한다. 함수의 체인은 이걸하고, 그리고 저걸하고 그리고 저것, ~ 을 우리가 원하는 데이터를 얻을때 까지 하라는 것이다.

 

Functional programming is generally considered more difficult to learn.  I think this is because working with mutable data allows someone to set a variable, then use standard programming constructs to change this value over time.  It also allows you to see the logic that is happening to your variable sequentially, often in the same block of code.  I suppose this is often called procedural code.  There isn't anything wrong with procedural code, it's just a different way manipulating data.  And you can combine both of these design patterns easily with a program.  PHP is a good example of this.  PHP if by in large procedural, but there are some functional aspects of it.  Like mapping, or filtering an array. You might use functional code to set up an array, but then procedurally evaluate and change this array afterwards.  

fp는 일반적으로 배우기 더 어렵다 한다. 왜냐하면 뮤터블 데이터는 누군가 변수를 놓고, 표준 프로그래밍 구성들을 사용해 그 값을 시간에 따라 바꾸도록한다. 뮤터블 데이터는 또한 우리가 우리 변수에 순차적으로 작동하는 로직을 볼수 있게한다, 종종 동일한 코드 블록에서도. 이것은 우리가 말하는 절차적 코드이다. 절차적 코드에는 문제가 없다, 이것은 단지 다른 방식의 데이터 조작방식이다. 우리는 두가지 디자인 패턴 모두를 프로그램에 쉽게 가져올수 있다. php는 좋은 예시이다. php는 절차적이지만, 몇몇 함수적 측면들도 있다. 배열의 mapping 또는 filtering 같은것이다. 우리는 함수형 코드를 배열의 준비를 위해 사용할수 있다, 하지만 이후 데이터를 절차적으로 평가하고 변화시킨다.

 

Loops (or lack there of) are often talked about when describing Functional Programming.  Probably due to the fact that it is such a common structure in code that functional programming approaches differently.  So in a loop, you are checking a series of values, either changing them or using them to construct something else.  An example will help explain this...

루프는 fp를 설명할때 자주 사용된다. 아마도 fp에서 다르게 접근하는 흔한 코드 구조이기 때문인거 같다. 그래서 루프에서, 일련의 값들을 확인하고, 그것들을 변화시키거나 무엇인가 구성하기 위해 그것을 사용한다. 이제 예시이다.

 

$arr = array(1,2,3);
$total = 0;
foreach ($arr as $number) {
  $total = $total + $number;
}
print $total;

There are a bunch of ways to approach this functionally in PHP.  You can use array_reduce() to return the total.  

$arr = array(1,2,3);
$total = array_reduce($arr, "add", 0);
print $total;

function add($a, $b) {
  return $a + $b;
}

This is a bad example though, because PHP isn't really set up for functional programming.  Ideally we would chain array_reduce to our array variable rather than call a function that passes the array as a parameter.

이것은 않좋은 예시다, 왜냐면 php는 fp를 위해 준비된 언어가 아니다. 이상적으로 우리는 array_reduce를 우리의 array 변수로 체인할것이다, 함수의 파라미터로 배열을 넘겨주기 보다는.

 

스위프트가 이런 측면에서 훨씬 좋다.

 

???근데 내가 알기로 이렇게 사용하려면 메소드여야 되는거 아닌가? 근데 왜 reduce가 메소드인가??

 

let arr = [1,2,3]
let total: Int = arr.reduce(0, add)
print(total)

func add($a: Int, $b Int) -> Int {
  return $a + $b
}

This is more functional.  We are calling reduce as a method of the array itself, telling it to start with 0, and run the add function for each value in the array.  Pass in two values... one that in this case is the running total, and the second the next element in the array.

이게 훨씬 함수적이다. 우리는 배열의 메소드로 reduce를 호출한다, 0부터 시작하라고, 그리고 add 함수를 배열의 각각의 값에 대해 실행한다. 두가지 값을 전달해라...한개는 running total, 그리고 둘째는 array이다.

 

But Swift is set up to handle these kinds of things much "cleaner".  It's kind of a pain to define a whole function just to add values (I think this is one barrier to developers when switching to functional programming). Swift (as well as many other languages) introduces closures.  So defining a function seperately isn't really necessary, it can be done on the fly.  Like this...

하지만 스위프트는 이런 것들을 훨씬 깔금하게 다룰수 있다. 전체 함수를 단지 값들을 더하기 위해 정의하는것은 고통스럽다(이분 생각에는 이 시점에서 fp로 개발자가 넘어가는 경계라 생각한다.) 스위프트는 closure들을 제공한다. 그래서 함수를 개별적으로 정의할 필요가 없다, 그냥 공중에서 가능하다. 이렇게....

 

let arr = [1,2,3]
let total: Int = arr.reduce(0) { $a, $b in
  return $a + $b
}
print(total)

또는 더 쉽게....

let arr = [1,2,3]
let total: Int = arr.reduce(0) { $0 + $1 }
print(total)

This is such a common pattern in Swift that they make things easier on developers developing functionally by assuming some things.  No need for a return statement in the ad hoc function. It just assumes that the evaluation is the return value.  No defining parameters to the function, just use $0, $1, etc for the values being passed in.  I displayed the second way after showing more explicitly what was going on to make things more understandable to someone used to programming procedurally.

이것은 개발자가 무엇인가 가정하며 함수적으로 개발하는데 더욱더 쉽게해주는 스위프트에서 공통적인 패턴이다. 애드혹 함수에서(애드혹이 to this라는데 다른 의미같은데) 반환 문장이 필요 없다. 단지 계산값이 리턴값이라 가정한다. 파라미터들이 정의될 필요도 없다, 단지 $0,$1등을 값을 넘기기위해 사용한다. 나는 두번째 방법을 통해 절차적 프로그래밍을 사용하는 사람이 작동중인 것을 더욱더 잘 이해하기 위해 명시적으로 사용했다. 

 

One last concept to mention is High Order functions, because you will see this term quite a bit in the functional world.  High Order functions are simply functions that can take other functions as parameters.  This is an important part of chaining things functionally.

마지막 개념은 high order 함수들이다, 왜냐하면 우리는 함수 세계에서 이런것들을 볼것이다. high order 함수들은 다른 함수를 파라미터들로 받는 단순한 함수들이다. 함수적으로 체이닝하는데 중요한 부분이다.

 

This brings us one step closer to understanding Reactive Cocoa.  The next post will be exploring the "Reactive" part.

이것을 통해 우리는 리액티브 코코아를 이해하는데 한걸음 더 가져다 준다.

 

다음은 리액티브 파트를 알아보자. 음 좋은듯 이것도 더 해보자.