3.3 함수

NetLogo에서 함수들로 코드를 정리하는 유틸리티를 보았다. 각 함수는 코드의 이름과 몸체에 의해 정의된다. 함수의 코드는 함수의 이름이 실행문으로 사용되어질 때 마다 실행된다. 이 작업을 함수의 “calling”또는 “invoking”이라고 한다. 함수의 집합으로 큰 프로그램을 조직화하는 것에 대한 장점은 다음과 같이 요약된다.

  • intelligibility(명료성) - 함수들로 구축한 큰 프로그램은 이해하기 쉽다.
  • reuse within(재사용성) - 함수는 다른 위치에서 호출 될 수 있고, 프로그램 전체 크기를 줄일 수 있다.
  • replacement(대체성) - 함수의 몸체는 훈련 방식으로 프로그램의 의미를 변경하는 다른 코드 또는 동일한 효과를 가진 더 좋은 코드로 대체 할 수 있다.
  • reuse across - 새로운 프로그램을 구축하는 것에 이전 프로그램에 함수를 사용한다.
  • construction - 많은 프로그래머들이 동일한 프로그램을 개발하는 것에 유용한 방법은 다른 함수에 대한 코드를 각자 하나씩 개발하는 것이다.

 

Blockly에서 함수를 정의하고 사용하는 방법뿐만 아니라, 더 강력하고 유용한 함수의 새로운 측면을 볼 것이다.

 

3.3.1 기본 함수

다음에 표시된 Blockly 환경에서 “Functions”카테고리 블록들이 팔렛트에 포함되어 있다. Functions 카테고리에는 3가지 기본 블록들이 있다.

  • to do something - 이름을do something으로 대체하는 함수로 정의한다.
  • to do something...return - ● 지정한 값으로 반환(return) 할 수 있는 기능이 추가된 것으로 이전 블록과 유사하다.
  • if...return... -반환 값을 지정하기 위한 또 다른 방법이다.

함수의 아이디어를 설명할 수 있는 예제들을 볼 것이다.

첫 번째 예는 데이터 스트림을 변환하는 방법을 설명하는 Blockly 코드를 사용한다. 아래 Blockly 환경에서 변환 코드는 함수를 사용하기 위해 재구성되어 있다. Blockly 코드가 두 부분으로 되어있다는 것을 알 수 있다. 아랫 부분은 convert라는 함수의 정의이다. 코드의 윗 부분은 main 프로그램이라 불린다. convert함수의 몸체는 변환(화씨 데이터 스트림을 섭씨 데이터 스트림으로 만드는)을 하는 본래 예제에 코드이다. 윗 부분은 본래 예제 Blockly code에 한 가지 추가된 것이다. 두 개의 출력 블록 사이에 convert라는 이름을 새 블록이 있다. convert 이 블록은 함수의 몸체를 실행시키기 때문에 “call block”이다. 아래 예제 코드를 실행하고, 본래 예제와 같은 출력을 생성하는지 확인하여라.

이 코드와 함수를 실행하는 프로그램 사용에 특정 방법을 이해하는 것이 중요하다. 프로그램 실행은 주 프로그램에 첫 상태로 시작한다. 위의 예제 코드는 주 프로그램에 첫 상태로 시작하는 “Run” 버튼에 응답으로 실행한다.
  1. The set Cstream to... 블록 실행

  2. The set Fstream to... 블록 실행

  3. The print Fstream 블록 실행

  4. 함수를 호출해야되기 때문에, convert call 실행

    4.1. convert 함수에 for each item... 반복 실행; 각 반복은 Cstream 리스트에 또 다른 아이템을 추가함

    4.2.반복이 완료될 때, 함수에 모든 상태들이 실행되어지고, 함수는 반환 값을 반환함

  5. The print Cstream 블록 실행

 

아래 그림은 시각적으로 이벤트의 순서를 보여준다. 화살표는 코드의 상위 부분과 함수간 “제어 흐름"을 표현한다. call 블록이 실행될 때, “제어 흐름” 은 실행을 시작하기 위해 함수를 가져온다. 함수가 실행을 완료할 때 “제어 흐름"은 반환하고, call 블록 이후에 상태를 즉시 실행시킨다.


