Silver Library (Archived)
백준 1330번 JS - closure, node.js template? 본문
백준 1330번 JS - closure, node.js template?
Ayin Kim 2021. 7. 19. 17:33Q.
두 정수 A와 B가 주어졌을 때, A와 B를 비교하는 프로그램을 작성하시오.
Condition.
첫째 줄에 A와 B가 주어진다. A와 B는 공백 한 칸으로 구분되어져 있다.
첫째 줄에 다음 세 가지 중 하나를 출력한다.
- A가 B보다 큰 경우에는 '>'를 출력한다.
- A가 B보다 작은 경우에는 '<'를 출력한다.
- A와 B가 같은 경우에는 '=='를 출력한다.
Ans.
const fs = require("fs")
const inputData = fs.readFileSync("/dev/stdin").toString().split(" ").map(val=>+val)
const [a,b] = inputData
if (a > b){
console.log(">")
}
else if (a < b){
console.log("<")
}
else {
console.log("==")
}
공략.
const fs = require("fs") 까지는 초기화 하는 const 변수로 이해가 가능하다.
다만 inputData 이후 부터, fs.readFileSync 는 처음보는 메소드다.
우선 fs 부터 알아볼 필요가 있어보인다. 하지만 fs 도 딱히 유추되는게 없다. 뭘까?
https://balmostory.tistory.com/33
결론만 말하자면, node.js 에서 제공하는 filesystem 이라고 한다.
용도는 : 파일을 불러오는 등의 기능 제공.
이는 https://3dmpengines.tistory.com/1855 를 참고해보니,
readFileSync 는 '동기'(정말 동기화의 그것 인가)
readFile 만 있으면 '비동기' 이다.
이건 콜백 함수, 그리고 특정 파일을 먼저 읽고 진행시키려면 동기적인 readFileSync 를.
그게 아니면 readFile 로 진행해서 참조하라는 의미로 보여진다.
node.js 에서 컴파일을 다음과 같이 소개하고 있다고 한다.
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split(' ');
var a = parseInt(input[0]);
var b = parseInt(input[1]);
console.log(a+b);
만약 공백으로 구분된 값들이, 여러줄로 들어온다면 아래와 같이 표현한다.
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split('\n');
var line0 = input[0].split(' ');
var line1 = input[1].split(' ');
var line2 = input[2].split(' ');
...
하지만 이 경우에는, 불편하다고 한다.
생각해보면 맞는 말인게, 일일히 배열에 참조(접근)를 하고 있다.
input 인덱스 고려 없이, 들어오는 순서대로 바로바로 실행되게 하는 방법이 있다고 한다.
JS의 closure 를 적극 활용하면 다음과 같은 표현식이 가능하다.
const fs = require('fs');
const stdin = fs.readFileSync('/dev/stdin').toString().split('\n');
function makeInput(){
let line = 0;
return function(){
return stdin[line++];
};
};
const input = makeInput();
문제의 해답에 나온 그 코드다!
'이렇게 return 된 function은, 이제 실행 할 때 마다 stdin 을 한 줄씩 return 한다.' 이다.
여기서 ES6 의 arrow function 기법을 사용하면, 다음과 같다.
const fs = require('fs');
const stdin = fs.readFileSync('/dev/stdin').toString().split('\n');
const input = (() => {
let line = 0;
return () => stdin[line++];
})();
예상하다 시피, arrow function 의 유일한 장점은 '간편함' 과 '축소' 다.
보너스.
const stdin = fs.readFileSync('/dev/stdin').toString().split('\n'); 의 경우, 일단 node.js 에서 사용되는 빌트인의 무언가 라는 것 만큼은 확실히 알겠는데, 그래서 저건 언제 쓰고, 왜 쓰지? 이다.
<불확실!>
현 시점에서 내릴 수 있는 판단은, 저 stdin 이 핵심이고, readFileSync 가 동기적으로 하나하나 stdin 을 호출 하는 식으로 실행 하여 return 을 하도록 하는 것이, 주된 목적으로 보여진다. 뒤의 toString 이나 split은, 문자 그대로의 목적으로 사료된다.
우선, "클로저(closure)를 이용해 특정 함수 내에서만 접근할 수 있는 변수를 만들고, 그 값을 input의 인덱스로 이용." 에서 영감을 얻었다고 했으니, 이 closure 에 대해 한번 읽어봐야 겠다.
Accoridng to MDN...
클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.
즉, closure 는 Lexical environment 와 밀접한 관계가 있다고 볼 수 있을 것 같다.
이건 스코핑의 개념 일부 중 하나로 보여진다.
만약 헷깔려서 돌아왔다면, 이 부분은 시원하게 링크로 보고 가는 것이 좋겠다.
아래의 코드블록이 그 예시인데, makeFunc 가 myFunc 변수에(다가)서
displayName 을 return 하는 것이 closure 예시의 핵심으로 보여진다.
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
//myFunc변수에 displayName을 리턴함
//유효범위의 어휘적 환경을 유지
myFunc();
//리턴된 displayName 함수를 실행(name 변수에 접근)
그외 단어:
구조 분해 할당 (Destructuring assignment)
참조:
'CS Library > JavaScript - Data Structure' 카테고리의 다른 글
백준 2753번 - JS (0) | 2021.07.20 |
---|---|
9498 번 JS, 풀어보자. (0) | 2021.07.19 |
백준 JS 소스코드 템플릿 겸 - 2588 곱셈 (0) | 2021.07.19 |
class in JS (0) | 2021.07.18 |
Callback in JS? (0) | 2021.07.17 |