Programming Languages I Write

ตอนนี้เขียนโปรแกรมอยู่หลายภาษา ก็คิดว่าอยากลองเขียนดูบ้างว่าเราคิดว่าจุดแข็งของแต่ละภาษาคืออะไร แล้วเราเลือกใช้มันยังไง

กฎส่วนตัวเราเวลาบอกว่าเขียนภาษานี้ “เป็น” พอจะใส่ใน Resume คือถ้า Ecosystem ในเรื่องนั้นมันพร้อมเราสามารถทำ Task อะไรก็ได้ในภาษานั้นๆ และเขียนออกมา Idiomatic เฉพาะตัวแบบที่ภาษานั้นๆ เขียนอยู่ด้วย

หลักๆ ที่เขียนเลยก็จะมี

  • Python
  • Go
  • JavaScript & TypeScript

ภาษาอื่นๆ ที่เคยเขียนก็จะมี Java, C, C++, Rust, Kotlin, PHP แต่ในบทความนี้คงจะไม่พูดให้ครบทุกอัน

Python

Rule of thumb ตอนนี้คือถ้ามันจะต้องต่อ database เราจะเลือกใช้ Python และ Django เท่านั้น ไม่มีอะไรที่ทำให้เราทำงานเสร็จเร็วเท่า Django อีกแล้ว

นอกจาก Django แล้ว Python ฝั่ง Data Science ก็ค่อนข้างแข็ง แต่เราไม่ค่อยได้ใช้เท่าไร แล้วก็ยังทำ scripting ต่างๆ ได้เร็ว

ข้อเสียของ Python คือมันเป็นภาษาที่ปวกเปียกมาก

Package manager มันอยู่ระหว่าง requirements.txt ที่ใช้ได้แต่ค่อนข้าง manual และไม่มี lock กับ Poetry ที่ยังไม่ดัง (และคนไปเลือกใช้ Pipenv ที่เลิกทำแล้วมากกว่า) และ Virtualenv มันค่อนข้าง Hack หน่อยๆ เมื่อเทียบกับภาษาใหม่ๆ ที่เลิกมี global package repository แล้ว

Import syntax ที่ถ้ามีไฟล์อยู่ folder ข้างๆ จะนั่งงงมากว่าต้อง import ยังไง (มันไม่มี “absolute” import มีแต่ relative โดยใช้ syntax แปลกๆ)

Type checking ที่ยังตั้งไข่มากๆ ถึงจะทำมาหลายปีแล้ว และ syntax ที่มันแปลกๆ หน่อย

Speed ของมันที่ค่อนข้างช้าในการ execute ซึ่งปกติก็จะไม่ค่อยใส่ใจ แต่ก็มีครั้งนึงที่ทำให้พลาดข้อใน Codejam มาแล้วเพราะโค้ดเหมือนกันรันใน Python เกิน 5 นาที ไม่ผ่าน ไปเขียนใหม่ใช้วิธีเดิมใน C รันจบใน 30 วินาที

Web server deployment มันที่ยังต้อง deploy WSGI container เหมือนภาษาโบราณๆ ไม่ใช่ one click และก็จะติดเรื่อง thread pool ที่ต้องมาจูน

JavaScript

ผมไม่ชอบ JavaScript เท่าไรนัก แต่จำเป็นต้องเขียนเพราะมันใช้ได้หลายที่มากๆ มันเป็นภาษาเดียวที่รันได้ใน Browser เวลาจะทำอะไรที่เขียนครั้งเดียวใช้ได้ทุกที่ต้องใช้ JavaScript เลย

ข้อดีของ JavaScript คือ syntax มันค่อนข้างมาตรฐานไม่หวือหวา แล้วพอบวก TypeScript มามันทำให้การ code project ใหญ่ๆ ทำงานงายขึ้นเพราะ editor จะฉลาดขึ้นเยอะ

ข้อเสียของ JavaScript คือภาษามันค่อนข้างฟรีสไตล์และมันไม่เก่ง Class กลายเป็นว่าคนชอบเขียนเป็น functional แต่มันก็ไม่ใช่ภาษาที่ออกแบบเป็น functional มาตั้งแต่แรก โค้ดมันก็เลยเละมาก

