Open JamesxX opened 1 month ago
Hi, good to know that someone would like to use that. Originally, variables were not supported and it was possible to document curried functions just like any other function. But variables were more important, so that was changed.
But I think, what you suggested should be possible. Let's find out the precise behaviour. When a documented declaration of the form
/// ...
#let alias = func.with()
is encountered, it should be added to the functions, not the variables.
.with()
)What do you mean exactly by importing the documentation? Shouldn't the new function have an own documentation in most cases? Maybe it is enough to link to the "parent" function?
The curried function will obviously share a lot of functionality with the parent function, which we will assume is already well documented. It wouldn't make sense to duplicate those comments documenting the function in the source code unnecessarily. Hopefully the package could automatically detect which function the parent is, and therefore know its docs. In that case, it could either render parts of that documentation automatically, and/or link to the parent function's documentation while explaining that it shares those arguments just with certain defaults set.
How to go about default arguments (that would be set with .with())
It probably makes sense to reflect that the default of the argument is changed to something else. Perhaps some text in a colour that stands out that this argument has been specialized to such and such value?
Mmh, this thing seems not so straightforward. How much of the parent's documentation should be included? I can also imagine cases where the fact that this is just a curried function should not be mentioned, i.e., where a really general function is broken into several specific ones. Maybe someone wants to have a full documentation for those.
I wouldn't like making a default decision and taking away some fine-grained control for these cases.
One option would be to just store some information about curried functions in the docstring info that is returned by the parser and make it the task of a style to deal with the details. For example, the parser could just detect curried functions and store the name of the "parent". In the showing step, the style can look up the docstring of the parent function (recursively, if necessary).
That wouldn't work out-of-the-box between different modules though.
Hi @JamesxX ,
I implemented some detection for curried functions in the branch detect-curried-functions
. It looks for a .with
statement in the same line and extracts the name of the parent function as well as the provided arguments (which need not be on the same line). This information is stored under the key parent
in the function info dictionaries returned by parse-module()
and contains the name
of the parent function, a list of pos
arguments and a dictionary of named
arguments.
The utilized style would be responsible for using this information. Currently, the shipped styles just ignore it but by customizing one, it should be possible to display some useful information.
Would you like to try it out and see if this satisfies your needs?
Sweet, thanks! I'll take a look after work.
@JamesxX Hi, did you already have time to check it out?
@Mc-Zen I took a look at the branch, but couldn't make it work. Curried functions are still passed to#show-variable
without any additional fields. Do I need any additional setup?
I used this file for testing:
/// My base function.
/// - foo (content): Something.
/// - bar (boolean): A boolean.
/// -> content
#let myfunc(foo, bar: false) = strong(foo)
/// My curried function.
/// -> content
#let curried = myfunc.with(bar: true)
@jneug ouf, my bad. It still thinks that it is a variable because there are of course no parentheses😆
I wonder, should they go under functions
or variables
?
(justified suggestions welcome!)
I think they should look like any other function, but all functions should have a parent
key that is none
for normal functions and set to the name of the parent for curried functions.
The parameters of the parent should be copied to the curried function with updated defaults. This way, the theme could show the full function signature and a reference to the parent for further details.
For my example, it would look something like this:
#{
(functions: (
(
name: "myfunc",
parent: none,
description: "My base function.",
args: (
foo: (
description: "Something",
types: ("content",),
),
bar: (
default: "false",
description: "A boolean",
types: ("bool",),
),
),
return-types: ("content",),
),
(
name: "curried",
parent: "myfunc",
description: "My curried function.",
args: (
foo: (
description: "Something",
types: ("content",),
),
bar: (
default: "true",
description: "A boolean",
types: ("bool",),
),
),
return-types: ("content",),
),
))
}
So, for once the issue is fixed (and your code sample works)!
At the moment, the parent is not resolved, i.e., functions
contains the entry
(
name: "curried",
description: " My curried function.\n\n",
type: "content",
parent: (name: "myfunc", pos: (), named: (bar: "true")),
),
The parent
info consists of the name, an array of prepended positional arguments and a dictionary of prepended named arguments.
I test-implemented (not yet pushed) an additional resolving step that copies the docstring info for the parent.Then, the dictionary from above would instead read as:
(
name: "curried",
description: " My curried function.\n\n",
type: "content",
parent: (
name: "myfunc",
pos: (),
named: (bar: "true"),
description: " My base function.\n",
args: (
foo: (description: "Something.", types: ("content",)),
bar: (
default: "false",
description: "A boolean.",
types: ("boolean",),
),
),
return-types: ("content",),
),
),
One could say that the resolving part is up to the showing step (and therefore the style) but for show-function
(which will in future be replaced by a type for better customization options) it would be hard to retrieve the parent's info.
So the pos
and named
keys in parent
hold the parameters that are passed to .with()
?
Yes
The parent definitely should be resolved as suggested, imo. The style logic gets really convoluted for parsing curried functions right now because they have a different structure from "normal" functions. (As a side note: the default style fails right now because of this).
I still think from the styles' perspective there should be no difference between a curried function and others (other than a parent
key with the name of the parent function to show a reference to it). They are both functions with parameters. The resolving should be done by Tidy.
There is no difference between these two functions:
#let func-b = func-a.with(x: "y")
#let func-c(x: "y", ..args) = func-a(x: x, ..args)
Both are basically func-a
with x
set to "y"
. To the user of these functions, the docs should probably look the same.
As per title, functions defined by currying are treated as variables rather than functions. Perhaps, could Tidy check if a variable is set using
.with()
, and import the documentation (if any) for that function? (recursively)