Aug 29, 2014

เพราะห้องสมุดใหญ่เกินกว่าที่คนเดียวจะอ่านหนังสือครบทุกเล่ม

น่าเสียดายนะครับ ชีวิตคนเรานี้มันสั้นสิ้นดี

อย่าว่าแต่หนังสือในห้องสมุดทั้งหมดที่ไม่มีทางอ่านครบเลย แค่หนังสือเล่มเดียวที่อ่านก็ไม่แน่ว่าเราจะเก็บประเด็นอะไรได้หมด

ร้ายสุดคือหนังสือที่ไม่ใช่ข้อสรุปเชิงวิทยาศาสตร์ แต่เป็นสันนิษฐานที่เป็นไปได้ที่ยังต้องการข้อมูลมากกว่านี้มาสนับสนุนความคิด แบบนี้ผู้เขียนแต่ละคนก็เขียนมาได้หลายร้อยพันแบบเลย

การที่คนสองคนมาพูดคุยแลกเปลี่ยนกัน มันจึงไม่แปลกถ้าจะเข้าใจไม่ตรงกัน เพราะเราอ่านหนังสือกันมาคนละเล่ม หรือถึงแม้จะอ่านเล่มเดียวกันก็อาจเข้าใจไม่ตรงกัน

ดังนั้นเวลาคุยกันไม่รู้เรื่อง การไล่ไปหาหนังสืออ่านเองในห้องสมุด ผมว่ามันเสียมารยาทมากๆ นะ

อย่างน้อยก็บอกมาหน่อยว่าต้องหยิบหนังสือเล่มไหน ใจความสำคัญอยู่หน้าที่เท่าไหร่

hint: ลองเปลี่ยนคำว่าห้องสมุดเป็น Google

Aug 26, 2014

O Mio Babbino Caro

พอดี @isamare แนะนำวิชา Listening to Music มาครับ ก็นั่งดูไปเรื่อยๆ ด้วยความสนุกสนาน จนถึงตอนนึงอาจารย์ Craig Wright เล่าเหตุการณ์ในบ้านแกให้ฟังว่า

อาจารย์: (นั่งเล่นเปียโนอย่างสบายอารมณ์)
ลูกชาย: เพลงนี้เพราะมากเลยนะพ่อ
อาจารย์: โอ้ ให้มันได้อย่างนี่สิลูกชายฉัน (คงตัวลอยฝันไปไกลว่าลูกโตขึ้นเป็นนักดนตรีตามรอยตัวเองแน่ๆ 555)
ลูกชาย: ได้ยินมาหลายครั้งละใน Grand Thief Auto เพลงนี้เพลงอะไรครับพ่อ?
อาจารย์: เดี๋ยวก่อนนะ ... อะไรคือ Grand Thief Auto???



จุดเด่นของเพลงนี้ที่อาจารย์แกยกมาเล่าเรื่องเมโลดี้ครับ ปรกติเพลงร้องมักจะค่อยๆ ไล่โน้ตไปทีละขั้นสองขั้น แต่เพลงนี้กลับใช้การกระโดด 1 octave เลยทีเดียว

Jul 23, 2014

Wolfgang Amadeus Mozart - Symphony No. 25 in G minor, K. 183



มีคำกล่าวว่า Mozart ไม่ค่อยแต่งเพลงในกุญแจไมเนอร์ ซึ่งก็จริงอยู่เพราะจาก Symphony ราว 40 บท มีเพียง 2 บทเท่านั้นที่อยู่ในกุญแจไมเนอร์

แต่นั่นไม่ได้หมายความว่า Mozart แต่ง Symphony ในกุญแจไมเนอร์ไม่เก่ง

เพราะหมายเลข 25 นี้เอง ที่เป็นสิ่งพิสูจน์ข้อความข้างต้นครับ

I. Allegro Con Brio (8:00 นาที)