แล้วที่ผมไม่ชอบ functional ใน JavaScript มากคือการที่เราเอา higher order function ที่ add functionality ทีละนิด แต่ใช้ซ้อนกันเยอะๆ เวลาไล่โค้ดมันจะงง flow มากว่ามันเข้าแล้วอะไรโผล่เข้ามาตอนไหน รวมถึง syntax มันที่จะเป็น a(b(c(d))) ซึ่งไม่ค่อยเป็นธรรมชาติในการอ่านเพราะ functionality หลักมักจะอยู่ที่ d

นึกภาพว่าถ้า Unix pipe มันเขียนว่า wc(tar('xf', gzcat(file)))ก็คงใช้ลำบากกว่า gzcat file | tar xf - | wc

แล้วการเขียน helper มาทำให้มันกลายเป็นซ้ายไปขวา ก็ทำได้ยุ่งยากใน Javascript เพราะถ้าเราเขียน chain(a, instance.methodB, c, d) this ใน methodB ก็จะผิดอีก ต้องมา bind ก่อน ซึ่งไม่มีภาษาอื่นทำกัน (แล้วผมก็ยังไม่เคยเห็นว่ามี use case ไหนเลยที่จะใช้มันโดยไม่ bind)

สรุปคือมันทำได้ทุกอย่างแต่ไม่เก่งสักอย่าง แต่ก็ยังต้องใช้มันอยู่เพราะใน Browser มันผูกขาด

Node.js

ผมจำไม่ได้ว่าสมัยที่ Node.js เพิ่งมาผมคิดกับมันไว้ยังไง (สมัยนั้นเขียน PHP กับ Web.py) น่าจะไม่ชอบที่เอา JavaScript ไปรันบน server เพราะมันช้า

แต่ในปัจจุบันปรากฏว่ามันเร็วมาก เร็วกว่า Python เสียอีกเพราะ JavaScript ใน browser มีเงินลงทุนมหาศาลจากบริษัทเว็บต่างๆ

ข้อดีของ Node คือ async io ซึ่งมาแรกๆ หลายคนไม่เชื่อว่าไม่ต้องมี application server คั่นหน้าแล้ว เอา Node รับ load ได้ตรงๆ เลย

แต่ข้อเสียของ async io ใน Node คือ syntax มันไม่ค่อยสวยเท่าไรนัก ไม่ว่าจะเป็น Callback หรือ Promise + Await ก็ตามมันก็ไม่ดูดีเท่า Sequential (a().b().c() vs. await (await (await a()).b()).c())

นอกจากนี้เนื่องจาก standard library ที่มีให้ค่อนข้างจำกัด ทำให้เกิด npm ecosystem ที่บูมมากๆ อะไรก็อยู่บน npm ได้หมดแม้แต่ application อย่าง Chromium ก็โหลดผ่าน npm ได้ ข้อเสียก็คือแต่ละคนก็เลือกใช้ lib คนละตัวแตกต่างกันไป รวมถึงพอแยกกัน maintenance คุณภาพก็แตกต่างกันออกไปตั้งแต่ระดับดีมากๆ อย่าง React ไปจนถึง left-pad ที่คนทำอยู่ดีๆ ก็เอาลง

พอ community มันเปิดกว้าง มันก็กลายเป็นว่า project structure เปิดมาแต่ละอันไม่ซ้ำกันเลย เวลาอ่านก็ต้องไปนั่งไล่ก่อนว่าทางเข้าทางออกอยู่ตรงไหนบ้าง แล้วแต่ละคนก็จะทำท่าไม่เหมือนกันเลยเพราะคนไม่ค่อยใช้ Framework (อาจจะมีใช้ Next/Nuxt.js บ้างแต่ก็ไม่ใช่ทุกคนจะชอบ)

ข้อจำกัดอีกเรื่องของ Node คือมันทำอะไรที่ CPU bound ไม่ได้เลยเพราะมันเป็น single thread แถมยังไม่มีวิธีแตก thread เลยแม้แต่วิธีเดียวเนื่องจากมันมี Global lock เหมือน Python (แต่ Python ยังมี multiprocess ให้ใน standard library) แต่คิดว่าเร็วๆ นี้น่าจะมา

