This update is available on-wiki here:
https://www.wikifunctions.org/wiki/Wikifunctions:Status_updates/2024-03-21 
--

On the way to internationalizing numbers

Multiplication without renderer

We now have the ability to internationalize numbers in Wikifunctions by implementing renderers and parsers. For now, this is only configured for natural numbers, but it should work for future types out of the box.

However, there’s a caveat! It has not been tested at large scale yet, and it currently runs into some speed issues. But let’s start with how it should be working.

In the first screenshot, we see how the system used to work before, using the example of the multiplication function: the instances of natural numbers are expanded, displaying their type and their value as the string types they use internally.

The second screenshot displays the status after we configured the renderer (the display function) and the parser (the reading function) for natural numbers. With these two functions configured, the UX collapses the values into single lines, both for input (for the two arguments of the multiplication) as well as output (for the result).

The configuration itself happens on-wiki, on the natural number type, where we can see that the renderer is set to display natural number and the parser to read natural number. The right to edit types will be handed over to the community at a later date, but the configured functions are editable for you right now.

Multiplication with renderer

This makes the display for all functions using natural numbers much more compact. But that’s not all! Both functions to display and read natural numbers also take a natural language as a parameter, with the idea that both displaying and reading the values can be adjusted based on the language set in the user interface. As of sending this newsletter, this argument is ignored, but things are almost all set up.

If you are not interested in gory technical details, you might want to skip the rest of this section.

In order to display a number appropriately for a given language, we first need to have a function to do so. On Wikifunctions, we already had a function that formats a large natural number string by adding commas. But since it was defined on Strings, we went ahead and recreated it for numbers, and made a little change (more to initiate a discussion than to make an editorial decision), by putting commas into the resulting display only if the number has more than four digits. For the implementation, we basically copied the previous implementation.

This gives us a function to format the number for English texts. Now, we need to somehow connect this function with the renderer function that is set above. For that, we have created two new types that help us with configuring which languages should use which function: a configuration of functions for a given language, which uses the function option for a list of languages. This has been used to create a configuration for the display function and one for the reading function.

Furthermore, we need a function that selects the right function given a language from that configuration structure. This is needed because different languages will expect different ways of showing values – French and German will use dots rather than commas as three-digit group separators, Indian English will use commas like International English but in a different pattern than three-digit groups, some languages might want to use non-Arabic digits for familiarity, etc.. And finally, we need to apply the selected function to the number. We discuss the apply function in the Function of the Week section below.

But alas, as of now, this frequently times out. You can see the two implementations connected to the display function: the simple one, that just returns the unformatted string, and the implementation trying to apply the appropriate function based on the language. As the latter randomly, but rather frequently times out, it is currently disconnected, in order to avoid disrupting the site.

What’s the call to action?

  1. Create functions that display and read numbers as appropriate for your language.
  2. Add those functions to the configuration object for reading and display.
  3. Help us speed up the system.

For the parsers, it is recommended to be lenient. If, for example, it is common to enter numbers both in a language-specific script as well as with Western Arabic digits, it is totally OK to allow for both. The current default parser allows for commas and dots in any place, instead of ensuring that they split exactly three numbers. It’s up to the community to make the editorial decision on what they accept as input for a given language. A good quality check is if the output of a Type's display function for a language is valid for the reader function for that language – that it 'round-trips' without errors.

All of these are entirely new, early-stage mechanisms working on Wikifunctions. We are curious to hear your feedback and to hear about what works and what doesn’t. And also for creating more functions and for help with getting this rolled out.

Recent Changes in the software

This week we worked on a few smaller features and bug-fixes, as well as improvements to the back-end services. We adjusted how the new reading and display functions for Types (parsers and renderers) are called, avoiding confusing mis-readings of user input depending on how you clicked (T359987). The edit link for old revisions was mis-configured, and now actually points to the edit page for that old revision, rather than the current one (T343653); our apologies!

We addressed a missing feature in the table of Implementations on Function pages, which showed only a '–' rather than the number of Test cases passed, like '3/5' (T347536). We improved some of the Object conversion code, which should avoid mysterious errors breaking the front-end experience in some cases (T357594). We now allow empty strings to be used in a function selector, unbreaking the experience in some edge cases (T346006).

We've improved the accessibility experience by adding longer, explanatory titles for the three dialogs missing them using the 'aria-title' attribute, and two icon-only buttons, one in the mode selector control, and the other in the Function Explorer. We rewrote how fetching state is handled in the front-end, which should handle pending status better when loading Test case results (T360018).

As part of our migration work for programming language references, we now have a maintenance script that will update on-wiki content; we will run this shortly (T287153). We audited our use of i18n and found a few messages that are no longer used; their removal will reduce the burden on translators. Finally, we've started tracking view actions on Function pages, so that we can better understand who is using Wikifunctions and where we might need to improve (T357069).

Ongoing discussion on identity

Last week we introduced a question on how to work with identity. The discussion is ongoing, and the team will devote more time to the discussion very soon.

Function of the Week: apply (Z13036)

Apply is one of the most foundational functions in computer science, and yet it is not available in a large number of programming languages and systems, or only by going through hoops. Apply, in the way it is defined in Wikifunctions, takes two arguments, a function and a value, and applies the given function to the given value, meaning that it runs the function with the given value as the argument.

One good way to understand the function is to look at the existing tests. Tests always live a triple life:

  1. They ensure that the implementations are working correctly.
  2. They capture agreement and declare what the function is supposed to do. If there are two possible ways a function could react, then tests can be used to resolve that ambiguity.
  3. They document for the reader what the function does by providing examples.

In this case, we can benefit from the tests and read them as great examples of what the apply function does:

  1. The first test applies the reverse function (which was our first Function of the Week) to the string "abc", and it checks that we get "cba". Using apply with reverse and "abc" is the same as calling reverse itself with the argument "abc".
  2. The second test applies another Function of the Week, not, to the value true, and checks whether we indeed get false. This shows us that apply works across different types: it works both with strings and Booleans.
  3. The third test applies one of our earliest user-created functions, to uppercase, to the string "hello" and checks that the result is "HELLO".
  4. The fourth test applies the square function to the number 9, and checks that the result is 81. This demonstrates that it also works with the new types, not just the initial, built-in types.

For now, this function can only be implemented as a composition, not in JavaScript or Python, because we don’t yet allow code implementations to call further functions.

The first implementation was created by 99of9, and it is entirely composed of built-in functions: it centers around the map higher-order function (which became famous as the first half of Google’s MapReduce technology), a function that takes a list and a function, and applies the function to each element of the list, resulting in a new list.

The rest of the function is taking the value and adding it to an empty list, in order to create the list necessary for the map function. Map is then applied to that one-element list, and then first element is used to get the resulting value out of the list again.

To recapitulate: we take the value, put it in a list, map the list, and then get the resulting value out of the list again. There’s a task to add apply as a built-in function, so that hop in and out of a list wouldn’t be necessary.

The second implementation copies the same approach, but skips the use of the function adding the value to an empty list and instead creates a list directly with the value. I built it because I expected it to be a bit faster, and hoped it would run the display function faster.

The humor here is that I have previously scolded TomT0m and 99of9 for working on the apply function and related functions, pointing out that we currently don’t have great support for functions using functions. I would still prefer for these things to be tried out on the Beta Cluster, where I had recreated their apply function, but to be entirely honest, without their work and their exploration I would have been stuck trying to create the routing to the right function based on the language. Thank you!