บทเพลงเริ่มต้นท่อนแรกขึ้นมาอย่างหดหู่สิ้นหวัง ด้วยโมทีฟที่เป็นเอกลักษณ์จดจำง่าย ฟังแล้วเหมือนจะขาดใจตายยังไงยังงั้น แม้จะมีช่วงแทรกสั้นๆ ให้ดูเหมือนจะมองเห็นความหวังอยู่ไกลๆ แต่โดยรวมทั้งท่อนแล้วมันมีแต่ความพ่ายแพ้ต่อโชคชะตาจริงๆ

ในภาพยนต์เรื่อง Amadeus ซึ่งเป็นชีวประวัติของ Mozart ฉากแรกที่เปิดตัวมาด้วยภาพผู้คนจำนวนมากล้มตาย ก็ได้ท่อนนี้มาประกอบนี่แหละครับ เข้ากั๊นเข้ากัน ฟังแล้วเหมือนรอความตายยังไงหยั่งงั้นเลย

II. Andante (3:30 นาที)

มันน่าจะเป็นธรรมเนียมของการจัดวางองประกอบศิลป์ในโลกตะวันตกครับ ที่เวลาเล่าเรื่องเศร้าแล้ว มันต้องสลับกลับมาเล่าเรื่องสุข ถ้าตอนแรกเริ่มต้นด้วยความเร่งรีบ ถัดมาต้องเป็นช่วงที่เยือกเย็นผ่อนคลาย สลับสับเปลี่ยนกันไปแบบนี้

ท่อนนี้เริ่มอย่างช้าๆ เนิบนาบ ดั่งเช่นเมื่อล้มตัวลงนอนคิดถึงคืนวันหอมหวานที่ไม่หวนกลับมา แต่พอท้ายท่อนนี้ก็ส่อแววไปถึงการตั้งคำถาม ด้วยการแปรทำนองออกเป็นความเศร้าที่แฝงอยู่ เปรียบเช่นว่าการมองหวนนึกถึงแต่อดีตนี้จะดีจริงหรือ

III. Menuetto & Trio (3:30 นาที)

ท่อนนี้จัดว่าเป็นการเต้นรำก็ได้ครับ ออกจะเป็นการเต้นรำที่เริ่มมาอย่างไม่สบอารมณ์ซักหน่อย ซึ่งท่อนนี้เป็นแบบ trio หรือก็คือแบ่งเพลงออกเป็น 3 ส่วน ซึ่งส่วนแรกที่เล่าแบบเซ็งๆ นี้จะกลับมาย้อนเล่าสรุปอีกทีเป็นการปิดท้าย ส่วนตรงกลางอาจนับว่าเป็นช่วงที่เริ่มมีความสุขขึ้นมาบ้างก็ได้ ทำให้ท่อนนี้ออกจะมีหลายอารมณ์ปนกันครับ

IV. Allegro (6:00 นาที)

ท่อนสุดท้ายที่เป็นการสรุปใจความทั้งหมดของเพลงที่เล่ามา จังหวะการเล่นกลับมารวดเร็วและใช้กุญแจเสียง minor ซึ่งเป็นกุญแจเสียงตั้งต้นของเพลง แต่เราก็อาจได้ยินทำนองที่ออกไปทางปิติยินดีมากขึ้น เรียกว่าสุขๆ เศร้าๆ ปนๆ กันไป เปรียบดังยอมรับได้ว่าชีวิตก็เท่านี้แหละ มีเกิดก็มีดับ ในเมื่อมันเป็นเรื่องธรรมชาติที่หนีไม่พ้นอยู่ดี แล้วจะเศร้าให้มันมากมายไปทำไม มองซะว่ามันเป็นความสุขเสียอีก ที่สุดท้ายก็ได้พักผ่อนยาวให้หายจากความเหนื่อยล้านี้เสียที

ก็เป็นเพลงแบบเศร้าๆ มืดๆ จาก Mozart ที่เจ๋งดีครับ ฟังแล้วจินตนาการเป็นอย่างอื่นไม่ค่อยออก นอกจากเห็นภาพความตายที่รอคอยอยู่เบื้องหน้าจริงๆ