ตอนนี้จุดเดียวที่เรายังเลือก Node.js อยู่คือ Socket.io เนื่องจากภาษาอื่นๆ ในยุคก่อนมันทำ Streaming ไม่ได้ (thread pool จะเต็มเอา) พอมาถึงยุคนี้ที่ใครๆ ก็ทำ async แล้วก็เลยโดดข้ามไป WebSocket เลย จะมีแต่ Socket.io เท่านั้นที่ทำได้ทั้ง Long polling และ WebSocket ได้ในเวลาเดียวกัน และใช้โค้ดเดียวกัน

Go

ช่วงที่เขียน Rust ผมบอกว่าจะไม่เขียน Go เดี๋ยวใจแตก แล้วก็เป็นอย่างนั้นจริงๆ

Go แก้ทุกปัญหาของ Node ที่ผมบ่นไว้ด้านบนได้เกือบหมด

ภาษามันเป็น Static typed ในขณะเดียวกัน map เป็น first class data structure ของภาษา ไม่เหมือนภาษายุคก่อนหน้า และมันยังไม่กลัวที่จะใช้ interface{} type

Go มี Standard library + golang.org/x ที่ค่อนข้างดีทำให้ third party ไม่ต้องนั่งตบตีกันว่า HTTP client ต้องใช้ตัวไหน (Go ก็มีให้เลือก แต่ส่วนมากคนก็ยังเชียร์ http.Client ใน standard library อยู่)

Syntax ของภาษาที่เรียบง่ายมากๆ ทีม Go เคยบอกว่าเขียน Go คือเขียนโค้ด ไม่ใช่ไปนั่งเขียน Type

Go มี gofmt และ compiler เองก็เป็น linter ในตัว (no unused variable, enforce ชื่อ function ตัวใหญ่เป็น public เป็นต้น) ทำให้โค้ด Go ไม่ว่า project ไหนส่วนมากก็แทบจะเป็นแบบเดียว

ตั้งแต่เขียนโค้ดมาคิดว่าเรา contribute Go pull request มากที่สุดแล้วถึงจะมาเขียนหลังสุด เพราะมันไม่ต้องกลัวว่า maintainer จะด่าอะไรเราในโค้ดมั้ย

(แอบชอบสไตล์ modulename.FunctionName() ของ Go ด้วย อ่านแล้วมันเคลียร์เลยทันทีว่า function มาจากไหน และตัวใหญ่ทำให้สะดุดตาโดดข้ามไปอ่านง่าย ต่างกับใน JS ที่คนชอบ destructure เอาแต่ functionName มา มันเพิ่ม cognitive load ต้องจำว่าตัวแปรนี้มาจากไหน)

วิธีแก้ปัญหา async แล้ว syntax ไม่สวยของ Go คือเลิกทำ async ทุกอย่างกลายเป็น sync อะไรที่อยากจะรันข้างหลังค่อยสั่งเปิด goroutine ซึ่งเพิ่มแค่คำว่า go ข้างหน้า (เทียบกับ Python thread นี่เขียนกันหลายบรรทัดเลย)

ที่คนเขียน Go อาจจะไม่รู้คือที่เห็น Go เป็น sync จริงๆ ด้านล่างมันก็เป็น async คล้ายๆ กับที่ Node ทำ แล้วมันใช้ scheduler เป็น abstraction ทำให้มันกลายเป็น sync (เหยด!)

แล้ว Go ไม่มี Global lock เหมือน Python หรือ JavaScript มันทำให้ performance ยิ่งดีขึ้นไปอีก แต่ก็อาจจะต้องระมัดระวัง race condition เองมากขึ้น สำหรับเราเราคิดว่ามันตื่นเต้นและเป็นประสบการณ์ที่อยากเรียนรู้ เพราะภาษาอื่นที่เขียนมี global lock หมดเลย

เวลา Deploy Go ก็ทำได้ง่ายกว่าภาษาอื่นๆ มาก เพราะมัน compile มาได้ binary ตัวเดียวใหญ่ๆ (20-200MB) แล้วคลิกเดียวรันได้เลย

