[FLUS 스터디 1주차] Dart 기초 - Functions(함수)

sucream·2022년 9월 3일
1

flutter-study

목록 보기
5/17
post-custom-banner

지금까지 다트를 하면서 아래와 같이 main이라는 블록에 각종 코드를 작성하였다.

void main() {
	print('Hello World!');
    
    var limit = 10;
    
    for (var i = 0; i < limit; i++) {
    	print('i: ${i}');
    }
}

여기서 main은 다트를 시작하는 진입점이며, 함수이다. 그렇다면 함수란 무엇일까?

1. 함수란?

수학에서 함수(函數, 영어: function) 또는 사상(寫像, 영어: map, mapping)은 어떤 집합의 각 원소를 다른 집합의 유일한 원소에 대응시키는 이항 관계다. 즉, 한 변수의 값에 따라 정해지는 다른 변수의 값을 먼저 주어지는 값에 상대하여 일컫는 말이다.

그만 알아보자...

쉽게 설명하기 위해 아래 그림을 보자. 그림에서 ff라고 하는 함수는 xx를 입력으로 받아서 그 값을 제곱(x2x^2)한 값을 반환한다. 그렇다. 함수란 특정 입력을 받아서 함수내에서 어떠한 연산을 진행하고 결과를 반환해 주는 것이다.
함수

우리가 지금까지 써온 main()은 물론, print() 역시 어떤 문자열을 입력으로 받아서 표준출력(모니터)에 출력하는 함수이다. 함수에서 크게 알아야 하는 것은 함수를 구성하는 입력값, 함수내용, 출력값 이렇게 3가지라고 할 수 있다.


함수의 정의

다트의 함수는 아래과 같이 사용하며, 각각을 정리하면 다음과 같다.

functionName: 함수의 이름을 나타내며, 외부에서 해당 이름으로 함수에 접근할 수 있다. 수학에서 f(x)f(x)에서 ff에 해당한다.

paramType param: 해당 함수에서 사용하기 위해 입력으로 받는 값을 의미하며, 기존에 변수를 선언하듯 변수의 타입고 변수명을 지정하면 된다. 여기서 선언된 변수는 일반적으로 함수 내에서만 접근이 가능하며, 함수가 종료될 때 함수 내에 있는 변수의 생명주기가 종료된다.

returnType: 해당 함수가 종료될 때 함수를 호출한 쪽에게 어떤 타입의 데이터가 반환되는지 알려주는 용도이며, 실제로 해당 타입으로 반환을 해야 한다.

returnType functionName(param1Type param1, [param2Type param2, ...]) {
	function contents;
    
    return someData;
}

예시

// int형 파라미터 a, b를 입력으로 받고 int형 값을 반환하는 addFunc라는 함수
int addFunc(int a, int b) {
	var result = a + b;
    
    return result;
}

void main() {
	int num1 = 10;
    int num2 = 20;
    
	int result = addFunc(num1, num2);  // 함수를 호출하는 쪽에서는 함수명과 파라미터에 들어갈 값을 넣어주고, int형을 반환하는 함수이기 때문에 함수의 결과를 result라는 int형 변수에 저장한다.
    
    print('result: ${result}');
}

결과

result: 30

함수의 반환형

위 예시를 보면 addFunc 함수는 int형을 반환한다는 것은 알겠다. 그런데 main 함수 앞에 있는 void는 무엇일까?
예상했겠지만 함수의 결과값이 없다는 의미로 void를 사용한 것이다.
다트에서 함수의 결과, 즉 함수가 return하는 값이 존재하면 해당 값의 타입을 작성하고 return할 값이 없으면 void를 작성하여 명시적으로 해당 함수의 결과가 없음을 알려준다. 따라서 main 함수는 별도로 반환하는 값이 없다는 것을 알 수 있다. main에서 리턴이 존재하는 언어도 있으니 주의하도록 하자.

예시

// int형 파라미터 a, b를 입력으로 받고 int형 값을 반환하는 addFunc라는 함수
int addFunc(int a, int b) {
	var result = a + b;
    
    return result;
}