Jul 15, 2014

The Swing

ดู Frozen เมื่อปีก่อนก็ตะหงิดๆ อยู่ในใจว่า ตอนที่อันนากระโดดดึ๋งๆ ในเพลง For the First Time in Forever แล้วทำท่าเลียนแบบรูปวาดบนผนัง มันมีรูปนึงที่คุ้นตาเอาซะมากๆ

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

แต่หนังสนุก เพลงเพราะ ก็ลืมไปเลยว่าเคยสงสัยข้อนี้

จนกระทั่งวันก่อนเดินเข้าร้านหนังสือฆ่าเวลาเล่น แล้วไปเปิด 1001 Paintings You Must See Before You Die (edition ไหนไม่รู้ แต่น่าจะล่าสุด) พลิกกระดาษมั่วๆ ไปไม่กี่หน้าก็เจอภาพนี้เข้าพอดี


Les Hasards Heureux de l'Escarpolette โดย Jean-Honoré Fragonard วาดในปี 1767

อันนี้เทียบกับเวอร์ชั่นดิสนีย์


ภาพวาดที่อันนาทำท่าเลียนแบบ (บน) และภาพแบบธรรมดา (ล่าง) ภาพจาก Animate Film Review

ก็เป็นอันว่า ปริศนาในขีวิตไขกระจ่างไปอีกหนึ่งข้อ :P

Jul 12, 2014

Self Printing Program

หลายวันก่อนเปิดเจอโพสนี้ของคุณ @theppitak ซึ่งเป็นเรื่องของการเขียนโปรแกรมที่ต้องการผลลัพท์เป็นโปรแกรมที่กลับมาพิมพ์โปรแกรมตัวเอง

พูดง่ายๆ ว่าถ้าสมมติว่าโปรแกรมนั้นชื่อ self.c การสั่งคำสั่ง diff ครั้งสุดท้ายในโค้ดต่อไปนี้ต้องให้ค่าคืนมาเป็นว่า 2 ไฟล์มีเนื้อหาเหมือนกัน
$ gcc self.c
$ ./a.out > other.c
$ diff self.c other.c
เนื่องจากคุ้นว่าจะเคยเห็นคำถามแนวนี้ใน Ruby มาก่อนแล้ว ตอนแรกก็ไม่ได้คิดว่าจะลองทำหรอก แต่เท่าที่สังเกตแล้วจุดที่น่าจะเป็นปัญหาน่าจะมาจากเรื่อง escape string ซึ่งใน Python มันคงไม่ยุ่งยากเท่าไหร่ เพราะมี raw string และฟังก์ชั่น repr ไว้คอยจัดการปัญหา escape string อยู่แล้ว

แต่คิดไปคิดมา เอ่อ แล้วถ้าเป็นใน C (ที่ต้นทางเค้าสงสัย) นี่มันจะทำยังไงหว่า? เลยลงมือเขียนเล่นๆ จนได้ออกมาดังนี้
void main() {
  int i = 0, j = 0;
  char* x = "void main() {\n\tint i = 0, j = 0;\n\tchar* x = \"%s\";\n\twhile (x[i]) {\n\t\tif (x[i++] == '%%' && x[i++] == 's') {\n\t\t\twhile (x[j]) {\n\t\t\t\tswitch (x[j++]) {\n\t\t\t\t\tcase '\\n': putchar('\\\\'); putchar('n'); break;\n\t\t\t\t\tcase '\\t': putchar('\\\\'); putchar('t'); break;\n\t\t\t\t\tcase '\\\"': putchar('\\\\'); putchar('\"'); break;\n\t\t\t\t\tcase '\\\\': putchar('\\\\'); putchar('\\\\'); break;\n\t\t\t\t\tdefault: putchar(x[j-1]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tputchar(x[i-1]);\n\t\t}\n\t}\n}\n";
  while (x[i]) {
    if (x[i++] == '%' && x[i++] == 's') {
      while (x[j]) {
        switch (x[j++]) {
          case '\n': putchar('\\'); putchar('n'); break;
          case '\t': putchar('\\'); putchar('t'); break;
          case '\"': putchar('\\'); putchar('"'); break;
          case '\\': putchar('\\'); putchar('\\'); break;
          default: putchar(x[j-1]);
        }
      }
    } else {
      putchar(x[i-1]);
    }
  }
}
ไม่ได้จับ C มาหลายปี หมดพลังไปเยอะกว่าคิดออก 555+