ทุกวันนี้เราเลยพบว่ามาเขียน Go บ่อยขึ้นมาก แทบทุกอย่างที่ไม่ต้องแตะ Database ก็จะไปเขียน Go แม้แต่ scripting บางทียังเลือกใช้ Go เพราะมัน Deploy ได้ง่ายกว่าเยอะ

ข้อเสียของ Go คือ module ซึ่งมันมาช้าไปหน่อย และก็ยังออกแบบมาไม่ค่อยดีอยู่ดี ปัญหาที่เห็นคือระบบ versioning ที่ไม่เคลียร์เท่า Node.js และการใช้ URL import ทำให้เวลา fork ต้องแก้ทั้ง project (แล้วเกิดอยากจะ merge กลับจะทำได้ยาก)

Go ไม่มี generic ทำให้บางอย่างทำได้ยาก โดยเฉพาะการ search in array ที่เป็น operator ใน Python แต่ใน Go ต้องนั่งเขียน loop ทุกครั้ง

Go ไม่มี implements ที่เอาไว้เช็คว่า function/struct นี้ satisfy interface แล้วหรือยัง ถ้าไม่ตรง มันจะไป error ตรง call site แทนที่จะ error ที่ struct (ซึ่งลำดับการเขียนโค้ด เรามักจะเขียน struct ให้เสร็จก่อนแล้วค่อยไป create + pass ไปยังคนที่ใช้)

แล้วด้วยความที่มันเป็น static typed ก็คิดว่ายังไม่อยากเอามันไปทำงานที่ใช้ JSON มากๆ เท่าไร

Java

ยังไม่แน่ใจว่าไม่ชอบ Java หรือไม่ชอบ Spring แต่ที่แน่ๆ คือไม่ชอบที่ Java เพราะพยายาม violate YAGNI ทุกวันนี้ยังตั้งคำถามอยู่ว่าถ้าให้เรา rebuild ecosystem Java ให้ใช้ standard เหมือน Python (แต่ไม่แก้ compiler) จะอยากเขียน Java มั้ย

ปัญหาของ Java คือ type system มัน strict เกินไป เวลาจะเพิ่มนิดๆ หน่อยๆ ทำไม่ได้ เช่น ถ้ามี request object แล้วอยากจะฝากข้อมูลไปบน request object ก็ต้องทำ object อีกตัวมาครอบแล้ว delegate เข้าไปใน request (เทียบกับ JavaScript/Python ที่ใช้ req.data ได้เลย หรือ Go ก็มี embed struct ไปบน struct อีกตัว)

คนเขียน Java ก็เลยจะนิยมว่าทำ interface ไว้ให้ทุกอย่าง “เผื่อแก้” data ต่างๆ บน class อื่น ต้องวิ่งผ่าน getter เท่านั้น (ใน Go เรา mutate field บน http.Request กันสนุกเลย)

สองคือภาษามันเก่าแล้วมันไม่มี first class map เหมือนภาษาใหม่ๆ ทำให้ท่าที่จะเขียนโค้ดง่ายขึ้นกลับกลายเป็นโค้ดยุบยับที่อ่านลำบาก

สามคือภาษามันไม่มี first class function & class เวลาส่ง function และ class เข้าไปมันจะฟีลเหมือนเขียน reflection หน่อยๆ ซึ่งทำให้หลายๆ ท่าลำบากในการเขียน

หลายๆ ฟีเจอร์พวกนี้ถูกแก้ด้วย code generation บนภาษาใหม่ๆ เช่น Kotlin, Groovy หรือ Scala ที่ข้างหลังก็ไป generate class ออกมาอยู่ดี

PHP

ตอนเรียนจบ PHP เคยอยู่ใน resume ทุกวันนี้หลายๆ ครั้งก็ยังวิเคราะห์ PHP design อยู่ว่ามันพลาดไปตรงไหน

เราคิดว่า Design ของ PHP ออกแบบมาน่าสนใจ มันเป็นภาษากระแสหลักภาษาเดียวที่ออกแบบมาให้เขียนเว็บเพียงอย่างเดียว

ไม่มีภาษาอื่นไหนที่เขียน hello world เป็นหน้าเว็บได้ใน 1 บรรทัด อย่างน้อยๆ ก็ต้องเขียนส่วนที่รับ request object เข้ามาก่อน แต่ใน PHP มันอยู่ใน global มาตั้งแต่แรก

