Abstract Wikipedia/Function model/ja: Difference between revisions
Appearance
Content deleted Content added
Updating to match new version of source page |
Updating to match new version of source page Tag: Replaced |
||
| (One intermediate revision by one other user not shown) | |||
| Line 1: | Line 1: | ||
<noinclude><languages /> |
<noinclude><languages /></noinclude> |
||
{{TNT|Abstract Wikipedia navbox}} |
|||
</noinclude> |
|||
[[Special:MyLanguage/Abstract Wikipedia/Glossary#Wikifunctions|''ウィキ関数'']] とは多言語で展開する'''[[Special:MyLanguage/Abstract Wikipedia/Glossary#Function|関数]]'''のカタログで誰でも投稿でき、関数を書いたり管理したり、呼び出したり使ったりできます。 |
|||
どの関数も複数の実行があり、たとえばプログラム言語が変わったり用いるアルゴリズムが異なったりします。 |
|||
「関数の[[Special:MyLanguage/Abstract Wikipedia/Glossary#Wikipedia|ウィキペディア]]」であり、[[Special:MyLanguage/Abstract Wikipedia/Glossary#Wikimedia Foundation|ウィキメディア財団]]が動かす姉妹プロジェクトのひとつです。 |
|||
<span lang="en" dir="ltr" class="mw-content-ltr"><!-- Please translate this page on Wikifunctions.org instead --></span> |
|||
この説明文書では、''ウィキ関数'' のデータモデルとその評価を扱います。 |
|||
: このモデルの説明全体を通じて、大文字表記の言葉は'''[[Special:MyLanguage/Abstract Wikipedia/Glossary|用語集]]'''で定義してあります。 |
|||
: <span lang="en" dir="ltr" class="mw-content-ltr">Reading the [https://github.com/google/abstracttext/blob/master/eneyj/docs/walkthrough.md walkthrough of a previous prototype] has been very helpful to get a better intuition of what is going on here before reading the following model.</span> |
|||
{{interwiki redirect|f:Wikifunctions:Function model{{#ifeq:{{PAGELANGUAGE}}|en||/{{PAGELANGUAGE}}}}}} |
|||
{{Anchor|Z1}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z1/ZObjects == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">''Wikifunctions'' is a wiki. As in all wikis, the content of ''Wikifunctions'' is mainly stored in wiki pages.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Wiki pages can be individually edited, and yet the project as a whole must retain a certain consistency.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Also, wiki pages should be individually editable without having to understand all of the other pages.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We introduce ZObjects to represent the content of ''Wikifunctions''.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Each wiki page of the main namespace of ''Wikifunctions'' contains exactly one ZObject<ref name="typed" /> of type Z2/Persistent object.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Other namespaces can contain other content, such as policy pages, user pages, discussion pages, etc.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A ZObject<ref name="typed" /> can be serialized as a JSON object.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A ZObject<ref name="typed" /> consists of a list of Key/value pairs.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Every value in a Key/value pair is a ZObject<ref name="syntactic" />.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Every Key can only appear once on each ZObject<ref name="typed" /> (but may reappear on an embedded ZObject<ref name="typed" />).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">ZObjects<ref name="typed" /> are basically abstract syntax trees.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If there was a TLDR of the project it would probably be “something like LISP in JSON”.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The goal is to provide an easy UX to allow the creation and manipulation of ZObjects<ref name="typed" /> through a wiki interface, and thus create a coding environment that can reach a large number of contributors and may become a Wikimedia project with an active community.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Every ZObject<ref name="typed" /> must have a key Z1K1/type with a value that evaluates to a Z4/Type (this will be explained soon).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We use the notation ''ZID/label'' to refer to ZIDs in a more or less readable fashion where ‘''ZID''’ is a ZObject<ref name="typed" /> id or a key on such an object, and ‘''label''’ is the (English language) label attached to that language-neutral id or key.</span> |
|||
{{Anchor|syntax}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Syntax == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The canonical representation of a ZObject<ref name="syntactic" /> is a subset of JSON. A well-formed ZObject<ref name="syntactic" /> has the following syntax:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
|style="font-size:90%;line-height:1.6;font-family:monospace;margin:.6em 0;border:1px solid #AAA;padding:2px .5em;background:#F8F9FA;color:#222| |
|||
''ZObject'' := ''String'' | ''List'' | ''Record'' |
|||
<br /> |
|||
''String'' := <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">"</b>''Character''*<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">"</b> <span style="color:#777">// <span lang="en" dir="ltr" class="mw-content-ltr">to be specific, as in [http://www.ecma-international.org/publications/standards/Ecma-404.htm JSON / ECMA-404]</span></span> |
|||
<br /> |
|||
''List'' := <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">[</b> ( ''ZObject'' ( <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">,</b> ''ZObject'' )* )? <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">]</b> |
|||
<br /> |
|||
''Record'' := <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">{ "Z1K1":</b> ''ZObject'' ( <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">, "</b>''Key''<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">":</b> ''ZObject'' )* <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">}</b> |
|||
<br /> |
|||
''Key'' := ''ZNumber'' ''KNumber'' | ''KNumber'' |
|||
<br /> |
|||
''ZNumber'' := <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">Z</b> ''Number'' |
|||
<br /> |
|||
''KNumber'' := <b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">K</b> ''Number'' |
|||
<br /> |
|||
''Number'' := [<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">1</b>-<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">9</b>][<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">0</b>-<b style="margin:1px;border:1px solid #CCC;padding:1px;color:green">9</b>]* <span style="color:#777">// <span lang="en" dir="ltr" class="mw-content-ltr">a positive non-zero decimal integer</span></span> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">where:</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr"><code style="font-size:90%;line-height:1.4;font-family:monospace;margin:1px;border:1px solid #CCC;padding:1px;color:green">'''bold'''</code> characters are terminal symbols;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr"><code style="font-size:90%;line-height:1.4;font-family:monospace">''italic''</code> characters are used for non-terminal symbols;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr"><code style="font-size:90%;line-height:1.4;font-family:monospace">( )</code> are used to surround a group which may contain one or several alternatives separated by <code style="font-size:90%;line-height:1.4;font-family:monospace">|</code>;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">a group can be repeated using <code style="font-size:90%;line-height:1.4;font-family:monospace">*</code> which means repeat 0..''n'' times, or <code style="font-size:90%;line-height:1.4;font-family:monospace">+</code> which means repeat 1..''n'' times;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">a group followed by <code style="font-size:90%;line-height:1.4;font-family:monospace">?</code> is optional;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">whitespaces can be used as in JSON.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">That results in the subset of JSON without numbers, null, booleans, and with limited keys.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In order to be well-formed, the Z1K1 key must have a value that may evaluate to a Z4 Type, i.e. either is a well-formed literal of type Z4, a reference, or a function call.</span> |
|||
{{Anchor|serialization}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Serialization == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A ZObject<ref name="typed" /> is serialized to its canonical JSON representation using as keys the abstract ZID keys (“Z1K1”, etc.), and for values either:</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">the canonical JSON representation of another (transient) ZObject<ref name="typed" />,</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">the ZID<ref name="Z2K1" /> of a persistent (Z2) ZObject<ref name="typed" /> (i.e. a string value with a leading capital letter of the latin alphabet and digits following),</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">a simple string value, which can alternatively be represented as a ZObject<ref name="typed" /> itself (Z6/string type), or</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">a JSON array as a representation for Z10/list objects.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">An alternate more readable representation can be given by replacing the abstract keys and ZIDs with their labels in a given language, the “labelized” representation.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The following table gives an example of a ZObject<ref name="typed" /> representing the positive integer 2.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">On the left we see the ZObject<ref name="typed" /> labelized in English, in the middle labelized in German, and on the right we see the ZObject<ref name="typed" /> using ZIDs.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "positive integer", |
|||
"base 10 representation": "2" |
|||
}</syntaxhighlight> |
|||
|<syntaxhighlight lang="json">{ |
|||
"Typ": "natürliche Zahl", |
|||
"Dezimaldarstellung": "2" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "2" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">As you can see, the labels don’t have to be in English, but can be in any of the more than 300 languages ''Wikifunctions'' supports.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Also note that if the key is Z2K1/id or Z6K1/string value, then the value is always serialized as a simple string value.</span> |
|||
{{Anchor|deserialization}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Deserialization == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The canonical JSON representation for a ZObject<ref name="typed" /> is converted into its computational equivalent essentially through standard JSON parsing — that is the JSON object becomes a ZObject<ref name="typed" /> with the same (abstract) keys. The four different allowed value formats are parsed as follows:</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If the value is another JSON object, that in turn should follow the same deserialization rules, recursively.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For string values, if the value is a simple string that starts with a capital letter of the latin alphabet followed by a number then it is interpreted as a reference to a persistent ZObject<ref name="typed" />, a Z9/Reference.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In the above example, the value of Z1K1/type is given as the string "Z10070", but it should be parsed as a reference ZObject<ref name="typed" /> which would itself be represented as follows:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "reference", |
|||
"reference id": "positive integer" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z9", |
|||
"Z9K1": "Z10070" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">On the other hand if the value is a simple string that does not start with a capital letter of the latin alphabet followed by a number, the string is understood as a ZObject<ref name="typed" /> of the type Z6/String and the given value.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">I.e. the value of Z10070K1/base 10 representation is given as the string "2", but it should be parsed as a ZObject<ref name="typed" /> that looks as follows:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "string", |
|||
"string value": "2" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z6", |
|||
"Z6K1": "2" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note that the deserialization process should not be repeated as it could in these cases (the value of the Z1K1/type key would be interpreted as of type Z9/Reference, and the value of Z6K1/string value again as of type Z6/string) as that would lead to an infinite recursion; these are internally represented ZObjects<ref name="typed" />, not serialized JSON at this point.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Given these deserialization rules, if we need to write an actual string that starts with a capital letter of the latin alphabet and is followed by a number, we need to escape this.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This uses the exception regarding Z6K1/string value above. Here is the string value "Z1" on the key Z11K2/text.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "text", |
|||
"language": "English", |
|||
"text": { |
|||
"type": "string", |
|||
"string value": "Z1" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1251", |
|||
"Z11K2": { |
|||
"Z1K1": "Z6", |
|||
"Z6K1": "Z1" |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Finally, note that JSON arrays are deserialized as Z10/List ZObjects<ref name="typed" />. The full interpretation of JSON arrays is explained in the section on Z10/Lists below.</span> |
|||
{{Anchor|normalisation}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Normalization == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For the processing of ZObjects<ref name="typed" /> by the evaluator, all ZObjects<ref name="typed" /> are turned into a normalized version of themselves.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The normalized version is similar to the deserialized version, but we don't rely on any implicitness regarding whether to interpret a string value as a Z6/String or a Z9/Reference, but they are all expressed as explicit ZObjects.<ref name=typed /></span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This means the normalized representation of a ZObject<ref name="typed" /> is a tree where all leaves are either of the type Z6/String or Z9/Reference.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This also means that all Z10/Lists are represented as ZObjects<ref name=typed />, not as an array. Furthermore, all Z10/List objects must have both the (Z10)K1/head and (Z10)K2/tail keys. An empty list (including the tail of a list with one element) is a Z13/Empty<ref name="empty" /></span>. |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The following normalized form represents the positive integer 2.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": { |
|||
"type": "reference", |
|||
"reference id": "positive integer" |
|||
}, |
|||
"base 10 representation": { |
|||
"type": "string", |
|||
"string value": "2" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { |
|||
"Z1K1": "Z9", |
|||
"Z9K1": "Z10070" |
|||
}, |
|||
"Z10070K1": { |
|||
"Z1K1": "Z6", |
|||
"Z6K1": "2" |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Normalized views are used only as inputs for the evaluation engine. They ensure that the input for evaluation is always uniform and easy to process, and that it requires a minimal amount of special cases.</span> |
|||
{{Anchor|persistent-transient}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Persistent and transient == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Every top-level ZObject<ref name="typed" /> stored in a ''Wikifunctions'' wiki page is a Z2/Persistent object. ZObjects<ref name=syntactic /> that are not stored on their own wiki page are called transient ZObjects<ref name="syntactic" />.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Every persistent ZObject<ref name="typed" /> must have a Z2K1/id, a ZID which is equivalent to the name of the wiki page where it is stored.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Let’s assume that there is a ZObject<ref name="typed" /> for the positive integer 2 that we saw previously and that it is stored on the page Z382/two.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This is what it could look like (note that the ZIDs are not necessarily the ones we will use in ''Wikifunctions'').</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "persistent object", |
|||
"id": "Z382", |
|||
"value": { |
|||
"type": "positive integer", |
|||
"base 10 representation": "2" |
|||
}, |
|||
"label": { |
|||
"type": "multilingual text", |
|||
"texts": [ |
|||
{ |
|||
"type": "text", |
|||
"language": "English", |
|||
"text": "two" |
|||
}, |
|||
{ |
|||
"type": "text", |
|||
"language": "German", |
|||
"text": "zwei" |
|||
} |
|||
] |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z2", |
|||
"Z2K1": "Z382", |
|||
"Z2K2": { |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "2" |
|||
}, |
|||
"Z2K3": { |
|||
"Z1K1": "Z12", |
|||
"Z12K1": [ |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1251", |
|||
"Z11K2": "two" |
|||
}, |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1254", |
|||
"Z11K2": "zwei" |
|||
} |
|||
] |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The Z2/Persistent object provides metadata for the ZObject<ref name=typed /> embedded in the Z2K2/value.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The Z2K3/label is a ZObject<ref name="typed" /> of the type Z12/multilingual text which has one Z3/Key, Z12K1/texts, pointing to a Z10/list of Z11/monolingual text ZObjects<ref name="typed" /> (remember that a Z10/list is represented as an array in the JSON representation). The label allows for the labelization.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">There are further Z3/Keys on Z2/Persistent object that provide metadata, which are for documentation, presentation in the wiki, and to improve findability. They are all defined on Z2/Persistent object.</span> |
|||
{{Anchor|Z9}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z9/References == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">As we have seen on the positive number 2 is that the value of Z1K1/type is a ZObject<ref name="typed" /> of type Z9/Reference. If we extend that, it would look like this.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line='line'>{ |
|||
"type": { |
|||
"type": "reference", |
|||
"reference id": "positive integer" |
|||
}, |
|||
"base 10 representation": "2" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { |
|||
"Z1K1": "Z9", |
|||
"Z9K1": "Z10070" |
|||
}, |
|||
"Z10070K1": "2" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Z9/Reference is a reference to the Z2K2/value of the ZObject<ref name="typed" /> with the given ID, and means that this Z2K2/value should be inserted here.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">To give an example, given the following array with a single element:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">[ |
|||
"two" |
|||
]</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">[ |
|||
"Z382" |
|||
]</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The element is a shortcut Z9/Reference, that would look like this in the expanded form (as explained in the Section on [[#Deserialization|deserialization]]):</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">[ |
|||
{ |
|||
"type": "reference", |
|||
"reference id": "two" |
|||
} |
|||
]</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">[ |
|||
{ |
|||
"Z1K1": "Z9", |
|||
"Z9K1": "Z382" |
|||
} |
|||
]</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">And since this is a reference, this is to be replaced with the Z2K2/value of the Z2/Persistent object with the ZID Z382 (as given above), i.e. it would look as follow:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">[ |
|||
{ |
|||
"type": "positive integer", |
|||
"base 10 representation": "2" |
|||
} |
|||
]</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">[ |
|||
{ |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "2" |
|||
} |
|||
]</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note that if a Z8/Function has an argument type of Z2/Persistent object, then, instead of the Z2K2/value, the Z2/Persistent object itself is being substituted in.</span> |
|||
{{Anchor|Z4}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z4/Types == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Types are ZObjects<ref name="typed" /> of type Z4/Type. ZObjects<ref name="typed" /> of a type are called instances of that type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">So Z382/two we saw above was an instance of the type Z10070/positive integer.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Type provides us with the means to check the validity of a ZObject<ref name="typed" /> of that type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Type usually declares the keys available for its instances and a Function that is used to validate the Instances.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Here is (a simplified) type for positive integers.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "persistent object", |
|||
"id": "Z10070", |
|||
"value": { |
|||
"type": "type", |
|||
"identity": "positive integer", |
|||
"keys": [ |
|||
{ |
|||
"type": "key", |
|||
"value type": "string", |
|||
"key id": "Z10070K1", |
|||
"label": { |
|||
"type": "multilingual text", |
|||
"texts": [ |
|||
{ |
|||
"type": "text", |
|||
"language": "English", |
|||
"text": "base 10 representation" |
|||
}, |
|||
{ |
|||
"type": "text", |
|||
"language": "German", |
|||
"text": "Dezimaldarstellung" |
|||
} |
|||
] |
|||
}, |
|||
"default": "value required" |
|||
} |
|||
], |
|||
"validator": "validate positive integer" |
|||
}, |
|||
"label": { |
|||
"type": "multilingual text", |
|||
"texts": [ |
|||
{ |
|||
"type": "text", |
|||
"language": "English", |
|||
"text": "positive integer" |
|||
}, |
|||
{ |
|||
"type": "text", |
|||
"language": "German", |
|||
"text": "natürliche Zahl" |
|||
} |
|||
] |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z2", |
|||
"Z2K1": "Z10070", |
|||
"Z2K2": { |
|||
"Z1K1": "Z4", |
|||
"Z4K1": "Z10070", |
|||
"Z4K2": [ |
|||
{ |
|||
"Z1K1": "Z3", |
|||
"Z3K1": "Z6", |
|||
"Z3K2": "Z10070K1", |
|||
"Z3K3": { |
|||
"Z1K1": "Z12", |
|||
"Z12K1": [ |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1251", |
|||
"Z11K2": "base 10 representation" |
|||
}, |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1254", |
|||
"Z11K2": "Dezimaldarstellung" |
|||
} |
|||
] |
|||
}, |
|||
"Z3K4": "Z25" |
|||
} |
|||
], |
|||
"Z4K3": "Z10559" |
|||
}, |
|||
"Z2K3": { |
|||
"Z1K1": "Z12", |
|||
"Z12K1": [ |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1251", |
|||
"Z11K2": "positive integer" |
|||
}, |
|||
{ |
|||
"Z1K1": "Z11", |
|||
"Z11K1": "Z1254", |
|||
"Z11K2": "natürliche Zahl" |
|||
} |
|||
] |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">To make the core of the Type easier visible, let’s just look at the Z4/Type and remove the labels:</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "type", |
|||
"identity": "positive integer", |
|||
"keys": [ |
|||
{ |
|||
"type": "key", |
|||
"value type": "string", |
|||
"keyid": "Z10070K1", |
|||
"default": "value required" |
|||
} |
|||
], |
|||
"validator": "validate positive integer" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z4", |
|||
"Z4K1": "Z10070", |
|||
"Z4K2": [ |
|||
{ |
|||
"Z1K1": "Z3", |
|||
"Z3K1": "Z6", |
|||
"Z3K2": "Z10070K1", |
|||
"Z3K4": "Z25" |
|||
} |
|||
], |
|||
"Z4K3": "Z10559" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Type Z10070/positive integer defines in Z4K2/keys the new Z3/Key Z10070K1/base 10 representation, which we had used above in the instance representing the number 2.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z4K3/validator points to a Z8/Function that takes an instance as its argument and returns a Z10/List of Z5/errors.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If the Z10/List is empty then the instance has passed the validation. In the given case, the Z8/Function would do the following checks:</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">There is one and only one Key, Z10070K1/base 10 representation, on the instance, besides the metadata.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The value of the base 10 representation has the type Z6/String.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The base 10 representation contains only digits.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The base 10 representation does not start with a 0, unless it has a length of 1.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The base 10 representation is below 2<sup>32</sup> (or whatever else the limit is for this Type).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note that all these checks are done by Z8/Functions that are provided by contributors, and that all Types can be defined and modified by contributors.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">There is nothing hardcoded regarding the number type that we use here.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">An instance might use keys that are not defined on the Type. It is up to the validator function to allow that or not.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For example, instances of Z7/Function call often use keys not defined on Z7/Function call, as can be seen in the Section on [[#Z7/Function calls|Z7/Function calls]].</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Most validators are expected to require that all keys are defined, though.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">But a few things are hardcoded, such as the behavior of Z7/function call. More about this later.</span> |
|||
{{Anchor|Z3}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z3/Keys == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">All keys must have a K followed by a natural number, and may be preceded by a ZID.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If they are preceded by a ZID they are called Global Keys, if they are not they are called Local Keys. For example, the following two representations are equivalent.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"Z144K1": "Z382", |
|||
"Z144K2": "Z382" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"K1": "Z382", |
|||
"K2": "Z382" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Global Keys are named arguments whereas Local Keys are positional arguments.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The rule of thumb is to use Global Keys whenever possible.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The main use case for Local Keys is when a Z8/Function or Z4/Type is being created on the fly, and thus cannot have Global Keys because the created Z8/Function or Z4/Type itself is not persistent.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">One example is given by the call to Z79/curry right in the Section on Z20/Tests below.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Global Key is always defined on the ZObject<ref name="typed" /> the ZID part of its ID refers to.</span> |
|||
{{Anchor|Z8}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z8/Functions == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In the definition of Z10070/positive integer we saw a first reference to a Z8/Function, Z10559/validate positive integer.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Here, we will use a much simpler function, Z144/add. Z144/add is a Z8/Function which takes two Z10070/positive integers and returns a Z10070/positive integer.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note that we leave the value of Z1K1/Type empty for the moment. We will get back to this in a [[#Z8/Function types|later section]].</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We only show the value.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": { ... }, |
|||
"arguments": [ |
|||
{ |
|||
"type": "argument declaration", |
|||
"argument type": "positive integer", |
|||
"key id": "Z144K1", |
|||
"label": { ... } |
|||
}, |
|||
{ |
|||
"type": "argument declaration", |
|||
"argument type": "positive integer", |
|||
"key id": "Z144K2", |
|||
"label": { ... } |
|||
} |
|||
], |
|||
"return type": "positive integer", |
|||
"tests": [ |
|||
"add one and zero", |
|||
"add two and two" |
|||
], |
|||
"identity": "Z144" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { ... }, |
|||
"K1": [ |
|||
{ |
|||
"Z1K1": "Z17", |
|||
"Z17K1": "Z10070", |
|||
"Z17K2": "Z144K1", |
|||
"Z17K3": { ... } |
|||
}, |
|||
{ |
|||
"Z1K1": "Z17", |
|||
"Z17K1": "Z10070", |
|||
"Z17K2": "Z144K2", |
|||
"Z17K3": { ... } |
|||
} |
|||
], |
|||
"K2": "Z10070", |
|||
"K3": [ |
|||
"Z1441", |
|||
"Z1442" |
|||
], |
|||
"K5": "Z144" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">To remain concise, we removed the Z17K3/labels from the Z17/Argument declarations, which are identified using Z17K2/key IDs.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">But just like the Z3/Keys on Z4/Types, they have labels in all supported languages.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The Keys are Global when the Z8/Function is persistent, and Local when transient.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The Function is specified through the (omitted) documentation, but also through the K3/tests and the K1/type declarations on the arguments and the K2/return type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Furthermore, since a Function can have several Z14/Implementations (see below), the Implementations confirm each other.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z8/Functions are not allowed to have state-changing side effects.</span> |
|||
{{Anchor|Z7}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z7/Function calls == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The following ZObject<ref name="typed" /> represents a function call.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In the second row, we see a more compact representation of the function call, that uses a syntax that is more familiar for function calls.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "function call", |
|||
"function": "add", |
|||
"left": "two", |
|||
"right": "two" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"Z144K1": "Z382", |
|||
"Z144K2": "Z382" |
|||
}</syntaxhighlight> |
|||
|- |
|||
| <code>'''add'''('''two''', '''two''')</code> |
|||
| <code>'''Z144'''('''Z382''', '''Z382''')</code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Using literals instead of persistent ZObjects<ref name="typed" /> for the arguments, this would look as follows.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Note that we are creating the literals using the Z10070/positive integer as a constructor.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">All Z4/Types can be called like this, providing a value for each of their keys.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">This is not a Z7/Function call, but a notation for the object of the given Z4/Type.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "function call", |
|||
"function": "add", |
|||
"left": { |
|||
"type": "positive integer", |
|||
"base 10 representation": "2" |
|||
}, |
|||
"right": { |
|||
"type": "positive integer", |
|||
"base 10 representation": "2" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"Z144K1": { |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "2" |
|||
}, |
|||
"Z144K2": { |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "2" |
|||
} |
|||
}</syntaxhighlight> |
|||
|- |
|||
| <code>'''add'''('''positive_integer'''("2"), '''positive_integer'''("2"))</code> |
|||
| <code>'''Z144'''('''Z10070'''("2"), '''Z10070'''("2"))</code> |
|||
|} |
|||
When this Z7/Function call gets evaluated, it results as expected in the number four. |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "positive integer", |
|||
"base 10 representation": "4" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z10070", |
|||
"Z10070K1": "4" |
|||
}</syntaxhighlight> |
|||
|- |
|||
| <code>'''positive_integer'''("4")</code> |
|||
| <code>'''Z10070'''("4")</code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Evaluation is performed repeatedly on the evaluation result until a fixpoint is reached.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Z8/Function has an optional K4/implementation key that points to the Z14/Implementation to be used.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This is usually filled by the evaluation engine as part of the evaluation step, but if a specific implementation is given, the evaluator will honor it.</span> |
|||
{{Anchor|Z14}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z14/Implementations == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Every Z8/Function can have a number of different Z14/Implementations.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">There are three main types of Z14/Implementations: builtins, Z16/code, or through composition of other Z8/Functions.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Let us take the Z144/add Function and look at five different Z14/Implementations.</span> |
|||
{{Anchor|builtins}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
=== Builtin implementations === |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A builtin implementation tells the evaluator, i.e. the runtime, to return an appropriate evaluation result.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Builtins are hardcoded into the evaluator. Z14K4/builtin refers to the hard-coded builtin-ID (which usually should be ZID of the Z2/Persistent object, but does not have to).</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "implementation", |
|||
"implements": "add", |
|||
"builtin": "Z1443" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z14", |
|||
"Z14K1": "Z144", |
|||
"Z14K4": "Z1443" |
|||
}</syntaxhighlight> |
|||
|- |
|||
|colspan="2"| <code><span style="color:#777">// '''implementation'''('''add''', , , '''Z1443''')</span></code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Builtins do not have to be declared as ZObjects<ref name="typed" /> in order to be used.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">An evaluator would be aware of all its own builtins and could use them at will.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">It is still useful to declare a builtin in order to call them directly.</span> |
|||
{{Anchor|Z16}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
=== Z16/Code === |
|||
</div> |
|||
: ''<span lang="en" dir="ltr" class="mw-content-ltr">Note: This section might need to be reworked, in order to let different programming languages have different implementations.</span>'' |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">An implementation in Z16/Code represents a code snippet in a given programming language.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "implementation", |
|||
"implements": "add", |
|||
"code": { |
|||
"type": "code", |
|||
"language": "javascript", |
|||
"source": "K0 = Z144K1 + Z144K2" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z14", |
|||
"Z14K1": "Z144", |
|||
"Z14K3": { |
|||
"Z1K1": "Z16", |
|||
"Z16K1": "Z100701", |
|||
"Z16K2": "K0 = Z144K1 + Z144K2" |
|||
} |
|||
}</syntaxhighlight> |
|||
|- |
|||
|colspan="2"| <code><span style="color:#777">// '''implementation'''('''add''', , '''code'''('''javascript''', "'''_0''' = '''_1''' + '''_2'''"))</span></code> |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "implementation", |
|||
"implements": "add", |
|||
"code": { |
|||
"type": "code", |
|||
"language": "python3", |
|||
"source": "K0 = Z144K1 + Z144K2" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z14", |
|||
"Z14K1": "Z144", |
|||
"Z14K3": { |
|||
"Z1K1": "Z16", |
|||
"Z16K1": "Z100703", |
|||
"Z16K2": "K0 = Z144K1 + Z144K2" |
|||
} |
|||
}</syntaxhighlight> |
|||
|- |
|||
|colspan="2"| <code><span style="color:#777">// '''implementation'''('''add''', , '''code'''('''python3''', "'''_0''' = '''_1''' + '''_2'''"))</span></code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In this case, the implementations are the same for JavaScript and Python, but that is obviously rarely the case.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The evaluator would know how to transform the given ZObjects<ref name="typed" /> representing the arguments into the supported programming languages (which is also the reason we limit the positive integer type to 32 bit — as the behavior for the two supported languages is equivalent in that range), how to execute the provided code snippet, and then how to transform the result back into a ZObject<ref name="typed" /> representing the result.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Eventually, the translation of ZObjects<ref name="typed" /> to the native values of the supported programming languages would be handled inside ''Wikifunctions'' itself (which will require a new design document).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Until then, we only support Z16/Code for arguments and return types that have hard-coded support by the evaluator.</span> |
|||
{{Anchor|composition}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
=== Composition === |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The most portable (but often also the slowest) Z14/Implementation is achieved through composition of other Z8/Functions.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We will look at two different implementations.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We show both the ZObject<ref name="typed" /> of the implementation, as well as an easier to read notation based on function call syntax (note that this syntax also replaces spaces in labels with underscores).</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "implementation", |
|||
"implements": "add", |
|||
"composition": { |
|||
"type": "function call", |
|||
"function": "lambda to integer", |
|||
"arg": { |
|||
"type": "function call", |
|||
"function": "lambda add", |
|||
"left": { |
|||
"type": "function call", |
|||
"function": "integer to lambda", |
|||
"arg": { |
|||
"type": "argument reference", |
|||
"reference": "left" |
|||
} |
|||
}, |
|||
"right": { |
|||
"type": "function call", |
|||
"function": "integer to lambda", |
|||
"arg": { |
|||
"type": "argument reference", |
|||
"reference": "right" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z14", |
|||
"Z14K1": "Z144", |
|||
"Z14K2": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z71", |
|||
"Z71K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z77", |
|||
"Z77K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z72", |
|||
"Z72K1": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K1" |
|||
} |
|||
}, |
|||
"Z77K2": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z72", |
|||
"Z72K1": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K2" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
|- |
|||
| <code>'''lambda_to_positive_integer'''(<br> |
|||
'''lambda_add'''(<br> |
|||
'''positive_integer_to_lambda'''(''left''),<br> |
|||
'''positive_integer_to_lambda'''(''right'')<br> |
|||
)<br> |
|||
)</code> |
|||
| <code>'''Z71'''(<br> |
|||
'''Z77'''(<br> |
|||
'''Z72'''(''Z144K1''),<br> |
|||
'''Z72'''(''Z144K2'')<br> |
|||
)<br> |
|||
)</code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">''Wikifunctions'' contains a full implementation of the lambda-calculus (in fact, that’s one of the inspirations for the extension name).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This composition translates the Z10070/positive integers into Church numerals using Z72/positive integer to lambda, then uses the addition as it is implemented in the lambda-calculus of ''Wikifunctions'' (Z77/lambda add), and the result is translated to a Z10070/positive integer from a Church numeral using Z71/lambda to positive integer.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">(In case you’re curious - Z77/lambda add is implemented the same way as Z1445/add recursive below, but using lambda-based functions as defined over Church numerals).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This relies entirely on the Lambda calculus.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This is anything but fast — but it allows us to use a well-understood formalism and a very simple implementation of it in order to ensure that the other implementations of Z144/add are correct — admittedly, probably of less interest for addition, but we can imagine that there are Z8/Functions that have more obviously correct implementations and much cleverer faster implementations.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">''Wikifunctions'' can cross-test these implementations against each other and thus give us some sense of security regarding their correctness.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"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" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z14", |
|||
"Z14K1": "Z144", |
|||
"Z14K2": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z31", |
|||
"Z31K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z145", |
|||
"Z145K1": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K2" |
|||
} |
|||
}, |
|||
"Z31K2": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K1" |
|||
}, |
|||
"Z31K3": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"Z144K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z146", |
|||
"Z146K1": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K1" |
|||
} |
|||
}, |
|||
"Z144K2": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z147", |
|||
"Z147K1": { |
|||
"Z1K1": "Z18", |
|||
"Z18K1": "Z144K2" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
|- |
|||
| <code> |
|||
'''if'''(<br> |
|||
'''is_zero'''(''right''),<br> |
|||
'''left''',<br> |
|||
'''add'''(<br> |
|||
'''successor'''(''left''), <br> |
|||
'''predecessor'''(''right'')<br> |
|||
)<br> |
|||
)</code> |
|||
| <code> |
|||
'''Z31'''(<br> |
|||
'''Z145'''(''Z144K2''),<br> |
|||
'''Z144K1''',<br> |
|||
'''Z144'''(<br> |
|||
'''Z146'''(''Z144K1''), <br> |
|||
'''Z147'''(''Z144K2'')<br> |
|||
)<br> |
|||
)</code> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This composition relies on a number of other Z8/Functions:</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z145/is zero, Z146/successor, Z147/predecessor, Z31/if, and, most interestingly — itself.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">It is entirely OK for an Z14/Implementation to call its own Z8/Function recursively.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note though that the evaluator does not have to call the Z14/Implementation recursively — an evaluator is free to choose any implementation at each recursion step.</span> |
|||
{{Anchor|evaluation-order}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Evaluation order == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The evaluation order is up to the evaluator.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Since all Z8/Functions are not allowed to have side-effects, this will always lead to the same result.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">But an unwise evaluation strategy can lead to much more computation than necessary or even to the evaluator not terminating.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z1445/add recursive provides us with an example that might end up in an endless loop if we try a complete evaluation order:</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For the call to Z31/if in Z1445/add recursive it would be unwise to first evaluate all three arguments and then to return either the second or the third argument.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Depending on the first argument Z31K1/condition we will only need to return either Z31K2/consequent or Z31K3/alternative.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">There is never the case that we need to evaluate both the second and the third argument.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In fact we could even return the second or third argument unevaluated.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Remember that the evaluator will evaluate each result again anyway until a fixpoint is reached.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">So Z31/if can be implemented lazily, drop the irrelevant branch, and return the relevant branch as an unevaluated ZObject<ref name="typed" />.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">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.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">And then the evaluator might decide to first evaluate the arguments and then the outer call.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">In the end, there are opportunities to experiment with different evaluation strategies.</span> |
|||
{{Anchor|Z20}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z20/Tests == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z20/Tests are ZObjects<ref name="typed" /> that call a Z7/function call and then test the result using a Z8/Function.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If the Z8/Function returns an Z54/true, the Z20/Test passes, otherwise it fails.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Tests are used to ensure that all Z14/Implementations behave as they should, and should be considered similar to unit tests.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Z8/Function should list all the Z20/Tests that need to pass for an Z14/Implementation to be compliant.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Additionally, the different Z14/Implementations can be cross-tested against each other for consistency.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line='line'>{ |
|||
"type": "test", |
|||
"call": { |
|||
"type": "function call", |
|||
"function": "add", |
|||
"left": "two", |
|||
"right": "two" |
|||
}, |
|||
"check": { |
|||
"type": "function call", |
|||
"function": "curry right", |
|||
"function to curry": "equal positive integer", |
|||
"right": "four" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z20", |
|||
"Z20K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z144", |
|||
"Z144K1": "Z382", |
|||
"Z144K2": "Z382" |
|||
}, |
|||
"Z20K2": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z79", |
|||
"Z79K1": "Z150", |
|||
"Z79K2": "Z384" |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Z1442/Add two and two exhibits an interesting pattern: the Z20K2/check Function is created on the fly by currying the function Z150/equal positive integer.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We would not want to write a Z8/Function called “equals four”, but instead use the Z150/equal positive integer function and fix (curry) one of its arguments with a constant value, Z384/four in this case.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">So when it runs, Z20K2/check will have the value of a dynamically created Z8/Function, which in turn will be used to validate the result of the function call in Z20K1/call.</span> |
|||
{{Anchor|generic-types}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Generic types == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A generic type is realized by a Z7/Function call to a Z8/Function which takes some arguments and returns a Z4/Type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For example, perhaps Z10022/Pair is a function that takes two Z4/Types as its parameters, one for the first and one for the second element, and returns an inline Z4/Type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">So if we want to make a pair of Z10070/Positive integers, we would call Z10022/Pair(Z10070/Positive Integer, Z10070/Positive integer) and the result would be a Z4 which we can use for the Z1K1 field of a ZObject.<ref name="typed" /></span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": { |
|||
"type": "function call", |
|||
"function": "pair", |
|||
"first": "positive integer", |
|||
"second": "positive integer" |
|||
}, |
|||
"first": "one", |
|||
"second": "two" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z10022", |
|||
"Z10022K1": "Z10070", |
|||
"Z10022K2": "Z10070" |
|||
}, |
|||
"K1": "Z381", |
|||
"K2": "Z382" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The result of the Z7/Function call is a dynamically created Z4/Type that ensures that the two elements of the Pair have the right Z4/Type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The result of that Z7/Function call looks like this.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": "type", |
|||
"identity": { |
|||
"type": "function call", |
|||
"function": "pair", |
|||
"first": "positive integer", |
|||
"second": "positive integer" |
|||
}, |
|||
"keys": [ |
|||
{ |
|||
"type": "key", |
|||
"id": "K1", |
|||
"value type": "positive integer", |
|||
"required": "true" |
|||
}, |
|||
{ |
|||
"type": "key", |
|||
"id": "K2", |
|||
"value type": "positive integer", |
|||
"required": "true" |
|||
} |
|||
], |
|||
"validator": "validate pair" |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": "Z4", |
|||
"Z4K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z10022", |
|||
"Z10022K1": "Z10070", |
|||
"Z10022K2": "Z10070" |
|||
}, |
|||
"Z4K2": [ |
|||
{ |
|||
"Z1K1": "Z3", |
|||
"Z1K2": "K1", |
|||
"Z3K1": "Z10070", |
|||
"Z3K2": "Z54" |
|||
}, |
|||
{ |
|||
"Z1K1": "Z3", |
|||
"Z1K2": "K2", |
|||
"Z3K1": "Z10070", |
|||
"Z3K2": "Z54" |
|||
} |
|||
], |
|||
"Z4K3": "Z100702" |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This also explains the Z4K1/identity field on Z4/Type: it describes how the Z4/Type was created, and allows us to access the arguments used for Type creation.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Keeping this information declaratively is very helpful for validating a Function call statically, and for comparing types.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If we want a Z10022/Pair that doesn’t restrict the Z4/Type of one or both of its elements, one could call the Z10022/Pair function with Z1/ZObject<ref name="Z1" /> as one or both arguments.</span> |
|||
{{Anchor|Z10}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z10/Lists == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Here is a list of two strings.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">[ |
|||
"a", |
|||
"b" |
|||
]</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">[ |
|||
"a", |
|||
"b" |
|||
]</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If we turn this into ZObjects<ref name="typed" />, it looks as follows.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": { |
|||
"type": "function call", |
|||
"function": "list", |
|||
"elementtype": "string" |
|||
}, |
|||
"head": "a", |
|||
"tail": { |
|||
"type": { |
|||
"type": "function call", |
|||
"function": "list", |
|||
"elementtype": "string" |
|||
}, |
|||
"head": "b", |
|||
"tail": "nil" |
|||
} |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z10", |
|||
"Z10K1": "Z6" |
|||
}, |
|||
"K1": "a", |
|||
"K2": { |
|||
"Z1K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z10", |
|||
"Z10K1": "Z6" |
|||
}, |
|||
"K1": "b", |
|||
"K2": "Z13" |
|||
} |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Note that the deserialization of a JSON array literal has to first check whether all elements of the array have the same Z1K1/type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If yes, we create a Z10/List using that type as the argument. If not, we create a Z10 using Z1/ZObject<ref name=Z1 /> as the argument.</span> |
|||
{{Anchor|Z8}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z8/Function types == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Functions are using the same mechanism as generic types to be concrete Function types.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">I.e. Z8/Function is not the Z4/Type of a Function, but rather is a Function itself that creates a Z4/Type that can be used for a Function.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">On Z144/add, we previously skipped the Z1K1/type field. Here is the field.</span> |
|||
{|class="wikitable" style="margin:.6em 1.6em" |
|||
|- |
|||
| <syntaxhighlight lang="json" line="line">{ |
|||
"type": { |
|||
"type": "function call", |
|||
"function": "function", |
|||
"return type": "positive integer", |
|||
"argument types": [ |
|||
"positive integer", |
|||
"positive integer" |
|||
] |
|||
}, |
|||
... |
|||
}</syntaxhighlight> |
|||
| <syntaxhighlight lang="json">{ |
|||
"Z1K1": { |
|||
"Z1K1": "Z7", |
|||
"Z7K1": "Z8", |
|||
"Z8K1": "Z10070", |
|||
"Z8K2": [ |
|||
"Z10070", |
|||
"Z10070" |
|||
] |
|||
}, |
|||
... |
|||
}</syntaxhighlight> |
|||
|} |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This will return the Z4/Type that also contains its return and argument types.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If you need a Z4/Type for a Z8/Function that works with any Z8K1/return type and Z8K2/argument types, then we would use Z1/ZObject<ref name="Z1" /> for Z8K1/return type or the empty list as the Z8K2/argument type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This is useful, e.g., for a Z8/Function that tells you the number of arguments a Z8/Function has.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Obviously, if you would already need to know what the number of arguments is in order to select the right function, this would be quite useless.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The validator on Z4/Function ensures that the types as given on the Z7/function call to Z8/Function are consistent with the types given on the Z4K2/key declaration.</span> |
|||
{{Anchor|Z5}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Z5/Errors == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Z7/Function call could always result in a Z5/Error.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This can be for more or less unrecoverable cases (i.e. division by zero or out of memory both are handled the same way).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A Z5/Error is a generic type called with a Z15/Error type.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Normally, when a Z5/Error is being given as an argument to a Z7/Function call, the Z5/Error will be wrapped to enable tracing and passed through.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The evaluator won’t even call the Z14/Implementation.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If a Z8/Function wants to catch a Z5/Error, it has to explicitly list all the Z15/Error types it wants to catch in its signature.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">If then a Z5/Error of the listed Z15/Error types shows up, the Z14/Implementation will still be called and can now handle the Z5/Error.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">An Z5/Error is an instance of Z4/Type Z5/Error(Z15/Error type).</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The resulting type has further Z3/Keys, as specified by the Z15/Error type, in order to keep useful information about the Z5/Error.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Example: if you call the Z157/division function with a Z380/zero for the Z157K2/denominator, you would get back the the following object: Z5/error(Z442/division_by_zero)(Z384/four)</span> |
|||
{{Anchor|non-functional}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Non-functional Functions == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Whereas no Z8/Function is allowed to have side effects, some Z8/Functions might not be entirely functional.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">I.e. they might return different values when being called with the same parameters.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Typical such Z8/Functions are “return a random number”, “return the current time”, or “return a value from Wikidata”.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">We also see that it would make sense not only to say whether a Z8/Function is functional or not, but in fact to specify a caching regime for each Z8/Function.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">All these Z8/Functions need to be marked, and no Z8/Function that is fully functional may call a Function that is not.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The evaluator has to make sure that this condition is being fulfilled, or else results might be stale or otherwise unexpected.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This will be handled in a later document.</span> |
|||
{{Anchor|Zx-sum}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Zx/Sum types == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A particularly useful generic type is the Zx/Sum type, which takes a list of Z4/Types and returns a Z4/Type that can take exactly one instance of any of the given types.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This will also allow for non-required parameters in function calls.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This will be handled in a later document.</span> |
|||
{{Anchor|REPL}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== REPL == |
|||
</div> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This follows the definition of REPL: Read, Evaluate, Print, Loop:</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">The REPL, or command line interface, takes an input Z6/string.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">It then runs a Z8/Function over that input string which parses and preprocesses the input and returns a ZObject<ref name="typed" />.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">That ZObject<ref name="typed" /> gets validated by the validator of the Z4/Type of the ZObject<ref name="typed" />. If valid, the result then evaluates until it reaches a fix point.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Then the REPL calls a Z8/Function to linearize the resulting ZObject<ref name="typed" /> to a Z6/string. This string is then displayed or printed out to the user.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">And the REPL asks for new input.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">A good ''Wikifunctions'' REPL should allow to:</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">set the parsing function;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">switch validation on or off;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">switch evaluation on or off;</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">set the linearization function.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">This allows for many interesting patterns.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">For example, there could be parsers for many different syntaxes.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Simple function call syntaxes as we have seen above, a Haskell-like syntax without many brackets, a syntax that is closer to mathematics using infix operators, translations from labels to ZIDs, or entirely domain specific syntaxes.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">The parser can also include a preprocessor. One example of preprocessing is to automatically add type coercions, thus making it easier to write Z7/Function calls, or specify the Z14/Implementation on a Z8/Function, and thus force the evaluator to use a specific Z14/Implementation.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Also the linearizer can be highly flexible towards a given use case.</span> |
|||
<span lang="en" dir="ltr" class="mw-content-ltr">Parsers and linearizers will be Z8/Functions in ''Wikifunctions'', which will allow anyone to create new parsers and linearizers and use them in a wide range of interfaces, thus enabling interesting usage patterns</span>. |
|||
{{Anchor|reference-index}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Reference index of central Z4/Types and their Z3/Keys == |
|||
</div> |
|||
* Z1/ZObject<ref name="typed" /> |
|||
** Z1K1/type (Z4/Type) |
|||
* Z2/Persistent object |
|||
** Z2K1/id (Z6/string) |
|||
** Z2K2/value (Z1/ZObject<ref name="typed" />) |
|||
** Z2K3/label (Z12/Multilingual text) |
|||
* Z3/Key |
|||
** Z3K1/value type (Z4/Type) |
|||
** Z3K2/key id (Z6/String) |
|||
** Z3K3/label (Z12/Multilingual text) |
|||
* Z4/Type |
|||
** Z4K1/identity (Z4/Type) |
|||
** Z4K2/keys (Z10/List(Z3/Key)) |
|||
** Z4K3/validator (Z8/Function(...)) |
|||
* Z5/Error |
|||
** Z5K1/error type |
|||
* Z6/String |
|||
** Z6K1/string value (Z6/String) |
|||
* Z7/Function call |
|||
** Z7K1/function (Z8/Function) |
|||
** Others based on Z8/Function |
|||
* Z8/Function (generic) |
|||
** K1/arguments (Z10/List(Z17/Argument declaration)) |
|||
** K2/return type (Z4/Type) |
|||
** K3/tests (Z10/List(Z20/Test)) |
|||
** K4/implementation (Z14/Implementation) |
|||
** K5/identity (Z8/Function) |
|||
* Z9/Reference |
|||
** Z9K1/reference ID (Z6/String) |
|||
* Z10/List (generic) |
|||
** K1/head |
|||
** K2/tail |
|||
{{Anchor|diffs-to-AbstractText}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Main differences to AbstractText == |
|||
</div> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Only Z7/Function calls get evaluated. Everything else does not get evaluated.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Introduction of generic types</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Z10/String and Z22/Pair are now generic types.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Z8/Function is a generic type, based on the types of the inputs and outputs.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Added a K5 to Z8s</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Changed Z3K2 from validator to keyid, Z3K3 from required to label, added Z3K4-Z3K6</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Removed Z4K4-Z4K7</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Subtle change to Z4K1</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Changed all keys on Z14/Implementation, got rid of Z19/builtin</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Turn Z20/Test into top level ZObjects<ref name="typed" /> instead of subobjects of Z8/Function</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">By using autoquote on Z20/Test, got rid of Z21/Argumentlist</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Turn Z14/Implementation into top level ZObjects<ref name="typed" /> instead of subobjects of Z8/Function</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">ZID of Pair was changed from Z2 to Z22 (in order to give space for Z2/Persistent object)</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Z5/Error and Z15/Exception have been folded together into Z5/Error</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Z5/Error is now generic type.</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Specified REPL behavior</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Break out Z2/Persistent object from Z1</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Added Z17K2/Keyid and Z17K3/Label to Z17</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Builtins can now change their ZID</span> |
|||
{{Anchor|questions-todos}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Some questions and tasks to do == |
|||
</div> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Do we need “required/option” for keys anywhere in the beginning? — no</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Replace defaults on Z3/Key with Zx/Sum? (Or at least make it consistent with Z17/argument declaration)</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Could be left for later if we don’t need default on Z3 for now</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Remove Z2K4 for now?</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Break out Z16/Implementation by programming language?</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">If Errors can have their own fields, programming languages should too</span> |
|||
* <span lang="en" dir="ltr" class="mw-content-ltr">Make it generic on programming language. That’s for later.</span> |
|||
{{Anchor|questions-todos}} |
|||
<div lang="en" dir="ltr" class="mw-content-ltr"> |
|||
== Notes == |
|||
</div> |
|||
<references> |
|||
<ref name="typed"><span lang="en" dir="ltr" class="mw-content-ltr">''explicitly typed'' – beginning with a Z1K1/type.</span></ref> |
|||
<ref name="Z2K1">Z2K1</ref> |
|||
<ref name= "empty"><span lang="en" dir="ltr" class="mw-content-ltr">or a Z23/Nothing?</span></ref> |
|||
<ref name="syntactic"><span lang="en" dir="ltr" class="mw-content-ltr">as defined in [[#Syntax]].</span></ref> |
|||
<ref name="Z1"><span lang="en" dir="ltr" class="mw-content-ltr">literally with "Z1" as the value.</span></ref> |
|||
</references> |
|||
{{Anchor|see-also}} |
|||
<span id="See_also"></span> |
|||
== 関連項目 == |
|||
* [[Special:MyLanguage/Abstract Wikipedia/Pre-generic function model|プレジェネリック関数モデル]] |
|||
<noinclude> |
<noinclude> |
||
Latest revision as of 00:22, 5 August 2023
このページは f:Wikifunctions:Function model/ja にあります。
これはウィキ間リダイレクトのページです。 |