상세 컨텐츠

본문 제목

Dart - Function

Dart

by techbard 2023. 12. 18. 20:00

본문

반응형
int sum(int x, int y) {
  return x + y;
}

// 익명함수
var total = (int x, int y) => x + y;

void main(List<String> args) {
// 함수도 객체라서 변수에 할당 가능 (first class object)
  var result = sum(1, 2);
  print("sum: $result");

// 다트 공식 문서에는 익명 함수를 람다 또는 클로저라고 부른다.
  print("total: ${total(1, 2)}");
  print("--------------------------------------------------");
  print("sum is $sum.runtimeType");
  print("total is $total.runtimeType");
  print("main is $main.runtimeType");
}

// 결과
sum: 3
total: 3
--------------------------------------------------
sum is Closure: (int, int) => int from Function 'sum': static..runtimeType
total is Closure: (int, int) => int.runtimeType
main is Closure: (List<String>) => void from Function 'main': static..runtimeType

 

// 함수와 메서드는 모두 함수
// 클래스 내에 정의한 함수는 메서드

// 최상위 함수 - 어디서나 호출 가능
bool isEven(int num) {
  return num % 2 == 0;
}

// 클래스 내부의 함수는 메서드 - 클래스와 관련한 기능을 수행
class SomeClass {
  bool isEven(int num) {
    return num % 2 == 0;
  }

// static 함수는 최상위 함수처럼 사용 가능
  static bool isEvenStatic(int num) {
    return num % 2 == 0;
  }
}

void main(List<String> args) {
  print("function call: ${isEven(10)}"); // 함수 호출

  var myClass = SomeClass();
  print("class method call: ${myClass.isEven(10)}"); // 클래스 메서드 호출
  print("class static method call: ${SomeClass().isEven(10)}"); // 정적 메서드 호출
}

// 결과
function call: true
class method call: true
class static method call: true

 

void main(List<String> args) {
  // Dart의 함수
  // 1. 함수를 변수에 대입 가능 (변수가 함수를 참조할 수 있다)
  // 2. 다수 함수의 파라미터로 함수 전달 가능
  // 3. 이름이 있는 선택적 파라미터 사용 가능
  // 4. 위치적 파라미터 사용 가능
  // 5. 익명 함수 (이름없는 함수), 람다, 클로저
  // 6. Dart에서는 함수의 반환값의 타입 선언 생략 가능

  // 익명 함수의 기본 형태
  // (매개 변수) {표현식;}
  var anomFunc1 = (int n) {return n.toString();};
  var anomFunc2 = (int n) => n.toString();
  print("[0] anonymous function: ${anomFunc1(1)}");
  print("[1] anonymous function: ${anomFunc2(1)}");

  // 람다식의 기본 형태
  // (매개 변수) => 표현식;
  lambdaExpr(int x, int y) => x + y;
  print("[2] 람다식: ${lambdaExpr(1, 2)}");
}

// 결과
[0] anonymous function: 1
[1] anonymous function: 1
[2] 람다식: 3

 

void main(List<String> args) {
  // coding convention
  //
  // 주석
  // 1. 첫 단어가 대소문자를 구별하는 식별자(identifier)인 경우 소문자 가능
  // 2. 주석의 첫 글자는 모두 대문자로 쓰고 마침표로(.)로 끝난다.
  // 3. 블록 주석을 문서화 용도로 사용하지 않는다. (항상 한 줄 주석 // 을 사용한다.)

  // named parameter에서 optional parameter의 사용
  double divideByTwo({required int x, int y = 4}) {
    return x / y;
  }

  print(divideByTwo(x: 2));
  print(divideByTwo(x: 2, y: 4));
  print(divideByTwo(y: 4, x: 2));
}

// 결과
0.5
0.5
0.5

 

void main(List<String> args) {
  // Dart Functions are First-class Citizens
  // Passing a function to another function as an argument
  // 함수가 1급 객체임을 나타내는 억지 예제
  isOddNum(int i) {
    return i % 2 != 0;
  }

  isevenNum(int i) {
    return i % 2 == 0;
  }

  var io = isOddNum;
  var ie = isevenNum;

  showEvenOdd(Function fn, int i) {
    if (identical(fn, io)) {
      if (fn(i)) {
        print("$i is odd number.");
      } else {
        print("$i is not a odd number.");
      }
    }

    if (identical(fn, ie)) {
      if (fn(i)) {
        print("$i is even number.");
      } else {
        print("$i is not a even number.");
      }
    }
  }

  showEvenOdd(io, 1);
  showEvenOdd(ie, 2);
  showEvenOdd(ie, 3);
}

// 결과
1 is odd number.
2 is even number.
3 is not a even number.

 

void main(List<String> args) {
  void showEvenOdd(Function fn, int i) {
    if (fn(i)) {
      print("$i is even.");
    } else {
      print("$i is odd.");
    }
  }

  // 익명 함수의 사용
  // 함수와 값 모두 전달
  showEvenOdd((int x) {
    return x % 2 == 0;
  }, 1);

  showEvenOdd((int x) {
    return x % 2 == 0;
  }, 2);

  // 1 라인이므로 arrow function으로 대체 사용
  showEvenOdd((int x) => (x % 2 == 0), 3);
}

