함수

2025. 8. 31. 00:17·다트🎯

Functions

Dart는 진짜 객체지향 언어라서 함수도 객체야. 즉, 함수도 Function 타입을 가지고 있어서 변수에 담을 수 있고, 다른 함수의 인자로 넘길 수도 있어. 심지어 클래스의 인스턴스를 함수처럼 호출할 수도 있지.


함수 정의하기

보통 함수는 이렇게 정의해:

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

타입을 생략해도 되긴 하지만, 공식 스타일 가이드(Effective Dart)는 공개 API에는 타입 명시를 권장해.

짧은 함수라면 화살표 문법(=>)을 쓰면 간단해:

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

여기서 => expr는 사실 { return expr; }의 축약형이야.


매개변수

함수 매개변수는 크게 세 가지:

  • 필수 위치 매개변수
  • 이름 있는 매개변수 ({}로 감쌈)
  • 선택적 위치 매개변수 ([]로 감쌈)

Named parameters (이름 있는 매개변수)

이름 매개변수는 기본적으로 선택적이야.
정의할 땐 {param1, param2} 이렇게 쓰고, 호출할 땐 paramName: value 형태로 써.

void enableFlags({bool bold = false, bool hidden = false}) {
  ...
}

enableFlags(bold: true);
  • required 키워드를 붙이면 필수로 만들어야 함.
  • required라도 null을 허용할 수 있음 (required Widget? child).

Optional positional parameters (선택적 위치 매개변수)

[] 안에 넣으면 선택적 위치 매개변수야. 기본값을 지정하지 않으면 자동으로 null.

String say(String from, String msg, [String device = 'carrier pigeon']) {
  return '$from says $msg with a $device';
}

say('Bob', 'Howdy'); // 기본값 사용
say('Bob', 'Howdy', 'smoke signal');

main() 함수

모든 Dart 앱은 반드시 main() 함수가 있어야 해. 프로그램 시작점이야.
인자로 List<String>을 받을 수 있어.

void main() {
  print('Hello, World!');
}
void main(List<String> args) {
  print(args);
}

함수도 1급 객체

Dart에선 함수도 변수에 담을 수 있어.

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];
list.forEach(printElement); // 함수 전달

또는 아예 변수에 함수 자체를 담을 수도 있어:

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
print(loudify('hello'));

함수 타입(Function type)

함수 자체도 타입을 가짐.
함수의 선언부에서 이름을 빼고 Function으로 바꾸면 돼.

void greet(String name, {String greeting = 'Hello'}) =>
    print('$greeting $name!');

void Function(String, {String greeting}) g = greet;
g('Dash', greeting: 'Howdy');

익명 함수 (Anonymous functions)

이름 없는 함수도 만들 수 있어. 흔히 람다 또는 클로저라고도 부름.

const list = ['apples', 'bananas', 'oranges'];

var uppercaseList = list.map((item) {
  return item.toUpperCase();
}).toList();

uppercaseList.forEach((item) {
  print('$item: ${item.length}');
});

짧게 쓰고 싶으면 화살표 문법을 쓰면 돼:

var uppercaseList = list.map((item) => item.toUpperCase()).toList();

스코프와 클로저

Dart는 lexical scope를 따름. 즉, 중괄호 바깥으로 거슬러 올라가며 변수를 찾는 방식이야.

bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    void nestedFunction() {
      var insideNestedFunction = true;

      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}

이처럼 중첩 함수는 바깥 변수들을 자유롭게 쓸 수 있어.

클로저

클로저는 함수가 자신이 정의된 스코프의 변수를 캡처해서 나중에도 쓸 수 있는 기능이야.

Function makeAdder(int addBy) {
  return (int i) => addBy + i;
}

var add2 = makeAdder(2);
print(add2(3)); // 5

Tear-offs

괜히 람다로 감싸지 말고, 함수 이름을 그냥 넘기면 돼.

var charCodes = [68, 97, 114, 116];
var buffer = StringBuffer();

charCodes.forEach(print);       // 함수 tear-off
charCodes.forEach(buffer.write); // 메서드 tear-off

함수 동등성 비교

void foo() {}

class A {
  static void bar() {}
  void baz() {}
}

void main() {
  Function x;

  x = foo;
  assert(foo == x);

  x = A.bar;
  assert(A.bar == x);

  var v = A();
  var w = A();
  var y = w;
  x = w.baz;

  assert(y.baz == x);   // 같은 인스턴스면 동일
  assert(v.baz != w.baz); // 다른 인스턴스면 다름
}

반환값

모든 함수는 값을 반환해. 아무것도 안 쓰면 자동으로 return null;.

foo() {}

assert(foo() == null);

여러 값을 반환하고 싶으면 Record를 쓰면 돼:

(String, int) foo() {
  return ('something', 42);
}

제너레이터 (Generators)

값을 하나씩 게으르게 만들어내고 싶을 때 sync*와 async*를 쓴다.

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

yield*는 다른 제너레이터를 위임해서 실행할 때 씀.


외부 함수 (External functions)

external 키워드를 쓰면, 함수 몸체 없이 시그니처만 정의할 수 있어. 실제 구현은 다른 Dart 라이브러리나 C/JS 같은 외부 언어에서 가져오는 경우가 많아.

external void someFunc(int i);

이건 FFI(외부 함수 인터페이스) 같은 상황에서 주로 쓰임.


👉 정리하면, Dart에서 함수는 객체라서 변수에 담을 수도 있고, 다른 함수에 넘길 수도 있고, 심지어 tear-off나 클로저로 더 유연하게 쓸 수도 있어.

'다트🎯' 카테고리의 다른 글

라이브러리 가져오기  (0) 2025.08.31
메타데이터  (0) 2025.08.31
관리 흐름 - 에러 핸들링  (0) 2025.08.31
관리 흐름 - 분기  (0) 2025.08.31
관리 흐름 - 반복  (0) 2025.08.31
'다트🎯' 카테고리의 다른 글
  • 라이브러리 가져오기
  • 메타데이터
  • 관리 흐름 - 에러 핸들링
  • 관리 흐름 - 분기
flutters
flutters
  • flutters
    fts
    flutters
  • 전체
    오늘
    어제
  • 공지사항

    • 분류 전체보기 (23)
      • 자바스크립트 🍌 (0)
      • 다트🎯 (22)
      • 플러터🦋 (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

    • Github🌐
  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
flutters
함수
상단으로

티스토리툴바