แล้วถ้าอยากจะ set header สักตัว ก็แค่เพิ่ม header("Content-Type: application/json"); จากหนึ่งบรรทัดกลายเป็นสองบรรทัด

ตัวภาษาเองยัง compact พอที่จะเป็น template engine ในตัวด้วย อย่างที่ WordPress ทำอยู่

แต่ community PHP อยู่ดีๆ ก็อยากเป็น Java แล้วทิ้งพวกนี้ไปโดยไปทำ Symfony และ Laravel มา

จากภาษาที่ echo ก็ออกหน้าจอได้แล้ว กลายเป็นว่าต้อง return Response object กลับไปเหมือนภาษาอื่นๆ แถมยังพยายามทำเป็น OOP จัดๆ ทั้งๆ ที่ตอน PHP4 ไม่มี class เลย พวก function ต่างๆ เช่น echo หรือ header กลายเป็นสิ่งที่ไม่ควรใช้

ก็ไม่รู้ว่า PHP พลาดไปตรงไหน เพราะ Zend หรือเปล่านะที่พยายามทำให้ PHP กลายเป็นการค้าแล้วก็ทำให้มันขายได้ หรือเพราะช่วงเปลี่ยนผ่านที่คนยังไม่ซื้อ VPS กันแล้วจำเป็นต้องใช้ PHP (แล้วที่ JavaScript ทุกวันนี้มันเป็นแบบนี้ ก็เพราะเหตุผลนี้หรือเปล่านะ?)

ทุกวันนี้ก็ยังฝันอยู่ว่าถ้าสร้าง PHP ขึ้นมาใหม่ในยุคนี้จะออกแบบมันยังไงดี แล้วมีใครทำแล้วหรือยังนะ?

ที่เอา PHP ออกจาก resume ตอนนี้เพราะตั้งแต่มันมี Symfony และ Laravel มา ก็ไม่ได้ตามแล้ว เคยเขียนอยู่ 2 project ใน stack นั้นได้ ก็ยังคิดว่า Django ดีกว่า

สองคือ คนเขียน PHP แย่ๆ มีเยอะในประเทศนี้เลยไม่อยากเสี่ยงไปทำงานกับคนพวกนี้ (เหมือนที่ 37signals ใช้ Ruby เพราะใครเขียนเป็นในยุคนั้นคือเซียน จะได้คัดกรองคนง่าย) สมัยที่เคยทำ freelance มา ทุก project ที่มี PHP code เรา penetration test แล้วเจอช่องโหว่ทุกอัน พอแจ้งไปก็มักจะมีข้ออ้างที่ไม่สนใจจะแก้ (เคยเจอขนาดว่าแก้ให้แล้วมา overwrite ทับ)

สามคือคนที่ยังใช้ PHP อยู่ ส่วนนึงคือติดอยู่ใน environment ที่ต้องใช้ PHP (และมักจะเป็นรุ่นเก่า) เราคิดว่าพอหลุดพ้นจาก environment นั้นไปได้แล้ว มันเปิดกว้างให้ใช้ภาษาอะไรก็ได้

Rust

เคยจับ Rust มาผ่านๆ ด้วยเหตุผลว่าเราไม่มีภาษาไหนเขียน low level เลย (ตอนนั้นยังไม่ได้เขียน Go)

ปัจจุบันก็คงคิดว่าไม่กลับไปเขียนแล้ว เพราะ ecosystem มันพร้อมเลยสำหรับงาน high level และ borrow checker ที่ทำให้เรา unproductive (ถ้ายอมมี garbage collection แล้วเขียนโปรแกรมได้เร็วขึ้น 10 เท่า สำหรับงานที่ผมทำมันไม่เลือกก็พลาดแล้ว)

It Depends

สรุปว่าเราเลือกใช้ตามนี้

  • ถ้าทำเว็บ ต่อ Database ใช้ Python และ Django
  • ถ้าทำอะไรที่ไม่ต้องต่อ Database (เช่น stateless API) อาจจะใช้ Go
  • บน browser ยังคงต้องใช้ JavaScript อยู่
  • Scripting ต่างๆ ถ้าเอาเร็วใช้ Python
  • แต่ถ้าจะเอาความ Deploy ง่าย ใช้ Go

