Tutorial — dokumentasi hy 0.25.0

Berita29 Dilihat


Maskot Hy, Memeluk sotong.

Bab ini memberikan pengantar singkat tentang Hy. Ini mengasumsikan latar belakang dasar dalam pemrograman, tetapi tidak ada pengetahuan khusus sebelumnya tentang Python atau Lisp.

Lisp-stick pada Python

Mari kita mulai dengan yang klasik:

Program ini memanggil print() fungsi, yang, seperti semua fungsi Python
fungsi bawaantersedia di Hy.

Semua Python operator biner dan unary tersedia juga, meskipun == dieja = untuk menghormati tradisi Lisp. Inilah cara kami menggunakan operator tambahan +:

Kode ini kembali 4. Ini setara dengan 1 + 3 dengan Python dan banyak bahasa lainnya. Bahasa di Pelat keluarga, termasuk Hy, gunakan sintaks awalan: +seperti print atau sqrt, muncul sebelum semua argumennya. Panggilan dibatasi oleh tanda kurung, tetapi tanda kurung buka muncul sebelum operator dipanggil alih-alih setelahnya, jadi alih-alih sqrt(2)kami menulis (sqrt 2). Beberapa argumen, seperti dua bilangan bulat di (+ 1 3), dipisahkan oleh spasi. Banyak operator, termasuk +izinkan lebih dari dua argumen: (+ 1 2 3) setara dengan
1 + 2 + 3.

Berikut ini contoh yang lebih kompleks:

Kode ini kembali 176. Mengapa? Kita bisa melihat persamaan infiks dengan perintah echo "(- (* (+ 1 3 88) 2) 8)" | hy2pyyang mengembalikan kode Python yang sesuai dengan kode Hy yang diberikan, atau dengan meneruskan --spy opsi ke Hy saat memulai REPL, yang menunjukkan padanan Python dari setiap baris input sebelum hasilnya. Padanan infiks dalam hal ini adalah:

Untuk mengevaluasi ekspresi infiks ini, Anda tentu saja harus mengevaluasi ekspresi kurung terdalam terlebih dahulu dan bekerja keluar. Hal yang sama berlaku untuk Lisp. Inilah yang kami dapatkan dengan mengevaluasi kode Hy di atas satu per satu:

(- (* (+ 1 3 88) 2) 8)
(- (* 92 2) 8)
(- 184 8)
176

Unit dasar sintaks Lisp, yang mirip dengan ekspresi C atau Python, adalah membentuk. 92, *dan (* 92 2) adalah semua bentuk. Program Lisp terdiri dari urutan formulir yang bersarang di dalam formulir. Bentuk biasanya dipisahkan satu sama lain oleh spasi putih, tetapi beberapa bentuk, seperti string literal ("Hy, world!"), dapat berisi spasi itu sendiri. Sebuah
ekspresi adalah formulir yang diapit tanda kurung; bentuk anak pertamanya, disebut kepala, menentukan apa yang dilakukan ekspresi, dan umumnya harus berupa fungsi atau makro. Fungsi adalah jenis kepala yang paling umum, sedangkan makro (dijelaskan lebih detail di bawah) adalah fungsi yang dieksekusi pada waktu kompilasi dan mengembalikan kode untuk dieksekusi pada waktu proses.

Komentar dimulai dengan a ; karakter dan lanjutkan sampai akhir baris. Sebuah komentar secara fungsional setara dengan spasi.

(setv password "susan")   ; My daughter's name

Meskipun # bukan karakter komentar di Hy, program Hy bisa dimulai dengan a
garis shebangyang Hy sendiri akan abaikan:

#!/usr/bin/env hy
(print "Make me executable, and run me!")

Literal

Hy punya sintaks literal untuk semua tipe data yang sama dengan yang dilakukan Python. Berikut adalah contoh kode Hy untuk setiap jenis dan padanan Python.

Hy

Piton

Jenis

1

1

int

1.2

1.2

float

4j

4j

complex

True

True

bool

None

None

NoneType

"hy"

'hy'

str

b"hy"

b'hy'

bytes

#(1 2 3)

(1, 2, 3)

tuple

[1 2 3]

[1, 2, 3]

list

#{1 2 3}

{1, 2, 3}

set

{1 2  3 4}

{1: 2, 3: 4}

dict

Hy REPL mencetak output dalam sintaks Hy secara default, dengan fungsi hy.repr:

Tetapi jika Anda memulai Hy seperti ini:

$ hy --repl-output-fn=repr

REPL akan menggunakan bahasa asli Python repr sebagai gantinya, jadi Anda akan melihat nilai dalam sintaks Python:

Operasi dasar

Setel variabel dengan setv:

Akses elemen daftar, kamus, atau struktur data lainnya dengan
get:

