Wikifunctions:Model fungsi

From Wikifunctions
This page is a translated version of the page Wikifunctions:Function model and the translation is 81% complete.

Wikifunctions adalah sebuah katalog fungsi multibahasa di mana semua orang bisa berkontribusi, di mana semua orang bisa membuat, memelihara, memanggil, dan menggunakan fungsi. Setiap fungsi bisa punya beberapa implementasi. Implementasi-implementasinya bisa dalam beberapa bahasa pemrograman yang berbeda atau menggunakan algoritma yang berbeda. Proyek ini adalah “Wikipedianya fungsi”, dan merupakan proyek saudarinya yang dijalankan oleh Wikimedia Foundation.

Dokumen ini membahas model data dan model evaluasi di Wikifunctions.

Di sepanjang deskripsi model ini, istilah yang diawali huruf kapital merupakan istilah yang didefinisikan di glosarium.
Membaca panduan dari prototipe sebelumnya bisa sangat berguna untuk memahami apa yang sedang dilakukan di sini sebelum membaca model berikut.

Z1/ZObjek

Wikifunctions adalah sebuah wiki. Seperti semua wiki lainnya, kebanyakan konten Wikifunctions disimpan di halaman wiki. Setiap halaman wiki bisa disunting secara terpisah, tetapi proyek ini secara keseluruhan harus mempertahankan suatu konsistensi. Dan halaman wiki sebaiknya bisa disunting secara terpisah tanpa harus memahami halaman lainnya.

Kita membuat ZObjek untuk merepresentasikan konten Wikifunctions. Setiap halaman wiki di ruang nama utama Wikifunctions mengandung tepat satu ZObjek dengan tipe objek Z2/Persisten Ruang nama lainnya bisa mengandung konten lain, seperti halaman kebijakan, halaman pengguna, halaman pembicaraan, dll. ZObjek bisa diserialkan sebagai sebuah objek JSON.

Suatu ZObjek terdiri dari satu daftar pasangan Kunci/nilai.

  • Setiap nilai dalam suatu pasangan Kunci/nilai adalah sebuah ZObjek..
  • Nilai bisa berupa sebuah Z6/Untaian, sebuah Z9/Referensi, atau tipe apa pun. Z6/Untaian dan Z9/Referensi adalah nilai terminal. Mereka tidak bisa dikembangkan lebih lanjut.
  • Sebuah Z6/Untaian memiliki tepat dua kunci, Z1K1/tipe dengan nilai "Z6", dan Z6K1/nilai untaian, yang bisa diisi dengan sembarang teks.
  • Sebuah Z9/Referensi memiliki dua kunci, Z1K1/tipe dengan nilai "Z9", dan Z9K1/ID referensi, yang sebuah untaian yang melambangkan sebuah ZID.
  • Setiap Kunci hanya bisa muncul sekali di masing-masing ZObjek (tetapi bisa ditampilkan lagi di ZObjek lain yang ditempatkan di sana).

ZObjek pada dasarnya merupakan pohon sintaksis abstrak. Jika ada ringkasan penjelasan proyek, isinya kemungkinan adalah "sesuatu yang mirip LISP di JSON". Tujuannya adalah menyediakan pengalaman yang mudah dalam membuat dan memanipulasi ZObjek melalui antarmuka wiki, sehingga membuat lingkungan pengodean yang bisa menampung banyak kontributor dan bisa menjadi proyek Wikimedia yang punya komunitas aktif.

Setiap ZObjek harus punya kunci Z1K1/tipe dengan sebuah nilai yang merupakan sebuah Z4/Tipe.

Kita menggunakan notasi ZID/label untuk merujuk ZID dalam cara yang kira-kira mudah dibaca di mana ZID adalah ID ZObjek atau kunci dari objek tersebut, dan label adalah label (dalam bahasa tertentu) yang diberikan ke ID atau kunci berbahasa netral tersebut

Representasi sebuah ZObjek yang direpresentasikan hanya sebagai sekumpulan pasangan kunci/nilai, dan hanya berakhir di titik terminal, disebut bentuk normal. Bentuk normal ZObjek biasanya digunakan untuk evaluasi.

Bentuk kanonis

Untuk membuat ZObjek lebih mudah dibaca dan lebih padat, kita biasanya menyimpan dan mengirimkannya dalam bentuk yang disebut kanonis.

Bentuk kanonis menggunakan tiga transformasi sintaksis: untuk Z9/referensi, Z6/untaian, dan Z881/daftar.

Referensi Kanonis

Suatu referensi mengacu kepada suatu ZObjek menggunakan ZID-nya. Suatu ZID dimulai dengan huruf Z, diikuti oleh bilangan asli. Bentuk normal referensi tampak seperti berikut (di sini, dan di seluruh dokumen, kita selalu menampilkan ZObjek dua kali: di sisi kiri dalam versi yang diberi label, yaitu di mana semua ZID dan ID kunci diganti dengan label berbahasa Inggris, dan di sisi kanan dengan ZID dan ID kunci yang tidak diganti).

{
  "type": "reference",
  "reference id": "natural number"
}
{
  "Z1K1": "Z9",
  "Z9K1": "Z10"
}

Bentuk kanonis mengganti objek tersebut dengan satu string dengan ZID. Jadi, bentuk kanonis dari referensi di atas adalah:

"natural number"
"Z10"

Perhatikan bahwa bentuk normal dan kanonis memiliki makna yang sama.

Untaian Kanonis

Suatu Untaian adalah sebuah urutan Titik Kode Unicode, biasanya mewakili sebuah kata atau sebuah teks. Untaian dapat mengandung spasi dan karakter-karakter lainnya selain karakter kontrol.

Bentuk normal Untaian terlihat seperti berikut. Perhatikan bahwa nilai kunci yang kedua memang merupakan sebuah untaian, dan bukan versi berlabel dari suatu ZID, seperti yang dapat dilihat di sisi kanan.

{
  "type": "string",
  "string value": "Wikifunctions"
}
{
  "Z1K1": "Z6",
  "Z6K1": "Wikifunctions"
}

Untaian biasanya bisa dijadikan bentuk kanonis hanya dengan nilai untaiannya dan bukan dengan keseluruhan objek. Untaian di atas memiliki bentuk kanonis seperti berikut.

"Wikifunctions"
"Wikifunctions"

Perhatikan bahwa Untaian yang dimulai dengan huruf Latin besar dan diikuti oleh bilangan asli perlu dihindari, karena jika tidak akan bertentangan dengan representasi normal Referensi. Misalnya, Untaian "Z1" akan memiliki representasi berikut, baik dalam bentuk normal maupun kanonis. Karena jika tidak akan ambigu apakah "Z1" mengacu pada Untaian Z1 atau menjadi referensi untuk objek dengan ZID Z1.

{
  "type": "string",
  "string value": "Z1"
}
{
  "Z1K1": "Z6",
  "Z6K1": "Z1"
}

Daftar kanonis

Daftar direpresentasikan melalui apa yang disebut Larik Benjamin. Deskripsinya bisa dibaca di bawah di bagian Z881/Daftar bertipe.

Representasi dalam bentuk JSON

Suatu ZObjek dapat direpresentasikan dalam bentuk JSON menggunakan kunci ZID abstrak ("Z1K1", dll.), dan representasi JSON dari nilainya.

Representasi yang lebih mudah dibaca dapat dibuat dengan mengganti kunci dan ZID abstrak dengan label mereka dalam bahasa tertentu, disebut juga representasi "berlabel". Versi label seringkali ambigu dan tidak selalu dapat diterjemahkan menjadi representasi yang dapat dibaca mesin.

Tabel berikut memberikan contoh ZObjek yang mewakili bilangan asli 2. Di sebelah kiri kita melihat ZObjek dengan label berbahasa Inggris, di tengah labelnya berbahasa Jerman, dan di sebelah kanan kita melihat ZObjek yang menggunakan ZID.

{
  "type": "natural number",
  "base 10 representation": "2"
}
{
  "Typ": "natürliche Zahl",
  "Dezimaldarstellung": "2"
}
{
  "Z1K1": "Z10",
  "Z10K1": "2"
}

Seperti yang bisa dilihat, label tidak harus berbahasa Inggris, tetapi bisa berbahasa apa pun selama termasuk dalam lebih dari 300 bahasa yang didukung Wikifunctions.

Bentuk normal

Untuk pengolahan ZObjek oleh evaluator, semua ZObjek diubah menjadi bentuk normal yang dijelaskan di atas. Bentuk normal tidak bergantung pada hal tersirat apa pun yang menandakan apakah nilai untaian perlu ditafsirkan sebagai sebuah Z6/Untaian atau sebuah Z9/Referensi, tetapi mereka semua dinyatakan sebagai ZObjek tersurat.

Ini berarti bentuk normal ZObjek adalah sebuah pohon yang semua daunnya antara bertipe Z6/Untaian atau Z9/Referensi.

Ini juga berarti bahwa semua Daftar direpresentasikan sebagai ZObjek, bukan sebagai larik.

Bentuk normal berikut mewakili ZObjek di atas, yang memiliki nilai bilangan asli 2.

{
  "type": {
    "type": "reference",
    "reference id": "natural number"
   },
   "base 10 representation": {
     "type": "string",
     "string value": "2"
   }
}
{
  "Z1K1": {
    "Z1K1": "Z9",
    "Z9K1": "Z10"
   },
   "Z10K1": {
     "Z1K1": "Z6",
     "Z6K1": "2"
   }
}

Bentuk normal digunakan sebagai masukan untuk mesin evaluasi. Mereka memastikan bahwa masukan untuk evaluasi selalu seragam dan mudah diproses, dan hanya membutuhkan jumlah kasus khusus yang minimal.

Persisten dan transien

Semua ZObjek tingkat teratas yang disimpan dalam sebuah halaman wiki Wikifunctions adalah sebuah Z2/Objek bersinambung atau persisten. ZObjek yang tidak disimpan di halaman wikinya sendiri disebut ZObjek transien.

Setiap ZObjek bersinambung wajib memiliki sebuah Z2K1/ID, yaitu sebuah Z6/Untaian untuk ZID-nya, yang setara dengan nama halaman wiki di mana ia disimpan. Mari kita anggap bahwa ada suatu ZObjek untuk bilangan asli 2 yang kita lihat sebelumnya dan bahwa ZObjek tersebut disimpan di halaman Z702. Beginilah contoh tampilannya (perhatikan bahwa ZID tiga digit yang diawali Z7xx hanyalah penampung sementara sampai kita memiliki ZID yang tepat untuk mereka di Wikifunctions).

{
  "type": "persistent object",
  "id": {
    "type": "string",
    "string value": "Z702"
  },
  "value": {
    "type": "natural number",
    "base 10 representation": "2"
  },
  "label": {
    "type": "multilingual text",
    "texts": [
      "monolingual text",
      {
        "type": "monolingual text",
        "language": "English",
        "text": "two"
      },
      {
        "type": "monolingual text",
        "language": "German",
        "text": "zwei"
      }
    ]
  }
}
{
  "Z1K1": "Z2",
  "Z2K1": {
    "Z1K1": "Z6",
    "Z6K1": "Z702"
  },
  "Z2K2": {
    "Z1K1": "Z10",
    "Z10K1": "2"
  },
  "Z2K3": {
    "Z1K1": "Z12",
    "Z12K1": [
      "Z11",
      {
        "Z1K1": "Z11",
        "Z11K1": "Z1002",
        "Z11K2": "two"
      },
      {
        "Z1K1": "Z11",
        "Z11K1": "Z1430",
        "Z11K2": "zwei"
      }
    ]
  }
}

Semua objek JSON yang disimpan di Wikifunctions disimpan dalam bentuk normalisasi Unicode C. Semua nilai sebelum evaluasi juga harus dinormalkan sesuai Unicode dengan bentuk normal Unicode C.

Z2/Objek bersinambung adalah sebuah pembungkus yang menyediakan metadata untuk ZObjek yang tertanam dalam Z2K2/nilainya.

Z2K3/label adalah ZObjek bertipe Z12/teks multibahasa yang memiliki satu Z3/Kunci, yaitu Z12K1/teks, yang merujuk pada sebuah daftar ZObjek Z11/teks satu bahasa (ingatlah bahwa daftar direpresentasikan sebagai sebuah larik dalam representasi JSON). Label memungkinkan pelabelan dilakukan.

Ada pula Z3/Kunci lainnya pada Z2/Objek bersinambung yang tidak kita sebutkan di sini. Mereka semua didefinisikan di Z2/Objek bersinambung.