Jul 8, 2014

ชีวิต (เกือบ) ไม่ติดเน็ต

พอดีเดือนก่อนปิดเทอมกลับบ้านนานครับ เลยยกเลิกเน็ตหอไป พอกลับมาแล้วยังไม่ครบรอบ เลยไม่ได้กลับมาต่อเน็ตไวไฟ ใช้แต่บนมือถืออย่างเดียว

ก็เป็นประสบการณ์ที่แปลกดีนะ วันแรกๆ รู้สึกจดจ่อกับงานได้ดีขึ้นเยอะมาก ไม่มีสิ่งกวนใจเลย

แต่พอทำไปทำมาแล้วเจอปัญหาใหญ่ครับ เพราะต้องพึ่ง Google, StackOverflow บ่อยๆ ครั้นจะหาในมือถือจอเล็กๆ แล้วพิมพ์ code ซ้ำในคอมก็ลำบากไปหน่อย กลายเป็นว่าวันหลังๆ นี่งานเดินช้ากว่าช่วงที่มีเน็ตไวไฟซะอีก

เดี๋ยวว่าจะกลับไปติดเน็ตคืนละครับ แล้วค่อยหาวิธีคุมสิ่งกวนใจด้วยวิธีอื่นแทน งานนี้ถือว่า trade-off ไม่คุ้มซะเท่าไหร่ :s

Jun 17, 2014

The Angels' Share

พอดีมีเทศกาลหนังยุโรปครับ งานนี้ดูฟรีแถมมีคนชวน เลยตัดสินใจแวะไปลองอะไรที่ไม่เคยทำดูซะหน่อย

... ไปแบบไม่รู้อะไรซักอย่างจนกระทั่งเข้าโรงเนี่ยแหละ ถึงรู้ว่ามันคือเรื่อง The Angels' Share ครับ


เนื้อเรื่องกล่าวอันธพาลหนุ่มนายหนึ่งที่ดันไปทำร้ายร่างกายนักศึกษาเข้า แต่ศาลตัดสินลดโทษเหลือแค่ทำงานบริการชุมชน 300 ชั่วโมง เพราะตอนนั้นเขากำลังจะกลายเป็นพ่อของเด็กชายตัวน้อยๆ

ครับ นี่ไม่ใช่หนังบู้ระห่ำแอคชั่นแฟนตาซีชวนฝัน แต่มันคือการต่อสู้ในชีวิตจริงที่ไม่หอมหวานเดินทางเป็นเส้นตรง และไม่แน่ว่าซักวันหนึ่งเราก็อาจต้องประสบพบเจอ

ชีวิตบริการชุมชนทำให้เขาได้พบป่ะผองเพื่อนอาชญากรกลับใจมากมาย สิ่งที่ผลักดันให้เขาดิ้นรนคือครอบครัวเล็กๆ ที่เขาตระหนักถึงความรับผิดชอบ โชคดีที่เขามีหัวหน้างานเป็นทั้งเพื่อนและครูคอยดูแลเขาอยู่เสมอ

ชื่อหนังได้มาจากตอนที่หัวหน้างานพาตัวเอกและผองเพื่อนไปเที่ยวโรงบ่มวิสกี้ ที่ซึ่งคนงานแถวนั้นบอกว่าวิสกี้ในถังไม้โอ๊คจะระเหยหายไปปีละ 2% เปรียบดังเช่นส่วนแบ่งที่มอบให้แก่นางฟ้า

