기초

기초 에서 Julia

2개의 연습 문제

기초 소개

Julia는 동적이면서 강타입인 프로그래밍 언어예요. 프로그래밍 스타일은 주로 함수형이지만, Haskell 같은 언어보다 더 유연해요.

강력하고 다재다능한 타입 시스템이 있고, 이 시스템은 뒤의 개념에서 중요해져요. 실제로 Julia는 보통 문맥에서 알맞은 기본값을 추론해요.

읽기 쉬운 데 중점을 두어 Python이나 Ruby 같은 스크립트 언어처럼 보이지만, Julia 코드는 실행 전에 컴파일돼요. Just In Time (JIT) 컴파일러는 각 함수를 만날 때마다 고도로 최적화된 코드를 만들어 내서, 실행 속도가 빨라요.

Julia는 객체 지향 언어가 아니고, 다른 많은 언어에서 핵심적인 클래스 계층 구조도 없어요.

대신 (이 부분을 읽으면서 놀라지 마세요!), Julia는 다음에 기대요:

  • 타입 계층 구조.
  • 합성 가능한 함수 (다양하고 강력한 방식으로 쉽게 조합하도록 설계된 함수).
  • 다중 디스패치: 함수를 다양한 개수와 타입의 인자로 호출할 수 있다는 뜻이에요.

이 다소 혼란스러운 용어들은 교육 과정을 진행하면서 더 분명해질 거예요.

공식 문서에는 현재 릴리스에 관한 유용한 정보가 많이 담겨 있지만, 초보자에게는 조금 부담스러울 수 있어요.

영상도 있어요:

주석

코드에 주석을 다는 것은 사람이 코드를 읽고 의도를 이해하도록 돕는 데 아주 중요해요. 다른 사람일 수도 있고, 미래의 자신일 수도 있어요. 주석은 (대부분) 컴파일러가 무시해요.

Julia에서는 두 가지 방법을 쓸 수 있어요:

  • 한 줄 주석은 #으로 시작해요
  • 여러 줄 주석은 #=로 시작해서 =#로 끝나요. 중첩도 가능해요.
# This is a single-line comment

x = 3  # This is an inline comment

#=
	Multi-line comments can be used for longer explanations.

	They are especially useful to comment out blocks of code during debugging.
=#

변수와 할당

변수를 만들려면 값만 할당하면 돼요:

julia> myvar = 42  # an integer (in fact, Int64)
42

julia> bigint = 1_234_567_890  # optionally use underscore as digit separator, for readability
1234567890

julia> name = "Maria"  # strings are surrounded by double-quotes ""
"Maria"

할당은 값을 변수에 "묶는" 것이에요.

타입을 지정하는 것은 선택 사항이고, 대개 Julia가 문맥에서 알맞은 기본값을 추론해요.

타입은 Julia에서 중요한 주제예요. 뒤의 개념에서 더 자세히 살펴봐요. 지금은 크게 걱정하지 않는 게 좋아요.

많은 함수형 언어와 달리 Julia에서는 변수를 다시 할당할 수 있고, 변수에 묶인 값과 타입을 모두 자유롭게 바꿀 수 있어요:

julia> myvar = 3
3

julia> myvar = "now a string"
"now a string"

상수

함수 밖에서 만드는 전역 변수는:

  • 허용돼요.
  • 때로는 필요해요.
  • 대개는 권장하지 않아요 (다만 *.jl 파일 안에서만 그렇고, REPL은 다르게 동작해요).

값이 프로그램 전체에서 필요하지만 바뀔 일이 없다면, 대신 상수를 사용해요.

할당 앞에 const 키워드를 붙이면 컴파일러가 더 효율적인 코드를 만들어요.

실수로 const 값을 바꾸려 하면 경고가 나와요:

julia> const answer = 42
42

julia> answer = 24
WARNING: redefinition of constant Main.answer. This may fail, cause incorrect answers, or produce other errors.
24

산술 연산자

산술 연산은 대부분 일반적인 방식대로 동작해요:

2 + 3  # 5 (addition)
2 - 3  # -1 (subtraction)
2 * 3  # 6 (multiplication)
8 / 2  # 4.0 (division)
8 % 3  # 2 (remainder)
2 ^ 3  # 8 (exponentiation)

/를 사용한 나눗셈은 항상 실수 값이 나온다는 점을 기억해요.

이 내용은 뒤의 개념에서 다시 다뤄요. 거기서는 div()나 ÷로 나눗셈의 몫을 잘라 내는 정수 나눗셈과, //로 유리수를 얻는 방법을 설명해요.

함수

최고의 실행 성능을 위해서는 대부분의 코드를 함수 안에 넣는 게 좋아요. 다른 어떤 언어들과 달리, 작은 함수가 많아도 괜찮아요.

Julia에서 이름 있는 함수를 정의하는 방법은 주로 두 가지예요:

  1. function 키워드 사용하기

    function muladd(x, y, z)
        x * y + z
    end
    

    가독성을 위해 4칸 들여쓰기가 관례지만, 컴파일러는 들여쓰기를 무시해요. end 키워드는 꼭 필요해요. Python보다는 Ruby에 가까워요.

    return x * y + z라고 쓸 수도 있다는 점을 기억해요. 하지만 Julia 함수는 항상 마지막으로 평가된 표현식을 반환하기 때문에, return 키워드는 선택 사항이에요. 많은 프로그래머는 의도를 더 분명히 하려고 return을 넣는 쪽을 선호해요.

  2. "할당 형식" 사용하기

    muladd(x, y, z) = x * y + z
    

    이 형식은 함수 본문이 하나의 표현식인 한 줄짜리 함수 정의나 수학 함수에 가장 흔히 사용해요. 할당 형식에서는 return 키워드를 절대 쓰지 않아요.

두 형식은 동등하고 완전히 같은 방식으로 사용하므로, 더 읽기 쉬운 쪽을 고르면 돼요.

함수를 호출할 때는 이름을 쓰고, 함수의 매개변수마다 인자를 전달해요:

# invoking a function
muladd(10, 5, 1)

# and of course you can invoke a function within the body of another function:
square_plus_one(x) = muladd(x, x, 1)

이런 함수를 "이름 있는" 함수라고 부른다는 점에서, "익명" 함수도 있다는 걸 짐작할 수 있어요. 익명 함수는 뒤의 개념에서 다뤄요.

이름 규칙

많은 언어처럼 Julia도 (변수, 함수 등 여러 가지의) 이름이 문자로 시작하고, 그 뒤에 문자, 숫자, 밑줄이 어떤 조합으로든 올 수 있도록 요구해요.

관례상 변수, 상수, 함수 이름은 소문자로 쓰고, 혼동을 피해야 할 때를 빼면 밑줄은 피해요.

그런데 Julia는 유니코드를 전반적으로 사용하므로, "문자"를 꽤 유연하게 해석해요.

영어가 아닌 다른 언어도 지원되고, 이모지도 쓸 수 있어요 (다만 센스 있게, 어울리는 걸 골라 주세요).

특히 수학자들이 사랑하는 그리스 문자를 모두 쓸 수 있어요 (그리고 유용한 값 몇 개는 미리 정의되어 있어요):

julia> π   # a built-in constant
π = 3.1415926535897...

REPL, Pluto.jl, Julia 플러그인을 설치한 VS Code 같은 Julia를 잘 아는 편집기에서는 이런 문자를 쉽게 입력할 수 있어요.

π는 \pi를 입력한 다음 <Tab>을 누르면 돼요. 입력한 내용이 그리스 문자로 바뀌어요.

이런 예시는 뒤의 개념에서 훨씬 더 많이 볼 수 있어요.

사실 백슬래시 약어는 Julia만의 것이 아니에요. 이 약어는 많은 과학자와 엔지니어가 보고서를 쓸 때 거의 매일 사용하는 조판 시스템인 LaTeX에서 가져온 거예요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

기초 배우기