Z9/Referensi

Suatu Z9/Referensi adalah suatu referensi ke Z2K2/nilai dari ZObjek dengan ID yang diberikan; artinya, Z2K2/nilai memiliki arti yang sama dengan suatu referensi. Sebagai contoh, lihatlah referensi berikut:

"two"
"Z702"

Ini adalah Z9/Referensi pintasan; bentuknya seperti ini dalam bentuk yang dikembangkan (seperti dijelaskan di Bagian tentang deserialisasi):

{
  "type": "reference",
  "reference id": "two"
}
{
  "Z1K1": "Z9",
  "Z9K1": "Z702"
}

Dan karena ini adalah sebuah referensi, ini bisa diganti dengan Z2K2/nilai dari Z2/Objek bersinambung dengan ZID Z702 (seperti yang diberikan di atas); hasilnya akan terlihat seperti berikut:

{
  "type": "natural number",
  "base 10 representation": "2"
}
{
  "Z1K1": "Z10",
  "Z10K1": "2"
}

Semua representasi JSON dalam bagian ini memiliki arti yang sama untuk Wikifunctions. Mereka semua mengacu pada bilangan asli 2.

Perhatikan bahwa jika suatu Z8/Fungsi memiliki argumen bertipe Z2/Objek bersinambung, maka yang dimasukkan adalah Z2/Objek bersinambung itu sendiri dan bukan Z2K2/nilainya

Z4/Tipe

Tipe adalah ZObjek yang bertipe Z4/Tipe. ZObjek yang bertipe suatu tipe disebut contoh dari tipe tersebut. Jadi Z702/dua yang kita lihat di atas adalah contoh dari tipe Z10/bilangan bulat positif.

A Type tells us how to interpret a value. Tipe juga menyediakan cara untuk memeriksa validitas ZObjek yang memiliki tipe tersebut. Tipe biasanya menyatakan kunci apa saja yang tersedia untuk contoh dan sebuah Fungsi yang digunakan untuk memvalidasi contoh-contohnya.

Berikut adalah tipe untuk bilangan asli (disederhanakan, karena melewatkan deskripsi singkat dan alias, dan semua kunci kecuali tiga kunci pertama pada Z4/Tipe).

{
  "type": "persistent object",
  "id": {
    "type": "String",
    "string value": "Z10"
  },
  "value": {
    "type": "type",
    "identity": "natural number",
    "keys": [
      "key",
      {
        "type": "key",
        "value type": "string",
        "key id": "Z10K1",
        "label": {
          "type": "multilingual text",
          "texts": [
            "monolingual text",
            {
              "type": "monolingual text",
              "language": "English",
              "text": "base 10 representation"
            },
            {
              "type": "monolingual text",
              "language": "German",
              "text": "Dezimaldarstellung"
            }
          ]
        }
      }
    ],
    "validator": "validate natural number"
  },
  "label": {
    "type": "multilingual text",
    "texts": [
      "monolingual text",
      {
        "type": "monolingual text",
        "language": "English",
        "text": "natural number"
      },
      {
        "type": "monolingual text",
        "language": "German",
        "text": "natürliche Zahl"
      }
    ]
  }
}
{
  "Z1K1": "Z2",
  "Z2K1": {
    "Z1K1": "Z6",
    "Z6K1": "Z10"
  },
  "Z2K2": {
    "Z1K1": "Z4",
    "Z4K1": "Z10070",
    "Z4K2": [
      "Z3",
      {
        "Z1K1": "Z3",
        "Z3K1": "Z6",
        "Z3K2": "Z10K1",
        "Z3K3": {
          "Z1K1": "Z12",
          "Z12K1": [
            "Z11",
            {
              "Z1K1": "Z11",
              "Z11K1": "Z1251",
              "Z11K2": "base 10 representation"
            },
            {
              "Z1K1": "Z11",
              "Z11K1": "Z1254",
              "Z11K2": "Dezimaldarstellung"
            }
          ]
        }
      }
    ],
    "Z4K3": "Z110"
  },
  "Z2K3": {
    "Z1K1": "Z12",
    "Z12K1": [
      "Z11",
      {
        "Z1K1": "Z11",
        "Z11K1": "Z1251",
        "Z11K2": "positive integer"
      },
      {
        "Z1K1": "Z11",
        "Z11K1": "Z1254",
        "Z11K2": "natürliche Zahl"
      }
    ]
  }
}

Untuk membuat inti dari Tipe lebih mudah terlihat, mari kita lihat Z4/Tipenya dan hapus label-labelnya:

{
  "type": "type",
  "identity": "natural number",
  "keys": [
    "key",
    {
      "type": "key",
      "value type": "string",
      "keyid": "Z10K1"
    }
  ],
  "validator": "validate natural number"
}
{
  "Z1K1": "Z4",
  "Z4K1": "Z10",
  "Z4K2": [
    "Z3",
    {
      "Z1K1": "Z3",
      "Z3K1": "Z6",
      "Z3K2": "Z10K1"
    }
  ],
  "Z4K3": "Z110"
}

Tipe Z10/bilangan asli mendefinisikan dalam Z4K2/kunci sebuah Z3/Kunci baru yaitu Z10K1/representasi basis 10, yang telah kita gunakan di atas dalam contoh yang mewakili bilangan 2.

Z4K3/validator mengarah kepada sebuah Z8/Fungsi yang mengambil sebuah contoh bertipe ini sebagai argumennya dan menghasilkan sebuah galat atau nilai yang diambil, jika tidak terjadi galat. Jika tidak terjadi galat, contoh tersebut telah lulus validasi. Dalam hal ini, Z8/Fungsi dapat melakukan pemeriksaan berikut:

  • Hanya ada tepat satu Kunci, yaitu Z10K1/representasi basis 10, di contoh tadi, tidak termasuk Z1K1/tipenya.
  • Nilai representasi basis 10 memiliki tipe Z6/Untaian.
  • Representasi basis 10 hanya berisi angka.
  • Representasi basis 10 tidak dimulai dengan 0, kecuali seluruh isinya hanya 0.

Perhatikan bahwa semua pemeriksaan ini dilakukan oleh Z8/Fungsi yang disediakan oleh kontributor, dan bahwa semua Tipe dapat ditentukan dan diubah oleh kontributor. Tidak ada yang dikode secara bawaan untuk tipe bilangan yang sedang kita bicarakan di sini.