หนังดีพอประมาณครับ การตัดต่อช่วงแรกอาจทำให้จับใจความได้ยากไปบ้าง แถมยังมีตัวละครเยอะแล้วหน้าตาดันคล้ายกันไปหมดอีก แต่ถ้าก้าวข้ามตรงนี้ไปได้ ก็จะพบกับความแปลกใหม่ที่สตูดิโอหนังใหญ่ๆ อย่าง Hollywood ให้ไม่ได้ครับ

สิ่งที่ชอบที่สุดคงหนีไม่พ้นประโยคที่ว่า "หนึ่งเพื่อลิ้มลอง หนึ่งเพื่อสะสม หนึ่งเพื่อแบ่งบัน"

เพราะแม้ชีวิตต้องดิ้นรน แต่ก็อย่าลืมที่จะแบ่งบันสิ่งดีๆ บ้างนะครับ

Jun 7, 2014

ได้ Google+ Custom URL ซักที

จริงๆ Google+ Custom URL นี่ไม่ใช่ของใหม่ มันเปิดตัวตั้งแต่ปลายปี 2012 และขยายวงให้ผู้ใช้ทุกบัญชีตอนปลายปี 2013 อันที่จริงผมก็ได้หลังจากเปิดตัวไม่กี่เดือนนะ แต่ตอนนั้นดันปรับชื่อตามใจไม่ได้ (ใช้ได้อย่างเดียวคือชื่อและนามสกุลจริง) เลยงอน Google ไม่ยอมกดรับชื่อ แล้วก็ดองมาตั้งแต่นั้น

แต่ก็ยังแอบมีหวัง ไปเปิดดูเดือนละครั้งสองครั้ง ว่าพี่แกคิดจะเปลี่ยน policy บ้างมั้ย แบบยอมให้ตั้งชื่อได้ตามใจงี้

รอไปรอมาชักหมดหวังครับ ... จนเมื่อวันก่อนที่อยู่ดีๆ ก็เกิดไอเดียขึ้นมา ไหนๆ พี่ทั่นก็ไม่ยอมให้ตั้งชื่อ URL ได้เองใช่มั้ย ก็เปลี่ยนชื่อจริงไปเป็น URL ที่อยากใช้ซะสิ แล้วก็รอให้ระบบมันเรียนรู้ซักหน่อยว่าเราเปลี่ยนชื่อแล้วนะ เดี๋ยวก็คงส่งจดหมายเชิญให้ใช้ Custom URL มาเองแหละ

ก็เลยจัดการเปลี่ยนชื่อจริงเป็น nei และนามสกุลเป็น zod เพราะตอนนั้นเดาว่าตาม policy แล้ว อาจจะปรับตัวอักษรตัวแรกของชื่อ/นามสกุลให้เป็นตัวพิมพ์ใหญ่ ก็เลยแบ่งคำกันไว้ก่อน (จะว่าไป จริงๆ ก็น่าจะแบ่งว่า neiz กับ od นะ :P) หรือถ้าขี้เกียจตัดแบ่งคำ จะใช้นามสกุลเป็นจุดตัวเดียวเพื่อบอกว่าไม่มีนามสกุลก็ได้

ปรากฏว่ารอแค่ 3 วัน ก็ได้ Custom URL อย่างที่ต้องการครับ (ตอนแรกนึกว่าจะนานกว่านี้เสียอีก) ส่วนเรื่องที่เดาว่าอักษรตัวแรกของชื่อ/นามสกุลจะถูกเปลี่ยนเป็นตัวใหญ่นี่คิดผิดแฮะ ให้มาเป็นตัวเล็กหมดเลย ดีมากๆ

ก็เจอกันได้ที่ google.com/+neizod ครับ แม้จะไม่ค่อยได้เล่นเท่าไหร่ แต่เล่นเยอะกว่า Facebook แน่นอน ฮาาา

Jun 1, 2014

การสอนด้วยตัวอย่างที่ดีนั้นยาก

ถ้าช่วงนี้ใครเข้าเว็บ Python.org คงจะเห็นตัวอย่างโค้ดนี้
list = [2, 4, 6, 8]
sum = 0
for num in list:
    sum = sum + num
print("The sum is:", sum)
เรียบง่ายและงดงาม...

แต่ถ้าไปถามคนที่เขียน Python ประจำนี่ด่าตรึมเลย เพราะโค้ดด้านบนนี้มีจุดอ่อนอยู่ 2 ประการ
  1. มีการประกาศชื่อตัวแปร list กับ sum ซึ่งทั้ง 2 ชื่อนี้ เป็นชื่อของฟังก์ชันมาตฐาน ถึงแม้ว่าจะไม่มีข้อห้ามให้ประกาศชื่อซ้ำได้เหมือนกับพวก reserved keyword แต่การทำเช่นนี้ก็บาปมากเพราะ 2 ฟังก์ชันนี้จะไม่สารมารถถูกเรียกใช้ได้โดยง่ายอย่างที่ตัวภาษาออกแบบไว้
  2. Python มีฟังก์ชัน sum สำหรับหาผลรวมของชุดตัวเลขให้ใช้งาน นอกจากจะเขียนได้ง่ายและทำงานเร็วกว่าแล้ว มันยังสร้างสุขลักษณะที่ดีต่อการเขียนโปรแกรมสำหรับใช้งานในโลกจริงด้วย
  3. (ข้อนี้เพิ่มให้ในฐานะนักทฤษฎีคณิตศาสตร์และคอมพิวเตอร์) ขั้นตอนวิธีข้างต้นสามารถพิสูจน์ลดรูปให้เป็น O(1) ได้ ถ้าลำดับเลขนำเข้าเป็นเลขจำนวนเต็มเรียงกันทั้งหมด หรือเป็นเลขคู่เรียงกัน หรือเป็นเลขคี่เรียงกัน
ตัวอย่างนี้จึงเป็นตัวอย่างที่ไม่ค่อยดีในการนำมาสอนเขียนโปรแกรมที่จริงจังหน่อย เพราะว่าโค้ดแบบนี้ไม่ควรเกิดขึ้นในโลกจริงเลย (แน่นอนว่าคนที่ยกตัวอย่างนี้มา อาจแก้ต่างว่าโค้ดนี้มีเจตนาที่จะยกตัวอย่างลูปให้มือใหม่หัดเขียนโปรแกรม ซึ่งโดยส่วนตัวผมไม่ค่อยเห็นด้วยเพราะนี่คือหน้าเว็บที่มีทุกระดับฝีมือมาเยี่ยมเยียน ไม่ใช่บทที่ 1 ในหนังสือ Programming 101)

ถ้าเช่นนั้น แล้วจะมีตัวอย่างแบบไหนที่ดีพอหละ?

ผมคิดว่าตัวอย่างที่ดี เข้าเกณฑ์แค่ข้อเดียวก็พอ คือต้องไม่ทำหน้าที่ซ้ำซ้อนกับสิ่งที่มีอยู่แล้ว (do not reinvent the wheel)

ปัญหาสำคัญสำหรับแนวคิดนี้ คือของที่ง่ายพอจะเอามาเป็นตัวอย่างมักมีอยู่เกือบหมดแล้ว จะให้สอนโดยไม่ยกตัวอย่างซ้ำกับของที่มีเลยคงยาก

โชคดี (?) ที่ Python ยังไม่มีฟังก์ชันผลคูณรวม (product) ทำให้โค้ดในโลกความจริง ที่สามารถนำมาสอนเขียนได้ดังนี้
numbers = [2, 4, 6, 8]
product = 1
for number in numbers:
    product = product * number
print("The product is:", product)
เพราะการสร้างตัวอย่างที่ดีไม่ใช่เรื่องง่ายๆ

May 28, 2014

อย่าเสียเวลาให้กับลูปที่เรียก System บ่อยๆ