../_images/Blockly-Function-Call-Return.png
그림 3-21. 함수에서 호출 및 복귀

 

Blockly 코드에 대한 세부적인 것은 함수에 대한 “call” 블록을 생성하는 방법이다. 함수 정의 블록이 작업 영역에 배치될 때, 함수를 위한 call 블록이 Function 카테고리에 자동적으로 만들어진다. 함수 정의 블록이 이름이 변경될 때, 함수를 위한 call블록은 자동으로 이름이 변경된다.

 

3.3.2 파라미터를 가진 함수

위에 예제에서 정의된 convert함수는 완벽하게 동작하지만 잘못 디자인되었다. 잘못된 디자인은 특정 이름인 FstreamCstream과 연관되어 있다는 사실에서 나온다. 함수는 FstreamCstream으로 변환한다. 모든 도시에 대한 섭씨온도가 해당 화씨온도 다음에 출력되도록 하기 위하여 조직된 다른 도시들에 온도 테이블을 생산하려는 경우 이 디자인의 한계를 볼 수 있다. 기존 convert함수를 사용하여 두 도시에 대한 메인 프로그램 코드는 다음처럼 구성된다.

set Cstream to empty list

set Fstream to get forecasts for "Blacksburg, VA"
convert
print Cstream

set Fstream to get forecasts for "Seattle, WA"
convert
print Cstream

set Fstream to get forecasts for "Blacksburg, VA"
print Fstream
set Fstream to get forecasts for "Seattle, WA"
print Fstream

 

이 코드에서 각 스트림을 두 번 읽을 필요가 있다. 두 번째 도시에 대해 convert 함수를 사용하기 위해 첫 번째 도시에 대한 데이터스트림은 Fstream이 두 스트림 중 하나 또는 다른 하나만을 참조할 수 있기 때문에 덮어 쓰게 해야 한다. 필요한 것은 데이터 스트림을 나타내는 변수의 실제 이름과 관련되지 않은 더 유연한 함수이다. 즉, 함수는 리스트에 대한 변수를 무엇으로 부르던 하나의 리스트를 대표하는 데이터 스트림으로 변환할 수 있어야 한다.

 

원하는 유연성을 추가하기 위해 함수는 변환할 수 있는 데이터 스트림을 나타내는 파라미터를 정의하고 호출해야 한다. 아래 Blockly 환경은 파라미터로 convert 함수를 새 정의와 호출을 보여준다. 정의 블록과 호출 블록을 만드는 것을 Blockly에 다음 단계에서 볼 수 있다. 이전 변환 프로그램과 같은 출력을 만드는지 Blockly 프로그램을 실행해보아라.

 

convert f함수의 정의는 두 가지 변경사항이 있다. 첫째, 정의 블록에 함수의 이름을 정의하는 것 외에 TheStream을 가진다. TheStream은 파라미터의 이름이다. 둘째, 파라미터의 이름은 어떤 스트림을 변환하는 것을 표시하기 위해 반복 블록에 사용된다. convert함수의 정의는 입력으로 특정 이름 Fstream과 연결되지 않는다.

 

호출 블록은 한 가지 중요한 변화가 있다. 호출 블록을 호출하기 위해 함수의 이름을 제공하는 것 이외에 TheStream이라는 이름의 슬롯을 가진다. 파라미터의 이름은 함수가 호출될 때 제공되어야 한다. 현재 TheStream 이라는 슬롯은 이 버전의 함수가 이전과 같은 변환을 수행하도록 연결된 Fstream을 가진다.

 

더 나은 디자인은 위의 예로 다시 볼 수 있다. 모든 도시에 대한 섭씨온도를 해당 화씨 도 이후에 출력하게 하기 위해 다른 도시들의 온도 테이블을 생산할 수 있다. 이 코드는 다음과 같이 쓸 수 있다.

set Cstream to empty list

set Fstream to get forecasts for "Blacksburg, VA"
convert (Fstream)
print Cstream

set Gstream to get forecasts for "Seattle, WA"
convert (Gstream)
print Cstream

print Fstream
print Gstream

