라벨이 scope인 게시물 표시

[C++] 이름과 스코프

C++에서는 많은 것들이 이름을 가질 수 있다. 변수는 모두 이름을 가지고, 객체는 변수를 통해서 이름을 가질 수 있다. 타입도 이름이 있고, 함수도 이름이 있다. 람다 함수는 익명 함수라는 번역 그대로 이름이 없지만, 변수에 할당하여 이름을 통해 접근할 수도 있다. 이 이름을 어디서부터 어디까지 사용할 수 있는가를 그 이름의 스코프라고 하는데, C++은 상황에 따라 다른 스코프를 사용한다. 이번 글에서는 C++의 이름이 가지는 스코프에 관해서 설명하도록 하겠다. block scope block scope는 선언된 문장부터 선언된 block이 끝날 때까지 사용할 수 있다. 블록 밖에서 선언된 같은 이름이 있으면 이름이 선언되기 전까지는 블록 밖에서 선언된 이름을 그대로 가지고, 선언된 문장부터 새로 선언한 의미를 가진다. 예를 들어 위와 같은 코드가 있을 때 4번째 줄까지 a 는 2번째 줄에서 선언된 a 이지만, 4번째 줄부터 block이 끝나는 10번째 줄까지는 4번째 줄에서 선언된 a 이다. 또한, block scope를 가지는 이름은 같은 block 안에서 다른 의미를 가지기 위해 다시 사용될 수 없다. 즉, 위에서 5번째 줄에서 10번째 줄까지 사이에서는 a 를 다른 의미로 사용할 수 없다. 스코프를 가지는 이름의 대표적인 예제로는 함수 안에서 선언된 변수인 지역 변수(local variable)가 있다. 이때 지역 변수와 automatic storage 에 저장되는 지역 객체를 혼동하면 안 된다. 스코프는 어디까지나 컴파일 시 그 이름을 어디까지 사용할 수 있는가 하는 것이지 객체의 라이프타임과는 상관없다. 지역 변수 중에서도 static 이나 thread_local 같은 storage를 지정해주는 specifier가 붙은 경우 이 객체들은 automatic storage에 저장되지 않는다. 지역 변수 외에도 typedef 나 using 으로 선언되는 type alias, 함수 안에서 선언되는 class 와 enum 같은 경우도 함

[ECMAScript 6] block 안에서 함수 만들기

JavaScript 함수 선언의 가장 큰 특징은 함수의 선언 위치에 상관없이 언제나 코드의 가장 위에서 함수를 선언한 것처럼 코드가 실행된다는 것이다. 따라서 아래 두 코드는 사실 같은 코드라고 봐도 된다. 이를 function hoisting 이라고 한다. 이 덕분에 함수 선언문보다 앞에서 함수를 사용할 수 있다. 하지만 함수 선언은 언제나 스코프의 가장 윗부분으로 hoisting 된다. 따라서 함수 안에서 선언된 함수는 함수 내에서 언제나 같은 함수를 의미했고, 특정 block 안에서는 다른 함수를 의미하도록 사용할 수 없었다. 하지만 ECMAScript 6에서는 block 단위의 함수 선언을 허용한다. 즉, 위와 같이 if block 안에서만 다른 값을 의미하도록 하는 것이 가능하다. 하지만 아쉽게도 이는 아직 대부분 브라우저나 node.js에서는 구현되지 않았다 . 따라서 블록 단위 함수 선언을 사용하려면 babel.js 를 사용해야 한다.

[ECMAScript 6] const - 상수 선언하기

>const 는 >let 과 같이 ECMAScript 6 에 도입된 block 단위 상수 선언문이다. 중복으로 선언할 수 없고, 선언 전에 사용할 수 없다는 것은 >let 과 같다. 거기에 >const 는 추가적인 제약이 더 붙는다. 우선 >const 로 선언된 이름에는 값을 재할당할 수 없다. 이는 문법적으로 에러로 처리한다. 따라서 >const 에 값을 할당하는 구문을 실행할 때 발생하는 것이 아니라 >const 에 값을 할당하는 구문이 있는 함수가 선언될 때 에러가 발생한다. 또한, >const 를 이용해서 상수를 선언할 때는 언제나 값을 초기화해주어야 한다. >const 로 선언된 상수에 값을 할당하지 못한다는 것을 생각하면, 당연한 일이다. 이 또한 문법 에러로, 초기화하지 않는 >const 를 선언할 때가 아니라, 선언하는 구문이 있는 함수를 선언할 때 에러가 발생한다. 하지만 >const 도 상수 선언을 위한 완벽한 해결책은 아니다. >const 로 선언한 상수에는 값을 재할당할 수 없지만, 상수임에도 불구하고 값을 변경시킬 수 있기 때문이다. >const 로 선언한 상수는 어디까지나 값의 재할당을 막을 뿐, 그 값을 보호해주지 않는다. >const가 완벽한 해결책인 것은 아니지만 , 한계를 알고 적절하게 사용하면 좀 더 안정적이고 가독성 있는 코드를 작성할 수 있다.

[ECMAScript 6] let - block 단위 스코프

ECMAScript 6 에서는 기존의 function scope였던 >var 이외에 >let 이라는 block scope 변수 선언을 지원한다. >let 을 통한 변수 선언은, >var 를 통한 변수 선언과 다르게 hoisting 하지 않는다. 즉, 변수가 선언된 이후부터 변수가 유효하고 그전에는 해당 변수를 사용할 수 없다. hoisting을 없앤 것뿐 아니라 그 외의 실수하기 쉬운 부분을 에러로 처리하여 좀 더 안전한 코드를 작성할 수 있도록 하였다. 예를 들면, ECMAScript 5 에서는 hoisting 된 변수를 실수로 선언 전에 사용할 경우 그 변수는 >undefined 가 된다. 하지만 >let 을 사용하면, 변수를 hositing 하지 않을 뿐 아니라, 변수를 선언한 블록 안에서 선언 전에 해당하는 이름을 사용하는 것을 에러로 처리한다. 또한, 이전에는 같은 스코프, 다시 말해서 같은 함수 안에서 변수의 선언문이 여러 개 있는 것이 정상적인 구문으로 처리되었다. 하지만 >let 을 사용한다면 같은 스코프에서 중복으로 선언하는 것이 에러로 처리된다. 아쉬운 점은 위와 같은 에러가 함수의 선언에서 발생하는 것이 아니라, 실제로 그 구문을 실행할 때 발생한다는 것이다. 따라서 여전히 높은 커버리지의 테스트를 작성해야 안전한 코드라고 보장할 수 있다. 하지만 예전처럼 예상하지 못한 >undefined 가 나와서 문제가 발생한 부분이 아닌 다른 곳부터 추적해가야 할 일은 없어졌다. 또 다른 문제는 babel 에서 다르게 동작한다는 것이다. 파이어폭스나 크롬 등 모던 브라우저나 io.js는 ECMAScript 6를 지원하지만, 오래된 버전의 IE나 node.js 등에서는 아직 >let 을 지원하지 않는다. 그런 환경에서는 babel을 사용해야 하는데, babel에서는 중복된 선언이나, 선언 전에 사용하는 것을 에러로 처리하지 않는다. 하지만 조만간 node.js에서도 >let 을 지

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

RAII는 무엇인가

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API