티스토리 뷰
book 에도 나오는 내용일텐데 그냥 설명하고 싶어졌습니다.
rust 의 enum 에 값 넣기
rust 에서 enum 은 평범하게 다른 언어의 enum 처럼 쓸 수도 있지만,
// rust
enum MyEnum {
A,
B
}
rust 의 enum 에는 값이나 필드를 넣을수도 있습니다.
// rust
enum MyEnum {
A(String),
B(String)
}
엥 kotlin 의 enum class 도 값을 가질 수 있는데요? 거기다 enum 에 들어가는 값에 이름도 지정할 수 있잖아요
// kotlin
enum class MyEnum(var value: String) {
A("야호"),
B("호호")
}
fun main() {
val a = MyEnum.A
a.value += "!!"
println(a.value) // 야호!!
}
rust enum 은 union 같은 거
근데 kotlin 은 enum 의 각 케이스(variant)별로 다른 값을 넣을 수는 없잖아요. A 에는 String, B 에는 i32 처럼 말이죠.
// rust
enum MyEnum {
A(String), // A는 익명의 String 타입 값을 지닙니다. 변수이름.0 으로 접근합니다.
B(i32) // B는... 생략
}
이거 어디서 많이 안 보셨나요? C 의 union 이랑 비슷합니다.
// c lang
union MyStruct {
const char* str;
const int32_t intval;
}
차이점은 런타임에 어떤 케이스(variant)인지 알 수 있다는 것 정도겠네요.
// rust
enum MyEnum {
A(String),
B(i32)
}
fn main() {
let a = MyEnum::A("야호".into());
// 요렇게
if let MyEnum::A(val) = &a { // 아래에서도 쓰려고 "&"a 로 빌려왔습니다.
println!("{}", val); // 야호
}
// 아니면 요렇게
match a {
MyEnum::A(val) => println!("{}", val), // 야호
_ => {}
}
}
런타임에 케이스를 알고있다는 점에서 C 의 union 보다는 차라리 C++의 std::variant 가 비슷해보이네요. 안 써봐서 모르니 이건 예시는 스킵하구요.
kotlin 에서는 "sealed class" 를 사용해서 상속으로 구현이 가능하긴 합니다. 상세한 건 생략하자구요.
값이 없는 케이스(variant) 도 가능
여기에 더해서 아예 한 케이스에는 값이 있고, 다른 한 케이스에는 값이 없는 것도 가능합니다. 아 물론 Struct 처럼 필드의 이름을 지정하는 것도 되구요.
// rust
enum MyEnum
StringCase(String), // 익명의 값 String 이 멤버입니다. 변수이름.0 으로 접근합니다.
EmptyCase,
FieldCase { value_str: String }
}
fn main() {
let string_case = MyEnum::StringCase("야호".into());
let empty_case = MyEnum::EmptyCase;
let field_case = MyEnum::FieldCase { value_str: "야호오오".into() };
if let MyEnum::StringCase(val) = string_case { println!("{}", val); };
if let MyEnum::EmptyCase = empty_case { println!("비었어요"); };
if let MyEnum::FieldCase { value_str } = field_case { println!("{}", value_str); };
}
null 이라는 실수를 없애기 위해 enum 을 사용하다
이렇게까지 필요한가? 하실수도 있습니다. 근데 필요합니다. 이게 바로 rust 가 null 을 없앤 방법이거든요.
rust 에서는 null 대신에 enum Option 을 사용합니다. Option::Some 일 때는 값이 있고, Option::None 일 때는 값이 없죠. 너무 자료구조가 뻔해서 struct 자체는 눈 감고도 어떻게 생겼는지 알 수 있어요.
// rust
pub Option<T> {
Some(T), // 익명의 값 T 가 멤버입니다.
None
}
null 을 반환해야 할 거 같은 많은 API 에서 대신 Option 을 반환합니다.
요건 iterator 의 next() 함수의 문서로 대체할게요. pub fn next(&mut self) -> Option<Self::Item>
처럼 생겼는데 예시가 있으니 꼭 보세요!
// rust - 위 링크의 문서에서 일부 발췌
let a = [1, 2];
let mut iter = a.iter();
assert_eq!(Some(&1), iter.next());
assert_eq!(Some(&2), iter.next());
assert_eq!(None, iter.next());
비슷한 걸로 Result 도 있습니다.
"Option" 은 C++ 에도 있긴 합니다. std::optional 이라구 있어요.
ADT 라고 부른다고?
이건 아마 함수형 프로그래밍 언어들의 개념에서 가져온 걸겁니다. 어쩌다가 Haskell 코드를 볼 일이 있었는데 똑같은 목적의 Maybe 라는 클래스? 가 있더라구요. 아마 많은 함수형 언어에 있을겁니다. 이런 자료구조를 대수적 자료구조 (Algebraic Data Type) 라고 부란다고 하더라구요. 뭐 아무렴 어때요, 잘 쓰면 그만이죠!
이거 디게 번거롭다... 어떻게 편하게 써요?
프로그램이 죽어도 상관없다면 unwrap() 이나 expect("나 죽었어요 메시지") 를 써보세요 (Option 에도 Result 에도 있음). 아니면 물음표 연산자나 map_err 같이 각 struct 에서 제공해주는 메서드를 사용해보세요.
(요 부분 쓸 시점에 슬슬 지쳐서 대충 쓰다 말았는데 아마 에러 처리 관련해서 찾아보시면 자세한 글들이 나올 겁니다)
아 좀 후련하다임금님 귀는 당나귀귀
여담인데 최적화를 좋아하는 C++ 여러분들은 nomicon 을 보세요. 으 검색하니 잘 모르는 게 나오는 걸로 봐서 저는 공부를 더 해야 할 거 같네요,,
또 하나 더, enum 이 단순 상수가 아닌 만큼 컨벤션도 전부 대문자로 쓰지는 않는 모양이에요. 코딩 컨벤션 하면 뭐다? 눈치밥 아니겠숨꽈. 제대로된 원칙이 있다면 제일이겠지만...
추가 참고: Rust container cheat sheet (그림이 풍부함), by Raph Levien / 같은 분이 더 나중에 만든 rust cheat sheet (같은 그림이 설명과 함께 있음)
- Total
- Today
- Yesterday
- exercism
- 개발기록
- pleroma
- 토이프로젝트
- 시스어드민
- 쿠버네티스
- 마스토돈
- 왜 생각이 안 났지
- javascript
- 오라클 클라우드
- Godot Engine
- ArchLinuxARM
- ActivityPub
- c++
- 업비트
- C#
- scss
- Sass
- upbit
- rust-lang
- K8s
- 오라클 클라우드 인프라
- OStatus
- pdf.js
- kotlin당했다
- C++ FAQ
- Oracle Cloud Infrastructure
- gitea
- vuex
- mvu
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |