veer66

veer66

โปรแกรม

คำสั่งคำสั่งเดียวหรือหลายๆ คำสั่งที่เรียงกันเป็นลำดับ

ตัวอย่างโปรแกรม

Dim i As Integer  
For i = 1 To 3
  Print "สวัสดี"
Next

ผลการรัน:

สวัสดี
สวัสดี
สวัสดี

ตัวแปร

ตัวแปรคือที่ที่มีชื่อเอาไว้เก็บข้อมูล

ตัวอย่างโปรแกรม

Dim i As Integer
i = 20
Print i

ผลการรัน

20

โปรแกรมย่อย

ส่วนของโปรแกรมที่ถูกเรียกใช้ได้ในโปรแกรมนั้น เรียกอีกอย่างว่า “Subroutine”

ตัวอย่างโปรแกรม

Sub GreetThreeTimes()
  Dim i As Integer
  For i = 1 To 3
    Print "สวัสดี"
  Next
End

GreetThreeTimes
GreetThreeTimes

ผลการรัน

สวัสดี
สวัสดี
สวัสดี
สวัสดี
สวัสดี
สวัสดี

ฟังก์ชัน

คือโปรแกรมย่อยที่ทำงานเสร็จแล้วให้ค่าบางอย่างเสมอ

ตัวอย่างโปรแกรม Book.class

Function Add10(n As Integer) As Integer
  Dim m As Integer
  m = n + 10  
  Return m
End

Print Add10(20)

ผลการรัน

30

อ็อบเจกต์และคลาส

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

ตัวอย่างโปรแกรม

Id As String
Title As String
Author As String

Sub PrintObject()  
  Print Id, Title, Author
End

ข้อกำหนดในการเข้าถึง

  • Public ใช้ได้จากทุกส่วนของโปรแกรม
  • Private ใช้ได้เฉพาะในอ็อบเจกต์เดียวกัน

ตัวอย่างโปรแกรม Book.class

Public Id As String
Public Title As String
Public Author As String

Public Sub PrintObject()  
  Print Id, Title, Author
End

การสร้างอ็อบเจกต์

สร้างอ็อบเจกต์ตามที่คลาสกำหนดโดยคำสั่ง “New”

ตัวอย่างแบบยาว

Dim Book1 As Book
Book1 = New Book

ตัวอย่างแบบสั้น

Dim Book1 As New Book

การใช้งานตัวแปรของอ็อบเจกต์

ชื่อออปเจกต์.ชื่อตัวแปร

ตัวอย่างโปรแกรม

  Dim Book1 As New Book
  Book1.Title = "โฉมหน้าศักดินาไทย"
  Print Book1.Title

การใช้งานโปรแกรมย่อยของอ็อบเจกต์

โปรแกรมย่อยของอ็อบเจกต์หรือที่เรียกอีกอย่างว่า “เมท็อด”

ชื่ออ็อบเจกต์.ชื่อโปรแกรมย่อย

ตัวอย่างโปรแกรม

  Dim Book1 As New Book
  Book1.Title = "โฉมหน้าศักดินาไทย"
  Book1.Author = "จิตร"
  Book1.Id = "TH001"
  Book1.PrintObject

ผลการรัน

โฉมหน้าศักดินาไทย	จิตร		TH001

สังกัดอ็อบเจกต์หรือคลาส

  • ปกติแล้วสังกัดอ็อบเจกต์
  • ให้สังกัดคลาสให้ใส่คำว่า “static”
  • โปรแกรมย่อยสังกัดคลาสใช้ได้โดยไม่ต้องสร้างอ็อบเจกต์

ตัวอย่างคลาส Book.class

Public Id As String
Public Title As String
Public Author As String

Public Sub PrintObject()  
  Print Id, Title, Author
End

Static Public Sub Info() 
  Print "หนังสือเป็นสื่อ"
End

ตัวอย่างการเรียกใช้งานโปรแกรมย่อยที่สังกัดคลาส

Book.Info

  1. Choose the right mirror, e.g. rpmfind
  2. Install taint codecs etc.
  3. Install Thai fonts
  4. Customize the keyboard layout
  5. Add fonts.conf
  6. Choose LibreOffice default language/fonts
  7. Add Flathub
  8. Install Discover and make Flatpak as the default package manager

คำออกตัว

ผมไม่ได้เรียนเกี่ยวกับกฎหมายและไม่ได้ทำงานเกี่ยวกับกฎหมาย

ซอฟต์แวร์เสรีและโอเพนซอร์ส

ซอฟต์แวร์เสรีเป็นซอฟต์แวร์ที่เคารพสิทธิของผู้ใช้และชุมชน ได้แก่ สิทธิในการรัน ทำซ้ำ เผยแพร่ ศึกษา แก้ไข และปรับปรุงโปรแกรม อย่างไรก็ตามในเวลาต่อมามีขบวนการโอเพนซอร์สเกิดขึ้นเพื่อสร้างแนวร่วมกับบริษัทกระแสหลัก โดยแก้จำกัด 2 ประการของซอฟต์แวร์เสรี ได้แก่ (1) ซอฟต์แวร์เสรีในภาษาอังกฤษเรียกว่า “free software” โดยคำว่า free หมายถึงเสรีก็ได้หรือไม่เสียค่าใช้จ่ายก็ได้และมักจะถูกเข้าใจผิดว่าหมายถึงไม่เสียค่าใช้จ่าย และ (2) ศัพท์ว่า “free software” ทำให้ชาวบริษัทจำนวนมากกังวลใจ

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

หลักการ

โปรแกรมใดจะเป็นซอฟต์แวร์เสรีก็ต่อเมื่อมีเสรีภาพ 4 อย่างข้อต่อไปนี้

  1. เสรีภาพที่จะใช้งานโปรแกรมเพื่อจุดประสงค์อะไรก็ตาม
  2. เสรีภาพในการศึกษาและแก้ไขดัดแปลงโปรแกรม ข้อนี้ทำให้ต้องเข้าถึง source code ได้
  3. เสรีภาพในการเผยแพร่ซอฟต์แวร์ที่ยังไม่ได้แก้ไข
  4. เสรีภาพในการเผยแพร่แวร์ที่แก้ไขแล้วออกไป

กฎหมายไทย

จากพระราชบัญญัติลิขสิทธิ์ มาตรา 27 “การกระทำอย่างใดอย่างหนึ่งแก่งานอันมีลิขสิทธิ์ตามพระราชบัญญัตินี้ โดยไม่ได้รับอนุญาตตามมาตรา ๑๕ (๕) ให้ถือว่าเป็นการละเมิดลิขสิทธิ์ ถ้าได้กระทำดังต่อไปนี้ (๑) ทำซ้ำหรือดัดแปลง (๒) เผยแพร่ต่อสาธารณชน” เห็นได้ว่ามาตรานี้จำกัดเสรีภาพในดัดแปลงแก้และเผยแพร่งานซึ่งขัดกับหลักซอฟต์แวร์เสรี นอกจากนั้นในมาตรา 4 ระบุไว้ว่าโปรแกรมคอมพิวเตอร์เป็นวรรณกรรมและในมาตรา 6 ระบุว่าวรรณกรรมเป็นงานอันมีลิขสิทธิ์ทำให้โปรแกรมคอมพิวเตอร์เข้าข่ายนี้ด้วย

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

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

ส่วนประกอบของสัญญาอนุญาตพื้นฐาน

สัญญาอนุญาตก็คืออนุญาตอย่างน้อยให้ทำตามเสรีภาพที่ควรมีของซอฟต์แวรเสรีคืออนุญาตให้ใช้งาน ทำซ้ำ เผยแพร่ เช่น บางส่วนของสัญญาอนุญาตแบบ Expat/MIT «Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:» จะเห็นว่ามีคำว่า use copy modify publish และ distribute ด้วย

ความเป็นสาธารณะ

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

คนทั่วไปยิ่งไม่อยากให้คู่แข่งเอาเปรียบ สำหรับซอฟต์แวร์เสรีการที่คู่แข่งแก้ไขปรับปรุงแล้วเอาไปขายหรือใช้ในกิจการแต่ไม่เผยแพร่รหัสต้นฉบับ (source code) สู่สาธารณะ อาจมองว่าเป็นการเอาเปรียบคนอื่นจนเกินไป สัญญาอนุญาตบางแบบโดย เช่น GNU General Public License (GPL) สร้างมาเพื่อจัดการประเด็นนี้โดยมีข้อความส่วนหนึ่งว่า “You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:” ซึ่งมีเงื่อนไขให้เผยแพร่รหัสต้นฉบับที่แก้ไขแล้ว ตัวอย่างซอฟร์แวร์ที่ใช้สัญญาอนุญาต GPL เช่น Linux Wordpress VLC Blender ซึ่งเป็นซอฟต์แวร์ที่ได้รับความนิยม และโดยเฉพาะ Linux มีเอกชนหลายเจ้าช่วยกันพัฒนา

อย่างไรก็ตามในยุคที่ใช้งานผ่านเครือข่ายก็มีการอ้างว่าไม่ได้เผยแพร่โปรแกรม จึงไม่ต้องแจกจ่ายรหัสต้นฉบับจึงมีสัญญาอนุญาต GNU AFFERO GENERAL PUBLIC LICENSE (AGPL) ซึ่งมีข้อความส่วนหนึ่งว่า “Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software.” เป็นเงื่อนไขว่าต้องแจกจ่ายรหัสต้นฉบับเมื่อมีนำโปรแกรมที่แก้ไขปรับปรุงไปให้ใช้ผ่านเครือข่ายคอมพิวเตอร์ ตัวอย่างซอฟต์แวร์ที่ใช้สัญญาอนุญาต AGPL เช่น Mastodon Nextcloud OnlyOffice ทั้งหมดเป็นโปรแกรมสำหรับใช้งานผ่านระบบเครือข่าย

สิทธิบัตร

ประเทศไทยยังไม่สิทธิบัตรซอฟต์แวร์ แต่ไม่ใช่ทุกคนอยู่ในประเทศไทยหรือจะอยู่ในประเทศไทยตลอดเวลา จึงต้องคำนึงถึงสิทธิบัตรด้วย เพราะไม่ละเมิดลิขสิทธิ์แต่ละเมิดสิทธิบัตรก็เสียทรัพย์ได้ ดังนั้นสัญญาอนุญาต GPL รุ่นที่ 3 จึงมีข้อความเกี่ยวกับการยุติสิทธิบัตรและค่าสินไหมด้วย «A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License» เช่น เดียวกับสัญญาอนุญาต Apache รุ่นที่ 2 ก็มีความลักษณะคล้ายกันว่า “Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work”

ส่วนที่ไม่ใช่โปรแกรม

สัญญาอนุญาตที่เป็นที่นิยมใช้กับเอกสาร รูปภาพ วิดีโอ และเพลงโดยเฉพาะคือสัญญาอนุญาตครีเอทีฟคอมมอนส์ ซึ่งเขียนย่อว่า CC โดยมีเงื่อนไขย่อยให้เลือกคือ BY คือให้เครดิตว่าเจ้าของผลงาน SA คือหากมีการแก้ไขปรับปรุงต้องเผยแพร่งานที่แก้ไขในสัญญาอนุญาตแบบเดียวกัน NC คือห้ามใช้เพื่อการค้า ND คือห้ามดัดแปลง ซึ่งจะเป็นได้ว่าเงื่อนไข NC และ ND ขัดกับหลักการซอฟต์แวร์เสรี โครงการที่ใช้สัญญาอนุญาตครีเอทีฟคอมมอนส์ เช่น วิกิพีเดีย สัญญาอนุญาตครีเอทีฟคอมมอนส์ถึงแม้จะมีบางบางที่เข้ากันไม่ได้กับซอฟต์แวร์เสรี แต่ก็เป็นการให้สิทธิเป็นการทั่วไปกับสาธารณะกล่าวคือทุกคนได้รับสิทธิ ต่างจากข้อตกลงที่ของบริการโซเชียลมีเดียหลายรายที่ผู้ใช้จะใช้งานได้ก็ต่อเมื่อยอมรับข้อตกลงที่ให้สิทธิแพลตฟอร์มนำผลงานไปใช้ ประมวลผล แก้ไขดัดแปลง เผยแพร่ หรือแม้แต่อนุญาตคนอื่นต่อ

การเลือกสัญญาอนุญาต