ช่วงนี้มีวิเคราะห์ string บนไฟล์จำนวนมหาศาล (หลายแสนไฟล์) ตอนแรกก็เขียน Python ง่ายๆ ตามความเคยชิน
counter = 0
for file in glob('*.cpp'):
    if '//' in file.read():
        counter += 1
print(counter)
โค้ดนี้ทำงานได้ดีเลยแหละ ติดตรงที่ไฟล์ที่นำมาวิเคราะห์บางไฟล์ก็ใช้ encoding แปลกๆ แล้วเปิดอ่านไม่ได้ (ยังงงอยู่ว่า Python ไม่เช็คว่าเป็น ASCII หรือ UTF-8 ให้อัติโนมัติ?) ก็แก้ๆ โค้ดด้านบนนี้โดยใช้โมดูล codecs เข้าช่วย ไม่มีปัญหาอะไร

แต่แล้วก็คิดขึ้นมาได้ว่า งานประเภทนี้ถ้าทำใน Bash ไปเลยก็น่าจะแจ่มเหมือนกัน เพราะปรัชญาของ Unix คือให้โปรแกรมจัดการกับ I/O Stream แบบข้อความอยู่แล้ว เลยได้โค้ดออกมาเป็น
counter=0
for file in *.cpp
do
    grep -q '//' "$file" && : $((counter++))
done
echo $counter
ผลลัพท์ออกมาไม่ต่างกับ Python ด้านบน แต่ว่า Bash ทำงานช้ามากกกกก (ก.ไก่ 140 ตัว) ตอนแรกก็คิดว่า Bash มันน่าจะทำลูปไม่เก่งมั้ง เพราะเท่าที่อ่านโค้ดของโครงการ Linux ก็ไม่ค่อยเห็นเขียนลูปกันเท่าไหร่ แต่พอลองเขียนลูปเปล่าแสนรอบใน Bash มันก็ไม่เห็นจะช้า เลยคิดว่าน่าจะเป็นที่ grep มั้ง? แต่ก็ไม่อยากจะเชื่ออยู่ดีเพราะเคยอ่านงานของ Russ Cox ก็ไม่เห็นว่า grep มันจะช้าซักเท่าไหร่

อาจารย์ @juggapong ผ่านมาเห็นเลยยิงคำถามมาว่า มันช้าเพราะมัวแต่มุดเข้ามุดออก system หรือเปล่า?

ได้ยินดังนั้นเลยใช้ time จับเวลาดู โอ้ว user กับ sys ใช้เวลาพอๆ กันเลยแฮะ

ถึงตอนนี้ก็รู้แล้วว่าสาเหตุที่มันช้าเพราะ grep แต่ละครั้งเป็น process ใหม่เลย ต้องรอให้ system จองทรัพยากรเสร็จก่อนจึงจะใช้งานได้ แถมพอจบงานก็ทำลาย process นี้ทิ้งซะอีก ไม่ได้จัดสรรทรัพยากรอะไรกันระหว่างลูปเลย ... เทียบง่ายๆ คงเหมือนกับการที่มีเตารีดแสนอัน เสียบปลั๊กเตารีดตัวแรกรอร้อนแล้วจึงรีดผ้าหนึ่งชิ้น พอผ้าชิ้นนี้เรียบเนี๊ยบจนพอใจก็ถอดปลั๊กเตารีดซะงั้น แล้วไปเสียบปลั๊กเตารีดอีกตัวมารีดผ้าอีกชิ้นนั่นเอง

คิดได้ดังนี้ก็เปลี่ยนโค้ดไปเป็น (ใช้เตารีดตัวเดียว เสียบปลั๊กรอร้อนครั้งเดียว)
grep -l '//' *.cpp | wc -l
คราวนี้เร็วส์เสียยิ่งกว่า Python อีก :P

(แต่สุดท้ายก็คงกลับไปเขียน Python อยู่ดี เพราะมีปัจจัยที่ใช้วิเคราะห์ซับซ้อนกว่านี้ ใช้ Python แล้วรู้สึกถนัดมือกว่า)