using ... for 문법
using A for B; 구문을 쓰면 라이브러리 A 의 함수들을 타입 B 의 메서드처럼 호출할 수 있습니다.
라이브러리이름.함수이름(값, ...) 이라는 다소 장황한 호출을, 값.함수이름(...) 이라는 자연스러운
문법으로 바꿔주는 문법 설탕(syntactic sugar) 입니다.
using Math for uint256; 를 선언하면 Math.max(a, b) 대신 a.max(b) 처럼 쓸 수 있습니다. 이때
a 가 라이브러리 함수의 첫 번째 인자로 자동 전달됩니다.
동작 방식
a.max(b) 는 컴파일러가 내부적으로 Math.max(a, b) 로 변환합니다.
즉, 점(.) 앞의 값이 함수의 첫 인자가 되고, 괄호 안의 값들이 두 번째 인자부터 채워집니다.
그래서 코드가 위에서 아래로, 왼쪽에서 오른쪽으로 읽기 쉬워집니다.
체이닝으로 가독성 높이기
반환 타입이 다시 같은 타입이면, 메서드를 연달아 이어 붙이는 체이닝(chaining) 이 가능합니다.
x.double().add(5) 처럼 읽으면 "x를 두 배 한 뒤 5를 더한다"는 의도가 한눈에 드러납니다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library Math {
function double(uint256 a) internal pure returns (uint256) {
return a * 2;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
}
contract Demo {
// uint256 타입에 Math 라이브러리를 연결한다.
using Math for uint256;
function run(uint256 x) public pure returns (uint256) {
// x.double() == Math.double(x)
// x.add(5) == Math.add(x, 5)
return x.double().add(5);
}
}OpenZeppelin 의 using SafeERC20 for IERC20; 처럼, using ... for 는 특정 타입에 안전한 헬퍼
함수를 메서드처럼 붙이는 실무 패턴으로 자주 등장합니다. 특정 타입 대신 using A for *; 로 모든
타입에 적용할 수도 있습니다.