위키함수:함수 모델
”위키함수”는 누구나 기여할 수 있는 다국어 함수 카탈로그로, 누구나 함수를 만들고 유지하며 호출하고 사용할 수 있습니다. 모든 함수는 여러 가지 구현을 가질 수 있습니다. 예를 들어 다른 프로그래밍 언어에서 또는 다른 알고리즘을 사용합니다. 이것은 "함수 위키백과"로 위키미디어 재단이 운영하는 자매 프로젝트입니다.
이 문서는 "위키함수"의 데이터 모델과 평가 모델을 다룹니다
- 이 모델 설명 전체에서 대문자로 표시된 용어는 용어집에서 정의된 용어를 나타냅니다.
- 이전 프로토 타입의 연습을 읽는 것은 다음 모델을 읽기 전에 여기서 진행되는 작업을 더 잘 이해하는 데 매우 도움이 되었습니다.
Z1/ZObject
"위키함수"는 위키입니다. 모든 위키에서와 마찬가지로 "위키함수"의 내용은 주로 위키 페이지에 저장됩니다. 위키 페이지는 개별적으로 편집할 수 있지만 전체 프로젝트는 일정한 일관성을 유지해야합니다. 또한 위키 페이지는 다른 모든 페이지를 이해하지 않고도 개별적으로 편집할 수 있어야합니다.
"위키함수"의 내용을 나타내는 Z객체를 소개합니다. "위키함수" 이름공간의 각 위키 페이지에는 Z2/영속 객체 유형의 Z객체가 정확히 하나만 포함되어 있습니다. 다른 이름 공간에는 정책 페이지와 사용자 페이지, 토론 페이지 등과 같은 다른 콘텐츠가 포함될 수 있습니다. Z객체는 JSON 객체로 직렬화할 수 있습니다.
Z객체는 키/값 쌍 목록으로 구성됩니다.
- 키/값 쌍의 모든 값은 Z객체입니다.
- Values can be either a Z6/String, a Z9/Reference, or have any other type. Z6/String and Z9/Reference are called terminal values. They don't expand further.
- A Z6/String has exactly two keys, Z1K1/type with the value "Z6", and Z6K1/string value, with an arbitrary string.
- A Z9/Reference has exactly two keys, Z1K1/type with the value "Z9", and Z9K1/reference ID, with a string representing a ZID.
- 모든 키는 각 Z객체에 한 번만 나타날 수 있지만 포함된 Z객체에는 다시 나타날 수 있습니다.
Z객체는 기본적으로 추상 구문 트리입니다. 프로젝트의 TLDR이 있다면 아마도 "JSON의 LISP와 같은 것"일 것입니다. 목표는 위키 인터페이스를 통해 Z객체를 만들고 조작할 수 있는 쉬운 사용자 환경(UX)을 제공하여 많은 기여자에게 다가 갈 수 있는 코딩 환경을 만들고 활발한 공동체와 함께 위키미디어 프로젝트가 될 수 있는 것입니다.
모든 Z객체에는 Z4/유형으로 평가되는 값이 있는 키 Z1K1/유형이 있어야합니다.
우리는 "ZID/레이블" 표기법을 사용하여 다소 읽기 쉬운 방식으로 ZID를 참조합니다. 여기서 ZID는 Z객체 id 또는 이러한 객체의 키이고 레이블(label)입니다. 해당 언어 중립적 id 또는 키에 첨부된 (영어) 레이블입니다.
The representation of a ZObject that is represented only as records of key/value pairs, and that only ends in terminal nodes, is called a normal form. The normal form of a ZObject is usually the one used for evaluation.
Canonical form
In order to make ZObjects more readable and more compact, we usually store and transmit them in the so-called canonical form.
Canonical forms use three syntactic transformations: for Z9/references, Z6/strings, and Z881/lists.
Canonical References
A reference refers to a ZObject by its ZID. A ZID starts with the letter Z, followed by a natural number. The normal form of a reference looks as follows (here, and throughout the document, we display ZObjects always twice: on the left hand side in the labelized version, i.e. where all ZIDs and key IDs are replaced with an English label, and on the right hand side with the ZIDs and key IDs unreplaced).
{
"type": "reference",
"reference id": "natural number"
}
|
{
"Z1K1": "Z9",
"Z9K1": "Z10"
}
|
The canonical form replaces that object with a single string with the ZID. The canonical form of the above reference is thus the following:
"natural number"
|
"Z10"
|
Note that the normal and canonical form have the same meaning.
Canonical Strings
A String is a sequence of Unicode Code Points, representing usually a word or a text. It can include spaces and any other character besides control characters.
The normal form of a String looks as follows. Note that the value of the second key is indeed the string, and not the labelized version of a ZID, as can be seen on the right hand side.
{
"type": "string",
"string value": "Wikifunctions"
}
|
{
"Z1K1": "Z6",
"Z6K1": "Wikifunctions"
}
|
Strings can usually be canonicalized by just their string instead of the whole object. The above string can be canonicalized as follows.
"Wikifunctions"
|
"Wikifunctions"
|
Note that Strings that start with a capital Latin letter and are followed by a natural number need to be escaped, as they would otherwise clash with the normal representation of a Reference.
For example, the String "Z1"
would have the following representation, both in the normal and canonical form.
This is because otherwise it would be ambiguous whether "Z1"
refers to the String Z1 or is a reference to the object with the ZID Z1.
{
"type": "string",
"string value": "Z1"
}
|
{
"Z1K1": "Z6",
"Z6K1": "Z1"
}
|
Canonical lists
Lists are represented through so-called Benjamin Arrays. Their description can be found below in the section Z881/Typed lists.
직렬화
Z객체[1]는 추상 ZID 키("Z1K1" 등)를 키로 사용하고 값에 대해 다음 중 하나를 사용하여 표준 JSON 표현으로 직렬화됩니다.
추상 키와 ZID를 주어진 언어, "레이블화" 표현으로 된 레이블로 대체하여 더 읽기 쉬운 대체 표현을 제공 할 수 있습니다. The labelized version is often ambiguous and can not always be translated to the machine-readable representation.
다음 표는 양의 정수 2를 나타내는 Z객체의 예를 제공합니다. 왼쪽에는 영어로 레이블이 지정된 Z객체, 독일어로 레이블이 지정된 가운데, 오른쪽에는 ZID를 사용하는 Z객체가 있습니다.
{
"type": "natural number",
"base 10 representation": "2"
}
|
{
"Typ": "natürliche Zahl",
"Dezimaldarstellung": "2"
}
|
{
"Z1K1": "Z10",
"Z10K1": "2"
}
|
보시다시피 레이블은 영어로 되어 있을 필요는 없지만 "위키함수"가 지원하는 300개 이상의 언어 중 하나 일 수 있습니다.
정규화
평가자가 Z객체를 처리하기 위해 모든 Z객체는 자체의 정규화된 버전으로 변환됩니다. 표준화된 버전은 역직렬화 된 버전과 유사하지만 문자열 값을 Z6/문자열 또는 Z9/참조로 해석할지 여부에 대한 암시성에 의존하지 않지만 모두 명시적인 Z객체로 표현됩니다.
이것은 Z객체의 정규화 된 표현이 모든 리프가 Z6/문자열 또는 Z9/참조 유형인 트리임을 의미합니다.
이것은 또한 모든 Z10/List가 배열이 아닌 Z객체[1]로 표현된다는 것을 의미합니다. 또한 모든 Z10/List 객체에는 (Z10) K1/head 및 (Z10) K2/tail 키가 모두 있어야합니다. 빈 목록 (하나의 요소가 있는 목록의 꼬리 포함)은 Z13/Empty[2]입니다.
다음 정규화 된 형식은 양의 정수 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"
}
}
|
정규화 된 뷰는 평가 엔진의 입력으로 만 사용됩니다. 평가를 위한 입력은 항상 균일하고, 처리하기 쉬우며 최소한의 특수 사례 만 필요로합니다.
영속적 및 일시적
"위키함수" 위키 페이지에 저장된 모든 최상위 Z객체는 Z2/영속 객체입니다. 자신의 위키 페이지에 저장되지 않은 Z객체를 일시적 Z객체라고 합니다.
Z2K1/id가 있어야 하는 모든 영속적 Z객체, ZID는 그것이 저장된 위키 페이지의 이름과 동일합니다. 이전에 본 양의 정수 2에 대한 Z객체가 있고, Z382/two 페이지에 저장되어 있다고 가정 해 보겠습니다. 이것이 어떻게 보일 수 있는지 (ZID가 반드시 우리가 "위키함수"에서 사용하는 것은 아닙니다).
{
"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"
}
]
}
}
|
All JSON objects stored on Wikifunctions are stored in Unicode normalization form C. All values before evaluation must also be Unicode-normalized to Unicode normal form C.
Z2/영속 개체는 Z2K2/값에 포함 된 Z객체에 대한 메타 데이터를 제공합니다.
Z2K3/레이블은 Z3/키와 Z12K1/텍스트가 하나 인 Z12/다국어 텍스트 유형의 Z객체이고, Z11/단일어 텍스트 Z객체의 z10/리스트를 가리킵니다(Z10/리스트는 JSON 표현에서 배열로 표현된다는 것을 기억). 레이블은 레이블화를 허용합니다.
Z2/영속 객체에 대한 추가 Z3/키는 문서화, 위키의 프레젠테이션 및 검색 가능성 향상을 위한 메타 데이터를 제공합니다. 그것들은 모두 Z2/영속 객체에 정의되어 있습니다.
Z9/참조
Z9/참조는 지정된 ID를 가진 Z객체의 Z2K2/값에 대한 참조이며, 이 Z2K2/값이 여기에 삽입되어야 함을 의미합니다. 예를 들어, 단일 요소가 있는 다음 배열이 제공됩니다:
"two"
|
"Z702"
|
요소는 바로 가기 Z9/참조이며, 확장된 형식으로 표시됩니다(역직렬화에 관한 섹션에서 설명):
{
"type": "reference",
"reference id": "two"
}
|
{
"Z1K1": "Z9",
"Z9K1": "Z702"
}
|
그리고 이것은 참조이기 때문에 ZID Z382(위에 주어진 바와 같이)를 가진 Z2/영속 객체의 Z2K2/값으로 대체되어야합니다. 즉, 다음과 같이 보일 것입니다:
{
"type": "natural number",
"base 10 representation": "2"
}
|
{
"Z1K1": "Z10",
"Z10K1": "2"
}
|
All three JSON representations in this section have the same meaning for Wikifunctions. They all refer to the natural number 2.
Z8/함수에 Z2/영속 객체의 인수 유형이 있는 경우 Z2K2/값 대신에 Z2/영속 객체 자체가 대체됩니다.
Z4/유형
유형은 유형 Z4/유형의 Z객체입니다. 유형의 Z객체를 해당 유형의 인스턴스라고합니다. 따라서 위에서 본 Z382/two는 Z10070/양의 정수 유형의 인스턴스입니다.
A Type tells us how to interpret a value. 유형은 해당 유형의 Z객체의 유효성을 확인하는 수단을 제공합니다. 유형은 일반적으로 인스턴스에 사용할 수있는 키와 인스턴스의 유효성을 검사하는 데 사용되는 함수를 선언합니다.
다음은 양의 정수에 대한 (간단한) 유형입니다.
{
"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"
}
]
}
}
|
유형의 핵심을 더 쉽게 보이게 하려면 Z4/유형을 보고 레이블을 제거하겠습니다:
{
"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"
}
|
유형 Z10070/양의 정수는 Z4K2/키에서 새로운 Z3/키 Z10070K1/밑 10 표기법을 정의하며, 위에서 숫자 2를 나타내는 인스턴스에서 사용했습니다.
Z4K3/검증자는 인스턴스를 인수로 사용하고 Z5/오류의 Z10/리스트를 반환하는 Z8/함수를 가리킵니다. Z10/리스트가 비어 있으면 인스턴스가 유효성 검사를 통과 한 것입니다. 주어진 경우 Z8/함수는 다음 검사를 수행합니다.
- 인스턴스에는 메타 데이터 외에 단 하나의 키, Z10070K1/밑 10 표기법이 있습니다.
- 밑 10 표기법 값은 Z6/문자열 유형입니다.
- 밑이 10 표현에는 숫자 만 포함됩니다.
- 밑 10 표기법은 길이가 1이 아니면 0으로 시작하지 않습니다
이러한 모든 검사는 기여자가 제공하는 Z8/함수에 의해 수행되며 모든 유형은 기여자가 정의하고 수정할 수 있습니다. 여기서 사용하는 숫자 유형과 관련하여 하드 코딩 된 것은 없습니다.
인스턴스는 유형에 정의되지 않은 키를 사용할 수 있습니다. 이를 허용할지 여부는 검증자 함수에 달려 있습니다. 예를 들어, Z7/함수 호출의 인스턴스는 Z7/함수 호출의 섹션에서 볼 수 있듯이 Z7/함수 호출에 정의되지 않은 키를 자주 사용합니다. 하지만 대부분의 검증자에서는 모든 키를 정의해야합니다.
그러나 Z7/함수 호출의 동작과 같은 몇 가지 사항이 하드 코딩되어 있습니다. 이것에 대해서는 나중에 자세히 설명합니다.
Z3/키
모든 키에는 K 다음에 자연수가 있어야하며 앞에 ZID가 올 수 있습니다. ZID가 앞에 오는 경우 전역 키라고하고 그렇지 않은 경우 로컬 키라고합니다. 예를 들어 다음 두 표현은 동일합니다.
{
"Z1K1": "Z7",
"Z7K1": "Z781",
"Z781K1": "Z702",
"Z781K2": "Z702"
}
|
{
"Z1K1": "Z7",
"Z7K1": "Z10000",
"K1": "Z702",
"K2": "Z702"
}
|
전역 키는 명명된 인수인 반면 로컬 키는 위치 인수입니다.
- 경험상 가능한 한 전역 키를 사용하는 것이 좋습니다.
- 로컬 키의 주요 사용 사례는 Z8/함수 또는 Z4/유형이 즉석에서 생성되고 생성된 Z8/함수 또는 Z4/유형 자체가 영구적이지 않기 때문에 전역 키를 가질 수없는 경우입니다.
전역 키는 항상 ID의 ZID 부분이 참조하는 Z객체에 정의됩니다.
In their definition, a Key contains information of what type of object it must contain (Z3K1), the global ID that identifies that key (Z3K2), its human-readable labels (Z3K3) and whether this key is an identity field (Z3K4).
An identity key allows objects to store their persisted ID. For example, Functions and Types contain an identity field. Also planned types, particularly enumerations, such as grammatical features, require identity.
Enumerations
An enumeration is a type that has a limited number of values. Examples of enumerations are the type Boolean (with the values "false" and "true"), or Integer sign (with the values "positive", "neutral" or "negative"). Enumerations are also an important tool to support linguistic functions.
Every enumeration type has one key that is marked as an identity field. For example, let's look at the Type definition for Boolean (removing key labels for simplicity):
{
"type": "Type",
"identity": "Boolean",
"keys": [
"Key",
{
"type": "Key",
"value type": "Boolean",
"key id": "Z40K1",
"label": { /* "identity" */ },
"is identity": "True"
}
],
...
}
|
{
"Z1K1": "Z4",
"Z4K1": "Z40",
"Z4K2": [
"Z3",
{
"Z1K1": "Z3",
"Z3K1": "Z40",
"Z3K2": "Z40K1",
"Z3K3": { /* "identity" */ },
"Z3K4": "Z41"
}
],
...
}
|
All limited values for Boolean will assign their ZID as the value for their identity/Z40K1 key. See, for example, True, which contains its identity and additionally the multilingual data (name, description, aliases) as part of the Persistent Object keys.
{
"type": "Persistent object",
"identity": {
"type": "String",
"value": "Z41"
},
"value": {
"type": "Boolean",
"identity": "True"
},
"labels": {
"type": "Multilingual text",
"texts": [
"Monolingual text",
{
"type": "Monolingual text",
"language": "English",
"text": "true"
}
]
}
}
|
{
"Z1K1": "Z2",
"Z2K1": {
"Z1K1": "Z6",
"Z6K1": "Z41"
},
"Z2K2": {
"Z1K1": "Z40",
"Z40K1": "Z41"
},
"Z2K3": {
"Z1K1": "Z12",
"Z12K1": [
"Z11",
{
"Z1K1": "Z11",
"Z11K1": "Z1002",
"Z11K2": "true"
}
]
}
}
|
Z8/함수
Z10070/양의 정수 정의에서 Z8/함수, Z10559/양의 정수 유효성 검사에 대한 첫 번째 참조를 보았습니다. 여기서는 훨씬 더 간단한 함수인 Z144/add를 사용합니다. Z144/add는 두 개의 Z10070/양의 정수를 취하고 Z10070/양의 정수를 반환하는 Z8/함수입니다.
우리는 값만을 보여줍니다.
{
"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"
}
|
간결하게 유지하기 위해 Z17K2/키 ID를 사용하여 식별되는 Z17/인수 선언에서 Z17K3/레이블을 제거했습니다. 그러나 Z4/유형의 Z3/키와 마찬가지로 지원되는 모든 언어로 된 레이블이 있습니다. 키는 Z8/함수가이 지속적일 때 전역이고 일시적일 때 로컬입니다.
함수는 (생략 된) 문서를 통해 지정되지만 인수 및 K2/반환 유형에 대한 K3/테스트 및 K1/유형 선언을 통해서도 지정됩니다. 또한 함수에는 여러 Z14/구현(아래 참조)이 있을 수 있으므로 구현은 서로를 확인합니다.
Z8/함수는 상태를 변경하는 부작용이 허용되지 않습니다.
Z7/함수 호출
다음 Z객체는 함수 호출을 나타냅니다. 두 번째 행에서는 함수 호출에 더 익숙한 구문을 사용하는 함수 호출의 보다 간결한 표현을 볼 수 있습니다.
{
"type": "function call",
"function": "add",
"left": "two",
"right": "two"
}
|
{
"Z1K1": "Z7",
"Z7K1": "Z781",
"Z781K1": "Z702",
"Z781K2": "Z702"
}
|
add(two, two)
|
Z781(Z702, Z702)
|
인수에 영구 Z객체 대신 리터럴을 사용하면 다음과 같이 보일 것입니다.
- Z10070/양의 정수를 생성자로 사용하여 리터럴을 생성하고 있습니다.
- 모든 Z4/유형은 이와 같이 호출하여 각 키에 대한 값을 제공 할 수 있습니다.
- 이것은 Z7/함수 호출이 아니라 주어진 Z4/유형의 객체에 대한 표기법입니다.
{
"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">)
|
When this Z7/Function call gets evaluated, it results as expected in the number four.
{
"type": "natural number",
"base 10 representation": "4"
}
|
{
"Z1K1": "Z10",
"Z10K1": "4"
}
|
natural number<"4">
|
Z10<"4">
|
부동점에 도달 할 때까지 평가 결과에 대한 평가가 반복적으로 수행됩니다.
Z14/구현
모든 Z8/함수는 다양한 Z14/구현을 가질 수 있습니다. Z14/구현에는 세 가지 주요 유형이 있습니다: 내장, Z16/코드 또는 다른 Z8/함수 구성을 통해.
Z144/추가 함수를 사용하여 다섯 가지 Z14/구현을 살펴 보겠습니다.
내장 구현
내장 구현은 평가자, 즉 런타임에 적절한 평가 결과를 반환하도록 지시합니다. 내장 기능은 평가자에 하드 코딩됩니다. Z14K4/내장은 하드 코딩 된 내장 ID를 나타냅니다(일반적으로 Z2/영구 객체의 ZID 여야하지만 반드시 그럴 필요는 없음).
{
"type": "implementation",
"implements": "add",
"builtin": "Z791"
}
|
{
"Z1K1": "Z14",
"Z14K1": "Z781",
"Z14K4": "Z791"
}
|
평가자는 자신의 모든 내장 기능을 인식하고 마음대로 사용할 수 있습니다. 직접 호출하기 위해 내장을 선언하는 것이 여전히 유용합니다.
Z16/코드
Z16/코드의 구현은 주어진 프로그래밍 언어로 된 코드 조각을 나타냅니다.
{
"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"
}
}
|
평가자는 인수를 나타내는 주어진 Z객체를 지원되는 프로그래밍 언어로 변환하는 방법, 제공된 코드 조각을 실행하는 방법, 결과를 다시 결과를 나타내는 Z객체로 변환하는 방법을 알고 있습니다.
결국 Z객체를 지원되는 프로그래밍 언어의 기본 값으로 변환하는 작업은 "위키함수" 자체에서 처리됩니다(새로운 디자인 문서가 필요함). 그때까지는 평가자에 의해 하드 코딩된 지원이 있는 인수 및 반환 유형에 대해서만 Z16/코드를 지원합니다.
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': Z789K1.toString()
}
}
}"
},
"Z64K4": "BigInt"
}
|
구성
가장 휴대 성이 뛰어난 (가장 느린 경우도 있음) Z14/구현은 다른 Z8/함수의 구성을 통해 달성됩니다.
구현의 Z객체와 함수 호출 구문을 기반으로 읽기 쉬운 표기법을 모두 보여줍니다.
{
"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(
|
Z802(
|
이 구성은 다른 여러 Z8/함수에 의존합니다: Z145/is 0, Z146/다음, Z147/이전 Z3/if, 그리고 가장 흥미롭게도 그 자체입니다. Z14/구현이 자체 Z8/함수를 재귀적으로 호출하는 것은 전적으로 괜찮습니다. 평가자가 Z14/구현을 재귀적으로 호출할 필요는 없습니다. 평가자는 각 재귀 단계에서 구현을 자유롭게 선택할 수 있습니다.
이것은 빠르지 않습니다 — 그러나 Z144/add의 다른 구현이 올바른지 확인하기 위해 잘 이해된 형식주의와 매우 간단한 구현을 사용할 수 있습니다. 물론 추가에 대한 관심이 적습니다. 보다 분명하게 올바른 구현과 훨씬 더 빠른 구현을 가진 Z8/함수가 있다고 상상할 수 있습니다. "위키함수"는 이러한 구현을 서로 교차 테스트 할 수 있으므로 정확성에 대한 보안 감각을 제공합니다.
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.
평가 순서
평가 순서는 평가자에게 달려 있습니다. 모든 Z8/함수에는 부작용이 허용되지 않으므로 항상 동일한 결과가 발생합니다. 그러나 현명하지 않은 평가 전략은 필요한 것보다 훨씬 더 많은 계산으로 이어지거나 평가자가 종료하지 않을 수 있습니다. Z1445/add 재귀는 완전한 평가 순서를 시도하면 끝없는 루프로 끝날 수있는 예제를 제공합니다:
Z1445/add 재귀에서 Z31/if에 대한 호출의 경우 먼저 세 인수를 모두 평가한 다음 두 번째 또는 세 번째 인수를 반환하는 것은 현명하지 않습니다. 첫 번째 인수 Z31K1/condition에 따라 Z31K2/consequent 또는 Z31K3/alternative 중 하나만 반환하면 됩니다 두 번째 인수와 세 번째 인수를 모두 평가해야하는 경우는 없습니다.
사실 우리는 평가되지 않은 두 번째 또는 세 번째 인수를 반환할 수도 있습니다. 평가자는 고정점에 도달할 때까지 어쨌든 각 결과를 다시 평가할 것임을 기억하세요. 따라서 Z31/if를 느리게 구현하고 관련없는 분기를 삭제하고 관련 분기를 평가되지 않은 Z객체[1]로 반환 할 수 있습니다.
일반적으로 지연 평가 전략이 권장되지만 평가자가 Z16/코드 기반 구현을 사용하려는 경우 실현 가능하지 않을 수 있습니다. 평가자는 먼저 인수를 평가 한 다음 외부 호출을 평가하기로 결정할 수 있습니다. 결국 다양한 평가 전략을 실험할 수있는 기회가 있습니다.
Z20/테스트
Z20/테스트는 Z7/함수 호출을 호출한 다음 Z8/함수를 사용하여 결과를 테스트하는 Z객체[1]입니다. Z8/함수가 Z54/true를 반환하면 Z20/테스트는 통과하고 그렇지 않으면 실패합니다.
테스트는 모든 Z14/구현이 정상적으로 작동하는지 확인하는 데 사용되며 단위 테스트와 유사한 것으로 간주되어야합니다. Z8/함수는 Z14/구현이 규정을 준수하기 위해 통과해야하는 모든 Z20/테스트를 나열해야합니다. 또한 서로 다른 Z14/구현은 일관성을 위해 서로 교차 테스트할 수 있습니다.
{
"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"
}
}
|
In this case we evaluate first the Z20K2/call, which is Z781/add(Z702/two, Z702/two)
, resulting in Z10/Natural number<"4">
.
That, in turn, is then used in the Z20K3/result validator, where it is injected as the first argument, resulting in Z788/natural number equality(Z10/Natural number<"4">, Z704/four)
.
That call should result in Z41/true, and thus the Z20/Tester should pass.
제네릭 유형
제네릭 유형은 Z8/함수에 대한 Z7/함수 호출에 의해 실현됩니다.이 호출은 일부 인수를 취하고 Z4/유형을 반환합니다.
예를 들어, Z10022/쌍은 매개변수로 두 개의 Z4/유형(첫 번째 요소와 두 번째 요소에 대해 하나씩)를 사용하고 인라인 Z4/유형을 반환하는 함수일 수 있습니다. 따라서 Z10070/양의 정수 쌍을 만들고 싶다면 Z10022/쌍(Z10070/양의 정수, Z10070/양의 정수)를 호출하고 결과는 Z객체의 Z1K1 필드에 사용할 수있는 Z4가 됩니다.[1]
{
"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": "Z702"
}
|
Z7/함수 호출의 결과는 쌍의 두 요소가 올바른 Z4/유형을 갖도록하는 동적으로 생성된 Z4/유형입니다. Z7/함수 호출의 결과는 다음과 같습니다.
{
"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"
}
|
또한 Z4/유형의 Z4K1/identity 필드에 대해서도 설명합니다. Z4/유형이 생성된 방법을 설명하고 유형 생성에 사용된 인수에 접근할 수 있습니다. 이 정보를 선언적으로 유지하는 것은 함수 호출을 정적으로 검증하고 유형을 비교하는 데 매우 유용합니다.
하나 또는 두 요소의 Z4/유형을 제한하지 않는 Z10022/쌍을 원한다면 Z1/Z객체[3]를 하나 또는 두 인수로 사용하여 Z10022/쌍 함수를 호출할 수 있습니다.
Z10/리스트
다음은 두 문자열 목록입니다.
[
"string",
"a",
"b"
]
|
[
"Z6",
"a",
"b"
]
|
이것을 Z객체로 바꾸면 다음과 같이 보입니다.
{
"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"
}
}
|
JSON 배열 리터럴의 역직렬화는 먼저 배열의 모든 요소가 동일한 Z1K1/유형을 갖는지 확인해야합니다. 그렇다면 해당 유형을 인수로 사용하여 Z10/리스트를 만듭니다. 그렇지 않은 경우 Z1/Z객체[3]를 인수로 사용하여 Z10을 만듭니다.
[
"object"
]
|
[
"Z1"
]
|
Z22/Evaluation result
A Z7/Function call executed in Wikifunctions always returns an object of type Z22/Evaluation result.
An Evaluation result object always contains the value returned from the execution of a Function Call and a collection of metadata gathered during the evaluation. Here's an example of a successful response:
{
"type": "evaluation result",
"result": "Hello, World!",
"metadata": {
"type": {
"type": "function call",
"function": "typed map",
"key type": "string",
"value type": "object"
},
"map": [
{
"type": "function call",
"function": "typed pair",
"first type": "string",
"second type": "object"
},
{
"type": {
"type": "function call",
"function": "typed pair",
"first type": "string",
"second type": "object"
},
"key": "orchestrationDuration",
"value": "139 ms"
}
]
}
}
|
{
"Z1K1": "Z22",
"Z22K1": "Hello, World!",
"Z22K2": {
"Z1K1": {
"Z1K1": "Z7",
"Z7K1": "Z883",
"Z883K1": "Z6",
"Z883K2": "Z1"
},
"K1": [
{
"Z1K1": "Z7",
"Z7K1": "Z882",
"Z882K1": "Z6",
"Z882K2": "Z1"
},
{
"Z1K1": {
"Z1K1": "Z7",
"Z7K1": "Z882",
"Z882K1": "Z6",
"Z882K2": "Z1"
},
"K1": "orchestrationDuration",
"K2": "139 ms"
}
]
}
}
|
If the evaluation is unsuccessful, the response field will contain Z24/Void, while the metadata field will contain an "error" key with the details of the failure. This is an example of a failed Evaluation result object:
{
"type": "evaluation result",
"result": "void",
"metadata": {
"type": {
"type": "function call",
"function": "typed map",
"key type": "string",
"value type": "object"
},
"map": [
{
"type": "function call",
"function": "typed pair",
"first type": "string",
"second type": "object"
},
{
"type": {
"type": "function call",
"function": "typed pair",
"first type": "string",
"second type": "object"
},
"key": "errors",
"value": {
"type": "error",
"error type": "unspecified error",
"error value": {
"type": {
"type": "function call",
"function": "errortype to type",
"errortype": "unspecified error"
},
"error information": "Some error happened"
}
}
}
]
}
}
|
{
"Z1K1": "Z22",
"Z22K1": "Z24",
"Z22K2": {
"Z1K1": {
"Z1K1": "Z7",
"Z7K1": "Z883",
"Z883K1": "Z6",
"Z883K2": "Z1"
},
"K1": [
{
"Z1K1": "Z7",
"Z7K1": "Z882",
"Z882K1": "Z6",
"Z882K2": "Z1"
},
{
"Z1K1": {
"Z1K1": "Z7",
"Z7K1": "Z882",
"Z882K1": "Z6",
"Z882K2": "Z1"
},
"K1": "errors",
"K2": {
"Z1K1": "Z5",
"Z5K1": "Z500",
"Z5K2": {
"Z1K1": {
"Z1K1": "Z7",
"Z7K1": "Z885",
"Z885K1": "Z500"
},
"Z500K1": "Some error happened"
}
}
}
]
}
}
|
These examples are just condensed versions of the real Evaluation result objects and only contain one example key in the Metadata field. In real examples, the metadata collection will return all the metrics gathered by the backend services, including the run's duration, CPU usage, and memory usage.
For a more detailed description of all the possible metadata returned in the Evaluation result object, see the Function call metadata guide in Mediawiki.
Z5/오류
Z7/함수 호출은 항상 Z5/오류를 발생시킬 수 있습니다. 이것은 다소 복구 불가능한 경우 일 수 있습니다(즉, 0으로 나누거나 메모리 부족이 모두 동일한 방식으로 처리됨).
Z5 is a generic type. Each instance of Z5 references the ZID of an error type (in Z5K1/error type), and that error type determines the type of Z5K2/error value, and the keys that will be present therein. Each error type is an instance of Z50/error type, and ZIDs Z500–Z599 are reserved for error types.
Additional information is available at Abstract Wikipedia/Representation of errors.
Z99/Quote
Z99/Quote is used as a wrapper around another ZObject, to indicate that it should not be evaluated ("resolved"). (This is similar to quoting in Lisp.) Z99/Quote has a single key, Z99K1/quotation, of type Z1/Object.
To illustrate, some parts of error objects (instances of Z5/Error) are quoted when they get created during the execution of a function call. For example, an error of type Z507/Error in evaluation includes a copy of the entire function call whose execution caused the error (as the value of Z507K1/function call). Because this function call is very likely to be malformed in some way, we ensure that no further attempt is made to evaluate it, by quoting it inside the error object. (Thus, the type of Z507K1 is declared as Z99, and its value is always quoted.)
We use the following guidelines for when to use Z99/Quote:
- Quote a ZObject when we believe it may be invalid in some way.
- But do not quote Z1K1 by itself. If its value is in doubt, quote the entire object that contains it.
- Quote resolvable keys (keys whose values contain instances of Z7, Z9, or Z18) that might inappropriately be ingested as the input to a function.
- Quote when resolving a value might cause a catastrophe (e.g. infinite recursion).
Note: as our resolution strategy evolves, it's possible that (3) and (4) could become unnecessary.
비 함수적 함수
Z8/함수는 부작용이 허용되지 않지만 일부 Z8/함수는 완전히 작동하지 않을 수 있습니다. 즉 동일한 매개 변수로 호출 될 때 다른 값을 반환할 수 있습니다. 일반적인 Z8/함수는 "난수 반환", "현재 시간 반환" 또는 "위키데이터에서 값 반환"입니다.
This might change in the future. 이것은 이후 문서에서 처리 될 것입니다.
Zx/합계 유형
특히 유용한 제네릭 유형은 Zx/합계 유형으로, Z4/유형 목록을 취하고 주어진 유형 중 정확히 하나의 인스턴스를 취할 수있는 Z4/유형을 반환합니다.
이것은 또한 함수 호출에서 필수가 아닌 매개 변수를 허용합니다.
이것은 이후 문서에서 처리 될 것입니다.
수행 할 몇 가지 질문 및 작업
- 처음에 키에 대한 "필수/선택 사항"이 필요하나요? - 아닙니다.
- Z3/키의 기본값을 Zx/Sum으로 바꾸시겠습니까? (또는 적어도 Z17/인수 선언과 일치하도록 만드세요)
- 당분간 Z3에서 기본값이 필요하지 않으면 나중에 남겨 둘 수 있습니다.
- 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