R은 동적 타입 언어라서, 일반적으로 변수의 타입을 지정할 필요가 없어요. 기본 타입은 numeric이고, 보통 배정밀도 부동소수점으로 구현돼요. 32비트 정수를 강제로 사용하려면 L 접미사를 붙여요 (Long의 약자예요).
객체의 "타입"을 알아내는 것은 (역사적인 이유로) 헷갈릴 수 있어요. typeof()와 class() 함수는 비슷하지만, 조금 다른 결과를 반환할 수 있어요:
typeof(50)
#> [1] "double" # more specific: an implementation detail
typeof(50L)
##> [1] "integer"
class(50)
#> [1] "numeric" # less specific: ignores implementation details
class(50L)
#> [1] "integer"
mode()에 대한 언급을 볼 수도 있는데, 이는 typeof()와 비슷해요.
mode()와 storage.mode()는 무시해 주세요. 이들은 하위 호환성을 위해서만 제공돼요.
선호되는 할당 연산자는 <-예요. RStudio에서 작업한다면, 키보드 단축키 Alt-minus로 입력할 수 있어요.
x <- 42
avogadro <- 6.02e23
mystr <- "Hello, World!"
<- 대신 =를 사용하는 것이 항상은 아니지만 대개는 동작하는데, 좋지 않은 스타일이라 권장하지 않아요.
연산자는 대부분 다른 여러 언어와 비슷하지만, %%와 %/%는 좀 더 특이해요. 이 % 문법은 매크로로 구현된 중위 연산자를 호출하는 방식이에요.
2 + 3 # 5
2 - 3 # -1
2 * 3 # 6
2 / 3 # 0.6666667
8 %/% 3 # 2 (integer division)
8 %% 3 # 2 (remainder)
2 ^ 3 # 8 (exponential)
R에서 #은 한 줄 주석을 시작해요. 여러 줄 주석을 위한 별도의 문법은 없어요.
함수를 정의하려면 이렇게 해요:
squareit <- function(x) {
x * x
}
함수는 0개 이상의 인자를 가질 수 있고, 인자는 쉼표로 구분해요. 매개변수가 없더라도 function()에는 괄호 ()가 필요해요.
함수 인자에는 기본값을 지정할 수 있는데, 기본값이 없는 인자들 뒤에 와야 하고, 기본값을 할당할 때는 <-가 아니라 =를 사용해요. 별 의미는 없지만, 예를 들어볼게요:
squareit <- function(x = 42) {
x * x
}
squareit()
#> [1] 1764
한 줄짜리 함수 본문에는 중괄호 { }가 꼭 필요한 것은 아니지만, 포함하는 것이 좋은 스타일로 여겨져요.
R은 위 예시들처럼 함수의 마지막 값을 자동으로 반환해요.
return()은 함수 본문 어디에서든 사용해서 반환값을 명시적으로 만들 수 있어요. 지정한 값을 즉시 반환하고, 함수 본문의 나머지 표현식을 실행하지 않은 채 함수를 종료해요.
return()을 명시적으로 호출하는 것은 보통 함수를 일찍 종료하고 어떤 이유로 특정 값을 반환하고 싶을 때만 필요해요. 예를 들어 if-else 절 안에서 그럴 수 있어요. 다만, 일부 개발자는 코드 스타일상 명시적 반환을 선호하기도 해요.
함수 호출은 다른 여러 언어와 같아요:
squareit(3)
#> [1] 9
앞으로 다룰 개념에서 결과 9가 사실 스칼라 숫자가 아니라 길이가 1인 벡터라는 것을 알게 될 거예요. 그래서 이것이 벡터의 시작임을 나타내기 위해 [1]이 포함돼요.
is.vector(9)
#> [1] TRUE
R에서는 대부분의 것이 일종의 벡터예요!
R 콘솔에서는 위 예시를 이렇게 표시해요:
> squareit(3)
[1] 9
이 학습 자료의 문서들은 대부분 여러 R 교재에서 쓰는 관례를 따라, 프롬프트를 없애고 결과를 주석으로 달아요. 이렇게 하면 코드 예제를 콘솔에 복사해서 붙여넣고 실행하기가 더 쉬워요.