โดยทั่วไปควรเลือกสัญญาอนุญาตที่มีความเป็นสาธารณะ เช่น GPL หรือ AGPL เพราะคนธรรมดาย่อมอยากช่วยส่วนรวมมากกว่าเอกชน ยกเว้น

  • โปรแกรมสั้นมากใช้ APACHE-2.0 เพราะเขียนใหม่เอาก็ได้ง่าย ๆ ใช้ GPL ก็ไม่มีประโยชน์
  • ต้องการใช้งานกว้างขวางถึงแม้บุคคลหรือนิติบุคคลที่นำไปใช้จะไม่เผยแพร่ส่วนที่แก้ไขก็ตาม เช่น libogg ที่อยากให้คนใช้ OGG แทน MP3 ให้ใช้สัญญาอนุญาต APACHE-2.0
  • ไลบรารี (Library) ที่ไม่ได้รวมเข้ามาเป็นส่วนเดียวกับโปรแกรม (dynamic link) ที่ต้องการให้คนใช้งานกว้างขวาง แต่ไม่ต้องการให้ไลบรารีเองโดนยังคงความเป็นสาธารณะ แต่ไม่มีเงื่อนกับโปรแกรมที่เรียกใช้ไลบรารี

ควรหลีกเลี่ยงสัญญาอนุญาตแบบ Expat หรือสัญญาอนุญาต MIT เพราะอาจจะทำให้ชุมชนที่พัฒนาและใช้งานซอฟต์แวร์ถูกคุกคามโดยใช้สิทธิบัตรได้ อย่างไรก็ตามอาจจะมีความจำเป็นต้องใช้สัญญาอนุญาตแบบนี้กับองค์กรที่มีความต้องพิเศษและพิจารณาแล้วว่าส่งผลดีกับตัวเองและส่วนรวม

อ่านเพิ่ม

(Posted on 2022-05-10)

I try to convert C-style for-loop in JS to Common Lisp's loop macro for a learning purpose.

for (i=0; i<10; i++) {
  console.log(i)
}

Above JS code can be converted to:

(loop with i = 0
      unless (< i 10) return nil
      do (print i)
      do (incf i))

And, of course, the version below is more appropriate.

(loop for i from 0 below 10 do
    (print i))

The first version looks more flexible in applying to another problem than the last one.

(Posted on 2022-05-09)

In static1.lisp:

(defpackage static1 
 (:use #:cl)) 
(in-package :static1) 

(declaim (ftype (function (string string) string) concat-strings)) 
(defun concat-strings (a b)
  (format nil "~A --- ~A" a b)) 

(declaim (ftype (function (fixnum fixnum) string) concat-nums)) 
(defun concat-nums (a b)
  (concat-strings a b))

Then I ran this command:

sbcl --noinform --eval '(compile-file "static1.lisp")' --quit

SBCL showed this warning:

; caught WARNING: 
;  Derived type of STATIC1::A is 
;    (VALUES FIXNUM &OPTIONAL), 
;  conflicting with its asserted type 
;    STRING. 
;  See also: 
;    The SBCL Manual, Node "Handling of Types"

So SBCL – a Common Lisp implementation, can check type in compile-time. Anyway, a programmer needs to read warnings.

(Posted on 2022-04-25)

Last week, I watched a video about coding and Docker configuration on a TV. I couldn't read any line of code. Then I thought about visually impaired people. How do they code? Every student in Thailand must learn to code. I presume the situation is similar in every country.

People widely use text-to-speech services these days. I cannot find any text-to-speech service for reading source code aloud. Let's assume we have a modified version of a text-to-speech service.

So I looked at source codes in different programming languages on the CodeRosetta website. I perceive Python code blocks by their visual structure purely. To read Python source code, I have to encode its visual structure, namely indents to sounds. Reading a nested code block won't be easy to understand. For example, reading twelve leading white spaces aloud will be very strange. In Lisp, reading open parenthesis and close parenthesis is more straightforward, but I will forget which parenthesis. So the best form of code blocks is in QuickBasic, which has different keywords between different kinds of blocks. For example, FOR with NEXT, and IF with END IF. Later I got a comment from Lemmy.ml, which told me that Ada also has different keywords between different kinds of blocks. Another idea from Lemmy.ml is the reader must convert the Python code block into a similar form as Ada or QuickBasic before reading.

MBasic refers to code by line numbers instead of code blocks. However, by listening to five lines, I forgot the line number. For example, when I heard gosub 70, I forgot what was at line 70.

In X86 Assembly, a programmer labels only the line that the program will jump to it. So X86 Assembly code looks much better than MBasic.

Still, coding in X86 Assembly can be exhaustive in many cases. For example, X86 Assembly doesn’t support recursion. Writing quick sort in X86 Assembly can be too difficult for learning to code.

Haskell doesn’t rely on code blocks. However, reading the symbols, for example, >>= is challenging. Prolog’s symbols are easy to read. For example, we can read :– as IF. Anyway, the Prolog programming paradigm is different from the mainstream one now. So Erlang, whose syntax is similar to Prolog, is a more practical alternative.

In brief, Erlang is a practical, less visual-centric program language. Because it mostly relies on names instead of code blocks, reading names aloud is much easier than reading code blocks aloud. Furthermore, the Erlang programming paradigm is more mainstream now.

(Posted on 2022-04-20)

According to this thread, I compared using only lazy sequences with transducers.

To add the I/O factor, I prepared a data file called “fake.txt” using the program below:

(with-open [w (io/writer "fake.txt")]
  (doseq [n (range 10000000)]
    (.write w (str n "\n"))))

F1 is the lazy-sequence-based version. It reads data from “fake.txt” and does a few steps of computations.

(defn f1
  []
  (with-open [r (io/reader "fake.txt")]
    (->> (line-seq r)
         (map parse-long)
         (map inc)
         (filter even?)
         (map inc)
         (reduce + 0))))

F2 is the transducer-based version of F1.

(defn f2
  []
  (with-open [r (io/reader "fake.txt")]
    (transduce (comp (map parse-long)
                     (map inc)
                     (filter even?)
                     (map inc))
               +
               (line-seq r))))

I evaluated them using Criterium.

(with-progress-reporting (quick-bench (f1) :verbose))
(with-progress-reporting (quick-bench (f2) :verbose))

Here is the result.

#################### F1 ###################
Evaluation count : 6 in 6 samples of 1 calls.
Execution time sample mean : 3.811858 sec
Execution time mean : 3.812064 sec

#################### F2 ###################
Evaluation count : 6 in 6 samples of 1 calls.
Execution time sample mean : 1.490624 sec
Execution time mean : 1.490777 sec

F1, which is the lazy sequence version, took 3.812064 seconds. F2, which is the transducer version, took 1.490777. So the transducer version is 155.71% faster than the lazy sequence version.

In brief, this biased experiment shows the transducer version is much faster than the pure lazy sequence version.

(Posted 2022-03-23)

I recommend Clojure as the first programming language to learn for beginners. I recommend “Poetry of Programming” as the first book for learning Clojure. I recommend “Clojure for the Brave and True” as the second book for learning Clojure.

(Posted on 2022-03-22)

  1. Lisp สอนให้ฉันสร้างฟังก์ชันที่แปลงข้อมูลทีละขั้นตอน แทนที่จะเพิ่มตัวแปรที่ถูกแก้ไขไปเรื่อย ๆ ลงในลูป โครงสร้างข้อมูลที่ไม่ถูกเปลี่ยนค่ามีความสำคัญสำหรับการแปลงข้อมูลทีละขั้นตอนโดยไม่ทำให้ข้อมูลที่มีอยู่แล้วยุ่งเหยิง โครงสร้างข้อมูลเริ่มต้นของ Lisp เป็นรายการเชื่อมโยงทางเดียว (singly linked list) ซึ่งเหมาะสำหรับใช้เป็นโครงสร้างข้อมูลที่ไม่ถูกเปลี่ยนค่า

  2. มาโครของ Lisp เขียนง่ายเมื่อเทียบกับคู่แข่ง มาโครของ Rust นั้นทรงพลัง มาโครของ Rust นั้นเกี่ยวกับการแปลง TokenStream และมาโครของ Lisp นั้นเกี่ยวกับการเปลี่ยนรายการ (list) อย่างไรก็ตามฉันชอบที่จะแปลงรายการกว่าเปลี่ยน TokenStream เนื่องจากฉันไม่ต้องเรียนรู้โครงสร้างใหม่และคำสั่งใหม่สำหรับจัดการโครงสร้างใหม่

(Posted on 2022-03-22)

  1. Lisp taught me to create functions that transform data step by step instead of adding mutable variables into loops. An immutable data structure is important for transforming data step by step without messing up existing data. Lisp's default data structure is a singly linked list.

  2. Lisp macro is easy to write compared to competitors. Rust's macro is powerful. Rust's macro is about transforming a TokenStream, and #Lisp's macro is about transforming a list. However, I prefer transforming a list to a TokenStream since I don't have to learn new structures and new commands for manipulating a new structure.