# [프로그래밍 언어] 6. Subprograms

## 추상화

---

- **프로세스 추상화**: 부프로그램의 형식으로 같은 문장을 반복하여 작성하지 않음

- **데이터 추상화**: 사용자가 정의한 추상 데이터 타입

## 부프로그램

---

### 부프로그램

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/223829_pt5QFxKgHfA1bNtRfh?q=80&s=1280x180&t=outside&f=webp)

- 인터페이스와 동작을 서술

    - 단일 진입점

    - 호출 프로그램의단위는 피호출 부프로그램의 실행 중 중단

    - 실행이 끝났을 때 제어는 항상 호출 프로그램에게 돌아감

- **부프로그램의 머리부**: 부프로그램 정의 → 이름 제공, 매개변수 리스트 지정

- **부프로그램의 몸체**

    - C, C++: {중괄호}, 시행하지 않아도 함수 번역

    - Java: {중괄호}, 매개변수가 다르면 매개변수 오버로딩 → 정적 타입 언어

    - Python: 들여쓰기, def 만날때까지 존재 X → 인터프리터 언어 (if-else로 오버라이딩)

```javascript
#include <stdio.h>
int add(int, int);         // 함수 선언 -> 헤더 파일에 위치
int main(void){add(2, 1);} // 함수 호출
int add (int x, int y){}   // 함수 정의
```

- **매개변수 프로파일:** 형식 매개변수의 개수, 순서 및 타입

- **매개변수 프로파일**

    - **프로시저**: 매개변수 프로파일

    - **함수**: 매개변수 프로파일 + 반환 타입

- **부프로그램 선언**: 프로토콜 제공, 몸체 X → 전방참조를 제공하지 않는 언어에서 필요

- **부프로그램 호출**: 명시적 요청

- **활성 프로그램**: 시작 O, 끝 X

### 프로시저와 함수

- **프로시저**: 반환값 X → 가시적인 변수 / 데이터 전달 허용 매개변수를 변경하여 결과 전달

- **함수**: 반환 값 O → 순수 함수는 함수 부작용 X (외부 정의 변수 수정 X, 반환 값만 결과 전달)

    - 프로시저가 없는 언어는 값을 반환하지 않는 void 등의 함수 제공

    - **사용자 정의 연산자 정의** 가능 → 대부분의 언어는 연산자를 중복하는 것을 허용

### 매개변수

**부프그램**

- **메소드가 아닌 부프로그램**: 클래스 외부에 독립적으로 존재

    - **비지역변수**: 함수의 외부에서 선언된 변수 → 가시적 변수 직접 접근 시 신뢰성↓

    - **매개변수 전달**: 함수 호출 시 전달되는 지역변수 → 유연성 제공

- **메소드**: 클래스 내부에에서 객체나 클래스에 의존

    - 메소드가 호출된 객체에 속함

    - 비지역 데이터 접근 시 신뢰성 문제 → 클래스 변수 메소드 접근 최소화

    - C언어와 마찬가지로 함수 부작용(함수가 결과값 이외 다른 상태 변경)이 발생한다

**형식 매개변수와 실 매개변수**

```javascript
def add(a, b): return a + b   # 형식 매개변수 a, b
result = add(3, 5)            # 실 매개변수: 3, 5
```

- **형식 매개변수**: 부프로그램 머리부 매개변수 → 실행 시간 바인딩 (호출 될 때만 기억장소 바인딩)

- **실 매개변수:** 형식 매개변수에 바인딩되는 매개변수 = 호출문에서의 매개 변수

**바인딩**

```javascript
# 형식 매개변수: income, tax_rate, exemptions
# 키워드 매개변수: exemptions=1 -> 디폴트 값은 1
float compute_pay(float income, float tax_rate, int exemptions=1)
```

- **위치 매개변수**: 형식 매개변수와 실 매개변수는 위치 기반하여 대응 → 효율적, 안전

