Compy's Blog
1356 words
7 minutes
[Mojo] Function(Part 1)
2025-02-07
No Tags

Mojo의 function system#

1. function define(def vs. fn)#

1.1 def#

먼저 모조는 기본적으로 파이썬과의 호환성을 챙기고 있으므로 파이썬에서 사용하는 방식을 그대로 사용할 수 있습니다

그래서 def keyword를 이용해서 함수를 정의할 수 있습니다

def sum(a, b):
    return a+b 

이렇게 정의할 수 있습니다. 물론 명시적으로 타입을 적어서 더 안전하게 처리할 수도 있죠

def sum1(a: Int32, b: Int32) -> Int32:
    return a + b

def sum2(a: Int32, b: Int32):
    return a + b
안되는 모양
def sum3(a, b) -> Int32:
    return a+b

error: cannot implicitly convert ‘object’ value to ‘SIMD[int32, 1]’ return a+b

이거를 보면 알 수 있듯이 return datatype이 정해져 있어서 object로 들어오는 a, b의 type을 변환하는데 이때 모조가 암시적 타입 변환(implicit type conversion)을 못해서 터지는 오류입니다

뭐 어떻게든지 선언할 수 있어요

그래서 이걸 좀 정리를 해보자면

  • 인자 타입을 명시하지 않아도 됨
  • 리턴 타입을 명시하지 않아도 됨
  • 타입을 명시하지 않은 인자는 object 타입으로 처리
  • 인자는 가변적(mutable)
  • 객체 타입 인자는 참조로 전달
  • 다른 선언된 타입의 인자는 값으로 전달

이렇게 됩니다!

1.2 fn#

fn같은 경우에는 좀 많이 엄격합니다. def의 경우 선택적이었던 타입 명시를 강제하고 있거든요!

fn sum1(a: Int32, b: Int32) -> Int32:
    return a + b

이렇게만! 사용할 수 있어요

바로 또 정리를 해봅시다.

  • 모든 인자의 타입을 명시해야 함
  • 리턴 타입을 명시해야 함 (값을 반환하지 않는 경우 제외)
  • 기본적으로 인자는 불변 참조로 전달
  • 오류를 발생시키는 경우 raises 키워드를 명시해야 함

이렇게 정리할 수 있습니다.

2. 함수의 활용#

지금부터는 fn 키워드를 주로 사용하겠습니다.

2.1 함수 인자#

2.1.1 선택적 인자#

fn pow(base: Int, exp: Int = 2) -> Int:
    return base ** exp

이렇게 기본값을 지정할 수 있음.

2.1.2 키워드 인자#

var value_case_1 = pow(base=3, exp=5) 

var value_case_2 = pow(exp=3, base=5) 

호출을 이렇게 활용할 수도 있습니다.

2.1.3 가변 인자#

fn sum(*values: Int) -> Int:
    var sum: Int = 0
    for value in values:
        sum = sum + value
    return sum
fn main():
    var value_case_1 = sum(10)
    print(sum(1, 2, 3))  # -> 6
    print(sum(10, 20, 30, 40))  # -> 100
    print(value_case_1) # -> 10
    return

이렇게 활용할 수 있어요!

2.1.4 키워드 전용 인자#

fn kw_only_args(a1: Int, a2: Int, *, double: Bool) -> Int:
    var product = a1 * a2
    if double:
        return product * 2
    else:
        return product
fn kw_only_args2(a1: Int, a2: Int, *, multi: Bool, amount: Int) -> Int:
    var product = a1 * a2
    if not multi: return product
    return product ** (amount+1)
fn main():
    print(kw_only_args(1, 2, double=True))
    print(kw_only_args2(1, 2, multi=True, amount = 3))
    return 

여기서 보면 중간에 *가 중요한데 이 기호 뒤에오는 모든 매개변수가 키워드 전용 인자라고 말하는 겁니다

이때 키워드를 직접 명시하지 않는다면?

print(kw_only_args2(1, 2, True, amount = 3))

이렇게되면 오류가 터지게 됩니다.

2.1.5 함수 오버로딩#

fn add(x: Int, y: Int) -> Int:
    return x + y

fn add(x: String, y: String) -> String:
    return x + y 
오버로딩

나온 김에 정리하고 갑시다.(원래 저는 자바를 먼저 사용했기에..)

같은 이름의 메서드를 여러 개 정의할 수 있게 해주는 기능인데,

    // 정수 두 개를 더하는 메서드
    public int add(int a, int b) {
        return a + b;
    }
    
    // 실수 두 개를 더하는 메서드
    public double add(double a, double b) {
        return a + b;
    }
    
    // 정수 세 개를 더하는 메서드
    public int add(int a, int b, int c) {
        return a + b + c;
    } 

자바에서는 이런 식으로 예시를 들 수 있습니다.

조건은

  1. 메서드 이름이 같아야 함
  2. 매개변수의 개수나 타입이 달라야 함
  3. 반환 타입은 오버로딩을 구분하는 기준이 되지 않음!

이렇게 되겠습니다.

fn add(x: Int, y: Int) -> Int:
    return x + y

fn add(x: Int, y: Int, z: Int) -> Int:
    return x + y + z

fn add(x: Float32, y: Float32) -> Float32:
    return x + y

fn add(x: String, y: String, delimiter: String) -> String:
    return x + delimiter + y

fn main():
    print(add(5, 3))                    # 두 정수의 합: 8
    print(add(1, 2, 3))                 # 세 정수의 합: 6
    print(add(3.14, 2.86))              # 두 실수의 합: 6.0
    print(add("Hello", "World", " "))   # 구분자를 포함한 문자열 연결: "Hello World"

이런식으로 사용할 수 있겠습니다!

2.2 오류 처리#

2.2.1 오류를 발생시키는 함수#

def raises_error():
    raise Error("This is the error")
fn handle_error():
    try:
        raises_error()
    except e:
        print("Handled an error," e) 

fn 함수에서 오류를 발생시키려면 raises 키워드를 사용해야 합니다. raises 키워드가 없는 fn 함수는 오류를 전파할 수 없습니다.

def divide(a: Int, b: Int) -> Float64:
    if b == 0:
        raise Error("0으로 나눌 수 없습니다!")
    return a / b

fn safe_divide(a: Int, b: Int) -> Float64:
    try:
        return divide(a, b)
    except e:
        print("나눗셈 오류 발생:", e)
        return 0.0
fn main():
    print(safe_divide(10, 0)) # 나눗셈 오류 발생: 0으로 나눌 수 없습니다! \n 0.0
    print(safe_divide(10, 1)) # 10.0

이렇게 활용할 수 있겠네요!


포스트가 길어지고, 추가로 다뤄야할 내용이 있어서 파트를 나눠서 하도록 하겠습니다!

go to Part 2

Reference
#

Mojo docs

[Mojo] Function(Part 1)
https://compy07.github.io/Blog/posts/mojo/tutorial/function/p1/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2025-02-07