Compy's Blog
1543 words
8 minutes
[Mojo] Variables
2025-02-01
No Tags

Mojo의 변수 선언과 사용#

mojo setup

Go to MojoSetup

1. 변수의 종류#

Mojo에서는 모든 변수가 가변적(mutable)이며, 두 가지 방식으로 변수를 선언할 수 있습니다

1.1 명시적 변수 선언 (Explicitly-declared variables)#

var 키워드를 사용하여 변수를 선언합니다. 타입 어노테이션을 포함할 수 있습니다

var a = 5
var b: Float64 = 3.14
  • 초기화 없이 선언 가능: var value: Float64
  • 렉시컬 스코핑(lexical scoping) 따름
  • 타입 어노테이션 사용 가능

1.2 암시적 변수 선언 (Implicitly-declared variables)#

할당 문장으로 직접 변수를 생성합니다

a = 5
b = 3.14 
  • 함수 레벨 스코핑
  • 첫 할당값의 타입으로 변수 타입이 결정됨

2. 타입 시스템#

2.1 강타입 시스템 (Strong typing)#

지식

모든 변수는 강타입입니다

  • 생성 시 타입이 결정되며 변경 불가
  • 다른 타입의 값 할당 시 에러 발생
count = 1        # count는 Int 타입
count = "One"  # 에러: StringLiteral을 Int로 변환 불가 

2.2 암시적 타입 변환 (Implicit conversion)#

지식

일부 타입은 다른 타입으로부터의 암시적 변환을 지원

var test: Float64 = 50  # Int에서 Float64로 자동 변환
print(test)  # 출력: 50.0 

3. 스코프 규칙#

3.1 var 키워드 사용 시 (렉시컬 스코프)#

def lexical_scopes():
    var num = 1
    if num == 1:
        var num = 2     # 새로운 변수 생성 (shadowing)
        print(num)      # 2 출력
    print(num)          # 1 출력 (외부 스코프 변수) 

3.2 암시적 선언 시 (함수 레벨 스코프)#

def function_scopes():
    num = 1
    if num == 1:
        num = 2        # 함수 레벨 변수 수정
        print(num)     # 2 출력
    print(num)         # 2 출력 

4. 타입 어노테이션 (Type Annotations)#

4.1 기본 사용법#

타입 어노테이션을 사용하면 변수의 타입을 명시적으로 지정할 수 있습니다

var name: String = get_name()
  • var 키워드와 함께 사용해야 함
  • 코드의 가독성과 의도를 명확히 전달
  • 함수 반환값의 타입을 모르더라도 변수 타입을 명시 가능

4.2 단일 인자 생성자를 가진 타입의 초기화#

지식

단일 인자 생성자를 가진 타입은 두 가지 방식으로 초기화 가능

var name1: String = "Sam"      # 타입 어노테이션 사용 
var name2 = String("Sam")      # 직접 생성자 호출

5. 지연 초기화 (Late Initialization)#

지식

타입 어노테이션을 사용하면 변수를 나중에 초기화 가능

fn my_function(x: Int):
    var z: Float32              # 타입만 선언
    if x != 0:
        z = 1.0                 # 조건에 따라 초기화
    else:
        z = foo()
    print(z) 
  • 초기화되지 않은 변수 사용 시 컴파일 에러 발생
  • 타입 선언이 반드시 필요
  • 값 할당 전 사용 불가

6. 암시적 타입 변환의 조건#

암시적 타입 변환이 가능 조건:

  • 대상 타입이 @implicit 데코레이터로 표시된 생성자를 가짐
  • 해당 생성자가 변환하려는 값과 일치하는 단일 필수 인자를 받음
var number: Float64 = Int(1)   # Int를 Float64로 암시적 변환
print(number)                  # 출력: 1.0 

==> 아래와 같이 표현할 수 있어요

var number = Float64(1)        # 직접 생성자 호출

함수 호출할 때도 암시적 변환이 적용됩니다

fn take_float(value: Float64):
    print(value)

fn pass_integer():
    var value: Int = 1
    take_float(value)          # Int가 Float64로 자동 변환 
조심조심

일반적으로 암시적 변환은 데이터 손실이 없는 경우에만 지원합니다

Function Scope in Mojo

함수 레벨 스코프 vs 렉시컬 스코프#

Mojo에서는 변수 선언 방식에 따라 두 가지 다른 스코프 규칙이 적용됩니다

1. 암시적 선언의 함수 레벨 스코프#

암시적으로 선언된 변수(var 키워드 없이 선언)는 Python과 같은 함수 레벨 스코프를 따릅니다

def demonstrate_function_scope():
    count = 0                    # 함수 레벨에서 변수 선언
    
    if True:
        count = 5               # 같은 변수를 수정
        temp = 10              # 새로운 변수 선언
        print(count)           # 출력: 5
        
    print(count)               # 출력: 5 (if 블록의 변경사항이 유지됨)
    print(temp)                # temp도 접근 가능 (함수 전체가 스코프)
  • 변수는 함수 전체에서 동일한 스코프를 공유
  • 내부 블록에서 수정된 값은 함수 전체에 영향
  • 새로 선언된 변수도 함수 전체에서 접근 가능
  • Python 스타일의 변수 스코핑과 동일

2. var 키워드의 렉시컬 스코프#

반면, var로 선언된 변수는 렉시컬 스코프를 따릅니다

def demonstrate_lexical_scope():
    var count = 0              # 외부 스코프 변수
    var outer = 1
    
    if True:
        var count = 5          # 새로운 변수 생성 (shadowing)
        var inner = 2          # 내부 스코프 변수
        print(count)           # 출력: 5
        print(outer)           # 외부 변수 접근 가능
        
    print(count)              # 출력: 0 (외부 변수는 변경되지 않음)
    # print(inner)            # 에러! inner는 if 블록 밖에서 접근 불가
  • 각 블록이 고유한 스코프를 생성
  • 내부 스코프에서 외부 변수 접근 가능
  • 같은 이름의 변수 선언 시 shadowing 발생
  • 내부 스코프의 변수는 해당 블록 밖에서 접근 불가

3. 두 스코프 규칙의 실제 응용#

두 스코프 규칙을 혼합해서 사용할 때

def mixed_scope_example():
    var x = 0                 # 렉시컬 스코프 변수
    y = 0                     # 함수 스코프 변수
    
    if True:
        var x = 1             # 새로운 x 생성 (shadowing)
        y = 1                 # 기존 y 수정
        var z = 2             # 렉시컬 스코프의 새 변수
        w = 3                 # 함수 스코프의 새 변수
        
    print(x)                  # 출력: 0 (원래 x 유지)
    print(y)                  # 출력: 1 (수정된 y)
    # print(z)               # 에러! z는 if 블록 스코프
    print(w)                  # 출력: 3 (함수 스코프라 접근 가능) 
  • 함수 레벨 스코프는 Python 개발자들에게 친숙한 동작을 제공
  • 렉시컬 스코프는 더 엄격한 변수 관리와 안전성을 제공
  • 두 스코프 규칙을 상황에 맞게 적절히 선택하여 사용 가능

Reference
#

Mojo docs

[Mojo] Variables
https://compy07.github.io/Blog/posts/mojo/tutorial/variable/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2025-02-01