[Flutter / Dart] Dart 기초문법(함수와 람다) (2)
1. 익명 함수와 람다 함수
익명함수와 람다함수는 둘 다 이름이 없음. 일회성으로 사용된다는 공통점이 있음.
통상적으로 많은 언어에서 익명 함수와 람다함수를 구분하지만, Dart언어에서는 구분하지 않음.
익명 함수와 람다 함수의 표현 방식
익명 함수 | 람다 함수 |
(매개변수) { 함수 바디 } |
(매개변수) => 단 하나의 스테이트먼트 |
익명 함수에서 { }를 빼고 `=>` 기호를 추가한 것이 람다 함수임! 매개변수는 아예 없거나 하나 이상이어도 됨.
익명 함수와 달리 코드 블럭을 묶는 { }가 없는 람다는 함수 로직을 수행하는 Statement가 하나여야만 함.(한 줄이 아닌 명령 단위가 하나!)
람다 함수는 이름을 정하고 미리 선언할 필요가 없어서 글로벌 스코프로 다룰 필요가 없음.
더 나아가 하나의 Statement만 다루기 때문에 적절히 사용하면 간결하게 코드를 작성할 수 있고 가독성이 높음.
그렇기 때문에 콜백 함수나 리스트의 `map()`, `reduce()`, `fold()` 함수 등에서 일회성이 높은 로직을 작성할 때 주로 사용함.
항목 | 익명 함수(Anonymous Function) | 람다 함수(Lambda Expression) |
정의 방법 | 중괄호 `{}`로 코드 블록을 감싸서 함수 형태로 정의 | `=>` 기호 사용, 한줄로 축약 |
함수 이름 | 없음 (이름 없이 정의) | 없음 (이름 없이 정의) |
사용 가능 로직 | 여러 줄의 코드 가능, 복잡한 처리 적합 | 단 하나의 표현식만 가능. 간결한 로직 작성 적합 |
중괄호 사용 여부 | 사용 | 사용 안함 |
return 키워드 | 명시적으로 `return` 사용 가능 | `=>` 뒤의 표현식이 자동으로 `return`됨 |
사용 예시 | 콜백, 이벤트 핸들러, 반복문 등 | `map`, `reduce`, `fold`, 일회성 짧은 로직에 적합 |
가독성 | 로직이 길거나 복잡할 때 사용 | 짧고 간결한 경우 가독성 우수 |
// 익명 함수로 List의 모든 값들을 더하는 로직
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
final allMembers = numbers.reduce((value, element) {
return value + element;
});
print(allMembers);
}
/* 출력값
15
*/
// 람다 함수로 List의 모든 값들을 더하는 로직
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
final allMembers = numbers.reduce((value, element) => value + element);
print(allMembers);
}
/* 출력값
15
*/
위 코드를 보면 `return value + element`의 코드를 `=> value + element`로 줄인것을 볼 수 있음. `=>`이 return의 기능을 대신한다?로 보면 될거같음.
하지만, 이렇게 간단한 로직은 어떤걸 쓰든 취향이지만 로직이 길어지고 복잡할 떄는 익명 함수를 사용해야한다는 점!
2. typedef와 함수
`typedef` 키워드는 함수의 시그니처를 정의하는 값으로 보면 됨. 여기서 시그니처는 반환값 타입, 매개변수 개수와 타입 등을 말함.
즉, 함수 선언부를 정의하는 키워드임. 함수가 무슨 동작을 하는지에 대한 정의는 없음!
typedef Operation = void Function(int x, int y);
함수를 위에 선언하기는 했지만 무얼하는지 동작이 없음. 그럼 이걸 어떻게 사용해야 할까? 시그니처에 맞춘 함수를 만들어서 사용하면 됨!
아래 코드를 보겠음.
typedef Operation = void Function(int x, int y);
void add(int x, int y) {
print("결과값 : ${x + y}");
}
void subtract(int x, int y) {
print("결과값 : ${x - y}");
}
void main() {
// typedef는 일반적인 변수의 type처럼 사용 가능
Operation oper = add;
oper(1, 2);
// subtract() 함수도 Operation에 해당되는 시그니처 이므로 oper변수에 저장 가능
oper = subtract;
oper(1, 2);
}
/* 출력값
결과값 : 3
결과값 : -1
*/
Dart언어에서 함수는 일급 객체 이므로 함수를 값처럼 사용할 수 있음.
그래서 플러터에서는 `typedef`로 선언한 함수를 다음과 같이 매개변수로 넣어 사용함.
typedef Operation = void Function(int x, int y);
void add(int x, int y) { // add라는 함수를 선언, 파라미터는 int x, int y, 반환 타입은 : void(아무것도 리턴하지 않음)
print("결과 값 : ${x + y}");
}
void calculate(int x, int y, Operation oper) { // 이곳에 있는 int x, int y, Operation oper는 파라미터
oper(x, y); // oper는 아까 전달한 add 함수 자체임 즉, oper == add
// 즉, oper == add라는 뜻, 결국엔 add(x, y)인 것임 여기에있는 x, y는 아규먼트
}
void main() {
calculate(1, 2, add); // 여기에 있는 1, 2, add도 아규먼트
}
/* 출력값
결과값 : 3
*/
처음 쓰다보니 이해가 잘안되서 한줄씩 해석해 보겠음!
typedef Operation = void Function(int x, int y);
- `Operation`이라는 함수 타입 별칭을 만듦
- "입력은 `int x, int y`고, 반환값은 `void`인 함수"를 우리는 `Operation`이라고 부르기로 정했다.
void add(int x, int y) { ... }
- `add`라는 함수를 만듦, 매개변수(파라미터)는 `int x`, `int y`, 반환 타입은 `void`(아무것도 리턴하지 않음)
- `(int, int)`를 받아서 `x + y`를 출력함
void calculate(int x, int y, Operation oper) {
oper(x, y);
}
- 세 번쨰 파라미터로 `Operation 타입 함수`를 전달받고 그걸 `oper(x, y)`로 실행함
- 즉, 넘겨받은 함수를 바로 실행하는 구조임.
void main() {
calculate(1, 2, add);
}
- `x = 1`, `y = 2`, `oper = add`
- 이걸로 `calcalate(1, 2, add)`가 실행됨 -> 내부에서 `add(1, 2)`가 호출됨
- 그러면 `print("결과값 : ${1 + 2}")`가 실행 -> `결과 값 : 3` 출력
그럼 갑자기 의문이 드는 것, 물론 내 지식이 모자라는 거지만,, 어디는 왜 파라미터고 어디는 왜 아규먼트지?
용어 | 설명 |
파라미터(매개변수) | 함수를 정의할 때 괄호 안에 쓰는 변수 |
아규먼트(인자) | 함수를 호출할 때 실제 전달하는 값 |
라고 보면 됨..! 어우 헷갈려. 마지막만 남았다.
3. try ... catch
`try...catch`문의 목적은 특정 코드의 실행을 시도(try)해보고 문제가 있다면 에러를 잡는다(catch)는 뜻임.
`try...catch`문은 `try`와 `catch` 사이의 괄호에 에러가 없을 떄 실행할 로직을 작성하고 `catch`가 감싸는 괄호에 에러가 났을 때 실행할 로직을 작성하면 됨. 만약 `try`에서 에러가 발생할 시 바로 `catch`로직으로 넘어감!
// 에러가 없을 때의 try...catch문
void main() {
try{
// 에러가 없을 때 실행할 로직
final String name = "이도서의 코딩 노트";
print(name); // 에러가 없으면 "이도서의 코딩 노트" 출력
} catch(error) {
//에러가 있을 때 로직
print(error);
}
}
/* 출력값
이도서의 코딩 노트
*/
그러면 이제 에러가 났을 떄의 코드를 보겠음 `throw`키워드를 사용해 에러를 만들어 보겠음
// 에러 있는 코드
void main() {
try {
final String name = "이도서의 코딩 노트";
throw Exception("이름이 잘못됐음!"); // 고의로 에러 발생
print(name);
} catch(error) {
// try에서 에러가 발생해서 catch로직이 실행됨.
print(error);
}
}
/* 출력값
Exception: 이름이 잘못됐음!
*/
`throw`키워드는 에러를 발생시키는 키워드임 일단 기억만 해두는 걸로!!
https://github.com/Leedoseo/Flutter_DartBasic
GitHub - Leedoseo/Flutter_DartBasic
Contribute to Leedoseo/Flutter_DartBasic development by creating an account on GitHub.
github.com
https://www.notion.so/Dart-Flutter-Study-1cf9fd9f157980a5ab7efad394810871?pvs=4
Dart / Flutter Study | Notion
Made with Notion, the all-in-one connected workspace with publishing capabilities.
www.notion.so
'Dart 언어' 카테고리의 다른 글
[Flutter / Dart] 객체지향 프로그래밍(상속과 오버라이드) (0) | 2025.04.07 |
---|---|
[Flutter / Dart] 객체지향 프로그래밍(클래스) (0) | 2025.04.04 |
[Flutter / Dart] Dart 기초문법(함수와 람다) (1) (0) | 2025.04.02 |
[Flutter / Dart] Dart 기초문법(제어문) (0) | 2025.03.31 |
[Flutter / Dart] Dart 기초문법(연산자) (0) | 2025.03.31 |