Blacksburg에 대한 데이터 스트림과 Seattle에 대한 데이터 스트림은 FstreamGstream라는 다른 리스트로 표현되는 것을 유념해야 한다. 각 스트림은 오직 한번만 읽는다.

예를 들어 convert (Fstream)Fstream>이 호출 블록 슬롯에 연결된 호출 블록을 표현하는데 사용되어지고, convert (Gstream)이 호출블록 슬롯에 연결된 호출 블록을 표현하는 것에 사용되어진다.

중요한 점은 파라미터를 가진 convert함수가 리스트를 표현하는데 사용되는 함수의 이름에 상관없는 어떤 입력 데이터 스트림에서도 동작하기 때문에 훨씬 더 나은 설계라는 점이다.

파라미터를 가진 함수를 위한 함수 정의와 호출 블록을 만드는 것은 약간의 설명이 필요하다. 무엇인가를 하는 함수 정의 블록은 왼쪽 구석에 파란 바탕의 별 아이콘에 있다. 이것을 클릭할 때 아이콘은 파라미터를 추가할 수 있는 화면을 보여준다. 그림에서 상단 부분에 이 화면을 보여주고 있다. 화면 왼쪽은 이름이 x인 일반 변수를 나타내는 입력 이름 x 블록을 포함한다. 화면 오른쪽은 파라미터가 연결될 수 있고, 이름을 입력 할 수 있는 슬롯을 가진 입력 블록을 포함한다. 그림에 아래 부분은 일반 변수 블록을 입력 슬롯에 끌어 놓을 수 있고, 삽입할 수 있고, 일반 이름 x가 변경 되어질 수 있다는 것을 보여준다. 이 경우 파라미터 이름은 TheStream으로 변경 하였다. 함수의 이름은 do something에서 convert로 변경되었다. 함수 정의를 완료하기 위해 별 아이콘을 클릭한다.


../_images/Blockly-Functions-Parameter-Definition.png

그림 3-23. 함수 정의에 매개 변수 추가

 

함수 정의를 완료할 때, 해당 호출 블록은 “Functions”메뉴에서 자동적으로 만들어지고 추가될 것이다.

 

3.3.3 Return 값을 가진 함수

convert함수의 디자인은convert 함수가 하나의 출력(섭씨 온도 값의 스트림을 표현하는 리스트)을 갖는 것을 인식함으로써 더 개선되어질 수 있다. 이전 예제에서 이 출력의 이름은 Cstream과 연결되어있다. 입력들에 대한 특정 이름과 연관되지 않고 동작할 수 있는 함수이길 바라고 또한 출력이 특정 이름에 관련되어지지 않는 것이 바람직 할 것이다.

함수는 하나의 값을 “반환"하도록 정의할 수 있다. 다음의 Blockly 예는 하나의 값을 반환하는 convert 함수의 수정된 버전을 보여준다.

수정된 예에서 주목해야 할 중요한 세 가지가 있다.

  1. convert함수는 return이라는 이름의 추가 슬롯을 가진 정의 블록을 가진다. 이것은 함수가 완료될 때 호출 블록에 제공되는 슬롯의 변수 값이다.
  2. 고정된 이름에 연결된 반환 값을 유지하기 위해 convertf함수는 스스로 반환 값의 이름을 정의한다. 이 경우, 변수 TempStreamconvert함수 내에서 정의되고 사용되어진다.
  3. convert함수에서 호출하는 블록은 함수의 호출이 완료될 때, 반환하는 값으로 무엇을 할 수 있는지 보여줘야 한다. 이 예에서 호출 블록은 set Cstream to블록의 슬롯에 삽입된다. 이것은 convert함수에 의해 반환된 값이 Cstream에 할당된다는 것을 의미한다.

 

위의 예가 제대로 작동하는지 실행해보아라.
함수 정의 블록을 정의하기 위해 Function 카테고리에 to “do something” return 블록을 사용한다. 이 블록에 파라미터는 전에 같은 방법으로 추가될 것이다. (파란 바탕에 별 아이콘 클릭)

Cohort 연습문제 : 화씨-섭씨 변환에 대한 함수를 정의하고, 위의 예제 코드를 수정하기 위해 이 함수를 사용하라.

Leave a Reply

Your email address will not be published. Required fields are marked *

*