- **키워드 매개변수**: 리스트가 긴 경우 형식 매개변수 이름이 실 매개변수와 함께 호출 (순서 자유)

- **디폴트값**: 실 매개변수가 전달되지 않을 때 사용

- **가변개수 매개변수**: 실 매개변수는 호출 매개변수 개수와 일치해야함 → 최근엔 컴파일 오류

### 부프로그램 설계 고려 사항

1. 지역 변수 **정적 할당 / 동적 할당** 여부 결정

2. 부프로그램의 정의가 **중첩 Nested** 될 수 있는가 

3. **매개변수-전달 방법**

4. 부프로그램의 **이름이 매개변수**로 전달될 수 있는가에 대한 여부

5. 부프로그램의 **중복 overloaded** 또는 **포괄형 generic** 부프로그램으로 허용하는가

    1. **중복**: 동일한 참조 환경 내 다른 부프로그램과 같은 이름

    2. **포괄형**: 다른 타입의 데이터에 계산을 수행

    3. **클로저**: 중첩 부프로그램과 중첩 부프로그램의 참조 환경

## 지역 참조 환경

---

### 지역 변수

- 부프로그램은 **지역 참조 환경을 정의**

```javascript
int adder(int list[], int listlen){
    static int sum = 0; // 정적
    int count;          // 스택 동적 -> 대부분의 언어에서 디폴트로 스택 동적
    for(count = 0; count < listlen; count++) sum+=list[count];
    return sum;
}
```

**스택동적**

- 부프로그램이 실행을 시작할 떄 기억 장소에 바인딩 → 실행이 끝날 때 기억장소 해제

- 장점: 유연성을 제공 (재귀 부프로그램)

- 단점: 할당, 초기화, 해제하는 시간 비용 필요 / 과거 민감형이 될 수 없음

**정적**

- 장점: 스택-동적 변수에 비해 효율적 / 오버헤드가 없음 / 직접적으로 접근

- 단점: 재귀 호출 부프로그램 지원 못함

### 중첩 부프로그램

- 부프로그램 (A)를 부프로그램 (B)안에 정의 → **정적 영역**이 일반적으로 사용

- 포함 부프로긂에 있는 비지역 변수에 대한 접근 허용

- Java 8 이후 람다식에서 허용 / Python 부프로그램 중첩 허용

## 매개변수-전달 방법

---

### 매개변수 전달

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/223950_IAbju4snXN2fL9BHvN?q=80&s=1280x180&t=outside&f=webp)

- **값 복사 / 접근 경로 (단순 포인터, 참조)**

- **입력 모드**: 값 전달

- **출력 모드**: 결과 전달

- **입출력모드**: 값-결과 전달, 참조-전달, 
-                  이름-전달

### 입력 모드 - 값 전달

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/224026_ba9VpBMgRTnt9IPMGK?q=80&s=1280x180&t=outside&f=webp)

**값 전달**

- 매개변수가 값으로 전달될 때 형식 매개변수를 초기화 → 형식 매개변수는 지역 변수로 사용

- 값을 **스택 장소**에 저장

- 장점: 값 전달은 보통 **복사**로 구현 → 연결 비용과 접근 시간이 빠르다

- 단점: 부가적인 기억 장소가 할당되어야 한다 → 배열 처럼 사이즈가 크면 비용이 많이 필요

### 출력 모드 - 결과 전달

```javascript
void Fixer(out int x, out int y){
    x = 17;
    y = 35;
}
f.Fixer(out a, out a);
```

```javascript
void DoIt(out int x, out int index){
    x = 17;
    index = 42;
}
sub = 21;
f.DoIt(list[sub], sub);
```

**결과 전달**

- 형식 매개변수는 지역변수 처럼 사용 → 반환되기 바로 전에 실 매개변수로 전달 됨

- 값-전달의 반대로구현 → 실 매개변수에 배정된 값은 **스택**에 놓여짐