// 결과
1 is odd.
2 is even.
3 is odd.

 

// a few pieces of advice about function
//
// If you see code in your program that is repeated without changes(or even with minor variations.)
// in multiple places, refactor that code into a function and reuse it.
// 당신의 프로그램의 여러 곳에서 변경 없이 반복하거나 (또는 약간의 변형만 해서) 반복하는 경우
// 하나의 함수로 코드를 재구성해서 재사용한다.
//
// Use clear and meaningful names for functions. Not too long, not too short.
// Name calculateSum better than funct1. After reading the name of a function,
// you should have a better understanding of what that function does.
// 함수에 명확하고 의미있는 이름을 사용한다. 너무 길지 않고 너무 짧지 않게 짓는다.
// calculateSum 라는 함수 이름은 funct1 함수 이름보다 낫다. 함수명을 읽을 때
// 그 함수가 하는 일을 잘 이해할 수 있어야 한다.
//
// A function should be created for a single, clear purpose.
// If a function, depending on its parameters, does logically unrelated things,
// it’s better to split the function into smaller ones.
// For example, if you have a function that adds, multiplies, or divides numbers,
// but performs only one of these actions per call,
// it’s better to split the function into three smaller ones.
// 하나의 함수는 한 가지 명확한 목적을 위해 만들어야 한다.
// 하나의 함수가 받아 들이는 파라미터에 따라 논리적으로 관련 없는 일을 한다면,
// 함수는 더 작은 단위로 나누는 것이 좋다.
// 예를 들어, 덧셈, 곱셈, 나눗셈을 수행하는 함수가 있고 호출할 때마다 이러한 액션 중
// 단 하나만 수행한다면, 함수를 더 작은 단위로 나누는 것이 좋다.
//
// Strive to create small functions that you can easily view in their entirety without scrolling.
// 스크롤 하지 않고 함수 전체를 쉽게 파악할 수 있게 작은 함수를 만들도록 노력한다.

void main(List<String> args) {
  int i = 13;
  Function aboutNumber;

  if (i > 10) {
    // aboutNumber = biggerTen;
    aboutNumber = () => print('more than 10.');
  } else {
    // aboutNumber = belowTen;
    aboutNumber = () => print('less than 10 or equal.');
  }
  aboutNumber();
}

void biggerTen() => print('more than 10.');
void belowTen() => print('less than 10 or equal.');

// 익명 함수
//
// 이름이 없다는 점만 빼고 일반 함수와 동일하다.
// Anonymous functions are convenient to use when you need a small function 
// for a one-time use. Or if you need to pass a function into another function.

// 결과
more than 10.

 

void main(List<String> args) {
  List ints = [1, 2, 3, 4, 5];
  List anotherInts1 = [];
  List anotherInts2 = [];

  // anonymous function
  ints.forEach((i) {
    anotherInts1.add(i + 1);
  });

  // anonymous arrow function
  ints.forEach((i) => anotherInts2.add(i + 1));

  print("ano func: $anotherInts1}");
  print("ano arrow func: $anotherInts2");
}

// 결과
ano func: [2, 3, 4, 5, 6]}
ano arrow func: [2, 3, 4, 5, 6]

 

// Dart Optional Parameters
void main(List<String> args) {
  print(showFullName('John'));
  print(showFullName('John', 'Doe'));
}

String showFullName(String firstName, [String lastName = '']) {
  if (lastName.isEmpty) {
    return 'Hello $firstName!';
  }

  return 'Hello $firstName $lastName!';
}

// 결과
Hello John!
Hello John Doe!

 

/*
In Dart, functions are first-class citizens. 
This means that you can treat a function as a value of other types. So you can:

- Assign a function to a variable.
- Pass a function to another function as an argument.
- Return a function from a function.
*/

void main(List<String> args) {
  print("Even number =>\n");
  judge(isEven);

  print("");
  print("Odd number =>\n");
  judge(isOdd);
}

isOdd(int i) => i % 2 != 0;
isEven(int i) => i % 2 == 0;
judge(Function f) {
  for (int n = 1; n < 11; n++) {
    if (f(n)) {
      print(n);
    }
  }
}

// 결과
Even number =>
2
4
6
8
10

Odd number =>

1
3
5
7
9

 

void main(List<String> args) {
  print(sum([]));
  print(sum([1, 2]));
  print(sum([1, 2, 3, 4, 5]));
}

// dynamic is useful in very specific cases
// for everything else, use var, final, const

// As programs grow, we want to organize our code,
// and break it into smaller chunks.
//
// Functions helps us to write more maintainable code.
// Change the way a function behaves without changing how we call it.
//
// Function arguments can be variables, expressions or literals
// (as long as they have the correct type and are in the right order)