Sebuah contoh bisa saja menggunakan kunci yang tidak didefinisikan pada Tipenya. Itu tergantung pada apakah fungsi validator mengizinkannya atau tidak. Sebagai contoh, contoh dari Z7/Panggilan fungsi sering menggunakan kunci yang tidak ditetapkan di Z7/Panggilan fungsi, seperti yang bisa dilihat di Bagian tentang Z7/Panggilan fungsi. Namun, kebanyakan validator diharapkan untuk mengharuskan semua kunci didefinisikan.

Namun, beberapa hal dikodekan secara bawaan, seperti perilaku Z7/panggilan fungsi. Nanti ini akan dibahas lebih lanjut.

Z3/Kunci

Semua kunci harus memiliki huruf K diikuti dengan bilangan asli, dan biasanya diawali dengan ZID. Jika mereka diawali oleh ZID, maka mereka disebut Kunci Global; jika tidak, mereka disebut Kunci Lokal. Misalnya, dua representasi berikut adalah setara.

{
  "Z1K1": "Z7",
  "Z7K1": "Z781",
  "Z781K1": "Z702",
  "Z781K2": "Z702"
}
{
  "Z1K1": "Z7",
  "Z7K1": "Z10000",
  "K1": "Z702",
  "K2": "Z702"
}

Kunci Global adalah argumen bernama sementara Kunci Lokal adalah argumen berbasis posisi.

  • Kebiasaan yang disarankan adalah untuk selalu menggunakan Kunci Global selama bisa.
  • Kasus penggunaan utama untuk Kunci Lokal adalah ketika Z8/Fungsi atau Z4/Tipe sedang dibuat pada saat itu juga, sehingga tidak dapat memiliki Kunci Global karena Z8/Fungsi atau Z4/Tipe yang dibuat itu sendiri tidak bersinambung.

Kunci Global selalu didefinisikan di ZObjek yang ZID-nya sama dengan bagian ZID dari ID kunci.

Z8/Fungsi

Dalam definisi Z10/bilangan asli, kita melihat referensi pertama ke sebuah Z8/Fungsi, yaitu Z110/Validasi bilangan asli. Di sini, kita akan menggunakan fungsi yang jauh lebih sederhana, Z781/tambah. Z781/tambah adalah Z8/Fungsi yang mengambil dua Z10/bilangan asli dan menghasilkan sebuah Z10/bilangan asli.

Kita hanya memperlihatkan nilainya.

{
 "type": "function",
 "arguments": [
   "argument declaration",
   {
     "type": "argument declaration",
     "argument type": "natural number",
     "key id": "Z781K1",
     "label": { ... }
   },
   {
     "type": "argument declaration",
     "argument type": "natural number",
     "key id": "Z781K2",
     "label": { ... }
   }
 ],
 "return type": "natural number",
 "tests": [
   "testers",
   "add one and zero",
   "add two and two"
 ],
 "implementations": [
   "implementation",
   "+ in Python",
   "recursive addition",
   "+ in JavaScript"
 ],
 "identity": "add"
}
{
 "Z1K1": "Z8",
 "Z8K1": [
   "Z17",
   {
     "Z1K1": "Z17",
     "Z17K1": "Z10",
     "Z17K2": "Z781K1",
     "Z17K3": { ... }
   },
   {
     "Z1K1": "Z17",
     "Z17K1": "Z10",
     "Z17K2": "Z781K2",
     "Z17K3": { ... }
   }
 ],
 "Z8K2": "Z10",
 "Z8K3": [
   "Z20",
   "Z711",
   "Z712"
 ],
 "Z8K4": [
   "Z14",
   "Z721",
   "Z722",
   "Z723"
 ],
 "Z8K5": "Z144"
}

Agar ringkas, kami menghapus Z17K3/label dari deklarasi Z17/Argumen, yang diidentifikasi menggunakan Z17K2/ID kunci. Namun, seperti Z3/Kunci pada Z4/Tipe, mereka memiliki label berbahasa semua bahasa yang didukung. Kunci bersifat Global ketika Z8/Fungsinya bersinambung, dan Lokal ketika transien.

Fungsi ditetapkan melalui dokumentasi (tidak ditampilkan), tetapi juga melalui Z8K3/tes dan Z8K1/deklarasi tipe argumen-argumen dan Z8K2/tipe keluaran. Selain itu, karena Fungsi dapat memiliki beberapa Z8K4/Implementasi, Implementasi saling mengonfirmasi.

Z8/Fungsi tidak dibolehkan memiliki efek samping yang mengubah keadaan.

Z7/Panggilan fungsi

ZObject berikut mewakili suatu panggilan fungsi. Di baris kedua, kita melihat representasi yang lebih padat untuk panggilan fungsi. Representasinya menggunakan sintaksis yang lebih mudah dikenali untuk panggilan fungsi.

{
  "type": "function call",
  "function": "add",
  "left": "two",
  "right": "two"
}
{
  "Z1K1": "Z7",
  "Z7K1": "Z781",
  "Z781K1": "Z702",
  "Z781K2": "Z702"
}
add(two, two) Z781(Z702, Z702)

Jika menggunakan literal dan bukan ZObjek bersinambung untuk argumennya, ini akan terlihat seperti berikut.

  • Perhatikan bahwa kita membuat literal menggunakan Z10/bilangan bulat positif sebagai konstruktor.
  • Semua Z4/Tipe dapat dipanggil seperti ini, dengan memberikan nilai untuk setiap kunci mereka.
  • Ini bukan sebuah Z7/Panggilan fungsi, melainkan sebuah notasi untuk objek bertipe Z4/Tipe yang diberikan.
{
  "type": "function call",
  "function": "add",
  "left": {
    "type": "natural number",
    "base 10 representation": "2"
  },
  "right": {
    "type": "natural number",
    "base 10 representation": "2"
  }
}
{
  "Z1K1": "Z7",
  "Z7K1": "Z781",
  "Z781K1": {
    "Z1K1": "Z10",
    "Z10K1": "2"
  },
  "Z781K2": {
    "Z1K1": "Z10",
    "Z10K1": "2"
  }
}
add(natural number<"2">, natural number<"2">) Z781(Z10<"2">, Z10<"2">)