- 장점: 연결 비용과 접근 시간 관점에서 빠르다

- 단점: 추가적인 기억 장소와 복사 연산 필요 / 실 매개변수와 충돌

    - `f.Fixer(out a, out a)`: x, y에 다른 값을 반환할 수 있음 → 복사 순서가 값 결정

    - `f.DoIt(list[sub], sub);`: `index=42` 실행 순서에 따라 `list[sub]`가 달라짐

### 입출력 모드 - 값 결과 전달, 참조 전달, 이름 전달

**값 결과 전달**

- 값 전달 + 결과 전달 →값-결과 전달 (복사 전달)

- 형식 매개변수를 초기화하는 데 사용 → 지역변수로 사용 (값은 실 매개변수로 반환)

- 스택 장소는 호출에 의해서 초기화, 지역변수 처럼 사용

- 장점: 별칭 상황 제거 가능

- 단점: 값 전달, 결과-전달의 단점을 모두 포함

**참조 전달**

- 접근 경로를 피호출 부프로그램에 전달 → 실 매개변수를 공유

- 실 매개변수의 주소가 스택에 놓여짐

    - 리터럴: 리터럴 주소 / 표현식: 표현식의 결과값 저장된 메모리 셀의 주소를 스택에

    - 리터럴, 표현식 → 값을 변경하는 것을 컴파일러가 막아야 함

- 장점: 시간과 기억 장소 관점에서 효율적 → 기억 장소 중복 X, 복사 X

- 단점:

    - 간접 주소 → 느림

    - 부주의하고 오류적인 변화 → 실 매개변수를 행해질 수 음

    - 별칭 생성 → 가독성↓, 신뢰성↓, 검증 어려움

```javascript
// 별칭 생성 방법
// 1. 실 매개변수 사이 충돌
void fun(int &first int &second){...}
fun(total, total);

// 2. 배열 원소 사이의 충돌
fun(list[i], list[j]) // i = j

// 3. 배열의 원소 vs 배열
fun(list[i], list);
```

```javascript
// 4. 형식 매개변수 vs 비지역변수
int *global; // tree의 root
void sub(int *param){...}
void main(){
    sub(global);
}
```

**이름 전달**

- 광범위하게 사용되는 언어에서 사용되지 않음

### **매개변수 부프로그램 스택**

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/224101_LcKMRhUQY8sNviL2qR?q=80&s=1280x180&t=outside&f=webp)

- 값 전달 매개변수: 값을 스택 장소에 복사

- 결과 전달 매개변수: 값 전달의 반대

- 값-결과 전달 매개변수: 값-전달 + 결과-전달

- 참조-전달 매개변수: 실매개변수 주소가 스택에 저장

```javascript
void swap(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
    a = 1000;
}
```

```javascript
void swap(int *a, int *b)
{
    *a += *b;
    *b = *a - *b;
    *a = *b - *a;
}
```

### 언어별

**일반적인 언어**

- C: 값 전달

- C++: 값 전달 (참조 타입 → 역 참조 가능)

- Java: 값 전달 (참조 변수로 전달, 스칼라 X, 객체는 가능)

- Python: 배정 전달 (참조 변수 → 참조 전달 → 값 전달)

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/224227_5uCmYjcvuxPLENN1D8?q=80&s=1280x180&t=outside&f=webp)

```javascript
address(mat[i, j]) = address(mat[0, 0]) + i * number_of_columns + j
*(mat_ptr + (i * num_cols) + j) = x;
```

**다차원 배열**

- C: 행 우선 순서 → 기억 장소 - 사상 함수 (실행 시간 서술자 X → 열 개수 필요), 
-    각 행은 다른 길이 가능

- Java: 배열은 1차원 → 원소가 배열이 될 수 있음, 각 행은 다른 길이 가능

## 간접 부프로그램 호출

---

- **이벤트 처리**: 거의 모든 Web응용에서 사용