// String형 파라미터 name를 입력으로 받고 String형 값을 반환하는 makeNewName 함수
String makeNewName(String name) {
	var result = name + ' 최고';
    
    return result;
}

// String형 파라미터 name를 입력으로 받고 값을 반환하지 않는 printName 함수
void printName(String name) {
	print(name);
}

2. Optional Parameters

함수를 정의할 때 항상 모든 입력값이 필요한건 아니다. 경우에 따라 필요하지 않은 값을 처리하기 위해 다트는 Optional Parameters기능을 지원한다.

  • []를 사용하여 파라미터를 감싸면 해당 파라미터는 필수가 아닌 선택형 파라미터로 지정되며, 이를 Optional Positional Parameter라고 한다. 또한 선택형 파라미터를 전달하지 않으면 해당 변수는 null값을 가지게 된다.
  • {}를 사용하여 파라미터를 감싸면 해당 파라미터는 필수가 아닌 선택형 파라미터로 지정되며, 이를 Optional Named Parameter라고 한다. {} 내에 위치한 파라미터는 {pram1: defaultValue}형식으로 기본값을 지정할 수도 있다. 또한 {}로 감싸진 파라미터는 함수를 호출할 때 반드시 해당 파라미터명을 지정하여 호출해야 한다.
// b 변수를 int?형으로 지정한 이유는 b의 값이 없으면 null이 될 수도 있기 때문임. 다트 최신 버전은 null check를 잘 해야 함
void optionalPositional(int a, [int? b]) {  
	print('a: ${a}');
    print('b: ${b}');
}


void optionalNamed(int a, {int? b}) {
	print('a: ${a}');
    print('b: ${b}');
}


// int?형으로 지정하지 않아도 에러가 나지 않는 이유는 b의 값이 없으면 자동으로 10이 되기 때문임.
void optionalNamedWithDefaultValue(int a, {int b: 10}) {
	print('a: ${a}');
    print('b: ${b}');
}


void main() {
	optionalPositional(10);
    print('-'*20);
    optionalNamed(10, b:20);
    print('-'*20);
    optionalNamedWithDefaultValue(10);
}

결과

a: 10
b: null
--------------------
a: 10
b: 20
--------------------
a: 10
b: 10

3. Recursive Function

다트는 함수의 재귀, 즉 자기 자신을 호출하는 것을 허용한다. 재귀함수는 함수가 끝나지 않았을 때 자기 자신을 자기 호출할 수 있는데, 피보나치 수열이나 팩토리얼을 구하는 등의 경우에 사용하면 유용하게 사용할 수 있다.

일반적으로 함수 내에 함수를 빠져나갈 수 있는 분기를 두고 가장 깊은 곳까지 들어갔다가 순차적으로 값을 반환하게 된다.

int factorial(int num) {
  // 재귀함수 종료 조건으로, num이 1이하일 때만 1을 반환한다.
  if (num <= 1) {
    return 1;
  } else {
    return num * factorial(num - 1); // 재귀함수를 호출한다.
  }
}

void main() {
  const num = 5;
  final fact = factorial(num);
  print('Factorial of 5 is: ${fact}');
}

4. Lambda Functions

다트는 람다함수도 지원하며 아래와 같다. 일반 함수와 다른 점은 expression 부분에 표현식 즉, (반환타입에 맞는)특정 값을 반환하는 식이 들어가야 하며 긴 구문을 사용할 수 없다. 람다함수는 =>를 사용하여 화살표 함수라고도 불린다. 람다 함수를 1회성으로 사용하는 경우, 함수의 이름을 생략한 익명함수를 사용할 수도 있다.(일반 함수도 함수명을 생략하는 익명함수를 만들 수 있다.)

[return_type]functionName(parameters)=>expression;

예시

String myFunc(String name) => '안녕하세요. ${name}입니다.';

void main() {
	String name = '남슈크림빵';
	print(myFunc(name));
    
    ((name) => print('안녕히가세요. ${name}입니다.'))(name);
}

결과

안녕하세요. 남슈크림빵입니다.
안녕히가세요. 남슈크림빵입니다.

Refference

profile
작은 오븐의 작은 빵
post-custom-banner

0개의 댓글