ตอนนี้ยังไม่มีแผนจะเรียนภาษาเพิ่ม เพราะดูจะยังไม่มี use case ไหนขาดตกจนใช้ภาษาที่เขียนแก้ไม่ได้เลยเลยสักภาษา แล้วพอเรียนภาษาใหม่แต่ไม่ได้ใช้มันก็จะลืม (เคยจะลองเขียน Ruby แต่พอพบว่ามันทับซ้อนกับ Python ก็ไม่ได้ใช้ ลืมหมดแล้ว)

สุดท้ายแล้วถึงแต่ละภาษาจะมีจุดแข็ง – จุดอ่อนต่างๆ และมี clear use case ที่เราเลือกใช้ แต่หลายๆ ครั้งก็จะเลือกตามนั้นไม่ได้ถ้าทำหลายคน แล้วคนอื่นไม่ได้เขียนด้วย อันนั้นก็ต้องคุยกันอีกที

Rust first time

ว่าจะเขียนในเฟส แต่ยาวแล้ว formatting ในเฟสคนคงอ่านไม่รู้เรื่อง เลยเขียนในบล็อคละกัน

Cargo

  • งงชื่อไฟล์มาก คือตอนแรกนึกว่าตั้งชื่อไฟล์มั่วๆ ได้ ปรากฏว่าไม่ใช่ มันมีชื่อไฟล์บังคับ src/main.rs src/lib.rs เข้าใจว่ามาจาก cargo เลยไม่อยู่ในเอกสารของ rust – -!!
  • งง import ต่อ คือถ้าใช้ library ภายนอก ต้องประกาศ extern crate ที่ไฟล์ main ไม่ใช่ไฟล์ที่จะใช้ ในไฟล์ที่จะใช้ให้ใช้คำสั่ง use อย่างเดียว
  • นั่นแปลว่าถ้าใช้ในไฟล์ main ต้องย้ำ extern crate ..; use ..; ฮ่วย
  • เป็น package manager ที่เป็น build tool ด้วย เราว่าโอเคดี ยกเว้นแต่ว่ามันระบุ option rustc ตรงๆ ไม่ได้ (ว่าจะลอง -C target-cpu=native)
  • เขียน C แล้วเอา rust เรียก C ง่ายมาก ตัว cargo มันจะ compile C ให้ในขั้นตอน build เลยด้วย ไม่ต้องทำแยกกัน
    • ปัญหาอย่างเดียวคือ C String เป็น 0 terminate แต่ rust string เป็น vector (เข้าใจว่า C++ ก็ใช้ vector เป็น string?) เวลาแปลงข้ามไปมาก็สนุกเลย

Data type

  • คอมไพล์ไม่ผ่านบ่อยมาก ครึ่งวันน่าจะหมดไปกับแก้ compile error
  • คอมไพล์เสร็จตามที่เค้าโม้ครับคือคุณไม่มีทาง segmentation fault ได้จริงๆ
  • การ proof ให้ rust เชื่อว่า memory safe มหาโหดมาก
    • ในภาษาปกติ let a = b; นี่แปลว่า a มีค่าเหมือนกับ b แต่ใน rust มันแปลว่าเลิกใช้ b ได้เลย เพราะ a เป็นเจ้าของค่าใน b แล้ว และค่าหนึ่งมีเจ้าของคนเดียว
    • เดี๋ยวมีต่อด้านล่างว่ามันทำให้ optimize ไม่ได้ด้วย
  • ที่ตลกมาก คืออ่าน struct จากไฟล์ทำไม่ได้… เหตุผล เพราะคุณแน่ใจได้ยังไงว่าอ่านมาแล้ว struct ในไฟล์มันตรงกับ memory layout คุณจริง
    • ผลคือ ไปเขียนตัวอ่าน struct ใน C มาแล้วคอมไพล์เข้ามาเป็น rust เขียนง่ายกว่า ไม่งั้นคุณต้องมานั่ง proof ให้ rust เชื่อเรื่อง data type มหาศาล
  • Type inference ของ rust โคตรเก่ง ยอมรับเลย คือนอกจากตรงที่ภาษาบังคับแทบจะไม่ต้องระบุ data type เลย
  • Compiler บังคับ coding standard ด้วย คุณจะต้องใช้ under_score_function_name ทั้งหมด ไม่งั้น warning
  • rust string เป็น utf8 เท่านั้น ถ้าคุณจะใช้ encoding อื่นกรุณาเก็บใน [u8] (array ของ nt8_t)

  • ถ้าต้องการจะอ่าน uint_32 ในไฟล์ แต่ read ของ rust มันอ่านเป็น [u8]; จะแปลงยังไง
    • คำตอบคือ let id: u32 = unsafe{::std::mem::transmute_copy(& buffer);}
    • transmute_copy คือบอกว่า pointer นั้นอะจริงๆ แล้วมันชี้ไปหา data type นี้นะ คือไม่มีการ cast อะไรทั้งสิ้น เปลี่ยนวิธีมองตำแหน่งใน memory เลย แต่ถึงจะบอกว่า unsafe มันก็ยังเช็คให้ว่า memory ตรงนั้น กับ data type ใหม่มีขนาดเท่ากัน
  • rust ไม่มี null รู้สึกภาษาใหม่ๆ จะมาแนวนี้หมด ไม่ว่าจะ Kotlin หรือ swift คือจะใช้ระบบ Optional แทน
    • ไอเดียคือฟังก์ชั่นต้องประกาศว่าฟังก์ชั่นนี้ return เป็น optional แล้วคนที่เรียกก็ต้องไปเช็คเสมอว่า return มามีค่าหรือเปล่า
    • ข้อดีคือไม่เกิด null pointer แน่ๆ เพราะบังคับให้คุณเขียนจัดการ null
    • ข้อเสีย if ทุก method call เลยมั้ยครับท่าน…
  • Rust ไม่มี Class แต่ struct มี method ได้เรียกว่า implementation (สุดท้ายคือหน้าตาออกมาโคตรเหมือน class แค่ไม่มี inheritance)
  • ไม่ใส่ ; ก็ได้ แต่การใส่ ; มีผล!!!! ผมนี่สตั้นเลย ลองดูโค้ดนี้นะครับ
fn x() -> u8 {
   y();
}
fn x() -> u8 {
   y()
}
  • จะบอกว่าโค้ดแรก คอมไพล์ไม่ผ่าน ครับ เพราะมันถือว่ามี 2 statement คือ y() กับ statement เปล่า มันเลย return เป็นค่าว่างเปล่า (()) ไป!!! ในขณะที่อันหลังมีแค่ statement เดียว ก็จะ return คำตอบของ y() (ตรงนี้คล้ายๆ ruby ที่ expression สุดท้ายของฟังก์ชั่นเป็น return value ของฟังก์ชั่นด้วย)

บ่น

ผมจะทำ object pool ก็เขียนมา

let record = Record{
    id: 0,
    text: ....,
};

อ่าว… แล้ว text เป็น String จะใส่ว่าอะไร… เอางี้ละกัน

let empty_string = String::new();
let mut record = Record{
   id: 0,
   text: empty_string,
};
loop{
   reader.read_recycle(&mut record);
   let text = record.text;
   record.text = empty_string;
   put_ds(text);
}

ปรากฏว่า empty_string อันหลังนั่นมันถือว่าบรรทัดที่ 3 ยึดเป็นเจ้าของไปแล้ว ใช้ไม่ได้ สุดท้ายก็เลยต้อง String::new() สองรอบ นี่มันก็ไม่ต่างกับไม่ทำ object pool แล้วนะ!!

Speed

  • สรุปแล้วถามว่า rust เร็วมั้ย คำตอบคือไม่ครับ มันเป็นห่วง memory safety เกินไป คือบางอันคุณเห็นกับตาว่าคุณไม่ใช้ แต่คุณพิสูจน์เป็นโค้ดให้ rust ไม่ได้คุณก็เขียนไม่ได้ แล้วมันทำให้ต้องมานั่งอ้อมโลกจนน่ารำคาญ
  • แต่อย่าลืมนะครับว่ามันเป็นภาษา low level ฉะนั้นแล้วมันแค่ช้ากว่า C แค่นั้นแหละครับ….