Ketika Z7/Panggilan fungsi ini dievaluasi, hasilnya seperti yang diharapkan yaitu bilangan empat.

{
  "type": "natural number",
  "base 10 representation": "4"
}
{
  "Z1K1": "Z10",
  "Z10K1": "4"
}
natural number<"4"> Z10<"4">

Evaluasi dilakukan berulang kali pada hasil evaluasi sampai titik tetap dicapai.

Z14/Implementasi

Setiap Z8/Fungsi dapat memiliki sejumlah Z14/Implementasi berbeda. Ada tiga jenis utama dari Z14/Implementasi: terbina, Z16/kode, atau melalui komposisi Z8/Fungsi lainnya.

Mari kita lihat Fungsi Z781/tambah dan empat Z14/Implementasi berbeda untuk fungsi tersebut.

Implementasi terbina

Implementasi terbina memberi evaluator untuk mengirimkan hasil evaluasi yang sesuai. Terbina berarti kodenya sudah ada di evaluator secara langsung. Z14K4/terbina diarahkan ke ID-terbina yang sudah ada (harus merupakan ZID dari sebuah Z2/Objek bersinambung).

{
  "type": "implementation",
  "implements": "add",
  "builtin": "Z791"
}
{
  "Z1K1": "Z14",
  "Z14K1": "Z781",
  "Z14K4": "Z791"
}

Evaluator mengetahui semua implementasi terbinanya dan bisa menggunakannya setiap saat. Perhatikan bahwa penjumlahan tidak akan menjadi fungsi dengan implementasi terbina. Hal ini diberikan untuk tujuan ilustrasi saja.

Z16/Kode

Implementasi yang berupa Z16/Kode merepresentasikan sebuah cuplikan kode dalam bahasa pemrograman tertentu.

{
  "type": "implementation",
  "implements": "add",
  "code": {
    "type": "code",
    "language": "javascript",
    "source": "function add(left, right) {
                 return left + right;
               }"
  }
}
{
  "Z1K1": "Z14",
  "Z14K1": "Z781",
  "Z14K3": {
    "Z1K1": "Z16",
    "Z16K1": "Z600",
    "Z16K2": "function Z781(Z781K1, Z781K2) {
                return Z781K1 + Z781K2;
              }"
  }
}
{
  "type": "implementation",
  "implements": "add",
  "code": {
    "type": "code",
    "language": "python",
    "source": "def add(left, right):
                 return left + right"
  }
}
{
  "Z1K1": "Z14",
  "Z14K1": "Z781",
  "Z14K3": {
    "Z1K1": "Z16",
    "Z16K1": "Z610",
    "Z16K2": "def Z781(Z781K1, Z781K2):
                return Z781K1 + Z781K2"
  }
}

Evaluator akan tahu cara mengubah ZObjek yang diberikan dan mewakili argumen-argumen ke dalam bahasa pemrograman yang didukung, bagaimana mengeksekusi cuplikan kode yang diberikan, dan kemudian bagaimana mengubah hasilnya kembali menjadi ZObjek yang mewakili hasil tersebut.

Pada suatu hari nanti, penerjemahan ZObjek ke nilai aslinya di bahasa pemrograman yang didukung akan ditangani di dalam Wikifunctions itu sendiri (ini akan membutuhkan dokumen desain baru). Sampai itu terjadi, kami hanya mendukung Z16/Kode untuk tipe argumen dan hasil yang didukung secara langsung oleh evaluator.

Z46/Deserializer

A Z46/Deserializer takes a ZObject of a specific Type and turns it into a value for a given programming language.

For example, the following Z46/Deserializers takes a ZObject of type Z10/Natural number and turns it into a JavaScript BigInt value.

{
  "type": "deserializer",
  "identity": "to BigInt",
  "type": "Natural number"
  "converter": {
    "type": "code",
    "language": "javascript",
    "source": "function deserialize( value ) {
	   return BigInt( value.decimal_representation.string_value );
     }"
  },
  "native type": "BigInt"
}
{
  "Z1K1": "Z46",
  "Z46K1": "Z787",
  "Z46K2": "Z10",
  "Z46K3": {
    "Z1K1": "Z16",
    "Z16K1": "Z600",
    "Z16K2": "function Z787(Z787K1) {
       return BigInt( Z787K1.Z10K1.Z6K1 );
     }"
  },
  "Z46K4": "BigInt"
}

The Z46K4/native type says in which type the deserializer will result. This allows us to use natural implementations like above for addition.

Z64/Serializer

The reverse operation of a Z46/Deserializer is the Z64/Serializer. A Z64/Serializer takes a value in the given programming language and turns it into a ZObject of the requested type.

{
  "type": "serializer",
  "identity": "from BigInt",
  "type": "Natural number"
  "converter": {
    "type": "code",
    "language": "javascript",
    "source": "function serialize( value ) {
	   return {
         "type": {
           "type": "reference",
           "reference id": "natural number"
         },
         "base 10 representation": {
           "type": "string",
           "string value": value.toString()
         }
       }
     }"
  },
  "native type": "BigInt"
}
{
  "Z1K1": "Z64",
  "Z64K1": "Z789",
  "Z64K2": "Z10",
  "Z64K3": {
    "Z1K1": "Z16",
    "Z16K1": "Z600",
    "Z16K2": "function Z789(Z789K1) {
	   return {
         "Z1K1": {
           "Z1K1": "Z9",
           "Z9K1": "Z10"
         },
         "Z10K1": {
           "Z1K1": "Z6",
           "Z6K1": value.toString()
         }
       }
     }"
  },
  "Z64K4": "BigInt"
}

Komposisi

Z14/Implementasi yang paling portabel (tetapi sering juga paling lambat) dicapai dengan melakukan komposisi Z8/Fungsi-fungsi lainnya.

Kami menunjukkan ZObjek implementasi serta notasi yang lebih mudah dibaca berdasarkan sintaks panggilan fungsi.