// We create functions to do something.
//  -> Function names should be or start with verb.
//  -> Variable names should be nouns.

double sum(List<double> numList) {
  if (numList.length == 0) {
    return 0;
  }

  return numList.reduce((value, element) => value + element);
}

// 결과
0.0
3.0
15.0

 

void main(List<String> args) {
  const orders = ['margherita', 'pepperoni', 'pineapple'];
  var totalPrice = 0.0;
  totalPrice = calcSum(orders);

  print('Total: \$$totalPrice');
}

/*
Functions with named arguments

Without Null Safety: arguments can be omitted.
With Null Safety:
  - make arguments nullable (eg. {String? name})
  - make arguments non-nullable
    - use a default value (e.g. {String name = 'John'})
    - mark them as required (e.g. {required String name})

* Null safety gives you compule-time guarantees about what can and cannot be null.

*/

double calcSum(List<String> orders) {
  double _sum = 0.0;
  const Map<String, double> pizzaPrices = {
    'margherita': 5.5,
    'pepperoni': 7.5,
    'vegetarian': 6.5,
  };

  if (orders.length == 0) return 0.0;

  for (var order in orders) {
    if (pizzaPrices.containsKey(order)) {
      _sum += pizzaPrices[order] as double;
    }
  }
  return _sum;
}

// 결과
Total: $13.0

 

// Functions as first-class object.

void main(List<String> args) {
  // 'sayHi' is a reference to our anonymous function.
  // Assign functions to variavles.
  final sayHi = (name) => 'Hi! $name';

  print(sayHi('John'));

  print('');

  welcome(sayHi, 'John');

  // Argument types are often omitted in anonymous functions
  // (they tend to be small)
}

// Pass functions as arguments to other functions
void welcome(String Function(String) greet, String name) {
  print(greet(name));
  print('Welcome to new world.');
}


 /*
  Complex programs:
    - many mutable global variables
    - hard to keep track of what changes and where
    - Adding mutable global state is one of the worst things you can do
 */
 
 // 결과
 Hi! John

Hi! John
Welcome to new world.

 

void main(List<String> args) {
  var result = exec(add, 10, 20);
  print('Result is $result');
}

int add(int x, int y) {
  return x + y;
}

exec(Function op, x, y) {
  return op(x, y);
}

// 결과
Result is 30

 

void main(List<String> args) {
  print(customerDiscount('11123', name: 'John', age: 20));
}

// positional argument combines named argument
String customerDiscount(String staffNr, {required String name, int age = 30}) {
  if (age >= 60) {
    return ('$name, you will get 80 discount');
  } else if (age < 10) {
    return ('$name, you will get 20 discount');
  } else {
    return ('$name, you will get no discount');
  }
}

// Dart functions - Named and positional arguments

// 결과
John, you will get no discount

 

// the various type of function format

void main(List<String> args) {
  var sum = calculateSum(num1: 1, num2: 2);

  print('sum: $sum');

  print('');

  // anonympous function
  var total = (n1, n2) => n1 + n2;

  print('total is ${total(1, 2)}');

  print('');

  int Function(int, int) totalSum = (num1, num2) => num1 + num2;

  print('total sum is ${totalSum(1, 1)}');
}

int calculateSum({required int num1, required int num2}) {
  return num1 + num2;
}

/*
the fat arrow notation =>
anonymous function
typedef
*/

// 결과
sum: 3

total is 3

total sum is 2

 

typedef Action = void Function(int);

void main(List<String> args) {
  var values = [1, 2, 3, 4, 5, 6, 7, 8, 9];
  var newValues = <int>[];

  void Function(int) addTwo = (value) => newValues.add(value + 2);
  listOperation(values, addTwo);
  print(newValues);

  print('=====' * 6);

  newValues.clear();
  var addThree = (value) => newValues.add(value + 3);
  listOperation(values, addThree);
  print(newValues);

  print('=====' * 6);
  newValues.clear();
  listOperatoin2(values, (value) => newValues.add(value + 4));
  print(newValues);
}

void listOperation(List<int> list, void Function(int) action) {
  for (var item in list) {
    action(item);
  }
}

void listOperatoin2(List<int> list, Action action) {
  list.forEach(action);
}

// 결과
[3, 4, 5, 6, 7, 8, 9, 10, 11]
==============================
[4, 5, 6, 7, 8, 9, 10, 11, 12]
==============================
[5, 6, 7, 8, 9, 10, 11, 12, 13]

 

void main(List<String> args) {
  Operation oper = add;
  oper(1, 2);
  oper = mutiply;
  oper(1, 2);

  print('');

  calc(1, 2, add);
  calc(1, 2, mutiply);
}

typedef Operation = Function(int x, int y);

void add(int x, int y) {
  print('x + y = ${x + y}');
}

void mutiply(int x, int y) {
  print('x * y = ${x * y}');
}

void calc(int x, int y, Operation operation) {
  operation(x, y);
}

// 결과
x + y = 3
x * y = 2

x + y = 3
x * y = 2
반응형

관련글 더보기

댓글 영역