Dart

[Dart] Dart Docs - Function

  • -
728x90

Dart는 function이 존재하지만 객체 지향 언어이므로 함수도 Function이라는 타입을 가지는 객체로 존재한다.

 

기본적으로 아래와 같이 사용할 수 있다. (c/c++과 비슷한 느낌)

반환타입 함수이름(매개변수 ...) {
  
  ... 작업
  
  return 반환할 표현식
}

 

하나의 표현식만을 가지는 함수를 선언할 때 한 줄 코딩도 가능하다.

반환타입 함수명(매개변수 ...) => 매개변수 + 1;

Parameter

Named Parameter

함수를 정의할 때 매개변수에 이름을 부여하는 것을 Named Parameter라고 한다. Named 매개변수는 required로 표시되지 않는 이상 선택적인 매개변수이다. 

Named Parameter를 정의하려면 아래와 같이 정의할 수 있다.

String func1({String name ="", int age = 0, String country = ""}) {
  return 'hello $name';
}

void main() {
  final res = func1(name:'WONILLISM', age:1, country:'Seoul');
  print(res);
}

Named 매개변수에 default값이 없으면 dart에서는 에러가 발생한다.

따라서 위와 같이 default값을 지정해주어 null이 발생하지 않도록 하거나, required를 이용하여 컴파일되지 않도록 할 수 있다.

 

아래는 required를 사용한 예시이다. default값으로 지정해둔 매개변수들은 호출시 입력하지않아도 되지만, required 키워드가 있는 매개변수는 필수로 입력하여야 한다.

String func1({required String name, int age = 0, String country = ""}) {
  return 'hello $name';
}

void main() {
  final res = func1(name: "WONILLISM");
  print(res);
}

 

Optional Positional Parameter

Optional Parameter는 함수를 호출할 때 선택적으로 매개변수를 전달할 수 있도록 지정할 때 사용한다. Optional Parameter는 디폴트 값을 제공하지 않으면, 매개변수의 디폴트 값이 null이 되므로 타입은 반드시 nullable이 되어야 한다.

 

Positional의 의미는 매개변수의 순서를 정할 수 있다는 의미이다.

String func1(String name, int age, [String? country]) {
  print(name);
  print(age);
  print(country);
  return 'hello $name';
}

void main() {
  final res = func1("WONILLISM");
  print(res);
}

위와 같은 경우에 age 값을 넘겨주지 않았으므로 에러가 발생한다.

 

앞서 보았던 Named Parameter는 순서가 중요하지 않고, 제공된 이름에 맞춰 매개변수를 넘겨주면 되는 방면, Optional Positional Parameter는 순서에따라 매개변수를 넣어주어야 한다.

 

main() Function

모든 앱은 엔트리 포인트 역할을 하는 최상위 main()함수를 반드시 가지고 있어야 한다. main() 함수는 void를 반환하고 optional List<String>을 매개변수로 가진다.

// 다음과 같이 앱을 실행하세요: dart args.dart 1 test
void main(List<String> arguments) {
  print(arguments);

  assert(arguments.length == 2);
  assert(int.parse(arguments[0]) == 1);
  assert(arguments[1] == 'test');
}

 

Anonymous functions 익명함수

Dart에서는 Anonymous function, Lambda, Closure과 같은 이름이 없는 함수가 존재한다. 익명 함수를 변수에 선언하여 컬렉션에 추가하고 제거하는 것도 가능하다.

 

const list = ['apples', 'bananas', 'oranges'];
list.map((item) {
  return item.toUpperCase();
}).forEach((item) {
  print('$item: ${item.length}');
});

 

 

렉시컬 클로저

클로저 함수 객체이며, 함수 객체의 호출이 스코프 밖에서 발생하더라도 렉시컬 스코프 내의 변수에 접근할 수 있다.

Function func(int x) {
  int lx = x;
  return (int y) => lx + y;
}


void main() {
  final add2 = func(2);
  final add4 = func(4);
  
  print(add2(3));
  print(add4(3));
}

 

Generators

데이터의 시퀀스를 지연하여 생성하고 싶다면, 제너레이터 함수를 사용하면 된다.

Dart는 두가지 내장 제너레이터 함수를 가지고 있다.

  • 동기식 제너레이터: Iterable객체 반환
  • 비동기식 제너레이터: Stream 객체 반환

동기식 제너레이터 함수를 구현하려면, 함수의 바디를 sync*로 표시하고 yield 문으로 값을 생성

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

 

비동기식 제너레이터 함수를 구현하려면, 함수의 바디를 async*로 표시하고 yield 문으로 값을 생성

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

 

제너레이터가 재귀적이라면, yield*를 사용하여 성능을 향상시킬 수 있다.

Iterable<int> naturalsDownFrom(int n) sync* {
  if (n > 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}

 

728x90
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.