The on-wiki version with the embedded video can be found here:
https://meta.wikimedia.org/wiki/Abstract_Wikipedia/Updates/2021-08-13
--
The team has been busy developing features and designing interfaces for
Wikifunctions, and we are moving towards closing the current phase of the
development
<https://meta.wikimedia.org/wiki/Abstract_Wikipedia/Phases#Phase_%CE%B6_(zeta):_composition>.
Aliases are now available in the data model, the data model for testers has
been updated, error objects have been considerably reworked, the evaluation
model can now deal with recursive calls and lazy evaluation, new built-in
functions for string and boolean equality have landed, and more. It is
exciting to see the pieces coming together.
In today’s weekly, we want to take a look at Testers and their current
implementation. Lindsay has created a screencast that you can watch (it is
without sound), and here we will describe what is happening in the video.
<https://meta.wikimedia.org/wiki/File:Wikilambda_Zeta_Tester.webm>
<https://meta.wikimedia.org/wiki/File:Wikilambda_Zeta_Tester.webm>
We start with creating a new function definition, *“reverse string”*, which
takes a single string as an input and returns a string. On saving (0:19),
the function is created and assigned Z10000. Now we edit the newly created
function, and we create a first tester inline. We give it the name *“test
-> tset”*, and set the argument to “test” and then use the *“String
equality”* function to compare it to the expected result, “tset” (0:45).
*“String equality”* is a built-in function (Z866 on a fresh Wikilambda
installation) that takes two strings as the arguments and returns True if
they are the same, and False otherwise.
Note that even though we have created the Tester inline, in the background
a new page was created (entirely behind the scenes it was assigned ZID
Z10001) that holds the test.
Next, we create a test for the input “racecar”, which is a palindrome,
using the same built-in function (1:00), and a test reversing “banana” and
getting the output “wrong” (which is an example for a bad test) (1:19).
Next we create an implementation for *“reverse string”* in JavaScript. At
the bottom of the page we already see our three testers working, showing
that they all fail initially (1:30). Now we start implementing the
function, and we enter “return Z10000K1” - and without even saving, the
testers are run against our implementation and we can see that the “racecar”
test passes! (It passes because it is a palindrome, and returning the input
unchanged happens to be a correct implementation for palindromes). The
other two tests keep failing, though (1:41).
We complete the implementation by taking the input, splitting it into an
array of strings, reversing that array, and then joining the strings of the
array again into a single string. Now the first test, *“test -> tset”* also
passes, but the “banana” test (due to being actually a faulty test)
continues to fail (1:54).
We save the implementation, go to the function page, and add the
implementation to the function. On the function page, just like on the
implementation page, we see the status of all the testers for the
implementation.
Next we create a second implementation, this time in Python. Again, we
start with an implementation that simply returns the input, and again it
passes for “racecar”. We go back to the function page, and connect the new
Python implementation with the function. On the bottom of the page we now
see, in a table, the implementations against all the testers, and whether
the individual testers pass or fail for each implementation (2:28).
We create another two tests, *“another -> rehtona”* and *“final test ->
tset lanif”*, again inline. The tests become immediately visible upon
creation. We still need to save the whole page in order to store the
association with the function page. We can see how both tests pass for the
JavaScript implementation and fail for the Python implementation (3:43).
Let’s go fix the Python implementation. We go to the implementation page
and edit it by adding “[::-1]” to the string. That’s some Python magic -
feel free to skip this paragraph explaining this syntax: Python has a few
very convenient short-hand syntaxes for specific operations which, in many
other languages, require functions or more complex constructs. What is
happening here is that by appending the square brackets to a string
variable, we treat the string implicitly as a list. Inside the square
brackets we have three arguments, separated by colons (:). The first
argument says at which element to start, the second argument at which
element to stop, and the third argument gives the step size (say, you only
want every second element of the list, you would state the step size as 2).
Here, the step is -1, which means you want to walk backwards through the
list. And since the first and second argument are omitted, default values
are used - and the default for a negative step size is from the end to the
beginning. In short, you can read this as *“go through the string,
backwards one by one, from the beginning to the end, and return the new
resulting string”*. You can find a more detailed explanation of Python’s
slice notation on StackOverflow
<https://stackoverflow.com/questions/509211/understanding-slice-notation>.
Once we fixed our Python code (4:07), all but one of the tests satisfyingly
switched to green. We confidently store the new improved version. When we
go to the function page of *“reverse string”*, we can see that now both the
JavaScript and the Python implementation behave consistently. Time to fix
the banana tester!
We go to the page for the banana tester and change the expected value from “
wrong” to “ananab”. Again, before even saving, the testers are re-run
against both implementations and switch from messaging failure to letting
you know they passed (4:26). Going back to the function page, we can now
see that all testers pass all implementations.
Finally, we see a feature added (and recorded, which explains the slightly
different format) a bit later, where a new test is being created inline
(4:39). While we are creating the new tester inline the result of the test
runs for all implementations is already shown - before the tester is even
stored yet. Once we can see both implementations pass, the new tester is
saved (and thus created, 5:28), and then we save the function page itself,
associating the function with the new tester (5:35).
I hope you enjoyed this whirlwind tour through our new tester features, and
it gives you a small glimpse of how Wikifunctions will be working. Feedback
and ideas are welcome, as always.
------------------------------
We are all excited about the weekend: Wikimania 2021 has started! Wikifunctions
and Abstract Wikipedia will host a session
<https://wikimania.wikimedia.org/wiki/2021:Submissions/Wikifunctions_and_Abstract_Wikipedia>
on
Saturday, 14 August, at 17:00 UTC
<https://iw.toolforge.org/zonestamp/1628960400>, where we will have a panel
to present our work and talk with you and the Wikimedia communities. Please
join us, bring your questions, and we are very much looking forward to a
lively discussion!