변수와 스코프는 프로그래밍의 핵심입니다. 토파즈는 현대적이고 안전한 변수 시스템을 제공하여 버그를 줄이고 코드의 명확성을 높입니다. 🎯
🔧 변수 선언
let - 불변 변수 (기본)
// 기본적으로 모든 변수는 불변입니다
let 이름 = "김토파즈"
let 나이 = 25
let 활성화됨 = true
// 한 번 정의된 후에는 변경할 수 없습니다
// 이름 = "다른이름" // 컴파일 에러!
let mut - 가변 변수
// 값을 변경해야 할 때는 let mut 사용
let mut 점수 = 100
let mut 메시지 = "초기 메시지"
// 값 변경 가능
점수 = 95
메시지 = "업데이트된 메시지"
print("현재 점수: {점수}") // "현재 점수: 95"
const - 컴파일 타임 상수
// 컴파일 시점에 결정되는 상수
const MAX_SIZE: int = 1000
const APP_NAME: string = "Topaz Calculator"
const PI: float = 3.141592653589793
// 다른 파일에서도 사용 가능한 전역 상수
const 기본설정 = {
언어: "한국어",
테마: "다크",
자동저장: true
}
🎯 타입 추론과 명시적 타입
// 타입 추론 (권장)
let 자동추론숫자 = 42 // int
let 자동추론문자열 = "Hello" // string
let 자동추론배열 = [1, 2, 3] // [int]
// 명시적 타입 (필요할 때)
let 명시적숫자: int = 42
let 명시적문자열: string = "Hello"
let 명시적배열: [int] = [1, 2, 3]
// 복잡한 경우 타입 명시가 도움됨
let 사용자데이터: { 이름: string, 나이: int } = {
이름: "김개발자",
나이: 30
}
🏠 스코프 규칙
전역 스코프
// 파일 최상위 레벨 - 전역 스코프
let 전역변수 = "모든 곳에서 접근 가능"
const 전역상수 = 100
function 어디서든사용() {
print(전역변수) // 접근 가능
print(전역상수) // 접근 가능
}
함수 스코프
function 계산기(a: int, b: int) -> int {
// 함수 매개변수도 함수 스코프에 속함
let 결과 = a + b // 함수 스코프
let mut 임시값 = a * 2 // 함수 스코프
print("결과: {결과}")
return 결과
}
// print(결과) // 에러! 함수 밖에서 접근 불가
블록 스코프
function 스코프예제() {
let 외부변수 = "바깥"
if true {
let 내부변수 = "안쪽" // 블록 스코프
let mut 블록가변 = 10 // 블록 스코프
print(외부변수) // 접근 가능 (상위 스코프)
print(내부변수) // 접근 가능 (같은 스코프)
}
print(외부변수) // 접근 가능
// print(내부변수) // 에러! 블록 밖에서 접근 불가
}
루프 스코프
// for 루프의 변수는 루프 스코프를 가짐
for i in 0..5 {
let 루프내변수 = i * 2
print("i: {i}, 값: {루프내변수}")
}
// print(i) // 에러! 루프 밖에서 접근 불가
// while 루프도 마찬가지
let mut 카운터 = 0
while 카운터 < 3 {
let 임시 = 카운터 + 10
print(임시)
카운터 += 1
}
🔒 섀도잉 (Variable Shadowing)
let 이름 = "김토파즈"
function 섀도잉예제() {
let 이름 = "박개발자" // 전역 이름을 가림 (섀도잉)
print("함수 내: {이름}") // "함수 내: 박개발자"
{
let 이름 = "이디자이너" // 함수의 이름을 가림
print("블록 내: {이름}") // "블록 내: 이디자이너"
}
print("블록 후: {이름}") // "블록 후: 박개발자"
}
print("전역: {이름}") // "전역: 김토파즈"
섀도잉예제()
🌟 클로저와 스코프
function 카운터생성기(초기값: int) -> function() -> int {
let mut 개수 = 초기값 // 클로저에 캡처됨
return function() -> int {
개수 += 1 // 상위 스코프의 변수 접근
return 개수
}
}
let 카운터1 = 카운터생성기(0)
let 카운터2 = 카운터생성기(100)
print(카운터1()) // 1
print(카운터1()) // 2
print(카운터2()) // 101
print(카운터1()) // 3
🎭 패턴 매칭과 변수
let 사용자 = {
이름: "김토파즈",
나이: 28,
직업: "개발자"
}
// 구조 분해로 새 변수 생성
let { 이름, 나이 } = 사용자
print("이름: {이름}, 나이: {나이}")
// match에서 변수 바인딩
match 사용자.나이 {
case 나이 if 나이 < 20 => print("학생일 가능성이 높음")
case 나이 if 나이 < 30 => print("청년층")
case 나이 => print("경력자: {나이}세")
}
// 배열 패턴 매칭
let 점수들 = [95, 87, 92, 88]
match 점수들 {
case [첫번째, 두번째, ...나머지] => {
print("첫 번째: {첫번째}")
print("두 번째: {두번째}")
print("나머지: {나머지}")
}
}
⚡ 고급 스코프 패턴
IIFE (즉시 실행 함수)
// 즉시 실행 함수로 스코프 격리
let 결과 = (function() -> int {
let 임시계산 = 10 * 20
let 보정값 = 50
return 임시계산 + 보정값
})()
print(결과) // 250
// 임시계산, 보정값은 접근 불가
모듈 스코프
// math_utils.tpz 파일
export const PI = 3.141592653589793
export let 기본정밀도 = 6
export function 원넓이(반지름: float) -> float {
let 내부계산 = 반지름 * 반지름 // 모듈 내부에서만 접근 가능
return PI * 내부계산
}
// main.tpz 파일
import { PI, 원넓이 } from "./math_utils"
print(PI) // 접근 가능
print(원넓이(5.0)) // 접근 가능
// print(내부계산) // 에러! 모듈 내부 변수는 접근 불가
🛡️ 베스트 프랙티스
1. 기본적으로 불변 사용
// 좋은 예: 기본적으로 let 사용
let 설정 = {
테마: "다크",
언어: "한국어"
}
// 필요할 때만 let mut 사용
let mut 진행상태 = "시작"
진행상태 = "진행중"
진행상태 = "완료"
2. 의미있는 변수명
// 나쁜 예
let a = 사용자목록.length()
let b = a * 0.1
// 좋은 예
let 총사용자수 = 사용자목록.length()
let 수수료 = 총사용자수 * 0.1
3. 스코프 최소화
function 데이터처리(원본데이터: [int]) -> [int] {
let 결과 = []
for 항목 in 원본데이터 {
// 루프 내에서만 필요한 변수는 루프 내에서 선언
let 변환된값 = 항목 * 2 + 1
let 검증된값 = if 변환된값 > 0 { 변환된값 } else { 0 }
결과.push(검증된값)
}
return 결과
}
🔍 디버깅 팁
// 스코프 디버깅을 위한 유틸리티
function 스코프정보출력() {
let 지역변수 = "local"
print("현재 함수의 변수들:")
print("- 지역변수: {지역변수}")
// 전역 변수 접근
if defined(전역변수) {
print("- 전역변수 접근 가능")
}
}
// 변수 존재 여부 확인
function 안전한접근(변수명: string) {
if defined(변수명) {
print("{변수명}가 정의되어 있습니다")
} else {
print("{변수명}가 정의되지 않았습니다")
}
}
토파즈의 변수와 스코프 시스템은 안전성과 명확성을 동시에 제공합니다. 불변성을 기본으로 하되 필요할 때 가변성을 허용하고, 명확한 스코프 규칙으로 예측 가능한 코드를 작성할 수 있습니다. 🚀