![](https://habrastorage.org/files/01e/b90/7e1/01eb907e1a0345b096f1aab0e7070ca6.png)
ãã®èšäºãæžããçç±ã¯ãSwiftèšèªã®ãœãŒã¹ã³ãŒãã®å ¬éã§ãã-ãããããããç¥ãããšãç§ã«ãšã£ãŠèå³æ·±ããã®ã«ãªããŸããã RustãšåŒã°ããå¥ã®è¥ãããã°ã©ãã³ã°èšèªãšã®æ§æã®é¡äŒŒæ§ã¯ããã«ç§ã®ç®ãåŒããŸããããŸããé¡äŒŒã®æ§ææ§é ã«å ããŠããããã®èšèªã®é¡äŒŒã®å¿çšåéãèŠãããŸããã ã©ã¡ãã®èšèªããããŒã«ã«åæšè«ã«ãã匷åãªéçåä»ããåããŠãããäž¡æ¹ãšããã·ã³ã³ãŒãã«çŽæ¥ã³ã³ãã€ã«ãããŸãã äž¡æ¹ã®èšèªã¯ãé¢æ°åããã°ã©ãã³ã°ã®äžçããå€ãã®ããªãã¯ãåžåããŸããã SwiftãšRustã®äž¡æ¹ã«ãCã§èšè¿°ãããã³ãŒããå®è¡ããããŒã«ããããŸããããã«ãããèšå€§ãªæ°ã®ã©ã€ãã©ãªã®ã©ãããŒãç°¡åã«äœæã§ããŸãã äž¡æ¹ã®èšèªã¯ãCãC ++ãObjectiveCãªã©ã®æ¢åã®ã·ã¹ãã èšèªã®ä»£æ¿ãšèŠãªãããŸãã ããã§ã¯ããããã«å ±éãããã®ãšãäœãéãã®ã§ããããïŒ
æ§æã®åºæ¬
ããã«2ã€ã®ããã°ã©ãã³ã°èšèªã®åºæ¬ãèªè ã«äŒããããšã¯ããŠããªããšèšããªããã°ãªããŸãããäœãäžæãªç¹ãããå Žåã¯ã RustbookãŸãã¯Swiftbookã«åãåãããããšããå§ãããŸãã
æåã«ãæãåçŽãªããã°ã©ã ãæ¯èŒããŠã¿ãŸãããã
ãã³
fn main() { let i:i32 = 16; let mut f = 8.0; f *= 2.0; println!("Hello Rust! within vars {} and {}", i, f); }
ã¹ã€ãã
let i:Int = 10 var f = 15.0 f /= 2 print("Hello Swift within vars \(i) \(f)")
letã¯ãã¡ãã¡ã§åãããšãæå³ããSwiftã®varããŒã¯ãŒãã¯Rustã®let mutã®çµã¿åããã«äŒŒãŠããããšã«æ°ä»ããããããŸããã ãã ããéãããããŸããRustã§ã¯ããã¹ãŠã®æ°å€åã§ãµã€ãºãæ確ã«ç€ºãããŸãããSwiftã¯Cã®äŒçµ±ã«åŸããŸãã ãã®è³ªåã§ã¯ãRustã¯ããäœãã¬ãã«ã®ããã§ãã
Rustã®æååè£éã¯ãprintlnïŒã®è žã§åŒã³åºãããformatïŒããã¯ãã䜿çšããŠè¡ãããŸããSwiftã§ã¯ãããã¯èšèªèªäœã®æ©èœã§ãããåæã«ããã¥ã¡ã³ãã§æžåŒèšå®ãªãã·ã§ã³ãèšå®ããæ¹æ³ãèŠã€ãããŸããã§ããã
ã;ãã®è§£éã®éãã¯èå³æ·±ãã§ããRustã®å Žåãããã¯åŒã®çµããã®å åã§ããããã«ããããšã¬ã¬ã³ããªããšãè¡ãããšãã§ããŸããããšãã°ãé¢æ°å ã®æåŸã®åŒãèªåçã«æ»ãå€ã«ãªããŸãã Swiftã¯ããã¹ã«ã«ã®äŒçµ±ã«åŸããŸããã»ãã³ãã³ã¯ãåãè¡ã§æŒç®åãåçŽã«åé¢ããŸãã
次ã«ã2ã€ã®åŒæ°ã®é¢æ°ãåããããã1ã€ã®é¢æ°ã«å€æããé¢æ°ãäœæããŠã¿ãŸãããã
ãã³
fn apply<F: 'static>(f: F, v1: i32) -> Box<Fn(i32) -> ()> where F: Fn(i32, i32) -> () { Box::new(move |v2| f(v1, v2)) } fn print_sum(a: i32, b: i32) -> () { println!("Rust: sum a and b is {}", a + b); } fn main() { let a = 2; let b = 5; print_sum(a, b); let f = print_sum; let f2 = apply(f, b); f2(a); }
ãã°ãã
func apply(f: (_: Int, _: Int) -> (), _ v1: Int) -> (_: Int) -> () { return {(c: Int) -> () in return f(v1, c) } } func print_sum(a: Int, second b: Int) -> () { print("Swift: sum a and b is \(a+b)") } let a = 2; let b = 5; print_sum(a, second:b) let f2 = apply(print_sum, b) f2(a)
ããã§éãã¯ãã§ã«é¡èã§ãããããSwiftã®ååä»ããã©ã¡ãŒã¿ãŒã®å€éšåãRustã®äžè¬åãªã©ã®çŽç²ã«æ§æäžã®éããé€å€ããããã«éèŠãªéããæ€èšããŸãã Swiftã®ã¢ãããŒãã¯æããã«é«ã¬ãã«ã§ããã³ã³ãã€ã©ãŒã¯çµæã®é¢æ°ãä¿åããæ¹æ³ã決å®ããŸããã移åããã¯ããŒãžã£ãŒã¯ç¡æ¬¡å åã§ãããããRustãããã¯ã¹ã«æ瀺çã«ããã¯ããå¿ èŠããããŸããã
誰ã®ã©ã ãé¢æ°ãéããã確èªããŸãããïŒ
ãã³ãããŒã¯ã³ãŒã
ãã³
ãã°ãã
fn apply<F: 'static>(f: F, v1: i32) -> Box<Fn(i32) -> i32> where F: Fn(i32, i32) -> i32 { Box::new(move |v2| f(v1, v2)) } fn make_sum(a: i32, b: i32) -> i32 { a + b } fn main() { let a = 2; let b = 5; let c = make_sum(a, b); println!("Rust: c is {}", c); let f2 = apply(make_sum, b); let mut d = 0; for i in 0..1000000000 { d = f2(i); } println!("Rust: d is {}", d); }
ãã°ãã
func apply(f: (_: Int, _: Int) -> Int, _ v1: Int) -> (_: Int) -> Int { return {(c: Int) -> Int in return f(v1, c) } } func make_sum(a: Int, second b: Int) -> Int { return a + b } let a = 2; let b = 5; let c = make_sum(a, second:b) print("Swift: c is \(c)") let f2 = apply(make_sum, b) f2(a) var d = 0; for i in 0...1000000000 { d = f2(i); } print("Swift: d is \(d)");
æçµçµæïŒRustã§4.0ç§ãSwiftã§1.17ã ããæœè±¡çãªã³ãŒãã®å Žåãã³ã³ãã€ã©ãŒã¯æé©åã®æ©äŒãå€ããªããŸãããruRust / generalãã£ãã«ã§ã¯ãããã»ã©çŸããèŠããªããããããªãã¡ãœããã§ããã³ããã衚瀺ãããŸãããããªããã£ãã€ã¶ãŒã¯ãã¹ãŠãå®å šã«äžããããšãã§ããŸãã æçµçã«ãRustã¯ã³ã³ãã€ã«æã«ã«ãŒãå šäœãèŠã€ããŸãããããã¯éåžžã«ã¯ãŒã«ã§ãã
çç·Žããæã§ãRustã¯äžæè°ãªããšãã§ããŸãã
ã¯ã€ãã¯ããŒãžã§ã³ã³ãŒã
struct Curry<'a> { f: &'a Fn(i32, i32) -> i32, v1: i32 } impl<'a> Curry<'a> { fn new<F: 'static>(f: &'a F, v1: i32) -> Curry<'a> where F: Fn(i32, i32) -> i32 { Curry { f: f, v1: v1 } } fn call(&'a self, v2: i32) -> i32 { (*self.f)(self.v1, v2) } } fn make_sum(a: i32, b: i32) -> i32 { a + b } fn main() { let a = 2; let b = 5; let c = make_sum(a, b); println!("Rust: c is {}", c); let borrow = &make_sum; let f2 = Curry::new(borrow, b); let mut d = 0; for i in 0..1000000000 { d = f2.call(i); } println!("Rust: d is {}", d); }
åæãšãã¿ãŒã³ãããã³ã°ïŒ
äž¡æ¹ã®èšèªã«ã¯ããã¿ãŒã³ãããã³ã°ã®å€§ããªå¯èœæ§ããããŸã;äž¡æ¹ã®èšèªã«ã¯ã代æ°ããŒã¿åããããŸãã ãããã®æ©èœã䜿çšããç°¡åãªäŸãäœæããŠã¿ãŸããããæ°åŠæŒç®ãå®è£ ããŠã¿ãŠãã ããã ãããè¡ãã«ã¯ã転éãååž°çã«ããå¿ èŠããããŸãã ããŒãã¹ãšããŠããããã³ã«ïŒç¹æ§ïŒã䜿çšããŠãæäœã®ååãç»é¢ã«å°å·ããããšããŸãã
ãã³
enum MathOperation { Value(i32), Sum(Box<MathOperation>, Box<MathOperation>), Mul(Box<MathOperation>, Box<MathOperation>) } trait HasName { fn name(&self) -> &'static str; } impl HasName for MathOperation { fn name(&self) -> &'static str { match *self { MathOperation::Value(..) => "Value", MathOperation::Sum(..) => "Sum", MathOperation::Mul(..) => "Mul" } } } impl MathOperation { fn solve(&self) -> i32 { match *self { MathOperation::Value(i) => i, MathOperation::Sum(ref left, ref right) => left.solve() + right.solve(), MathOperation::Mul(ref left, ref right) => left.solve() * right.solve() } } } fn main() { let op = MathOperation::Sum(Box::new(MathOperation::Value(10)), Box::new(MathOperation::Mul(Box::new(MathOperation::Value(20)), Box::new(MathOperation::Value(2))))); ; println!("Rust: op is {} solved {}", op.name(), op.solve()); }
ã¹ã€ãã
enum MathOperation { case Value(Int) indirect case Sum(MathOperation, MathOperation) indirect case Mul(MathOperation, MathOperation) func solve() -> Int { switch self { case .Value(let value): return value case .Sum(let left, let right): return left.solve() + right.solve() case .Mul(let left, let right): return left.solve() * right.solve() } } } protocol HasName { func name() -> String; } extension MathOperation : HasName { func name() -> String { switch self { case .Value(_): return "Value" case .Sum(_, _): return "Sum" case .Mul(_, _): return "Mul" } } } let op = MathOperation.Sum(MathOperation.Value(10), MathOperation.Mul(MathOperation.Value(20), MathOperation.Value(2))) print("Swift: op is \(op.name()) solved \(op.solve())");
Rustã§ã¯ãååž°çãªåæãæŽçããããã«ãããã¯ã¹ã³ã³ãããŒã«ããã¯ããå¿ èŠããããŸããããµã€ãºã¯ä»»æã§ãããã³ã³ãã€ã«æ®µéã§ããã«å¿ èŠãªã¡ã¢ãªéãããããªãããã§ãã Swiftã¯éæ¥çãªåèªã䜿çšããŠååž°çãªåæãæããŸããããã®ã¡ã¢ãªã¢ãã«ãèãããšãçåãçããŸãïŒã³ã³ãã€ã©ã¯ã¡ã¢ãªãå²ãåœãŠãæ¹æ³ãç解ã§ããŸãããïŒ ã©ããããã®ããŒã¯ãŒãã¯ããã®äººã«ãšã£ãŠããå¯èœæ§ãé«ããšæãããŸãã
ãŸããååãšããŠimplãšextensionãã»ãŒåãäœæ¥ãå®è¡ããã¿ã€ãããããã³ã«ã«äŒŒãŠããããšãããããŸãã ããããSwiftã§ã¯ãã¢ãããŒãã¯ãã劥åçã§ããã¡ãœãããæ¡åŒµæ©èœãšããŠè¿œå ããå¿ èŠã¯ãªãããªã¹ã宣èšã§çŽæ¥æå®ã§ããŸãã
次ã«ããã¿ãŒã³ãããã³ã°ã®äŸãããã€ãèŠãŠã¿ãŸãããã
Rust ïŒäŸã«ããRustã®äŸïŒ
match some_value { Ok(value) => println!("got a value: {}", value), Err(_) => println!("an error occurred"), } enum OptionalTuple { Value(i32, i32, i32), Missing, } let x = OptionalTuple::Value(5, -2, 3); match x { OptionalTuple::Value(..) => println!("Got a tuple!"), OptionalTuple::Missing => println!("No such luck."), } let x = 1; match x { 1 ... 5 => println!("one through five"), _ => println!("anything"), } let x = 1; match x { e @ 1 ... 5 => println!("got a range element {}", e), _ => println!("anything"), }
Swift ïŒSwiftbookããååŸãããµã³ãã«ã³ãŒãïŒ
let count = 3000000000000 let countedThings = "stars in the Milky Way" var naturalCount: String switch count { case 0: naturalCount = "no" case 1...3: naturalCount = "a few" case 4...9: naturalCount = "several" case 10...99: naturalCount = "tens of" case 100...999: naturalCount = "hundreds of" case 1000...999999: naturalCount = "thousands of" default: naturalCount = "millions and millions of" } print("There are \(naturalCount) \(countedThings).") // "There are millions and millions of stars in the Milky Way." let somePoint = (1, 1) switch somePoint { case (0, 0): print("(0, 0) is at the origin") case (_, 0): print("(\(somePoint.0), 0) is on the x-axis") case (0, _): print("(0, \(somePoint.1)) is on the y-axis") case (-2...2, -2...2): print("(\(somePoint.0), \(somePoint.1)) is inside the box") default: print("(\(somePoint.0), \(somePoint.1)) is outside of the box") }// "(1, 1) is inside the box let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): print("on the x-axis with an x value of \(x)") case (0, let y): print("on the y-axis with ay value of \(y)") case let (x, y): print("somewhere else at (\(x), \(y))") } // "on the x-axis with an x value of 2
ããã§ã¯ãäžè¬çã«ããã¹ãŠãéåžžã«äŒŒãŠããŸãã æ¯èŒã«ãã£ããããªãã¯ãã§ããå€ã®ç¯å²ãæå®ã§ããŸããå€ããã€ã³ãã§ããæ¯èŒã§ã¿ãã«ã䜿çšã§ããŸãã Rustã§ã¯ãäžèŽæã«æ§é å šäœã䜿çšããããšãã§ããŸãã ããããifãšwhereã§è¿œå ã®æ¡ä»¶ãæå®ã§ããŸãã ãããåæã«ãSwiftã«ã¯è¿œå ã®ãããŒå¶åŸ¡æŒç®åããããŸãã ãããã䜿çšããã®ãè¯ãã¢ã€ãã¢ãã©ããã¯ããããŸãããã
ããçŸå®çãªäŸ
Bresenhamã©ã¹ã¿ãŒåã¢ã«ãŽãªãºã ãèšè¿°ããŠã¿ãŸãããã éåžžã®åœ¢åŒã§ã¯ãªããn次å ãã¯ãã«ã®åœ¢åŒã§å®æ°ã䜿çšããŸããã ããã¯ãã¹ãŠãã³ã³ãã¥ãŒã¿ã°ã©ãã£ãã¯ã¹ã®çæã³ãŒã¹ãå匷ãããšãã«åœ¹ç«ã¡ãŸãã
ãŸãã3次å ãã¯ãã«ãäœæããŠãã€ã³ããã¯ã¹ã®ååŸãšæ¯èŒã®æäœã決å®ããŠã¿ãŠãã ããã
ãã³
#[derive(Copy, Clone, PartialEq)] struct Vec3 { x: i32, y: i32, z: i32 } impl Index<usize> for Vec3 { type Output = i32; fn index<'a>(&'a self, i: usize) -> &'a Self::Output { match i { 0 => &self.x, 1 => &self.y, 2 => &self.z, _ => panic!("Wrong index"), } } } impl IndexMut<usize> for Vec3 { fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Self::Output { match i { 0 => &mut self.x, 1 => &mut self.y, 2 => &mut self.z, _ => panic!("Wrong index"), } } }
ãã°ãã
struct Vector3 { var x: Int; var y: Int; var z: Int; subscript(i: Int) -> Int { get { precondition(i >= 0 && i < 3, "Index out-of-bounds") switch i { case 0: return self.x case 1: return self.y case 2: return self.z default: return 0 } } set { precondition(i >= 0 && i < 3, "Index out-of-bounds") switch i { case 0: self.x = newValue case 1: self.y = newValue case 2: self.z = newValue default: break } } } } func == (left: Vector3, right: Vector3) -> Bool { return (left.x == right.x) && (left.y == right.y) && (left.z == right.z) } func != (left: Vector3, right: Vector3) -> Bool { return !(left == right) }
å®éãRustã§ã¯ãæŒç®åã¯ç¹æ§ãä»ããŠå®è£ ãããŸããæ§é äœãã€ã³ããã¯ã¹ç¹æ§ãå®è£ ããå Žåã[]æŒç®åã䜿çšã§ããŸããSwiftã§ã¯ãã€ã³ããã¯ã¹ãååŸããæŒç®åã¯ããŒã¯ãŒãæ·»ãåã䜿çšããŠèšè¿°ãããç¹å¥ãªåææ¡ä»¶ãè¿œå ã§ããŸãã Rustã¯éåžžã®ã¢ãµãŒã·ã§ã³ã«äŸåããŠããŸãã ä»ã®æŒç®åã®å ŽåãSwiftã䜿çšãããšãæ¢åã®æŒç®åãåå®çŸ©ããããã«ç¬èªã®åªå 床ãçµåæ§ã瀺ãå®çŸ©ãè¡ãããšãã§ããŸãã ããã¯ãã¹ãŠãæ°åŠã©ã€ãã©ãªãäœæãããšãã«éåžžã«åœ¹ç«ã¡ãã³ãŒããå ã®æ°åŠåŒã«ããé¡äŒŒãããŸãã ãã ããRustã¯ãderivå±æ§ãä»ããŠäžéšã®ã¿ã€ãã®å®è£ ãèªåçã«äœæã§ããŸããããã«ãããå€ãã®ããããªã±ãŒã¹ã§ã³ãŒããèªåã§èšè¿°ããããšãåé¿ã§ããŸãã
次ã«ãã€ã³ããã¯ã¹æŒç®åã䜿çšããŠä»»æã®ãã¯ã»ã«ã®è²ã«ã¢ã¯ã»ã¹ã§ããããã«ãç»åãä¿åããããã®äŸ¿å©ãªãããã¡ãŒãäœæããŠã¿ãŸãããã åæã«ããã¯ã»ã«ããããç°ãªãè²æ·±åºŠã«å¯Ÿå¿ã§ãããšããèŠä»¶ãæå±ãããããäžè¬åããããšã«ããŸãã
éã³
struct GenericPixmap<T> { w: usize, h: usize, data: Vec<T> } impl<T> GenericPixmap<T> where T: Copy + Clone { fn new(w: usize, h: usize, fill_value: T) -> GenericPixmap<T> { GenericPixmap { w: w, h: h, data: vec![fill_value; w*h] } } } impl<T> Index<usize> for GenericPixmap<T> where T: Copy + Clone { type Output = [T]; fn index<'a>(&'a self, i: usize) -> &'a Self::Output { let from = i*self.w; let to = from+self.w; &self.data[from..to] } } impl<T> IndexMut<usize> for GenericPixmap<T> where T: Copy + Clone { fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Self::Output { let from = i*self.w; let to = from+self.w; &mut self.data[from..to] } } type Pixmap = GenericPixmap<u32>;
ãã°ãã
struct GenericPixmap<T> { let w: Int let h: Int var data: [T] init(width: Int, height: Int, fillValue: T) { self.w = width self.h = height self.data = [T](count: w*h, repeatedValue: fillValue) } func indexIsValid(x: Int, _ y: Int) -> Bool { return x >= 0 && x < w && y >= 0 && y < h } subscript(x: Int, y: Int) -> T { get { precondition(indexIsValid(x, y), "Index out-of-bounds") return data[x * y + y] } set { precondition(indexIsValid(x,y), "Index out-of-bounds") data[x * y + y] = newValue } } } typealias Pixmap = GenericPixmap<UInt32>
Rustã®äžè¬åã®ã«ãŒã«ã¯ããå³å¯ã§ããããã³ãã¬ãŒãã¿ã€ããç¬èªã®ã³ããŒãã³ããŒããã³äœæã§ããå¿ èŠãããããšãæ瀺çã«ç€ºãå¿ èŠããããŸãã Swiftã§ã¯ãæ§é äœãã£ãŒã«ãã«å¯ŸããŠããã®å¯å€æ§ãæ瀺çã«èšå®ã§ããŸãã initããŒã¯ãŒãã«ã泚ç®ã§ããŸãã ããã¯ã¯ã©ã¹ãŸãã¯æ§é ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ããããããã®ããã€ããååšããå¯èœæ§ãããããããã¯äºãã«åãå§ä»»ã§ããŸãã çµæãšããŠãããã¯ããªãè€éã§å€æ®µéã®ããã»ã¹ã«å€æãããŸãããããã§ãåã¡ã³ããŒãåæåãããããšãæ£ç¢ºã«ä¿èšŒããŸãã Rustã§ã¯ãéçé¢æ°newã«ãã£ãŠãªããžã§ã¯ããäœæãããšããçšèªããšã®åæåãšåæããããŸãã ããã»ã¹ãè€éã«ãªããšäºæ³ãããå Žåã¯ãå·¥å Žã䜿çšããããšããå§ãããŸãã éçé¢æ°ã«é¢ããŠã¯ããã®æå³ã§ã®Rustã®æ§æã¯pythonã®äŒçµ±ã«åŸããŸãããSwiftã¯C ++ã§ãã
Swiftã®ã€ã³ããã¯ã¹æŒç®åã¯ä»»æã®åã®åŒæ°ãããã€ã§ãåãããšãã§ããã®ã§ãé åã®ç¹å®ã®èŠçŽ ãããã«åãåãæŒç®åãæžãããšãã§ããŸãããRustã§ã¯ã¹ã©ã€ã¹ãäœæããå¿ èŠããããŸãã
次ã«ãããã»ã¹èªäœã®å®è£ ãèããã«æç»ã§ããCanvasãã¬ã€ããäœæããŸãããã
éã³
trait Canvas { fn set_pixel(&mut self, x: usize, y:usize, color:u32); } impl Canvas for Pixmap { fn set_pixel(&mut self, x: usize, y:usize, color:u32) { self[x][y] = color; } }
ãã°ãã
protocol Canvas { func setPixel(x: Int, _ y: Int, color: UInt32); } class MyCanvas : Canvas { var pixmap: Pixmap init(width: Int, height: Int, fillValue: UInt32) { self.pixmap = Pixmap(width:width, height:height, fillValue:fillValue) } func setPixel(x: Int, _ y: Int, color: UInt32) { pixmap[x, y] = color } }
æ®å¿µãªãããGenericPixmapåã®æ¡åŒµæ©èœãå®è£ ããæ¹æ³ããã°ããç解ã§ããªãã£ããããSwiftã®Rustãšã¯ç°ãªãããããã³ã«ãªã©ããç¶æ¿ã§ããCanvasãããã³ã«ãå®è£ ããæ°ããMyCanvasã¯ã©ã¹ãäœæããããšã«ããŸããã
次ã«ãæãèå³æ·±ãã®ã¯ããã¬ãŒã³ãã ã¢ã«ãŽãªãºã ã®å®è£ ã§ãã ãã€ã³ãïŒx1ãy1ãz1ïŒãããã€ã³ãïŒx2ãy2ãz2ïŒã«ç·ãåŒãããã®ã§ãæ¹åã«ïŒ| x2-x1 |ã| y2-y1 |ã| z2-z1 |ïŒã¹ããããèžãå¿ èŠããããŸãã ãåŒã®ç¬Šå·ïŒx2-x1ãy2-y1ãz2-z1ïŒã«äŸåããŸãã
ãããã£ãŠãæ¹åïŒsxãsyãszïŒã§ïŒrxãryãrzïŒã¹ããããå®è¡ããå¿ èŠããããŸããããã«ãããæ倧æ°ã®ã¹ããããäœæããå¿ èŠããã軞ãèŠã€ãããŸãã åã¹ãããã§ã®å€äœã¯ïŒrx / r [maxãry / r [max]ãrz / r [max]ïŒã«çãããã¹ãããã¯ç·å€äœdã1ãã倧ãããªã£ãå Žåã«ã®ã¿çºçãã軞ã«æ²¿ã£ãŠã¹ããããäœæãããŸããç·å€äœæ§é€ãŠãããã ããã¯ïŒ
d[i] += r[i] / r[max] if d[i] >= 1 { r[i] -= s[i]; d[i] -= 1; }
æ¡ä»¶ã«rmaxãæãããšãé€ç®æäœãè¡ããªããŠãããããšãããããŸãã
d[i] += r[i] if d[i] >= r[max] { r[i] -= s[i]; d[i] -= r[max]; }
ãã®çµæããã®ã¢ã«ãŽãªãºã ã®å€åœ¢ã¯ãä»»æã®æ°ã®åº§æšã§æ©èœããæµ®åå°æ°ç¹æŒç®ãåé¿ããŸããããã¯ãã»ãšãã©ã®å ŽåãæŽæ°ã«ããæŒç®ãããé«äŸ¡ã§ãã
ãšã³ãããŒãaãšbã®éã«äžé£ã®ãã€ã³ããäœæãããžã§ãã¬ãŒã¿ãŒãäœæããŠã¿ãŸãããã ãã®å Žåããã€ã³ãaãã·ãŒã±ã³ã¹ã«å«ãŸããŸãã
éã³
struct RasterState { step: Vec3, d: Vec3, major_axis: usize, } struct LineRasterizer { from: Vec3, to: Vec3, state: Option<RasterState> } impl LineRasterizer { fn new(from: Vec3, to: Vec3) -> LineRasterizer { LineRasterizer { from: from, to: to, state: None } } fn next_point(&mut self) -> Option<Vec3> { match self.state { None => { let mut state = RasterState { step: Vec3 { x: 0, y: 0, z: 0 }, d: Vec3 { x: 0, y: 0, z: 0 }, major_axis: 0 }; let mut max = 0; for i in 0..3 { let d = self.to[i] - self.from[i]; state.step[i] = if d > 0 { 1 } else { -1 }; let d = d.abs(); if d > max { max = d; state.major_axis = i as usize; }; } self.state = Some(state); Some(self.from) }, Some(ref mut state) => { if self.from == self.to { None } else { let from = self.from; let to = self.to; let calc_residual_steps = |axis| { (to[axis] - from[axis]).abs() }; self.from[state.major_axis] += state.step[state.major_axis]; let rs_base = calc_residual_steps(state.major_axis); for i in 0..3 { let rs = calc_residual_steps(i); if rs > 0 && i != state.major_axis { state.d[i] += rs; if state.d[i] >= rs_base { state.d[i] -= rs_base; self.from[i] += state.step[i]; } } } Some(self.from) } }, } } }
ãã°ãã
class LineRaster { class State { var step: Vector3 var d: Vector3 var majorAxis: Int init() { self.step = Vector3(x: 0, y: 0, z: 0) self.d = Vector3(x: 0, y: 0, z: 0) self.majorAxis = 0 } } var from: Vector3 let to: Vector3 var state: State? init(from: Vector3, to: Vector3) { self.from = from self.to = to } func next_point() -> Vector3? { if let state = self.state { if (self.from == self.to) { return nil } else { let calsResidualSteps = {axis in return abs(self.to[axis] - self.from[axis])} self.from[state.majorAxis] += state.step[state.majorAxis]; let rsBase = calsResidualSteps(state.majorAxis); for i in 0..<3 { let rs = calsResidualSteps(i); if rs > 0 && i != state.majorAxis { state.d[i] += rs; if state.d[i] >= rsBase { state.d[i] -= rsBase; self.from[i] += state.step[i]; } } } return self.from } } else { let state = State() var max = 0; for i in 0..<3 { let d = self.to[i] - self.from[i]; state.step[i] = d > 0 ? 1 : -1; let da = abs(d); if da > max { max = da; state.majorAxis = i; }; } self.state = state return self.from } } }
ãžã§ãã¬ãŒã¿ãŒã®ç¶æ ããªãã·ã§ã³ã®å€ã®åœ¢åŒã«ããããšã«ããŸãããããã«ãããè¿œå ã®ãã©ã°ãå¿ èŠãšããã«ããžã§ãã¬ãŒã¿ãŒããéå§ç¹ãç°¡åãã€å³åº§ã«è¿ãããšãã§ããŸãã Rustã§ã¯ããªãã·ã§ã³å€ã¯åã«enum Optionã§äœæãããŸãããSwiftã§ã¯ãããã¯èšèªã®äžéšã§ãããããæ§æäžã®ãã€ãºãããŸããªãããªãã·ã§ã³ã®ã³ãŒã«ãã§ãŒã³ãç°¡åã«èšè¿°ã§ããŸãã
Rustã¯ãåç §ã«ãã£ãŠåæããStateãåçšããŠããããšãäŒããããã«ãé«åºŠãªæææš©ã·ã¹ãã ã䜿çšããŠããŸããããŒã¯ãŒãrefãèšè¿°ããå¿ èŠããããŸãã Swiftã§ã¯ãç¶æ ã¯ããã©ã«ãã§åç §ããŒã¿åã§ãããèšèªã§ã¯ç§»åã®ã»ãã³ãã£ã¯ã¹ããŸã 芳å¯ãããŠããªããããäœãå¿é ããããšãªãç¶æ ãååŸããã³å±éã§ããŸãã
次ã®ãããªã³ãŒããèšè¿°ããŸãã
while let Some(point) = rasterizer.next_point() { ... }
ç§ã«ã¯ããŸããšã¬ã¬ã³ãã§ã¯ãªãããã§ãããããã¯ã¯ããã«è«ççã«èŠããŸãã
for point in generator { ... }
幞ããªããšã«ãforã«ãŒãã䜿çšããããã«ããžã§ãã¬ãŒã¿ãŒã«ããã€ãã®ã¿ã€ããå®è£ ããã®ã¯éåžžã«ç°¡åã§ãã
éã³
impl Iterator for LineRasterizer { type Item = Vec3; fn next(&mut self) -> Option<Self::Item> { self.next_point() } }
ãã°ãã
extension LineRaster : GeneratorType { func next() -> Vector3? { return self.next_point() } } extension LineRaster : SequenceType { func generate() -> LineRaster { return self } }
ããã«ãSwiftã®å Žåãæ倧2ã€ã®ãããã³ã«ãå®è£ ããå¿ èŠããããŸãããRustã®å Žåã¯1ã€ã§ååã§ãããæ ¹æ¬çãªéãã¯ãããŸããã
ããã©ãŒãã³ã¹ãå°ã枬å®ããŸããã
ã³ãŒãã®å®è¡é床ã¯ãç°ãªãããã°ã©ãã³ã°èšèªãæ¯èŒããéã®éèŠãªèŠçŽ ã®1ã€ã§ãããããã©ãŒãã³ã¹ã枬å®ããã«èšäºãæžãã®ã¯æããªããšã§ãã
åçŽãªæ¯èŒãªãã·ã§ã³ïŒ
éã³
fn test_code(canvas: &mut Canvas) { let a = Vec3 { x: 0, y:0, z:0 }; let b = Vec3 { x: 50, y: 55, z: -20 }; let rasterizer = LineRasterizer::new(a, b); for point in rasterizer { let color = std::u32::MAX; canvas.set_pixel(point.x as usize, point.y as usize, color); } } for _ in 0..1000000 { test_code(&mut canvas) }
ãã°ãã
func testCode(canvas: Canvas) -> () { let a = Vector3(x: 0, y:0, z:0) let b = Vector3(x: 50, y:55, z:-20) let raster = LineRaster(from: a, to: b) for point in raster { let color = UInt32.max canvas.setPixel(point.x, point.y, color: color) } } ... var myCanvas: Canvas = canvas for _ in 0..<1000000 { testCode(myCanvas) }
Canvasãžã®ãªã³ã¯ããã¹ãããé¢æ°ã«æž¡ãã ãã§ãæéã枬å®ããŸãã
Rustã§ã¯0.86ãSwiftã§ã¯5.3ã§ããã Swiftã¯åçãã£ã¹ãããã®ã¬ãã«ã«çãŸã£ãŠããäžæ¹ã§ãRustã¯äœããã®åœ¢ã§åŒã³åºããã€ã³ã©ã€ã³åããå¯èœæ§ããããŸãã ããã確èªããããã«ãäžè¬åãããé¢æ°ãæžããŸãã
éã³
fn test_code_generic<T: Canvas>(canvas: &mut T) { let a = Vec3 { x: 0, y:0, z:0 }; let b = Vec3 { x: 50, y: 55, z: -20 }; let rasterizer = LineRasterizer::new(a, b); for point in rasterizer { let color = std::u32::MAX; canvas.set_pixel(point.x as usize, point.y as usize, color); } }
ãã°ãã
func testCodeGeneric<T:Canvas>(canvas: T) -> () { let a = Vector3(x: 0, y:0, z:0) let b = Vector3(x: 50, y:55, z:-20) let raster = LineRaster(from: a, to: b) for point in raster { let color = UInt32.max canvas.setPixel(point.x, point.y, color: color) } }
Rustã®çµæã¯0.83ã§ããããSwiftã®4.94ãšæ¯èŒãããšãSwiftã®æ¹ãã³ãŒããæé©åã§ããããšãããããŸãããä»ã®ã©ããã«ããã«ããã¯ãèŠã€ãããŸããã§ããã
次ã«ãCanvasãããã¯ã¹ã«ããã¯ããŠã¿ãŸããããSwiftã«ã¯ãinout修食åã䜿çšããŸããããã¯ãå¹æãïŒmutã«äŒŒãŠããŸãã
éã³
fn test_code_boxed(canvas: &mut Box<Canvas>) { let a = Vec3 { x: 0, y:0, z:0 }; let b = Vec3 { x: 50, y: 55, z: -20 }; let rasterizer = LineRasterizer::new(a, b); for point in rasterizer { let color = std::u32::MAX; canvas.set_pixel(point.x as usize, point.y as usize, color); } }
ãã°ãã
func testCodeInout(inout canvas: Canvas) -> () { let a = Vector3(x: 0, y:0, z:0) let b = Vector3(x: 50, y:55, z:-20) let raster = LineRaster(from: a, to: b) for point in raster { let color = UInt32.max canvas.setPixel(point.x, point.y, color: color) } }
çµæã¯Rustã§0.91ãSwiftã§6.44ã§ãã
ãã¯ã·ã³ã°ã¯ã³ãŒãã®å®è¡ãå°ãé ãããŸããããããã»ã©å€§ããã¯ãããŸããã§ããããinoutã®è¿œå ã¯Swiftã«éåžžã«å€§ããªåœ±é¿ãäžããŸããã ã©ããããã£ã³ãã¹ãžã®ãªã³ã¯ãå€æŽããæ©èœã«ãããæããªããã£ãã€ã¶ãŒã«ãã€ã³ããããŸãã
äžè¬çã«ãRustã¯åæ§ã®ã³ãŒãã£ã³ã°ã¹ã¿ã€ã«ã§ããçç£çã§ãã æææš©ã®æŠå¿µã«ãããã³ã³ãã€ã©ãŒã¯ã³ã³ãã€ã«æ®µéã§ããã°ã©ã ã®æ£åœæ§ããã§ãã¯ããã ãã§ãªããå¿ èŠã§ãªãå Žåã«åç §ã«ãŠã³ã¿ãŒã®äœ¿çšãé¿ããããšãã§ããŸããå察ã«ãå¿ èŠãªå Žåã¯æããã«äœ¿çšããå¿ èŠããããŸãã Swiftã¯ãããã©ã«ãã§ããã¹ãŠã®å Žæã§ã¯ã©ã¹ã®åç §ã«ãŠã³ã¿ãŒã䜿çšããŸãããããã¯å€ãã®å Žåããã©ãŒãã³ã¹ã®äœäžã«ã€ãªãããŸããã³ã³ãã€ã©ãŒãããã€ãã®äºçŽ°ãªã±ãŒã¹ã§åç §ã«ãŠã³ããåé€ã§ãããšããŠãããããã«è€éãªã±ãŒã¹ã§å®è¡ã§ããããšãä¿èšŒããŸããã Rustã¯ã³ãŒããã³ã³ãã€ã«ããŸããã ããã¯ãã³ã³ãã€ã©ã®æç床ãšããã«å«ãŸããæŠå¿µã®æå¹æ§ã®äž¡æ¹ã瀺ããŠããŸãã
çµè«ãšããŠãRustãšSwiftãå€ãC ++ãèæ¯ã«ã©ã®ããã«èŠããããæ¯èŒããããšæããŸãã
ããªãäžè¬çãªãã³ãããŒã¯ã³ãŒã
#include <iostream> #include <vector> #include <cassert> #include <memory> #include <cstdlib> template <typename T> struct GenericPixmap { size_t w, h; std::vector<T> data; GenericPixmap(size_t w_, size_t h_, T fill_data = T()) : w(w_), h(h_), data(w_*h_, fill_data) { } T* operator[] (size_t i) { return &data[i*w]; } }; struct Vec3 { int x, y, z; int& operator[] (size_t i) { assert(i >=0 && i < 3); switch (i) { case 0: return x; case 1: return y; case 2: return z; default: break; } return z; } }; bool operator== (const Vec3 &a, const Vec3 &b) { return ax == bx && ay == by && az && bz; } bool operator!= (const Vec3 &a, const Vec3 &b) { return !(a == b); } struct RasterState { Vec3 step; Vec3 d; size_t majorAxis; }; struct LineRaster { Vec3 from; Vec3 to; bool firstStep; RasterState state; LineRaster(const Vec3 &f, const Vec3 &t) : from(f), to(t), firstStep(true), state{} {} bool next_point() { if (firstStep) { size_t max = 0; for (int i = 0; i < 3; ++i) { auto d = to[i] - from[i]; state.step[i] = d > 0 ? 1 : -1; d = std::abs(d); if (d > max) { max = d; state.majorAxis = i; } } firstStep = false; return true; } else { if (from == to) return false; else { auto calc_rs = [this](auto axis) { return std::abs(to[axis] - from[axis]); }; from[state.majorAxis] += state.step[state.majorAxis]; auto rs_base = calc_rs(state.majorAxis); for (int i = 0; i < 3; ++i) { auto rs = calc_rs(i); if (rs > 0 && i != state.majorAxis) { state.d[i] += rs; if (state.d[i] >= rs_base) { state.d[i] -= rs_base; from[i] += state.step[i]; } } } return true; } } } }; using Pixmap = GenericPixmap<uint32_t>; void test_code(Pixmap &pixmap) { Vec3 a { 0, 0, 0 }; Vec3 b { 50, 55, -20 }; LineRaster raster(a, b); while (raster.next_point()) { const auto &p = raster.from; pixmap[px][py] = 0xFFFFFF; } } int main(int, char **) { Pixmap pixmap(300, 300, 0); Vec3 a { 0, 0, 0 }; Vec3 b { 10, 5, -4 }; LineRaster raster(a, b); while (raster.next_point()) { const auto &p = raster.from; uint32_t color = 0xffffff; pixmap[px][py] = color; std::cout << "C++: point x:" << px << " y:" << py << " z:" << pz << " color:" << color << std::endl; } for (size_t i = 0; i < 1000000; ++i) test_code(pixmap); }
å·çã®éçšã§ãããã€ãã®ã»ã°ã¡ã³ããŒã·ã§ã³ãšã©ãŒãçºçããçµæãååŸããåã«lldbã§ãããã°ããå¿ èŠããããŸããã
Rustã§ã¯0.79ãgccã§ã¯0.31ã
çµæã¯éåžžã«èå³æ·±ããã®ã§ããäžæ¹ã§ãRustã¯clangãšã»ãŒåãé床ã瀺ããŸãããä»æ¹ã§ã¯ãgccã¯åã«ãã¹ãŠãäžåããŸãããã€ãŸããäžè¬ã«ãllvmãã©ãããã©ãŒã ã«ã¯å€ãã®åªåãå¿ èŠã§ããããã®ãã¬ãŒã ã¯ãŒã¯å ã§ã¯ãRustã¯æ¢ã«èåŸã§clangãåžã蟌ãã§ããŸããã€ãŸããããã©ãŒãã³ã¹èŠä»¶ã«éèŠãªã»ã¯ã·ã§ã³ãäœæããããã«æ¢ã«å®å šã«èµ·åã§ããŸãã
å®å šãªãã³ãããŒã¯ã³ãŒãã¯githubã«ãããŸããããã©ãŒãã³ã¹ã®æ¹åã«é¢ããææ¡ã¯åãå ¥ããããŸãã
æ®å¿µãªããšã«ããšã©ãŒåŠçãã€ã³ãã©ã¹ãã©ã¯ãã£ãCãŸãã¯ObjectiveCã³ãŒããšã®éä¿¡ãããããã£ãªã©ãèå³æ·±ããã®ã1ã€ã®èšäºã§ãã¹ãŠèæ ®ããããšã¯å°é£ã§ãããä»åŸãããã«è§Šããããšãã§ããããšãé¡ã£ãŠããŸãã
çµè«
Swiftã®éçºè ã¯ãå€ãã®æ§æç³ãèšèªã«è¿œå ããããšã«ãããã³ãŒãã®èªã¿åãã«ããå€ãã®æéãè²»ãããŸãã Rustã¯ãã®åé¡ã§ããçŠæ¬²çã§ããšã³ãã£ãã£ã®æ°ãæå°éã«æããããšããŸãããã ãããã¯ããŸãã¯ãã©ã°ã€ã³ã䜿çšããŠã³ã³ãã€ã©ã«å€ãã®ãã®ãè¿œå ã§ããŸããå¹æçãªãŒãã³ã¹ãã®æœè±¡åã«ãããRustã³ãŒãã®çç£æ§ã¯åäžããŸãããç解ãé£ãããªããŸãã Swiftã䜿çšãããšãã¡ã¢ãªç®¡çã«ããŸã泚æãæããã«ããã°ã©ã ãäœæã§ããŸãããã³ãŒãã¯éåžžã«å¹æçã§ããããã®ç¹ã§ã¯Rustã«å£ããŸãã
ã€ã³ãã©ã¹ãã©ã¯ãã£ã«é¢ããŠã¯ãSwiftã«ã¯åªããXcode IDEããããŸãããOS Xã§ã®ã¿äœ¿çšå¯èœã§ãããCocoaãã€ã³ãã£ã³ã°ã¯iOSãŸãã¯OS Xçšã®ã°ã©ãã£ã«ã«ã¢ããªã±ãŒã·ã§ã³ãèšè¿°ããã³ãªãªãŒã¹ã§ããããã«ãªããŸãããRustã¯ãcargoããã³crates.ioèšå€§ãªæ°ã®ã©ã€ãã©ãªãšã¢ããªã±ãŒã·ã§ã³ãååšããéçºãããŠããŸããããããŸã§ã®ãšãããéçºãããIDEãåªããGUIãã¬ãŒã ã¯ãŒã¯ããããŸããã
æ®å¿µãªãããSwiftã«ã¯ãŸã Grand Central Dispatchã«ãããã€ãã£ããµããŒãããªãããããã«ãã¹ã¬ããããã°ã©ãã³ã°ã«ã€ããŠã¯äœãèšããŸããããRustã®ã¢ãããŒãã«ãããé«éã§ä¿¡é Œæ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸããå³å¯ãªã³ã³ãã€ã©ã¯ãåæãšã©ãŒããããªããåã«æããŸãã
Swiftã®æ±äººã¯ã¯ããã«å€§ãããªããåŠç¿ã容æã«ãªããŸããããããã¯Rustã®ã¹ãã·ã£ãªã¹ããè¿ãå°æ¥ã«éèŠããªããšããæå³ã§ã¯ãããŸãããäžçã«ã¯ããããã®èšèªã®äž¡æ¹ã容赊ãªãäºãã«ç«¶åããå€ãã®åé¡ããããšæããŸãã
ããšãã
Rustã¯åŠ¥åãèš±ããçŠæ¬²çã§ããLightåŽã«æå©ã§ããSwiftã¯ãã®æ§æç³ãDarkåŽã«æã¡èŸŒãããšãã§ããŸãã
æŽæ°ãã
ãŠãŒã¶ãŒYarryããã«ãªã¯ãšã¹ããéä¿¡ããŸãããããã«ãããã¯ã©ã¹ãæ§é äœã«çœ®ãæããããšã§ãSwiftããŒãžã§ã³ãååã«é«éåããããšãã§ããŸãããSwiftã®æ§é äœã¯Cã®äžçã®å¯Ÿå¿ç©ãšããŠåäœããã¹ã¿ãã¯äžã§éç«ã£ãŠãããé¢æ°ã«æž¡ããããšãã«ãªã³ã¯ãã³ããŒãããããããªã³ã¯ãã«ãŠã³ãããå¿ èŠã¯ãããŸããããããåæã«ãSwiftã®ããã¥ã¡ã³ãã§ã¯ãå®éã«ã¯ãã³ããŒã¯å¿ èŠãªå Žåã«ã®ã¿çºçãããšäž»åŒµããŠããŸãããããã£ãŠããã®ãããªåŸ®åŠãªç¥èããããšãã³ãŒããå€§å¹ ã«é«éåã§ããŸããäžæ¹ãRustã§ã¯ãåŠç¿æ²ç·ãããæ¥ã«ããŸãããæ瀺çã«èããããšãäœåãªããããŸããããããã¡ã€ãªã³ã°ãããããçš®é¡ã®å®éšã§ã³ãŒããæé©åããæéãæžããå¿ èŠããããŸãã