diff options
-rw-r--r-- | common-lisp.html.markdown | 2 | ||||
-rw-r--r-- | de-de/git-de.html.markdown | 10 | ||||
-rw-r--r-- | fsharp.html.markdown | 5 | ||||
-rw-r--r-- | ms-my/clojure-macros-my.html.markdown | 154 | ||||
-rw-r--r-- | ms-my/common-lisp-my.html.markdown | 692 | ||||
-rw-r--r-- | ms-my/elisp-my.html.markdown | 347 | ||||
-rw-r--r-- | php.html.markdown | 2 | ||||
-rw-r--r-- | ru-ru/rust-ru.html.markdown | 316 | ||||
-rw-r--r-- | rust.html.markdown | 9 | ||||
-rw-r--r-- | vim.html.markdown | 5 |
10 files changed, 1533 insertions, 9 deletions
diff --git a/common-lisp.html.markdown b/common-lisp.html.markdown index 76e7735b..28b5173b 100644 --- a/common-lisp.html.markdown +++ b/common-lisp.html.markdown @@ -502,7 +502,7 @@ nil ; false; also, the empty list: () (fact 5) ; => 120 -(loop :for x :across "abc" :collect x) +(loop :for x :across "abcd" :collect x) ; => (#\a #\b #\c #\d) (dolist (i '(1 2 3 4)) diff --git a/de-de/git-de.html.markdown b/de-de/git-de.html.markdown index a0ed120f..d2222d2c 100644 --- a/de-de/git-de.html.markdown +++ b/de-de/git-de.html.markdown @@ -10,7 +10,7 @@ lang: de-de Git ist eine verteilte Versions- und Quellcodeverwaltung. -Es nimmt Schnappschüsse der Projekte, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können. +Es nimmt Schnappschüsse der Projekte auf, um mit diesen Schnappschüssen verschiedene Versionen unterscheiden und den Quellcode verwalten zu können. Anmerkung des Übersetzers: Einige englische Begriffe wie *Repository*, *Commit* oder *Head* sind idiomatische Bestandteile im Umgang mit Git. Sie wurden nicht übersetzt. @@ -43,7 +43,7 @@ Eine Versionsverwaltung erfasst die Änderungen einer Datei oder eines Verzeichn ### Repository (Repo) -Ein Satz von Dateien, Verzeichnisen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben. +Ein Satz von Dateien, Verzeichnissen, Historieneinträgen, Commits und Heads. Stell es dir wie eine Quellcode-Datenstruktur vor, unter anderem mit der Eigenschaft, dass alle *Elemente* dir Zugriff auf die Revisionshistorie geben. Ein Repository besteht in Git aus dem .git-Verzeichnis und dem Arbeitsverzeichnis. @@ -66,7 +66,7 @@ Ein Commit ist ein Schnappschuss von Änderungen in deinem Arbeitsverzeichnis. W ### Branch -Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf Stand gebracht und zeigt dann auf den neuen letzten Commit. +Ein Branch, ein Ast oder Zweig, ist im Kern ein Pointer auf den letzten Commit, den du gemacht hast. Während des Commits wird der Pointer automatisch auf diesen Stand gebracht und zeigt dann auf den neuen letzten Commit. ### HEAD und head (Teil des .git-Verzeichnisses) @@ -215,7 +215,7 @@ $ git commit --amend -m "Correct message" ### diff -Zeigt die Unterschiede zwischen Dateien von Arbeitsverzeichnisse, dem Index und Commits an. +Zeigt die Unterschiede zwischen Dateien vom Arbeitsverzeichnis, dem Index und Commits an. ```bash # Unterschiede zwischen deinem Arbeitsverzeichnis und dem Index anzeigen @@ -330,7 +330,7 @@ $ git push origin master ### rebase (mit Vorsicht einsetzen) -Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden. +Nimm alle Änderungen, die in einem Branch durch Commits vorgenommen wurden, und übertrage sie auf einen anderen Branch. Achtung: Führe keinen Rebase von Commits durch, die auf ein öffentliches Repo gepusht wurden! ```bash # Rebase "experimentBranch" in den "master"-Branch diff --git a/fsharp.html.markdown b/fsharp.html.markdown index dd85552d..59461eed 100644 --- a/fsharp.html.markdown +++ b/fsharp.html.markdown @@ -34,7 +34,7 @@ let myFloat = 3.14 let myString = "hello" // note that no types needed // ------ Lists ------ -let twoToFive = [2; 3; 4; 5] // Square brackets create a list with +let twoToFive = [2; 3; 4; 5] // Square brackets create a list with // semicolon delimiters. let oneToFive = 1 :: twoToFive // :: creates list with new 1st element // The result is [1; 2; 3; 4; 5] @@ -53,7 +53,8 @@ add 2 3 // Now run the function. // to define a multiline function, just use indents. No semicolons needed. let evens list = - let isEven x = x % 2 = 0 // Define "isEven" as a sub function + let isEven x = x % 2 = 0 // Define "isEven" as a sub function. Note + // that equality operator is single char "=". List.filter isEven list // List.filter is a library function // with two parameters: a boolean function // and a list to work on diff --git a/ms-my/clojure-macros-my.html.markdown b/ms-my/clojure-macros-my.html.markdown new file mode 100644 index 00000000..099f376e --- /dev/null +++ b/ms-my/clojure-macros-my.html.markdown @@ -0,0 +1,154 @@ +--- +language: "clojure macros" +filename: learnclojuremacros-ms.clj +contributors: + - ["Adam Bard", "http://adambard.com/"] +translators: + - ["Burhanuddin Baharuddin", "https://github.com/burhanloey"] +lang: ms-my +--- + +Sama seperti Lisp yang lain, sifat Clojure yang mempunyai [homoiconicity](https://en.wikipedia.org/wiki/Homoiconic) +membolehkan anda untuk menggunakan sepenuhnya language ini untuk menulis code yang boleh generate code sendiri yang +dipanggil "macro". Macro memberi cara yang sangat menarik untuk mengubahsuai language mengikut kehendak anda. + +Jaga-jaga. Penggunaan macro boleh dikatakan tidak elok jika digunakan secara berlebihan jika function sahaja sudah mencukupi. +Gunakan macro hanya apabila anda mahu lebih kawalan terhadap sesuatu form. + +Biasakan diri dengan Clojure terlebih dahulu. Pastikan anda memahami semuanya di +[Clojure in Y Minutes](/docs/ms-my/clojure-my/). + +```clojure +;; Define macro menggunakan defmacro. Macro anda akan output list yang boleh +;; dijalankan sebagai code clojure. +;; +;; Macro ini adalah sama seperti (reverse "Hello World") +(defmacro my-first-macro [] + (list reverse "Hello World")) + +;; Lihat hasil macro tersebut menggunakan macroexpand atau macroexpand-1. +;; +;; Pastikan panggilan kepada macro tersebut mempunyai tanda petikan +(macroexpand '(my-first-macro)) +;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World") + +;; Anda boleh menggunakan eval terus kepada macroexpand untuk mendapatkan hasil: +(eval (macroexpand '(my-first-macro))) +; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; Tetapi anda sepatutnya menggunakan cara yang lebih ringkas, sama seperti panggilan kepada function: +(my-first-macro) ; -> (\d \l \o \r \W \space \o \l \l \e \H) + +;; Anda boleh memudahkan cara untuk membuat macro dengan mengguna tanda petikan +;; untuk membuat list untuk macro: +(defmacro my-first-quoted-macro [] + '(reverse "Hello World")) + +(macroexpand '(my-first-quoted-macro)) +;; -> (reverse "Hello World") +;; Perhatikan yang reverse bukan lagi function tetapi adalah simbol. + +;; Macro boleh mengambil argument. +(defmacro inc2 [arg] + (list + 2 arg)) + +(inc2 2) ; -> 4 + +;; Tetapi jika anda membuat cara yang sama menggunakan tanda petikan, anda akan mendapat error sebab +;; argument tersebut juga akan mempunyai tanda petikan. Untuk mengatasi masalah ini, Clojure memberi +;; cara untuk meletak tanda petikan untuk macro: `. Di dalam `, anda boleh menggunakan ~ untuk mendapatkan scope luaran +(defmacro inc2-quoted [arg] + `(+ 2 ~arg)) + +(inc2-quoted 2) + +;; Anda boleh menggunakan destructuring untuk argument seperti biasa. Gunakan ~@ untuk mengembangkan variable +(defmacro unless [arg & body] + `(if (not ~arg) + (do ~@body))) ; Jangan lupa do! + +(macroexpand '(unless true (reverse "Hello World"))) +;; -> +;; (if (clojure.core/not true) (do (reverse "Hello World"))) + +;; (unless) mengembalikan body jika argument yang pertama adalah false. +;; Jika tidak, (unless) akan memulangkan nil + +(unless true "Hello") ; -> nil +(unless false "Hello") ; -> "Hello" + +;; Jika tidak berhati-hati, macro boleh memeningkan anda dengan mencampuradukkan nama variable +(defmacro define-x [] + '(do + (def x 2) + (list x))) + +(def x 4) +(define-x) ; -> (2) +(list x) ; -> (2) + +;; Untuk mengelakkan masalah ini, gunakan gensym untuk mendapatkan identifier yang berbeza +(gensym 'x) ; -> x1281 (atau yang sama waktu dengannya) + +(defmacro define-x-safely [] + (let [sym (gensym 'x)] + `(do + (def ~sym 2) + (list ~sym)))) + +(def x 4) +(define-x-safely) ; -> (2) +(list x) ; -> (4) + +;; Anda boleh menggunakan # di dalam ` untuk menghasilkan gensym untuk setiap simbol secara automatik +(defmacro define-x-hygienically [] + `(do + (def x# 2) + (list x#))) + +(def x 4) +(define-x-hygienically) ; -> (2) +(list x) ; -> (4) + +;; Kebiasaannya helper function digunakan untuk membuat macro. Jom buat beberapa function untuk +;; membuatkan program boleh memahami inline arithmetic. Saja suka-suka. +(declare inline-2-helper) +(defn clean-arg [arg] + (if (seq? arg) + (inline-2-helper arg) + arg)) + +(defn apply-arg + "Diberi argument [x (+ y)], pulangkan (+ x y)" + [val [op arg]] + (list op val (clean-arg arg))) + +(defn inline-2-helper + [[arg1 & ops-and-args]] + (let [ops (partition 2 ops-and-args)] + (reduce apply-arg (clean-arg arg1) ops))) + +;; Kita boleh test terlebih dahulu tanpa membuat macro +(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5)) + +; Tetapi, kita perlu membuat macro jika kita mahu jalankan code tersebut +(defmacro inline-2 [form] + (inline-2-helper form)) + +(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1))) +; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1) + +(inline-2 (1 + (3 / 2) - (1 / 2) + 1)) +; -> 3 (sepatutnya, 3N, sebab nombor tersebut ditukarkan kepada pecahan rasional menggunakan /) +``` + +### Bacaaan Lanjut + +Writing Macros daripada [Clojure for the Brave and True](http://www.braveclojure.com/) +[http://www.braveclojure.com/writing-macros/](http://www.braveclojure.com/writing-macros/) + +Dokumen rasmi +[http://clojure.org/macros](http://clojure.org/macros) + +Bila perlu guna macro? +[http://dunsmor.com/lisp/onlisp/onlisp_12.html](http://dunsmor.com/lisp/onlisp/onlisp_12.html) diff --git a/ms-my/common-lisp-my.html.markdown b/ms-my/common-lisp-my.html.markdown new file mode 100644 index 00000000..f5914aae --- /dev/null +++ b/ms-my/common-lisp-my.html.markdown @@ -0,0 +1,692 @@ +--- + +language: "Common Lisp" +filename: commonlisp-ms.lisp +contributors: + - ["Paul Nathan", "https://github.com/pnathan"] + - ["Rommel Martinez", "https://ebzzry.io"] +translators: + - ["Burhanuddin Baharuddin", "https://github.com/burhanloey"] +lang: ms-my +--- + +Common Lisp ialah programming language yang general-purpose (boleh digunakan untuk semua benda) dan multi-paradigm (konsep yang pelbagai) sesuai untuk pelbagai kegunaan di dalam +industri aplikasi. Common Lisp biasa digelar sebagai programmable programming language (programming language yang boleh di-program-kan). + +Sumber bacaan yang klasik ialah [Practical Common Lisp](http://www.gigamonkeys.com/book/). Sumber bacaan yang lain dan +yang terbaru ialah [Land of Lisp](http://landoflisp.com/). Buku baru mengenai best practices (amalan terbaik), +[Common Lisp Recipes](http://weitz.de/cl-recipes/), baru sahaja diterbitkan. + + + +```common-lisp + +;;;----------------------------------------------------------------------------- +;;; 0. Syntax +;;;----------------------------------------------------------------------------- + +;;; General form (Bentuk umum) + +;;; Ada dua asas dalam syntax CL: ATOM dan S-EXPRESSION. +;;; Kebiasaannya, gabungan S-expression dipanggil sebagai `forms`. + +10 ; atom; bermaksud seperti yang ditulis iaitu nombor 10 +:thing ; juga atom; bermaksud simbol :thing +t ; juga atom, bermaksud true (ya/betul/benar) +(+ 1 2 3 4) ; s-expression +'(4 :foo t) ; juga s-expression + + +;;; Comment (Komen) + +;;; Comment satu baris bermula dengan semicolon; gunakan empat untuk comment +;;; mengenai file, tiga untuk seksyen penghuraian, dua untuk yang dalam definition, +;;; dan satu untuk satu baris. Sebagai contoh, + +;;;; life.lisp + +;;; Foo bar baz, disebabkan quu quux. Sangat optimum untuk krakaboom dan umph. +;;; Diperlukan oleh function LINULUKO. Ini merepek sahaja kebaboom. + +(defun meaning (life) + "Memulangkan hasil pengiraan makna KEHIDUPAN" + (let ((meh "abc")) + ;; Jalankan krakaboom + (loop :for x :across meh + :collect x))) ; Simpan hasil ke x, kemudian pulangkan + +;;; Komen berbentuk blok, sebaliknya, membenarkan komen untuk bentuk bebas. Komen +;;; tersebut berada di antara #| dan |# + +#| Ini adalah komen berbentuk blok di mana + tulisan boleh ditulis dalam beberapa baris dan + #| + juga boleh dalam bentuk nested (berlapis-lapis)! + |# +|# + + +;;; Environment (benda-benda yang diperlukan untuk program menggunakan Common Lisp) + +;;; Common Lisp ada banyak jenis; kebanyakannya mengikut standard. SBCL +;;; ialah titik permulaan yang baik. Quicklisp boleh digunakan untuk install +;;; library third party. + +;;; CL kebiasaannya digunakan dengan text editor dan Real Eval Print +;;; Loop (REPL) yang dilancarkan dengan serentak. REPL membolehkan kita menjelajah +;;; program secara interaktif semasa program tersebut sedang berjalan secara "live". + + +;;;----------------------------------------------------------------------------- +;;; 1. Datatype primitif dan operator +;;;----------------------------------------------------------------------------- + +;;; Simbol + +'foo ; => FOO Perhatikan simbol menjadi huruf besar secara automatik. + +;;; INTERN menjadikan string sebagai simbol secara manual. + +(intern "AAAA") ; => AAAA +(intern "aaa") ; => |aaa| + +;;; Nombor + +9999999999999999999999 ; integer +#b111 ; binary => 7 +#o111 ; octal => 73 +#x111 ; hexadecimal => 273 +3.14159s0 ; single +3.14159d0 ; double +1/2 ; ratio +#C(1 2) ; complex number + +;;; Function ditulis sebagai (f x y z ...) di mana f ialah function dan +;;; x, y, z, ... adalah argument. + +(+ 1 2) ; => 3 + +;;; Jika anda ingin membuat data sebagai data bukannya function, gunakan QUOTE +;;; untuk mengelakkan data tersebut daripada dikira oleh program + +(quote (+ 1 2)) ; => (+ 1 2) +(quote a) ; => A + +;;; Singkatan untuk QUOTE ialah ' (tanda petikan) + +'(+ 1 2) ; => (+ 1 2) +'a ; => A + +;;; Operasi arithmetic asas + +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + +;;; Boolean + +t ; true; semua nilai yang bukan NIL ialah true +nil ; false; termasuklah list yang kosong: () +(not nil) ; => T +(and 0 t) ; => T +(or 0 nil) ; => 0 + +;;; Character + +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA + +;;; String ialah array character yang tidak berubah panjang + +"Hello, world!" +"Benjamin \"Bugsy\" Siegel" ; backslash ialah escape character + +;;; String boleh digabungkan + +(concatenate 'string "Hello, " "world!") ; => "Hello, world!" + +;;; String boleh diperlakukan seperti urutan character + +(elt "Apple" 0) ; => #\A + +;;; FORMAT digunakan untuk output mengikut format, daripada penggubahan string +;;; yang simple sehinggalah loop dan conditional. Argument pertama untuk FORMAT +;;; menentukan ke mana string akan pergi. Jika NIL, FORMAT +;;; akan pulangkan string sebagai data string; jika T, FORMAT akan output +;;; ke standard output, biasanya di screen, kemudian pulangkan NIL. + +(format nil "~A, ~A!" "Hello" "world") ; => "Hello, world!" +(format t "~A, ~A!" "Hello" "world") ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 2. Variable +;;;----------------------------------------------------------------------------- + +;;; Anda boleh membuat variable global (dynamically scoped) menggunakan DEFVAR dan +;;; DEFPARAMETER. Nama variable boleh guna mana-mana character kecuali: ()",'`;#|\ + +;;; Beza antara DEFVAR dengan DEFPARAMETER ialah DEFVAR tidak akan ubah nilai +;;; variable jika dijalankan semula. Manakala DEFPARAMETER, akan mengubah nilai +;;; jika dijalankan semula. + +;;; Kebiasaannya, variable global diletakkan earmuff (asterisk) pada nama. + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;;; Anda juga boleh menggunakan character unicode. +(defparameter *AΛB* nil) + +;;; Variable yang tidak wujud boleh diakses tetapi akan menyebabkan undefined +;;; behavior. Jangan buat. + +;;; Anda boleh membuat local binding menggunakan LET. Dalam snippet berikut, `me` +;;; terikat dengan "dance with you" hanya dalam (let ...). LET mesti akan pulangkan +;;; nilai `form` yang paling terakhir. + +(let ((me "dance with you")) me) ; => "dance with you" + + +;;;-----------------------------------------------------------------------------; +;;; 3. Struct dan collection +;;;-----------------------------------------------------------------------------; + + +;;; Struct + +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) +(dog-p *rover*) ; => T +(dog-name *rover*) ; => "rover" + +;;; DOG-P, MAKE-DOG, dan DOG-NAME semuanya dibuat oleh DEFSTRUCT secara automatik + + +;;; Pair + +;;; CONS membuat pair. CAR dan CDR pulangkan head (kepala) dan tail (ekor) CONS-pair. + +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + + +;;; List + +;;; List ialah data structure linked-list, dihasilkan daripada pair CONS dan +;;; berakhir dengan NIL (atau '()) menandakan akhirnya list tersebut + +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) + +;;; LIST ialah constructor untuk memudahkan penghasilan list + +(list 1 2 3) ; => '(1 2 3) + +;;; Apabila argument pertama untuk CONS ialah atom dan argument kedua ialah +;;; list, CONS akan pulangkan CONS-pair baru dengan argument pertama sebagai +;;; item pertama dan argument kedua sebagai CONS-pair yang lain + +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;;; Gunakan APPEND untuk menggabungkan list + +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; Atau CONCATENATE + +(concatenate 'list '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; List ialah type utama, jadi ada pelbagai function untuk mengendalikan +;;; list, contohnya: + +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => NIL +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; Vector + +;;; Vector ialah array yang tidak berubah panjang + +#(1 2 3) ; => #(1 2 3) + +;;; Gunakan CONCATENATE untuk menggabungkan vector + +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + + +;;; Array + +;;; Vector dan string adalah sejenis array. + +;;; 2D array + +(make-array (list 2 2)) ; => #2A((0 0) (0 0)) +(make-array '(2 2)) ; => #2A((0 0) (0 0)) +(make-array (list 2 2 2)) ; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;;; Perhatian: nilai awal MAKE-ARRAY adalah bergantung kepada jenis Common Lisp. +;;; Untuk meletakkan nilai awal secara manual: + +(make-array '(2) :initial-element 'unset) ; => #(UNSET UNSET) + +;;; Untuk mengakses element di kedudukan 1, 1, 1: + +(aref (make-array (list 2 2 2)) 1 1 1) ; => 0 + + +;;; Adjustable vector (vector yang boleh berubah) + +;;; Adjustable vector mempunyai rupa yang sama dengan +;;; vector yang tidak berubah panjang. + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) +*adjvec* ; => #(1 2 3) + +;;; Tambah element baru + +(vector-push-extend 4 *adjvec*) ; => 3 +*adjvec* ; => #(1 2 3 4) + + +;;; Set hanyalah list: + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;;; Tetapi, anda perlukan data structure yang lebih baik untuk digunakan dengan +;;; data set yang sangat banyak + +;;; Kamus dibuat menggunakan hash table. + +;;; Bina hash table + +(defparameter *m* (make-hash-table)) + +;;; Tetapkan nilai + +(setf (gethash 'a *m*) 1) + +;;; Baca nilai + +(gethash 'a *m*) ; => 1, T + +;;; CL boleh memulangkan beberapa nilai (multiple value). + +(values 1 2) ; => 1, 2 + +;;; dan boleh digunakan dengan MULTIPLE-VALUE-BIND untuk bind setiap nilai + +(multiple-value-bind (x y) + (values 1 2) + (list y x)) + +; => '(2 1) + +;;; GETHASH antara contoh function yang memulangkan multiple value. Value +;;; pertama ialah nilai untuk key dalam hash table; jika key tidak +;;; jumpa GETHASH akan pulangkan NIL. + +;;; Value kedua menentukan sama ada key tersebut betul-betul wujud dalam hash +;;; table. Jika key tidak jumpa dalam table value tersebut ialah NIL. Cara ini +;;; membolehkan kita untuk periksa sama ada value untuk key ialah NIL. + +;;; Dapatkan value yang tidak wujud akan pulangkan nil + +(gethash 'd *m*) ;=> NIL, NIL + +;;; Anda boleh menentukan value default untuk key yang tidak wujud + +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;;; Jom lihat penggunaan multiple return value di dalam code. + +(multiple-value-bind (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + + +;;;----------------------------------------------------------------------------- +;;; 3. Function +;;;----------------------------------------------------------------------------- + +;;; Gunakan LAMBDA untuk membuat anonymous function. Function sentiasa memulangkan +;;; value untuk expression terakhir. + +(lambda () "Hello World") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}> + +;;; Gunakan FUNCALL untuk memanggil anonymous function + +(funcall (lambda () "Hello World")) ; => "Hello World" +(funcall #'+ 1 2 3) ; => 6 + +;;; Panggilan kepada FUNCALL juga boleh terjadi apabila lambda tersebut ialah CAR +;;; (yang pertama) untuk list (yang tidak mempunyai tanda petikan) + +((lambda () "Hello World")) ; => "Hello World" +((lambda (val) val) "Hello World") ; => "Hello World" + +;;; FUNCALL digunakan apabila argument sudah diketahui. Jika tidak, gunakan APPLY + +(apply #'+ '(1 2 3)) ; => 6 +(apply (lambda () "Hello World") nil) ; => "Hello World" + +;;; Untuk menamakan sebuah function, guna DEFUN + +(defun hello-world () "Hello World") +(hello-world) ; => "Hello World" + +;;; Simbol () di atas bermaksud list kepada argument + +(defun hello (name) (format nil "Hello, ~A" name)) +(hello "Steve") ; => "Hello, Steve" + +;;; Function boleh ada argument optional (tidak wajib); argument tersebut bernilai +;;; NIL secara default + +(defun hello (name &optional from) + (if from + (format t "Hello, ~A, from ~A" name from) + (format t "Hello, ~A" name))) + +(hello "Jim" "Alpacas") ; => Hello, Jim, from Alpacas + +;;; Nilai default boleh ditetapkan untuk argument tersebut + +(defun hello (name &optional (from "The world")) + (format nil "Hello, ~A, from ~A" name from)) + +(hello "Steve") ; => Hello, Steve, from The world +(hello "Steve" "the alpacas") ; => Hello, Steve, from the alpacas + +;;; Function juga mempunyai keyword argument untuk membolehkan argument diletakkan +;;; tidak mengikut kedudukan + +(defun generalized-greeter (name &key (from "the world") (honorific "Mx")) + (format t "Hello, ~A ~A, from ~A" honorific name from)) + +(generalized-greeter "Jim") +; => Hello, Mx Jim, from the world + +(generalized-greeter "Jim" :from "the alpacas you met last summer" :honorific "Mr") +; => Hello, Mr Jim, from the alpacas you met last summer + + +;;;----------------------------------------------------------------------------- +;;; 4. Kesamaan +;;;----------------------------------------------------------------------------- + +;;; CL mempunyai sistem kesaksamaan yang canggih. Antaranya adalah seperti berikut. + +;;; Untuk nombor, guna `=' +(= 3 3.0) ; => T +(= 2 1) ; => NIL + +;;; Untuk identiti object (lebih kurang) guna EQL +(eql 3 3) ; => T +(eql 3 3.0) ; => NIL +(eql (list 3) (list 3)) ; => NIL + +;;; untuk list, string, dan bit-vector, guna EQUAL +(equal (list 'a 'b) (list 'a 'b)) ; => T +(equal (list 'a 'b) (list 'b 'a)) ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 5. Control Flow +;;;----------------------------------------------------------------------------- + +;;; Conditional (syarat) + +(if t ; test expression + "this is true" ; then expression + "this is false") ; else expression +; => "this is true" + +;;; Dalam conditional, semua value yang bukan NIL ialah true + +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;;; Guna COND untuk meletakkan beberapa test +(cond ((> 2 2) (error "wrong!")) + ((< 2 2) (error "wrong again!")) + (t 'ok)) ; => 'OK + +;;; TYPECASE adalah seperti switch tetapi untuk data type value tersebut +(typecase 1 + (string :string) + (integer :int)) +; => :int + + +;;; Loop + +;;; Recursion + +(defun fact (n) + (if (< n 2) + 1 + (* n (fact(- n 1))))) + +(fact 5) ; => 120 + +;;; Iteration + +(defun fact (n) + (loop :for result = 1 :then (* result i) + :for i :from 2 :to n + :finally (return result))) + +(fact 5) ; => 120 + +(loop :for x :across "abc" :collect x) +; => (#\a #\b #\c #\d) + +(dolist (i '(1 2 3 4)) + (format t "~A" i)) +; => 1234 + + +;;;----------------------------------------------------------------------------- +;;; 6. Mutation +;;;----------------------------------------------------------------------------- + +;;; Guna SETF untuk meletakkan nilai baru untuk variable yang sedia ada. Ini sama +;;; seperti contoh hash table di atas. + +(let ((variable 10)) + (setf variable 2)) +; => 2 + +;;; Sebaik-baiknya kurangkan penggunaan destructive function dan elakkan +;;; mutation jika boleh. + + +;;;----------------------------------------------------------------------------- +;;; 7. Class dan object +;;;----------------------------------------------------------------------------- + +;;; Takde dah class untuk haiwan. Jom buat Human-Powered Mechanical +;;; Conveyances (Kenderaan Mekanikal Berkuasa Manusia). + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "A human powered conveyance")) + +;;; Argument untuk DEFCLASS, mengikut susunan ialah: +;;; 1. nama class +;;; 2. list untuk superclass +;;; 3. list untuk slot +;;; 4. specifier optional (tidak wajib) + +;;; Apabile list untuk superclass tidak ditetapkan, list yang kosong bermaksud +;;; class standard-object. Ini *boleh* ditukar, kalau anda tahu apa yang anda buat. +;;; Baca Art of the Metaobject Protocol untuk maklumat lebih lanjut. + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + +;;; Panggilan DESCRIBE kepada class HUMAN-POWERED-CONVEYANCE di REPL akan memberi: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #<STANDARD-CLASS +; HUMAN-POWERED-CONVEYANCE>: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;;; Perhatikan apa yang berlaku. CL memang direka sebagai sistem interaktif. + +;;; Untuk membuat method, jom kira berapa panjang lilitan untuk +;;; roda basikal menggunakan formula: C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;;; Nilai PI memang sudah ada dalam CL + +;;; Katakanlah kita ingin ambil tahu efficiency value (nilai keberkesanan) +;;; rower (pendayung) di dalam canoe (perahu) adalah berbentuk logarithmic. Ini +;;; boleh ditetapkan di dalam constructor/initializer. + +;;; Untuk initialize instance selepas CL sudah siap construct: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + +;;; Kemudian untuk construct sesebuah instance dan periksa purata efficiency... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;----------------------------------------------------------------------------- +;;; 8. Macro +;;;----------------------------------------------------------------------------- + +;;; Macro membolehkan anda untuk menambah syntax language. CL tidak ada +;;; WHILE loop, tetapi, kita boleh mencipta syntax ter. Jika kita buat menggunakan +;;; naluri, kita akan dapat: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" + (let ((block-name (gensym)) (done (gensym))) + `(tagbody + ,block-name + (unless ,condition + (go ,done)) + (progn + ,@body) + (go ,block-name) + ,done))) + +;;; Jom lihat versi yang lebih high-level: + +(defmacro while (condition &body body) + "While `condition` is true, `body` is executed. +`condition` is tested prior to each execution of `body`" + `(loop while ,condition + do + (progn + ,@body))) + +;;; Namun, dengan compiler yang modern, cara ini tidak diperlukan; form LOOP +;;; compile sama sahaja dan juga mudah dibaca. + +;;; Perhatikan ``` digunakan, sama juga `,` dan `@`. ``` ialah operator jenis quote +;;; yang dipanggil quasiquote; operator tersebut membolehkan penggunaan `,` . +;;; `,` membolehkan variable "di-unquote-kan". @ mengembangkan list. + +;;; GENSYM membuat simbol unik yang pasti tidak wujud di tempat-tempat yang +;;; lain. Ini kerana macro dikembangkan semasa compile dan +;;; nama variable di dalam macro boleh bertembung dengan nama variable yang +;;; digunakan dalam code yang biasa. + +;;; Baca Practical Common Lisp dan On Lisp untuk maklumat lebih lanjut mengenai macro. +``` + + +## Bacaan lanjut + +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Common Lisp: A Gentle Introduction to Symbolic Computation](https://www.cs.cmu.edu/~dst/LispBook/book.pdf) + + +## Maklumat tambahan + +- [CLiki](http://www.cliki.net/) +- [common-lisp.net](https://common-lisp.net/) +- [Awesome Common Lisp](https://github.com/CodyReichert/awesome-cl) +- [Lisp Lang](http://lisp-lang.org/) + + +## Kredit + +Terima kasih banyak diucapkan kepada ahli Scheme yang membuat permulaan yang sangat +bagus dan mudah untuk diguna pakai untuk Common Lisp. + +- [Paul Khuong](https://github.com/pkhuong) untuk review yang bagus. diff --git a/ms-my/elisp-my.html.markdown b/ms-my/elisp-my.html.markdown new file mode 100644 index 00000000..73dff0f4 --- /dev/null +++ b/ms-my/elisp-my.html.markdown @@ -0,0 +1,347 @@ +--- +language: elisp +contributors: + - ["Bastien Guerry", "https://bzg.fr"] + - ["Saurabh Sandav", "http://github.com/SaurabhSandav"] +translators: + - ["Burhanuddin Baharuddin", "https://github.com/burhanloey"] +lang: ms-my +filename: learn-emacs-lisp-ms.el +--- + +```scheme +;; Ini adalah pengenalan kepada Emacs Lisp dalam masa 15 minit (v0.2d) +;; +;; Mula-mula pastikan anda sudah membaca artikel daripada Peter Norvig ini: +;; http://norvig.com/21-days.html +;; +;; Kemudian install GNU Emacs 24.3: +;; +;; Debian: apt-get install emacs (atau lihat arahan untuk distro anda) +;; OSX: http://emacsformacosx.com/emacs-builds/Emacs-24.3-universal-10.6.8.dmg +;; Windows: http://ftp.gnu.org/gnu/windows/emacs/emacs-24.3-bin-i386.zip +;; +;; Maklumat lanjut boleh didapati di: +;; http://www.gnu.org/software/emacs/#Obtaining + +;; Amaran penting: +;; +;; Tutorial ini tidak akan merosakkan komputer anda melainkan jika anda berasa +;; terlalu marah sehingga anda menghempap komputer anda ke lantai. Kalau begitu, +;; saya dengan ini tidak akan bertanggungjawab terhadap apa-apa. Berseronoklah ya! + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Buka Emacs. +;; +;; Tekan `q' untuk tutup mesej selamat datang. +;; +;; Sekarang lihat garis kelabu di bahagian bawah window: +;; +;; "*scratch*" ialah nama ruangan untuk anda edit. +;; Ruangan ini disebut sebagai "buffer". +;; +;; Buffer scratch ialah buffer yang default setiap kali Emacs dibuka. +;; Anda bukannya edit file: anda edit buffer yang kemudiannya +;; boleh save ke file. +;; +;; "Lisp interaction (interaksi)" merujuk kepada command yang wujud di sini. +;; +;; Emacs mempunyai beberapa command yang sedia ada dalam setiap buffer, +;; dan sesetengah command yang lain boleh didapati jika sesetengah mode +;; diaktifkan. Di sini kita menggunakan `lisp-interaction-mode', yang +;; mempunyai command untuk menjalankan dan mengendalikan code Elisp. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Semicolon akan menjadikan comment sepanjang baris tersebut. +;; +;; Program Elisp mengandungi symbolic expressions ("sexps"): +(+ 2 2) + +;; Symbolic expression di atas dibaca begini "Tambah 2 pada 2". + +;; Sexps dilitupi oleh parentheses, dan boleh dalam bentuk nested (parentheses +;; dalam parentheses): +(+ 2 (+ 1 1)) + +;; Symbolic expression mengandungi atom atau symbolic expression +;; yang lain. Untuk contoh di atas, 1 dan 2 ialah atom, +;; (+ 2 (+ 1 1)) dan (+ 1 1) ialah symbolic expression. + +;; Dengan menggunakan `lisp-interaction-mode', anda boleh evaluate +;; (mendapatkan hasil pengiraan) sexps. Letak cursor selepas parenthesis penutup +;; kemudian tekan control dan j ("C-j"). + +(+ 3 (+ 1 2)) +;; ^ cursor di sini +;; `C-j' => 6 + +;; `C-j' memasukkan jawapan pengiraan ke dalam buffer. + +;; `C-xC-e' memaparkan jawapan yang sama di bahagian bawah Emacs, +;; yang dipanggil "minibuffer". Secara umumnya kita akan menggunakan `C-xC-e', +;; sebab kita tidak mahu memenuhi buffer dengan teks yang tidak penting. + +;; `setq' menyimpan value ke dalam variable: +(setq my-name "Bastien") +;; `C-xC-e' => "Bastien" (terpapar di mini-buffer) + +;; `insert' akan memasukkan "Hello!" di tempat di mana cursor berada: +(insert "Hello!") +;; `C-xC-e' => "Hello!" + +;; Di atas, kita menggunakan `insert' dengan satu argument "Hello!", tetapi +;; kita boleh meletakkan beberapa argument -- di sini kita letak dua: + +(insert "Hello" " world!") +;; `C-xC-e' => "Hello world!" + +;; Anda boleh menggunakan variable selain string: +(insert "Hello, I am " my-name) +;; `C-xC-e' => "Hello, I am Bastien" + +;; Anda boleh menggabungkan sexps untuk membuat function: +(defun hello () (insert "Hello, I am " my-name)) +;; `C-xC-e' => hello + +;; Anda boleh evaluate function: +(hello) +;; `C-xC-e' => Hello, I am Bastien + +;; Parentheses kosong di dalam function bermaksud function tersebut tidak +;; terima argument. Sekarang kita tukar function untuk menerima satu argument. +;; Di sini, argument tersebut dinamakan "name": + +(defun hello (name) (insert "Hello " name)) +;; `C-xC-e' => hello + +;; Sekarang panggil function tersebut dengan string "you" sebagai value +;; untuk argument: +(hello "you") +;; `C-xC-e' => "Hello you" + +;; Yay! + +;; Tarik nafas. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Sekarang tukar ke buffer baru dengan nama "*test*" di window yang lain: + +(switch-to-buffer-other-window "*test*") +;; `C-xC-e' +;; => [The screen has two windows and cursor is in the *test* buffer] + +;; Gerakkan mouse ke window atas dan klik kiri untuk pergi balik ke buffer scratch. +;; Cara lain adalah dengan menggunakan `C-xo' (i.e. tekan control-x kemudian +;; tekan o) untuk pergi ke window yang lain. + +;; Anda boleh menggabungkan beberapa sexps menggunakan `progn': +(progn + (switch-to-buffer-other-window "*test*") + (hello "you")) +;; `C-xC-e' +;; => [The screen has two windows and cursor is in the *test* buffer] + +;; Mulai dari sekarang saya tidak akan beritahu anda untuk tekan `C-xC-e' lagi: +;; buat untuk setiap sexp yang akan datang. + +;; Pergi balik ke buffer *scratch* menggunakan mouse atau `C-xo'. + +;; Seelok-eloknya padam buffer tersebut: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "there")) + +;; Atau pergi balik ke window lain: +(progn + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello "you") + (other-window 1)) + +;; Anda boleh menetapkan value dengan local variable menggunakan `let': +(let ((local-name "you")) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (hello local-name) + (other-window 1)) + +;; Tidak perlu menggunakan `progn', sebab `let' juga menggabungkan +;; beberapa sexps. + +;; Jom format string: +(format "Hello %s!\n" "visitor") + +;; %s ialah tempat untuk meletakkan string, digantikan dengan "visitor". +;; \n ialah character untuk membuat baris baru. + +;; Jom tukar function kita menggunakan format: +(defun hello (name) + (insert (format "Hello %s!\n" name))) + +(hello "you") + +;; Jom buat function lain menggunakan `let': +(defun greeting (name) + (let ((your-name "Bastien")) + (insert (format "Hello %s!\n\nI am %s." + name ; argument untuk function + your-name ; variable "Bastien" daripada let + )))) + +;; Kemudian evaluate: +(greeting "you") + +;; Sesetengah function adalah interaktif: +(read-from-minibuffer "Enter your name: ") + +;; Function tersebut akan memulangkan kembali apa yang anda masukkan ke prompt. + +;; Jom jadikan function `greeting' untuk prompt nama anda: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (insert (format "Hello!\n\nI am %s and you are %s." + from-name ; argument untuk function + your-name ; variable daripada let, yang dimasukkan dari prompt + )))) + +(greeting "Bastien") + +;; Jom siapkan function dengan memaparkan result di window yang lain: +(defun greeting (from-name) + (let ((your-name (read-from-minibuffer "Enter your name: "))) + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (insert (format "Hello %s!\n\nI am %s." your-name from-name)) + (other-window 1))) + +;; Test function tersebut: +(greeting "Bastien") + +;; Tarik nafas. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Jom simpan senarai nama: +;; Jika anda ingin membuat list(senarai) data, guna ' untuk elak +;; daripada list tersebut evaluate. +(setq list-of-names '("Sarah" "Chloe" "Mathilde")) + +;; Dapatkan elemen pertama daripada list menggunakan `car': +(car list-of-names) + +;; Dapatkan semua elemen kecuali yang pertama menggunakan `cdr': +(cdr list-of-names) + +;; Tambah elemen di awal list menggunakan `push': +(push "Stephanie" list-of-names) + +;; NOTA: `car' dan `cdr' tidak ubah suai list, tetapi `push' ya. +;; Perbezaan ini penting: sesetengah function tiada side-effects (kesan sampingan) +;; (seperti `car') dan yang lain ada side-effect (seperti `push'). + +;; Jom panggil `hello' untuk setiap elemen dalam `list-of-names': +(mapcar 'hello list-of-names) + +;; Tukar `greeting' supaya ucapkan hello kepada semua orang dalam `list-of-names': +(defun greeting () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + (mapcar 'hello list-of-names) + (other-window 1)) + +(greeting) + +;; Ingat lagi function `hello' di atas? Function tersebut mengambil satu +;; argument, iaitu nama. `mapcar' memanggil `hello', kemudian menggunakan setiap +;; nama dalam `list-of-names' sebagai argument untuk function `hello'. + +;; Sekarang kita susun sedikit untuk apa yang terpapar di buffer: + +(defun replace-hello-by-bonjour () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (search-forward "Hello") + (replace-match "Bonjour")) + (other-window 1)) + +;; (goto-char (point-min)) akan pergi ke permulaan buffer. +;; (search-forward "Hello") akan mencari string "Hello". +;; (while x y) evaluate sexp(s) y selagi x masih pulangkan sesuatu. +;; Jika x pulangkan `nil', kita akan keluar daripada while loop. + +(replace-hello-by-bonjour) + +;; Anda akan dapat melihat semua "Hello" dalam buffer *test* +;; ditukarkan dengan "Bonjour". + +;; Anda juga akan dapat error: "Search failed: Hello". +;; +;; Bagi mengelakkan error tersebut, anda perlu beritahu `search-forward' sama ada +;; perlu berhenti mencari pada suatu ketika, dan sama ada perlu diam jika +;; tidak jumpa apa yang dicari: + +;; (search-forward "Hello" nil 't) selesai masalah: + +;; Argument `nil' cakap: carian tidak mengikut kedudukan. +;; Argument `'t' cakap: diam saja jika tidak jumpa apa yang dicari. + +;; Kita guna sexp ini di function berikut, barulah tidak keluar error: + +(defun hello-to-bonjour () + (switch-to-buffer-other-window "*test*") + (erase-buffer) + ;; Ucap hello pada nama-nama dalam `list-of-names' + (mapcar 'hello list-of-names) + (goto-char (point-min)) + ;; Ganti "Hello" dengan "Bonjour" + (while (search-forward "Hello" nil 't) + (replace-match "Bonjour")) + (other-window 1)) + +(hello-to-bonjour) + +;; Jom jadikan nama-nama tersebut bold: + +(defun boldify-names () + (switch-to-buffer-other-window "*test*") + (goto-char (point-min)) + (while (re-search-forward "Bonjour \\(.+\\)!" nil 't) + (add-text-properties (match-beginning 1) + (match-end 1) + (list 'face 'bold))) + (other-window 1)) + +;; Function ini memperkenalkan `re-search-forward': anda mencari menggunakan +;; pattern iaitu "regular expression", bukannya mencari string "Bonjour". + +;; Regular expression tersebut ialah "Bonjour \\(.+\\)!" dan dibaca begini: +;; string "Bonjour ", dan +;; kumpulan | ini ialah \\( ... \\) +;; mana-mana character | ini ialah . +;; yang boleh berulang | ini ialah + +;; dan string "!". + +;; Dah sedia? Test function tersebut! + +(boldify-names) + +;; `add-text-properties' tambah... ciri-ciri teks, seperti face. + +;; OK, kita sudah selesai. Selamat ber-hacking! + +;; Jika anda ingin tahu lebih mengenai variable atau function: +;; +;; C-h v a-variable RET +;; C-h f a-function RET +;; +;; Jika anda ingin membaca manual Emacs Lisp menggunakan Emacs: +;; +;; C-h i m elisp RET +;; +;; Jika ingin membaca pengenalan kepada Emacs Lisp secara online: +;; https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html +``` diff --git a/php.html.markdown b/php.html.markdown index d4fbaa32..6542035f 100644 --- a/php.html.markdown +++ b/php.html.markdown @@ -443,7 +443,7 @@ echo $function_name(1, 2); // => 3 // Or, use call_user_func(callable $callback [, $parameter [, ... ]]); -// You can get the all the parameters passed to a function +// You can get all the parameters passed to a function function parameters() { $numargs = func_num_args(); if ($numargs > 0) { diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown new file mode 100644 index 00000000..7bd2809a --- /dev/null +++ b/ru-ru/rust-ru.html.markdown @@ -0,0 +1,316 @@ +--- +language: rust + +filename: learnrust-ru.rs +contributors: + - ["P1start", "http://p1start.github.io/"] +translators: + - ["Anatolii Kosorukov", "https://github.com/java1cprog"] +lang: ru-ru + +--- + +Rust сочетает в себе низкоуровневый контроль над производительностью с удобством высокого уровня и предоставляет гарантии +безопасности. +Он достигает этих целей, не требуя сборщика мусора или времени выполнения, что позволяет использовать библиотеки Rust как замену +для C-библиотек. + +Первый выпуск Rust, 0.1, произошел в январе 2012 года, и в течение 3 лет развитие продвигалось настолько быстро, что до +недавнего времени использование стабильных выпусков было затруднено, и вместо этого общий совет заключался в том, чтобы +использовать последние сборки. + +15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Усовершенствования времени компиляции и +других аспектов компилятора в настоящее время доступны в ночных сборках. Rust приняла модель выпуска на поезде с регулярными выпусками каждые шесть недель. Rust 1.1 beta был доступен одновременно с выпуском Rust 1.0. + +Хотя Rust является языком относительно низкого уровня, Rust имеет некоторые функциональные концепции, которые обычно +встречаются на языках более высокого уровня. Это делает Rust не только быстрым, но и простым и эффективным для ввода кода. + + +```rust +// Это однострочный комментарии +// + +/// Так выглядит комментарий для документации +/// # Examples +/// +/// +/// let seven = 7 +/// + +/////////////// +// 1. Основы // +/////////////// + +// Функции +// `i32` это целочисленный знаковый тип 32-bit +#[allow(dead_code)] +fn add2(x: i32, y: i32) -> i32 { + // метод возвращает сумму x и y + x + y +} + +// Главная функция программы +#[allow(unused_variables)] +#[allow(unused_assignments)] +#[allow(dead_code)] +fn main() { + // Числа // + + // неизменяемая переменная + let x: i32 = 1; + + // Суффиксы целое/дробное + let y: i32 = 13i32; + let f: f64 = 1.3f64; + + // Автоматическое выявление типа данных + // В большинстве случаев компилятор Rust может вычислить + // тип переменной, поэтому + // вам не нужно писать явные аннотации типа. + + let implicit_x = 1; + let implicit_f = 1.3; + + // Арифметика + let sum = x + y + 13; + + // Изменяемая переменная + let mut mutable = 1; + mutable = 4; + mutable += 2; + + // Строки // + + // Строковые литералы + let x: &str = "hello world!"; + + // Печать на консоль + println!("{} {}", f, x); // 1.3 hello world + + // `String` – изменяемя строка + let s: String = "hello world".to_string(); + + // Строковый срез - неизменяемый вид в строки + // Это в основном неизменяемая пара указателей на строку - + // Это указатель на начало и конец строкового буфера + + let s_slice: &str = &s; + + println!("{} {}", s, s_slice); // hello world hello world + + // Vectors/arrays // + + // фиксированный массив + let four_ints: [i32; 4] = [1, 2, 3, 4]; + + // динамический массив + let mut vector: Vec<i32> = vec![1, 2, 3, 4]; + vector.push(5); + + // Срез - неизменяемое представление значений вектора + let slice: &[i32] = &vector; + + // Используйте шаблон `{:?}`для печати отладочной информации структур с данными + println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + + // Кортежи // + + // Кортеж - это фиксированный набор. + // В нём могут находиться значения разных типов данных. + let x: (i32, &str, f64) = (1, "hello", 3.4); + + // Инициализация группы переменных `let` + let (a, b, c) = x; + println!("{} {} {}", a, b, c); // 1 hello 3.4 + + // Доступ по индексу + println!("{}", x.1); // hello + + ////////////// + // 2. Типы // + ////////////// + + // Struct + struct Point { + x: i32, + y: i32, + } + + let origin: Point = Point { x: 0, y: 0 }; + + // Структуры могут быть с безымянными полями ‘tuple struct’ + struct Point2(i32, i32); + + let origin2 = Point2(0, 0); + + // Перечисление + enum Direction { + Left, + Right, + Up, + Down, + } + + let up = Direction::Up; + + // Перечисление с полями + enum OptionalI32 { + AnI32(i32), + Nothing, + } + + let two: OptionalI32 = OptionalI32::AnI32(2); + let nothing = OptionalI32::Nothing; + + // Обобщенные типы данных // + + struct Foo<T> { bar: T } + + // Частоиспользуемое перечисление стандартной библиотеки `Option` + enum Optional<T> { + SomeVal(T), + NoVal, + } + + // Методы // + + impl<T> Foo<T> { + fn get_bar(self) -> T { + self.bar + } + } + + let a_foo = Foo { bar: 1 }; + println!("{}", a_foo.get_bar()); // 1 + + // Типаж + + trait Frobnicate<T> { + fn frobnicate(self) -> Option<T>; + } + + impl<T> Frobnicate<T> for Foo<T> { + fn frobnicate(self) -> Option<T> { + Some(self.bar) + } + } + + let another_foo = Foo { bar: 1 }; + println!("{:?}", another_foo.frobnicate()); // Some(1) + + ///////////////////////// + // 3. Поиск по шаблону // + ///////////////////////// + + let foo = OptionalI32::AnI32(1); + match foo { + OptionalI32::AnI32(n) => println!("it’s an i32: {}", n), + OptionalI32::Nothing => println!("it’s nothing!"), + } + + // Более сложный пример + struct FooBar { x: i32, y: OptionalI32 } + let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; + + match bar { + FooBar { x: 0, y: OptionalI32::AnI32(0) } => + println!("The numbers are zero!"), + FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m => + println!("The numbers are the same"), + FooBar { x: n, y: OptionalI32::AnI32(m) } => + println!("Different numbers: {} {}", n, m), + FooBar { x: _, y: OptionalI32::Nothing } => + println!("The second number is Nothing!"), + } + + ///////////////////// + // 4. Управление ходом выполнения программы // + ///////////////////// + + // `for` loops/iteration + let array = [1, 2, 3]; + for i in array.iter() { + println!("{}", i); + } + + // Отрезки + for i in 0u32..10 { + print!("{} ", i); + } + println!(""); + // prints `0 1 2 3 4 5 6 7 8 9 ` + + // `if` + if 1 == 1 { + println!("Maths is working!"); + } else { + println!("Oh no..."); + } + + // `if` as expression + let value = if true { + "good" + } else { + "bad" + }; + + // `while` loop + while 1 == 1 { + println!("The universe is operating normally."); + break; + } + + // Infinite loop + loop { + println!("Hello!"); + break; + } + + ///////////////////////////////// + // 5. Защита памяти и указатели // + ///////////////////////////////// + + // Владеющий указатель – такой указатель может быть только один + // Это значит, что при вызоде из блока переменная автоматически становится недействительной. + let mut mine: Box<i32> = Box::new(3); + *mine = 5; // dereference + // Здесь, `now_its_mine` получает во владение `mine`. Т.е. `mine` была перемещена. + let mut now_its_mine = mine; + *now_its_mine += 2; + + println!("{}", now_its_mine); // 7 + // println!("{}", mine); + + // Ссылки - это неизменяемые указатели + // Если ссылка получает значения, то говорят, что она заимствует это значение. + // Такое значение не может быть изменено или перемещено. + let mut var = 4; + var = 3; + let ref_var: &i32 = &var; + + println!("{}", var); + println!("{}", *ref_var); + // var = 5; // не скомпилируется + // *ref_var = 6; // и это + + // Изменяемые ссылки + // + let mut var2 = 4; + let ref_var2: &mut i32 = &mut var2; + *ref_var2 += 2; // '*' используется для изменения значения + + println!("{}", *ref_var2); // 6 , // var2 would not compile. + // ref_var2 имеет тип &mut i32, т.е. он содержит ссылку на i32, а не значение. + // var2 = 2; // не скомпилируется, т.к. эта переменная уже была заимствована ранее +} + +``` + +## Более подробная информация о языке + +Уже есть хорошие книги для изучающих Rust. Основным источником остаётся +[The Rust Programming Language](http://doc.rust-lang.org/book/index.html) + +Для компиляции программ при изучении языка весьма удобно использовать +[Rust playpen](http://play.rust-lang.org). +Множество ресурсов на разных языках можно найти в [этом проекте](https://github.com/ctjhoa/rust-learning). diff --git a/rust.html.markdown b/rust.html.markdown index 6b75fa87..71bc16b5 100644 --- a/rust.html.markdown +++ b/rust.html.markdown @@ -41,6 +41,7 @@ Rust not only fast, but also easy and efficient to code in. // 1. Basics // /////////////// +#[allow(dead_code)] // Functions // `i32` is the type for 32-bit signed integers fn add2(x: i32, y: i32) -> i32 { @@ -48,6 +49,9 @@ fn add2(x: i32, y: i32) -> i32 { x + y } +#[allow(unused_variables)] +#[allow(unused_assignments)] +#[allow(dead_code)] // Main function fn main() { // Numbers // @@ -256,11 +260,16 @@ fn main() { // `while` loop while 1 == 1 { println!("The universe is operating normally."); + // break statement gets out of the while loop. + // It avoids useless iterations. + break } // Infinite loop loop { println!("Hello!"); + // break statement gets out of the loop + break } ///////////////////////////////// diff --git a/vim.html.markdown b/vim.html.markdown index d5c4e865..0eb2c37e 100644 --- a/vim.html.markdown +++ b/vim.html.markdown @@ -34,6 +34,11 @@ specific points in the file, and for fast editing. k # Move up one line l # Move right one character + Ctrl+B # Move back one full screen + Ctrl+F # Move forward one full screen + Ctrl+D # Move forward 1/2 a screen + Ctrl+U # Move back 1/2 a screen + # Moving within the line 0 # Move to beginning of line |