(setv fruit ["apple" "banana" "cantaloupe"])
(print (get fruit 0))  ; => apple
(setv (get fruit 1) "durian")
(print (get fruit 1))  ; => durian

Akses berbagai elemen dalam struktur yang teratur dengan cut:

(print (cut "abcdef" 1 4))  ; => bcd

Logika bersyarat dapat dibangun dengan if:

(if (= 1 1)
  (print "Math works. The universe is safe.")
  (print "Math has failed. The universe is doomed."))

Seperti dalam contoh ini, if disebut seperti (if CONDITION THEN ELSE). Itu mengeksekusi dan mengembalikan formulir THEN jika CONDITION benar (menurut
bool) dan ELSE jika tidak.

Bagaimana jika Anda ingin menggunakan lebih dari sekadar bentuk sebagai pengganti THEN atau ELSE
klausa, atau di tempat CONDITION, untuk masalah itu? Gunakan makro
do (dikenal lebih tradisional di Lisp sebagai progn), yang menggabungkan beberapa bentuk menjadi satu, mengembalikan yang terakhir:

(if (do (print "Let's check.") (= 1 1))
  (do
    (print "Math works.")
    (print "The universe is safe."))
  (do
    (print "Math has failed.")
    (print "The universe is doomed.")))

Untuk bercabang di lebih dari satu kasing, coba cond:

(setv somevar 33)
(cond
  (> somevar 50)
    (print "That variable is too big!")
  (< somevar 10)
    (print "That variable is too small!")
  True
    (print "That variable is jussssst right!"))

Makro (when CONDITION THEN-1 THEN-2 …) adalah singkatan dari (if CONDITION
(do THEN-1 THEN-2 …) None)
.

Perulangan dasar Hy adalah while dan for:

(setv x 3)
(while (> x 0)
  (print x)
  (setv x (- x 1)))  ; => 3 2 1

(for [x [1 2 3]]
  (print x))         ; => 1 2 3

Cara yang lebih fungsional untuk mengulang disediakan oleh bentuk pemahaman seperti
lfor. Sedangkan for selalu kembali None, lfor mengembalikan daftar dengan satu elemen per iterasi.

(print (lfor  x [1 2 3]  (* x 2)))  ; => [2, 4, 6]

Fungsi, kelas, dan modul

Tentukan fungsi bernama dengan defn:

(defn fib [n]
  (if (< n 2)
    n
    (+ (fib (- n 1)) (fib (- n 2)))))
(print (fib 8))  ; => 21

Tentukan fungsi anonim dengan fn:

(print (list (filter (fn [x] (% x 2)) (range 10))))
  ; => [1, 3, 5, 7, 9]

Simbol khusus dalam daftar parameter defn atau fn memungkinkan Anda untuk menunjukkan argumen opsional, memberikan nilai default, dan mengumpulkan argumen yang tidak terdaftar:

(defn test [a b [c None] [d "x"] #* e]
  [a b c d e])
(print (test 1 2))            ; => [1, 2, None, 'x', ()]
(print (test 1 2 3 4 5 6 7))  ; => [1, 2, 3, 4, (5, 6, 7)]

Tetapkan parameter fungsi berdasarkan nama dengan a :keyword:

(test 1 2 :d "y")             ; => [1, 2, None, 'y', ()]

Perhatikan bahwa tidak seperti Python, Hy tidak selalu mengevaluasi argumen fungsi (atau item dalam daftar literal, atau item dalam kamus literal, dll.) sesuai urutan kemunculannya dalam kode. Tetapi Anda selalu dapat memaksakan urutan evaluasi tertentu doatau dengan makro lain yang memberikan implisit domenyukai when atau fn.

Tentukan kelas dengan defclass:

(defclass FooBar []
  (defn __init__ [self x]
    (setv self.x x))
  (defn get-x [self]
    self.x))

Di sini kita membuat instance baru fb dari FooBar dan mengakses atributnya dengan berbagai cara:

(setv fb (FooBar 15))
(print fb.x)         ; => 15
(print (. fb x))     ; => 15
(print (.get-x fb))  ; => 15
(print (fb.get-x))   ; => 15

Perhatikan bahwa sintaks seperti fb.x dan fb.get-x hanya berfungsi ketika objek dipanggil (fb, dalam hal ini) adalah nama variabel sederhana. Untuk mendapatkan atribut atau memanggil metode bentuk arbitrer FORMAnda harus menggunakan sintaks (. FORM x) atau (.get-x FORM).

Akses modul eksternal, baik yang ditulis dengan Python atau Hy, dengan
import:

(import math)
(print (math.sqrt 2))  ; => 1.4142135623730951

Python dapat mengimpor modul Hy seperti modul lainnya selama Hy itu sendiri telah diimpor terlebih dahulu, yang tentunya sudah terjadi jika Anda menjalankan program Hy.

Makro

Macro adalah alat metaprogramming dasar dari Lisp. Makro adalah fungsi yang dipanggil pada waktu kompilasi (yaitu, ketika program Hy sedang diterjemahkan ke Python ast objek) dan mengembalikan kode, yang menjadi bagian dari program akhir. Berikut ini contoh sederhana:

(print "Executing")
(defmacro m []
  (print "Now for a slow computation")
  (setv x (% (** 10 10 7) 3))
  (print "Done computing")
  x)
(print "Value:" (m))
(print "Done executing")

Jika Anda menjalankan program ini dua kali berturut-turut, Anda akan melihat ini:

$ hy example.hy
Now for a slow computation
Done computing
Executing
Value: 1
Done executing
$ hy example.hy
Executing
Value: 1
Done executing

Komputasi lambat dilakukan saat mengkompilasi program pada pemanggilan pertama. Hanya setelah seluruh program dikompilasi, eksekusi normal dimulai dari atas, mencetak “Pelaksana”. Ketika program dipanggil untuk kedua kalinya, itu dijalankan dari bytecode yang dikompilasi sebelumnya, yang setara dengan sederhana:

(print "Executing")
(print "Value:" 1)
(print "Done executing")

Makro kami m memiliki nilai pengembalian yang sangat sederhana, bilangan bulat, yang pada waktu kompilasi diubah menjadi literal bilangan bulat. Secara umum, makro dapat mengembalikan sembarang bentuk Hy untuk dieksekusi sebagai kode. Ada beberapa operator dan makro khusus yang memudahkan pembuatan formulir secara terprogram, seperti
quote ('), quasiquote (`), unquote

(~), dan defmacro!. Bab sebelumnya sudah contoh sederhana menggunakan ` dan ~ untuk mendefinisikan konstruksi kontrol baru do-while.

Bagaimana jika Anda ingin menggunakan makro yang ditentukan dalam modul yang berbeda?
import tidak akan membantu, karena itu hanya diterjemahkan menjadi Python import
pernyataan yang dijalankan pada waktu proses, dan makro diperluas pada waktu kompilasi, yaitu, selama terjemahan dari Hy ke Python. Sebagai gantinya, gunakan requireyang mengimpor modul dan membuat makro tersedia pada waktu kompilasi.
require menggunakan sintaks yang sama dengan import.

=> (require tutorial.macros)
=> (tutorial.macros.rev (1 2 3 +))
6

Hy juga mendukung makro pembaca, yang mirip dengan makro biasa, tetapi beroperasi pada teks sumber mentah daripada bentuk Hy yang telah diurai sebelumnya. Mereka dapat memilih berapa banyak kode sumber yang akan digunakan setelah titik pemanggilan, dan mengembalikan kode apa pun. Dengan demikian, makro pembaca dapat menambahkan sintaks yang sama sekali baru ke Hy. Misalnya, Anda bisa menambahkan notasi literal untuk Python decimal.Decimal kelas seperti ini:

=> (import  decimal [Decimal]  fractions [Fraction])
=> (defreader d
...   (.slurp-space &reader)
...   `(Decimal ~(.read-ident &reader)))
=> (print (repr #d .1))
Decimal('0.1')
=> (print (Fraction #d .1))
1/10
=> ;; Contrast with the normal floating-point .1:
=> (print (Fraction .1))
3602879701896397/36028797018963968

require dapat menarik makro pembaca yang ditentukan dalam modul berbeda dengan sintaks seperti (require mymodule :readers [d]).

Hyrule

Hyrule adalah perpustakaan utilitas standar Hy. Ini menyediakan berbagai fungsi dan makro yang berguna untuk menulis program Hy.

=> (import hyrule [inc])
=> (list (map inc [1 2 3]))
[2 3 4]
=> (require hyrule [assoc])
=> (setv d {})
=> (assoc d  "a" 1  "b" 2)
=> d
{"a" 1  "b" 2}

Langkah selanjutnya

Anda sekarang cukup tahu untuk menjadi berbahaya dengan Hy. Anda sekarang dapat tersenyum jahat dan menyelinap ke Hydeaway Anda untuk melakukan hal-hal yang tak terkatakan.

Lihat dokumentasi Python untuk detail semantik Python, dan panduan selanjutnya untuk fitur khusus Hy. Seperti Hy sendiri, manualnya tidak lengkap, tapi kontribusi selalu diterima.

Ingatlah bahwa Hy masih tidak stabil, dan dengan setiap rilis di sepanjang jalan menuju Hy 1.0, ada perubahan terobosan baru. Mengacu pada berkas BERITA untuk mengetahui cara memperbarui kode saat Anda memutakhirkan Hy, dan pastikan Anda membaca versi manual ini (ditampilkan di bagian atas setiap halaman) yang cocok dengan versi Hy yang Anda jalankan.


#Tutorial #dokumentasi #0.25.0

Source link

Komentar