- **콜백**: 호출된 부프로그램 자업 종료 시 호출자에게 알리는 이벤트

```javascript
int myfun2(int, int);    // 함수 선언
int (*pfun2) (int, int); // 함수 포인터를 생성
...
pfun2 = myfun2;          // 포인터에 배정
...
(*pfun2)(first, second); // 역참조
...
pfun2(first, second);    // 역참조 X
```

```javascript
f = foo
```

- C, C++: 포인터

- Python: 소괄호 X → 함수 포인터

- Java: 포인터 X

## 중복 부프로그램

---

**중복 연산자**

- 피연산자의 타입에 의해서 결정

**중복 부프로그램**

```javascript
int fun(int x)
float fun(int x)
void fun(float b=0.0)
void fun()
```

- 같은 참조환경, 다른 부프로그램과 이름이 같은 부프로그램

- 고유한 프로토콜을 가짐 → 실 매개변수 리스트, 반환 값 타입으로 결정

- C, Java: 같은 이름 부프로그램(오버로딩) → 변수 타입으로 모호함 해결
-          혼합형 표현식 → 모호성 제거 X → 일부는 컴파일 실패

## 포괄형 부프로그램

---

- 소프트웨어 재사용 → 생산성 증가의 중요한 공헌자

- 여러 개의 다른 부프로그램 생성 필요성을 줄이면 재사용성 증가 가능

- **다형 부프로그램**: 활성화 시점마다, 다른 타입의 매개변수를 취할 수 있는 부프로그램
-                            중복 부프로그램의 특이 다형성을 제공

- **부타입 다형성**: 객체-지향 프로그래밍 언어들이 일반적으로 지원하는 다형성 (타입 <T>)

- **매개변수 다형성**: 포괄형 매개변수 → **포괄형 부프로그램**

## 함수 설계 고려 사항

---

- **함수 부작용**: 명령형 언어 (별칭) ↔ 순수 함수 언어

- **반환 타입**: 명령형 언어들은 반환 타입을 제한

    - C: 배열, 함수를 제외한 모든 타입

    - Python: 모든 타입 값 반환 가능

    - Java: 메소드를 제외한 임의의 타입이나 클래스

- **반환 개수**: 명령형 언어들은 한 개의 값만 함수로 반환 가능

    - Ruby: 값이 없을 경우 nil 반환, 배열 반환

    - Python: 튜플 반환

## 사용자-정의 중복 연산자

---

```javascript
def __add__(self, second):
    return Complex(self.real + second.real, self.image + second.image)
```

- 메서드 오버로딩 → 파이썬 불가능 → profile로 구분 X

- Java: 객체 설정 X → 자동부여 this

- Python: 객체 설정 O, 명시적 전달 → self

## 클로저

---

- 부프로그램과 +부프로그램의 참조 환경

- **중첩 부프로그램 허용하지 않는 경우**: 클로저 지원 X

    - 호출되는 장소에 관계 없이 접근 가능

    - C언어 → 전역변수 DS, 지역변수 stack

- **중첩 부프로그램 허용**: 클로저 지원 O

    - 부프로그램이 매개변수 전달

    - 부프로그램이 변수에 배정되어 호출

    - 활성화 기간 무제한 → 힙 동적

## 코루틴

---

- 실행을 중단했다가 다시 이어서 실행 가능한 서브루틴

- 호출, 피호출 프로그램이 대등한 위치 → 호출 대신 리쥼이라고 부름

- 과거 민감형 정적 지역변수

- Python Generators

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/224311_Y1OVSrd9vWFYOCGevc?q=80&s=1280x180&t=outside&f=webp)

![Image](https://upload.cafenono.com/image/slashpagePost/20250103/224318_HganWx0GWUWcYyhj6k?q=80&s=1280x180&t=outside&f=webp)

For the site tree, see the [root Markdown](https://slashpage.com/yerim-devnote.md).