{
 "type": "implementation",
 "implements": "add",
 "composition": {
   "type": "function call",
   "function": "if",
   "condition": {
     "type": "function call",
     "function": "is zero",
     "arg": {
       "type": "argument reference",
       "reference": "right"
     }
   },
   "consequent": {
     "type": "argument reference",
     "reference": "left"
   },
   "alternative": {
     "type": "function call",
     "function": "add",
     "left": {
       "type": "function call",
       "function": "successor",
       "arg": {
         "type": "argument reference",
         "reference": "left"
       }
     },
     "right": {
       "type": "function call",
       "function": "predecessor",
       "arg": {
         "type": "argument reference",
         "reference": "right"
       }
     }
   }
 }
}
{
 "Z1K1": "Z14",
 "Z14K1": "Z781",
 "Z14K2": {
   "Z1K1": "Z7",
   "Z7K1": "Z802",
   "Z802K1": {
     "Z1K1": "Z7",
     "Z7K1": "Z782",
     "Z782K1": {
       "Z1K1": "Z18",
       "Z18K1": "Z781K2"
     }
   },
   "Z802K2": {
     "Z1K1": "Z18",
     "Z18K1": "Z781K1"
   },
   "Z802K3": {
     "Z1K1": "Z7",
     "Z7K1": "Z781",
     "Z781K1": {
       "Z1K1": "Z7",
       "Z7K1": "Z783",
       "Z783K1": {
         "Z1K1": "Z18",
         "Z18K1": "Z781K1"
       }
     },
     "Z781K2": {
       "Z1K1": "Z7",
       "Z7K1": "Z784",
       "Z784K1": {
         "Z1K1": "Z18",
         "Z18K1": "Z781K2"
       }
     }
   }
 }
}
if(
  is zero(right),
  left,
  add(
    successor(left),
    predecessor(right)
  )
)
Z802(
  Z782(Z781K2),
  Z781K1,
  Z781(
    Z783(Z781K1),
    Z784(Z781K2)
  )
)

Komposisi ini didasarkan pada sejumlah Z8/Fungsi lainnya: Z782/adalah nol, Z783/penerus, Z784/pendahulu, Z801/jika, dan, yang paling menarik — dirinya sendiri. Tidak masalah apabila suatu Z14/Implementasi memanggil Z8/Fungsinya sendiri secara rekursif. Perhatikan bahwa evaluator tidak harus memanggil Z14/Implementasi secara rekursif — evaluator bebas memilih implementasi mana pun pada setiap langkah rekursi.

Ini adalah sesuatu yang tidak cepat — tapi memungkinkan kita untuk menggunakan formalisme yang dipahami dengan baik dan implementasinya yang sangat sederhana untuk memastikan bahwa implementasi lain dari Z781/tambah benar — memang, mungkin kurang menarik untuk ditambahkan, tetapi kita dapat membayangkan bahwa ada Z8/Fungsi yang memiliki implementasi yang lebih jelas benar dan implementasi yang jauh lebih cerdas dan lebih cepat. Wikifunctions bisa menguji silang implementasi-implementasi ini terhadap satu sama lain sehingga memberikan kita rasa aman terhadap kebenaran mereka.

Example evaluation

In the following we evaluate the above composition. We start with the following Z7/function call (we only stick to the functional syntax due to its brevity).

add(Natural number<"2">, Natural number<"2">)
Z781(Z10<"2">, Z10<"2">)

We replace the function call with the composition given above, and replace the arguments with the given values. That results in the following code.

if(
  is zero(Natural number<"2">),
  Natural number<"2">,
  add(
    successor(Natural number<"2">),
    predecessor(Natural number<"2">)
  )
)
Z802(
  Z782(Z10<"2">),
  Z10<"2">,
  Z781(
    Z783(Z10<"2">),
    Z784(Z10<"2">)
  )
)

We evaluate the Z782/is zero(Z10/Natural number<"2">) to the Z40/Boolean value of Z42/false (since 2 is not zero). That results in:

if(
  false,
  Natural number<"2">,
  add(
    successor(Natural number<"2">),
    predecessor(Natural number<"2">)
  )
)
Z802(
  Z42,
  Z10<"2">,
  Z781(
    Z783(Z10<"2">),
    Z784(Z10<"2">)
  )
)

This allows us to replace the call to Z802/if with the Z802K3/alternative, since the Z802K1/condition is false. That results in:

add(
  successor(Natural number<"2">),
  predecessor(Natural number<"2">)
)
Z781(
  Z783(Z10<"2">),
  Z784(Z10<"2">)
)

The Z783/successor function just adds one to a number, and the Z784/predecessor function removes one. Any of these functions may or may not be implemented in code or in some other way, this does not really matter. If we replace both these function calls, we get to the following call:

add(
  Natural number<"3">,
  Natural number<"1">
)
Z781(
  Z10<"3">,
  Z10<"1">
)

Again we substitute the call to Z781/add with its composition, and replace the arguments with the new values. That results in:

if(
  is zero(Natural number<"1">),
  Natural number<"3">,
  add(
    successor(Natural number<"3">),
    predecessor(Natural number<"1">)
  )
)
Z802(
  Z782(Z10<"1">),
  Z10<"3">,
  Z781(
    Z783(Z10<"3">),
    Z784(Z10<"1">)
  )
)

We again check if the value given to Z782/is zero (it is not, it is one). So we replace the call to Z782/is zero again with Z42/false.

if(
  false,
  Natural number<"3">,
  add(
    successor(Natural number<"3">),
    predecessor(Natural number<"1">)
  )
)
Z802(
  Z42,
  Z10<"3">,
  Z781(
    Z783(Z10<"3">),
    Z784(Z10<"1">)
  )
)

Since the Z802K1/condition is again false, we replace the call to Z802/if with the Z802K3/alternative.

add(
  successor(Natural number<"3">),
  predecessor(Natural number<"1">)
)
Z781(
  Z783(Z10<"3">),
  Z784(Z10<"1">)
)

Again we replace the function calls to Z783/successor and Z784/predecessor with the respective results, one number more, one number less.

add(
  Natural number<"4">,
  Natural number<"0">
)
Z781(
  Z10<"4">,
  Z10<"0">
)

We are now again at the point where we replace the call to Z781/add with its composition. That results in:

if(
  is zero(Natural number<"0">),
  Natural number<"4">,
  add(
    successor(Natural number<"4">),
    predecessor(Natural number<"0">)
  )
)
Z802(
  Z782(Z10<"0">),
  Z10<"4">,
  Z781(
    Z783(Z10<"4">),
    Z784(Z10<"0">)
  )
)

The call to Z782/is zero now got the argument Z10/natural number<"0"> which is indeed zero. So the call to Z782/is zero results in a Z41/true. That results in:

if(
  true,
  Natural number<"4">,
  add(
    successor(Natural number<"4">),
    predecessor(Natural number<"0">)
  )
)
Z802(
  Z41,
  Z10<"4">,
  Z781(
    Z783(Z10<"4">),
    Z784(Z10<"0">)
  )
)

The Z802/if function call now has a Z41/true Z802K1/condition, which means we replace the whole call with the Z802K2/consequence, not the Z802K3/alternative. That results in:

Natural number<"4">
Z10<"4">

This is a fixpoint, i.e. it does not change when evaluated, and thus is the result of our function call.

2 and 2 is 4.

Evaluation order

The evaluation order is up to the evaluator. Since all Z8/Functions are not allowed to have side-effects, this will always lead to the same result. But an unwise evaluation strategy can lead to much more computation than necessary or even to the evaluator not terminating. Z722/recursive addition provides us with an example that might end up in an endless loop if we try a complete evaluation order:

For the call to Z802/if in Z722/recursive addition it would be unwise to first evaluate all three arguments and then to return either the second or the third argument. Depending on the first argument Z802K1/condition we will only need to return either Z802K2/consequent or Z802K3/alternative. There is never the case that we need to evaluate both the second and the third argument.

In fact we could even return the second or third argument unevaluated. Remember that the evaluator will evaluate each result again anyway until a fixpoint is reached. So Z802/if can be implemented lazily, drop the irrelevant branch, and return the relevant branch as an unevaluated ZObject.

A lazy evaluation strategy is in general recommended, but for example when the evaluator wants to use a Z16/Code based implementation, it might not be feasible. And then the evaluator might decide to first evaluate the arguments and then the outer call. In the end, there are opportunities to experiment with different evaluation strategies.

Z20/Penguji

Z20/Penguji adalah ZObjek yang melakukan sebuah Z20K2/panggilan dan kemudian menggunakan suatu Z20K3/validator pada hasilnya. Z20K3/Validator adalah Z7/panggilan fungsi tidak lengkap yang argumen pertamanya sudah disuntikkan dari hasil Z20K2/panggilan. Jika Z20K3/validator menghasilkan nilai Z41/benar, maka Z20/Tes lulus; jika tidak, maka ia gagal.

Tes digunakan untuk memastikan bahwa semua Z14/Implementasi berperilaku seperti yang seharusnya, dan sebaiknya dianggap mirip dengan pengujian unit. Suatu Z8/Fungsi harus mencantumkan semua Z20/Tes yang perlu dilewati agar Z14/Implementasi dapat disebut sesuai. Selain itu, Z14/Implementasi yang berbeda dapat diuji silang satu sama lain demi konsistensi.

{
 "type": "tester",
 "function": "add",
 "call": {
   "type": "function call",
   "function": "add",
   "left": "two",
   "right": "two"
 },
 "result validator": {
   "type": "function call",
   "function": "equivalent natural number",
   "right": "four"
 }
}
{
 "Z1K1": "Z20",
 "Z20K1": "Z781",
 "Z20K2": {
   "Z1K1": "Z7",
   "Z7K1": "Z781",
   "Z781K1": "Z702",
   "Z781K2": "Z702"
 },
 "Z20K3": {
   "Z1K1": "Z7",
   "Z7K1": "Z788",
   "Z788K2": "Z704"
 }
}

Dalam kasus ini, kita pertama-tama mengevaluasi Z20K2/panggilan, yaitu Z781/tambah(Z702/dua, Z702/dua), dan mendapat hasilnya Z10/Bilangan asli<"4">. Hasil ini kemudian digunakan dalam Z20K3/validator hasil, di mana ia disuntikkan sebagai argumen pertama, menghasilkan Z788/kesamaan bilangan asli(Z10/Bilangan asli<"4">, Z704/empat). Panggilan tersebut seharusnya menghasilkan Z41/benar, dan dengan demikian panggilan lulus Z20/Tes.

Tipe generik

Tipe generik diwujudkan dengan sebuah Z7/Panggilan fungsi ke suatu Z8/Fungsi yang menerima beberapa argumen dan menghasilkan sebuah Z4/Tipe.

Contohnya, Z882/pasangan bertipe adalah fungsi yang mengambil dua Z4/Tipe sebagai argumen, satu untuk elemen pertama dan satu untuk elemen kedua, dan menghasilkan sebuah Z4/Tipe dalam baris. Jadi untuk membuat sebuah pasangan Z10/Bilangan asli, kita memanggil Z882/pasangan bertipe(Z10/Bilangan asli, Z10/Bilangan asli) dan hasilnya adalah sebuah Z4/Tipe yang dapat kita gunakan untuk isian Z1K1 dari suatu ZObjek.

{
 "type": {
   "type": "function call",
   "function": "typed pair",
   "first": "natural number",
   "second": "natural number"
 },
 "first": "one",
 "second": "two"
}
{
 "Z1K1": {
   "Z1K1": "Z7",
   "Z7K1": "Z882",
   "Z882K1": "Z10",
   "Z882K2": "Z10"
 },
 "K1": "Z701",
 "K2": "Z701"
}

Hasil Z7/Panggilan fungsinya adalah sebuah Z4/Tipe yang dibuat secara dinamis yang memastikan bahwa kedua elemen dari Pasangan memiliki Z4/Tipe yang tepat. Hasil Z7/Panggilan fungsi tersebut terlihat seperti ini.

{
 "type": "type",
 "identity": {
   "type": "function call",
   "function": "typed pair",
   "first": "natural number",
   "second": "natural number"
 },
 "keys": [
   "key",
   {
     "type": "key",
     "id": "K1",
     "value type": "natural number"
   },
   {
     "type": "key",
     "id": "K2",
     "value type": "natural number"
   }
 ],
 "validator": "validate typed pair"
}
{
 "Z1K1": "Z4",
 "Z4K1": {
   "Z1K1": "Z7",
   "Z7K1": "Z882",
   "Z882K1": "Z10",
   "Z882K2": "Z10"
 },
 "Z4K2": [
   "Z3",
   {
     "Z1K1": "Z3",
     "Z1K2": "K1",
     "Z3K1": "Z10"
   },
   {
     "Z1K1": "Z3",
     "Z1K2": "K2",
     "Z3K1": "Z10"
   }
 ],
 "Z4K3": "Z892"
}

