Page MenuHomePhabricator

Improve restrictions of ZReference when searching for a Function in a Function Call
Closed, ResolvedPublic

Description

Description

When we use a function call to create the value of a key, we know the output type that the function call should return thanks to the key value type. This should restrict the functions that are picked when composing the function call.

For example, when we use a function call as the value of the key Z11K2, because the key expects a type of Z6/String, we should only be able to call functions that return Z6/String. However, the lookup searches in all available Functions, even if they don't return the expected type. As shown in the screenshot, the functions selector lookup does not restrict the options to the given type, and is displaying options that return different types (in the image, Z6/String is expected, but some Z40/Boolean emitting functions are also displayed in the dropdown):

Screenshot from 2024-08-21 10-28-11.png (516×546 px, 29 KB)

Additional details

This information is available in the ZObjectKeyValue parent of the ZReference that renders the ZObjectSelector that's used to pick the function, so it should be simple to propagate this by just adding the right props in ZReference component.

The component ZObjectSelector can restrict searches easily by combining the properties type and returnType. To search for all objects of type Z8/Function just use :type="Z8", but if we want to also restrict the output types of the function (for example, to Z6/String), we should use (edited) :return-type="Z6".

Screenshot from 2024-08-20 17-03-51.png (932×1 px, 223 KB)

When to restrict returnType when selecting functions?

Only when they are expected to be resolved and a wrong output type would result in an invalid ZObject:

  • ZReference component in edit mode
  • Expected type is Z8/Function
  • The function is part of a function call (key is Z7K1)

How to know what is the expected type??

  • The parent ZObjectKeyValue computes this information in the parentExpectedType property

Completion checklist

Event Timeline

So I tried adding the return type + adding strict return type to true:
http://localhost:8080/w/api.php?action=query&format=json&list=wikilambdasearch_labels&callback=&formatversion=2&wikilambdasearch_search=same&wikilambdasearch_language=en&wikilambdasearch_type=Z8&wikilambdasearch_return_type=Z6&wikilambdasearch_strict_return_type=1

But as you can see this still returns results with return_type="Z40".

So I think what it does when searching:

  1. it checks if there is a searchresult for the query with the search_type provided (Z8) and return those results.
  2. Then checks if there are results with the query for the return_type (Z6) and return those results.

Which means its an OR and not an AND search. So we needed to change that as well.

Background:
We are using the query with type+returntype+stricttype also in the TypeSelector to select a type for the input labels.
If we change ALL logic to be 'AND' we wont be able to use a Type of (for example) 'Day Month Year Object' as input type value for a function. This is probably not what we want.

I adapted the ZObjectStore typeconditions and/or query as follows now:

  • Use andExpr if the key's type is ZTypeRegistry::Z_FUNCTION, the $returnType is specified, and $strictReturnType = true.
  • Use orExpr in all other cases.

See code reference:
// ZObjectStore.php LINE 725:

		// Set type conditions
		if ( count( $typeConditions ) > 0 ) {
			$conditions[] = $dbr->orExpr( $typeConditions );
		}

Change #1067335 had a related patch set uploaded (by Daphne Smit; author: Daphne Smit):

[mediawiki/extensions/WikiLambda@master] ZReference: Improve restrictions of ZReference when searching for a Function in a Function Call

https://gerrit.wikimedia.org/r/1067335

If we change ALL logic to be 'AND' we wont be able to use a Type of (for example) 'Day Month Year Object' as input type value for a function. This is probably not what we want.

I think this is a missing feature, as you can only make this work by passing an array to $type and/or $returnType, but they're typed as ?strings. I think switching it to AND is probably the correct fix anyway, and that we should file a Fix-It task for being able to search for functions that take/return multiple types, if we think that's needed.

For the input types it now just uses an OR function as in $type = Z4, $returnType = Z4.
So you can use as input params an object that is a TYPE (Z4) (eg: Date Month Object , returnType=null) or something that returns a Type (eg: Validate type (type=Z8))

Switching to AND without any logic will break above code, and input type selector will be broken.

I don't think we need to search for multiple types, either input or returning.

The Patch code works and does not break input labels BUT its not very future proof and heavily relies on the $type being a function including a $returnType and $strictReturnType=true. Which is super specific.

I am not sure if its strang to add something like this to the query params of the api call: wikilamdasearch_type_condition = 'AND' | 'OR'. To let the call determine if the type conditions should be an AND or an OR sql query.

Yes, what you coded is what I meant. I don't think we want the extra faff of searching for multiple types right now, but we might in future, yes.

DSmit-WMF changed the task status from Open to In Progress.Aug 27 2024, 2:19 PM
DSmit-WMF claimed this task.
DSmit-WMF triaged this task as Medium priority.
DSmit-WMF moved this task from To Triage to 25Q1 (Jul–Sep) on the Abstract Wikipedia team board.

Okay I see the confusion here, and it's an error in my task description. This is wrong:

we should use :type="Z8" and :return-type="Z6".

Reading through the API documentation, the returnType is built to be used exclusively, as it already involves the selection of functions

wikilambdasearch_return_type
Restrict matches to ZFunctions that can return the given type, including those who return a generic ZObject.

and

wikilambdasearch_strict_return_type
Restrict return type to be strictly the given one, excluding generic ZObject.

So, when ZReference key is Z7K1:

  • The API should only return functions
  • if parentExpectedType is unbound (parentExpectedType === Z1/Any Object), we should be filtering from all the functions, which means:
    • wikilambdasearch_type=Z8
    • wikilambdasearch_return_type=undefined // we shouldn't be passing this
    • wikilambdasearch_strict_return_type=undefined // this property isn't applicable, so undefined will set the default value. which is false
  • if parentExpectedType is bound (parentExpectedType !== Z1), we should be filtering from functions that can return parentExpectedType. For example say parentExpectedType===Z40
    • wikilambdasearch_return_type=Z40 // this already involves that the type will be Z8
    • wikilambdasearch_strict_return_type=false // but also we should be able to pick functions returning Z1, so for example Z802/If
    • wikilambdasearch_type=undefined // we shouldn't be passing this in this case

About the type selector in Function Editor

The reason why the API is built this way is to be able to pick items in cases like this:

  • we want Types OR Functions returning exclusively Types (typed list, typed pair, etc)
  • we don't want to allow for Functions returning Z1s

So in this case it's necessary to use a combination of those three:

  • type=Z4 // this includes all types
  • return_type=Z4 // this adds functions returning types
  • string_return_type=true // this excludes functions returning Z1s (such as Echo or If)

Change #1067335 merged by jenkins-bot:

[mediawiki/extensions/WikiLambda@master] ZReference: Improve restrictions of ZReference when searching for a Function in a Function Call

https://gerrit.wikimedia.org/r/1067335

Change #1072588 had a related patch set uploaded (by Genoveva Galarza; author: Genoveva Galarza):

[mediawiki/extensions/WikiLambda@master] Include resolver types as "unbound" parent type

https://gerrit.wikimedia.org/r/1072588

Change #1072588 merged by jenkins-bot:

[mediawiki/extensions/WikiLambda@master] Include resolver types as "unbound" parent type

https://gerrit.wikimedia.org/r/1072588