image

해당 포스트는 Dart 3.0 에 추가되는 New feature를 정리한 포스트입니다.

1. Multiple Returns

Dart 2.x 에서는 여러 개의 값을 리턴하기 위해서 아래 예제 처림 data class 선언해서 사용했어야 합니다.

class UserInfo {
  final String name;
  final int age;

  UserInfo(this.name, this.age)
}

UserInfo userInfo(Map<String, dynamic> json) {
  return UserInfo(json['name'] as String, json['age'] as int);
}

main() {
  var info = userInfo(json);
  var name = info.name;
  var age = info.age;
}

하지만 Dart 3.0 에서는 아래와 같이 여러개의 값을 리턴이 가능하여 더이상 data class 객체를 선언하지 않아도 됩니다.

(String,int) userInfo(Map<String, dynamic> json) {
  return (json['name'] as String, json['age'] as int);
}

main() {
  var info = userInfo(json);
  var name = info.$1;
  var age = info.$2;
}

이 때 (String, int) 처럼 N 개의 Data 를 담고 있는 타입을 Records 라고 합니다.

What are records?

  • First Class : Records 는 일급 객체로 취급하여 함수에 인자로 넘기기, 변수에 할당하기 등 다양한 연산이 가능하다.
  • Object : 객체로 취급이 된다.
  • Value semantics : == , hashcode 가 자동으로 define 되어 동등성 체크가 바로 가능하다.

Record destructuring

Records 을 아래와 같이 바로 분해해서 변수에 할당하는 것도 가능합니다.

var (name, age) = userInfo(json);

2. Control Flow in Argument Lists

위젯에서 상태에 따라서 속성이나 child widget 을 부여할 때 3항 연산자를 주로 사용하게 됩니다. 아래 예제는 hasNextStep 이라는 상태에 따라서 속성을 추가할지 아니면 null 로 set 할지를 결정하는 코드입니다.

ListTile(
  leading ; const Icon(Icons.weekend),
  title : const Text('Welcome'),
  enabled : hasNextStep,
  subtitle : hasNextStep ? const Text('Tap to Advance.') : null,
  onTap : hasNextStep ? () { advance(); } : null,
  trailing : hasNextStep() ? null : const Icon(Icons.stop)
)

다만 이런 코드가 많을 수록 가독성이 안 좋아지기 마련입니다. 하지만 Dart 3.0 에서는 이러한 부분이 개선되어 Widget 안에 if 문을 사용하여 좀 더 가독성있는 코드를 구현이 가능해집니다.

ListTile(
  leading ; const Icon(Icons.weekend),
  title : const Text('Welcome'),
  enabled : hasNextStep,

  if (hasNextStep) ...(
    subtitle : const Text('Tap to Advance.') ,
    onTap : () { advance(); },
  ) else ...(
    trailing : const Icon(Icons.stop)
  )
)

3. JSON Destructuring

일반적으로 JSON 내에서 내가 원하는 값을 파싱하기 위해서는 아래와 같이 코드를 작성하게 되며 그리고 원하는 값은 한번에 하나 씩만 가져올수 있었습니다.

var json = {'user' : ['Lily', 13]};

var name = json['user']![0];
var age = json['user']![1];

dart 3.0 에서는 한번에 여러개의 값을 파싱이 가능합니다.

var json = {'user' : ['Lily', 13]};
var {'user' : [name, age]} = json;

3. Usable Switches

dart 2.x 의 switch 문은 단순히 비교하는 값과 일치하는 label 로 점프를 해주는 기능만 제공하였습니다.

switch (charCode) {
  case slash:
    if (nextCharCode == slash) {
      skipComment ();
    } else {
      operator (charCode);
    }
  case star:
  case plus:
  case minus:
    operator (charCode);
  default:
    if (charCode >= digitO && charCode <= digit9) {
      number () ;
    } else {
      invalid ();
    }
}

dart 3.0 에서는 switch 문에 아래와 같이 다양한 기능이 추가가 되어 가독성을 향상 시킬수 있습니다.

switch (charCode) {
  case slash when nextCharCode == slash: // 조건을 더 추가 할수 있다.
    skipComment ();
  case slash || star || plus || minus: // case 를 여러 개로 묶어서 한줄로 표현이 가능하다.
    operator (charCode);
  case >= digito && <= digit9:       // 조건문 을 사용할수 았다.
    number();
  default:
    invalid();
}

그리고 switch 문 자체에 값을 return 이 가능해집니다. 따라서 switch 문의 실행 결과를 변수에 바로 할당이 가능합니다.

var token = switch (charCode) {
  slash when nextCharCode == slash => skipComment (), 
  slash || star || plus | minus => operator (charCode) ,
  >= digitO && <= digit9 => number () ,
  _ => throw invalid()
};

Switch 문과 JSON 파싱하는 코드를 결합하여 JSON 유효성 검사 및 데이터 파싱을 너무나 쉽게 할수 있습니다.

var json = {'user': ['Lily', 13]};

switch (json) {
  case ('user': [String name, int age]}:
    print ('User $name is $age years old.');
  default:
    throw 'Unknown message'
}

4. Next Steps

현재 Dart 3.0 은 alpha 버전이며 23년 중반에 stable 로 출시를 목표로 하고 있습니다.

Reference

Bringing pattern matching to Dart

댓글남기기