Ini juga merupakan contoh penggunaan isian Z4K1/identitas pada Z4/Tipe: ini menggambarkan bagaimana Z4/Tipe dibuat, dan memungkinkan kita mengakses argumen yang digunakan untuk pembuatan Tipe. Memegang informasi ini secara deklaratif sangat membantu dalam memvalidasi Panggilan fungsi secara statis, serta untuk membandingkan tipe-tipe.

Jika kita menginginkan Z882/Pasangan bertipe yang tidak membatasi Z4/Tipe dari satu atau kedua elemen, seseorang bisa memanggil fungsi Z882/Pasangan bertipe dengan Z1/ZObjek sebagai satu atau kedua argumennya.

Z881/Daftar

Berikut adalah daftar dua untaian.

[
 "string",
 "a",
 "b"
]
[
 "Z6",
 "a",
 "b"
]

Jika kita mengubahnya menjadi ZObjek, mereka akan terlihat seperti berikut.

{
 "type": {
   "type": "function call",
   "function": "typed list",
   "elementtype": "string"
 },
 "head": "a",
 "tail": {
   "type": {
     "type": "function call",
     "function": "typed list",
     "elementtype": "string"
   },
   "head": "b"
 }
}
{
 "Z1K1": {
   "Z1K1": "Z7",
   "Z7K1": "Z881",
   "Z881K1": "Z6"
 },
 "K1": "a",
 "K2": {
   "Z1K1": {
     "Z1K1": "Z7",
     "Z7K1": "Z881",
     "Z10K1": "Z6"
   },
   "K1": "b"
 }
}

Sebuah larik JSON literal selalu dimulai dengan tipe yang digunakan untuk Z881/Daftar bertipe. Ini bukan elemen pertama dari daftar, melainkan hanya tipe dari daftar bertipe. Larik ini disebut Larik Benjamin. Jika kita menginginkan daftar tak bertipe, kita akan menggunakan Z1/Objek sebagai argumennya. Daftar kosong yang tak bertipe akan terlihat seperti berikut.

[
 "object"
]
[
 "Z1"
]

Z5/Galat

Suatu Z7/Panggilan fungsi dapat menghasilkan sebuah Z5/Galat. Ini terjadi ketika panggilan fungsi tidak bisa dieksekusi dengan benar, dan tidak dapat dipulihkan (contohnya, pembagian dengan nol atau kehabisan memori).

Z5 adalah sebuah tipe generik. Setiap contoh Z5 merujuk ZID dari suatu tipe galat (dalam Z5K1/tipe galat), dan tipe galat tersebut menentukan tipe Z5K2/nilai galatnya, dan kunci yang akan ada di dalamnya. Setiap tipe galat merupakan contoh dari Z50/tipe galat, dan ZID Z500–Z599 disediakan untuk tipe-tipe galat.

Informasi lebih lanjut tersedia di Wikipedia Abstrak/Representasi galat.

Z99/Kutipan

Z99/Kutipan digunakan sebagai pembungkus ZObjek lainnya, untuk menandakan bahwa objek tersebut jangan dievaluasi ("terurai"). (Ini mirip dengan kutipan dalam Lisp.) Z99/Kutipan punya satu kunci, Z99K1/kutipan, dengan tipe Z1/Objek.

Untuk menggambarkannya, beberapa bagian dari objek galat (contoh dari Z5/Galat) dikutip ketika mereka dibuat selama pelaksanaan panggilan fungsi. Misalnya, galat bertipe Z507/Galat evaluasi mencakup salinan dari keseluruhan panggilan fungsi yang eksekusinya menyebabkan galat (sebagai nilai dari Z507K1/panggilan fungsi). Karena panggilan fungsi ini sangat mungkin akan cacat entah bagaimana bentuknya, kami memastikan ia tidak akan dicoba dievaluasi lagi, dengan mengutipnya di dalam objek galat. (Jadi, tipe Z507K1 dinyatakan sebagai Z99, dan nilainya selalu dikutip.)

Kami menggunakan pedoman berikut untuk kapan menggunakan Z99/Kutipan:

  1. Kutip suatu ZObjek ketika kita percaya objek tersebut mungkin entah bagaimana tidak valid.
  2. Tapi jangan mengutip Z1K1-nya sendiri. Jika nilainya diragukan, kutip seluruh objek yang mengandungnya.
  3. Kutip kunci yang dapat teruraikan (kunci yang nilai-nilainya berisi contoh Z7, Z9, atau Z18) yang mungkin tidak tepat untuk dicerna sebagai masukan fungsi.
  4. Kutip saat menguraikan nilai dapat menyebabkan bencana (misalnya rekursi tak terbatas).

Catatan: seiring strategi resolusi kami berkembang, bisa jadi (3) dan (4) tidak lagi diperlukan.

Fungsi nonfungsional

Z8/Fungsi tidak diperbolehkan memiliki efek samping. Semua Z8/Fungsi haruslah fungsional. Artinya, mereka harus menghasilkan nilai yang sama jika dipanggil dengan argumen yang sama. Ini berarti bahwa Z8/Fungsi seperti "hasilkan sembarang bilangan" atau "hasilkan waktu saat ini" tidaklah mungkin.

This might change in the future. Hal ini akan ditangani dalam suatu dokumen nanti.

Zx/Sum type

Tipe generik yang bisa sangat berguna adalah Zx/Sum type, yang mengambil daftar Z4/Tipe dan menghasilkan sebuah Z4/Tipe yang bisa merupakan tepat satu contoh dari tipe mana pun yang diberikan.

Ini juga akan memungkinkan adanya parameter yang tidak diwajibkan dalam panggilan fungsi.

Hal ini akan ditangani dalam suatu dokumen nanti.


Beberapa pertanyaan dan pekerjaan untuk dikerjakan

  • Apakah kita memerlukan "wajib/pilihan" untuk kunci di mana pun dari awal? — tidak
  • Mengganti nilai bawaan pada Z3/Kunci dengan Zx/Sum? (atau setidaknya membuatnya konsisten dengan Z17/deklarasi argumen)
  • Bisa ditunda untuk kemudian waktu jika kita tidak perlu nilai bawaan pada Z3 untuk saat ini
  • Make a note that all is Unicode and that all is the normalization required by MediaWiki
  • Rewrite intro to start with normal and then canonicalize

Lihat pula