-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeDB 3.0: functions #7038
Comments
This is brilliant, but can it be extended so Fetch statements can also be bound to a single name and parametrised? The aim is to collapse a Fetch statement into a single name, with parameters, so it can be used interactively!!! REASON: Fields like cybersecurity have composite Entities with many optional sub-parts, for example consider the basic File object, with its 10 optional sub-objects. The strength of TypeQL is that it can handle this intricacy with ease. The weakness of TypeQL is that you can't easily handle all of these optional variations interactively. Class hierarchies can reduce query complexity in the match statement, but you need to know which optional variations your desired object contains upfront. Fetch can handle all of this, since it is quite clever, but the downside is the statement will be very long, as the variations are described sequentially. Once query intricacy passes a certain point (e.g. 5-10 lines), it becomes impractical interactively for average users. What we need is a means of treating the Fetch statement in the same ways as the function, so it can be bound to a single name, parametrised, and used within other statements, particularly if it could be case-specific. The ideal would be the use of the lower case for the top-level entity (e.g. file), and the title case for the composite object's pre-registered Fetch statement (e.g. File). Then TypeQL could really become very powerful for interactive use, since currently it is too verbose to handle more intricate domains. Currently we have to use a higher level query language for our User Interfaces, and then down-transpile to TypeQL. It would be brilliant if we could surface TypeQL to users with composite objects, bound to single names. |
In case it helps, I packed some ideas around functions in the Functions section in my wishlist for 3.0 |
Problem to Solve
We want to address several shortcomings in TypeQB at the same time:
Current Workaround
Most of the above points are currently impossible to implement in TypeDB.
Proposed Solution
Introduce functions, which may be called from queries and from other functions. In the type-theoretic setting of TypeDB, functions are a natural counterpart to queries that can fulfill the above purposes.
How to define functions
Function keyword
Functions are introduced in
define
queries using the special syntaxdefine fun
, which is followed by the function declaration.Function declaration
A function declaration comprises:
get_ancestors
($child, $depth : integer = 5)
. Default values can be given if a type is specified, and that type is either a value type or an attribute type. If no type is specified, it will be inferred from the function.{person, name[]}
name[], int
. In this case, we may include optionality with?
(e.g.name, int?
)match <pattern>
) with stream modifiers (e.g.limit
,sort
,filter
,skip
,take
)return {$x, $y};
this filters the stream of concept maps from the match clause to a depuplicated stream of tuples. For example,return {$p};
could be the return statement for a function with output type{person}
.return EXPR;
whereEXPR
is a tuple of aggregation operations applied to the stream of concept maps (output by the query). For example,return count $x, sum $y, mean $z
, could be the return statement for a function with output typeint, double, double?
.return check;
which outputs a singletonbool
tuple, reflecting whether or not stream of concept maps (output by the query) is non-empty.Here is a full example of a function declaration.
How to use functions
Calling functions in
match
Functions can be called from within pattern of a
match
clause (note: since functions perform data retrievals, there is currently no plan to support functions in other clauses likeinsert
ordelete
). Function calls pass their arguments in brackets(...)
after the function name. By default, arguments are passed based on their position, but labels of variables the function's arguments can used to assign a parameter directly as well using=
(e.g. if the signature ismy_fun ($param1, $param2) -> output
we may callmy_fun(param2 = $x, param1 = $y)
).The precise way functions are used depends on their return type.
my_fun($param) -> {person,age}
) will be called with a statement using thein
keyword. For example, ourmatch
clause could contain the statement$p, $a in my_fun(param = $x);
my_fun($param) -> int, string
) will be called with a statement using the assignment operator=
. For example, ourmatch
clause could contain the statement$p, $a = my_fun(param = $x);
. Note the this pattern may fail to hold if the return type of a function includes optional value type: a missing value for a variable is considered a non-satisfied pattern.count_sth($param) > 0;
.my_fun($param) -> bool
) will be called just like a single value function. E.g.,my_check($param) == true;
.For example, the
avg_salary
functions above could be used as follows:Calling functions in
fetch
Functions can similarly be called in a fetch, as along as all arguments are bound:
The only functions allowed to be called are functions with printable return type:
Note: the grammar is TBD. Potentially, the following could be allowed:
or
Calling functions in
insert
,delete
,put
This will not be allowed. Instead, required variables may be assigned in preceding
match
clauses.Calling functions recursively
Since in a
match
query we may call functions, and since functions include amatch
query, in functions, too, we can call functions. Importantly, functions can call themselves recursively, or can call/be called by other functions in a mutually recursive fashion. There will be guards on recursion for functions containing negations following the idea of stratifications.Here is a simple example of a simple recursive function:
Additional comments
Not addressed in the above are so far:
$x, _ = my_fun(param = $p);
would only require$x
to be assigned, and disregard the second argument.(empty_
is returned by the function. An indirect way of handling this these cases could be achieved withor
along the following lines:The text was updated successfully, but these errors were encountered: