mirror of
https://github.com/nix-community/noogle.git
synced 2024-11-26 10:24:25 +03:00
add proper handling for functors
This commit is contained in:
parent
a8a7a0e88e
commit
54530f99e6
@ -187,11 +187,11 @@
|
||||
"nixpkgs-regression": "nixpkgs-regression"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1704367076,
|
||||
"narHash": "sha256-wy+M/+mryU2w4HXO0cWiKeoL2IICR715q+yWacnSg4o=",
|
||||
"lastModified": 1704635985,
|
||||
"narHash": "sha256-1RePtidMIkpuBokpO0iPtVdaXO077a1GsInv25wRVhQ=",
|
||||
"owner": "hsjobeki",
|
||||
"repo": "nix",
|
||||
"rev": "d86596aabc7e480858fd5d024deb8c4092200d47",
|
||||
"rev": "0df2e1a93b905185b3e2118651109d9a57ec1593",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -24,10 +24,16 @@ let
|
||||
let
|
||||
lambda =
|
||||
if lib.isFunction parent.${name} then
|
||||
if parent.${name} ? __functor then
|
||||
builtins.lambdaMeta (unwrapFunctor parent.${name})
|
||||
let
|
||||
pos = builtins.lambdaMeta parent.${name};
|
||||
in
|
||||
if parent.${name} ? __functor && pos ? position && pos.position == null then
|
||||
let
|
||||
res = builtins.lambdaMeta (unwrapFunctor parent.${name});
|
||||
in
|
||||
res // { countApplied = (res.countApplied or 0) + 1; isFunctor = true; }
|
||||
else
|
||||
builtins.lambdaMeta parent.${name}
|
||||
pos
|
||||
else
|
||||
null;
|
||||
attr = { position = builtins.unsafeGetAttrPos name parent; };
|
||||
|
@ -122,6 +122,9 @@ pub fn categorize(data: &Vec<Docs>) -> FnCategories {
|
||||
|
||||
for item in data.iter() {
|
||||
if let Some(lambda) = &item.docs.lambda {
|
||||
if lambda.isFunctor == Some(true) {
|
||||
continue;
|
||||
}
|
||||
match lambda.countApplied {
|
||||
// Some(0) | None => {
|
||||
Some(0) => {
|
||||
@ -161,6 +164,10 @@ pub fn init_alias_map(data: &Vec<Docs>, categories: FnCategories) -> AliasMap {
|
||||
let mut alias_map: AliasMap = HashMap::new();
|
||||
for item in data.iter() {
|
||||
if let Some(lambda) = &item.docs.lambda {
|
||||
// Skip functors
|
||||
if lambda.isFunctor == Some(true) {
|
||||
continue;
|
||||
}
|
||||
match lambda.countApplied {
|
||||
Some(0) => {
|
||||
if lambda.isPrimop {
|
||||
|
@ -171,6 +171,8 @@ struct DocumentFrontmatter<'a> {
|
||||
/// If an item is primop then it should have the PrimopMeta field.
|
||||
is_primop: Option<bool>,
|
||||
primop_meta: Option<PrimopMatter<'a>>,
|
||||
/// is functor
|
||||
is_functor: Option<bool>,
|
||||
/// Where the attribute is defined at.
|
||||
attr_position: Option<&'a FilePosition>,
|
||||
/// Where the original lambda is defined at.
|
||||
@ -207,6 +209,7 @@ impl<'a> FromDocs<'a> for Document<'a> {
|
||||
.map(|i| i.position.as_ref())
|
||||
.flatten(),
|
||||
is_primop: item.docs.lambda.as_ref().map(|i| i.isPrimop),
|
||||
is_functor: item.docs.lambda.as_ref().map(|i| i.isFunctor).flatten(),
|
||||
count_applied: item.docs.lambda.as_ref().map(|i| i.countApplied).flatten(),
|
||||
primop_meta: match &item.docs.lambda {
|
||||
None => None,
|
||||
|
@ -18,6 +18,8 @@ use crate::position::FilePosition;
|
||||
pub struct LambdaMeta {
|
||||
#[allow(non_snake_case)]
|
||||
pub isPrimop: bool,
|
||||
#[allow(non_snake_case)]
|
||||
pub isFunctor: Option<bool>,
|
||||
pub name: Option<String>,
|
||||
pub position: Option<FilePosition>,
|
||||
pub args: Option<Vec<String>>,
|
||||
|
@ -203,7 +203,7 @@ export default async function Page(props: { params: { path: string[] } }) {
|
||||
idx === all.length - 1 ? (
|
||||
<>
|
||||
<meta key={idx} data-pagefind-meta={`name:${attr}`} />
|
||||
<Box component="h3" sx={{ display: "none" }}>
|
||||
<Box key={idx * 2} component="h3" sx={{ display: "none" }}>
|
||||
{attr}
|
||||
</Box>
|
||||
</>
|
||||
@ -251,6 +251,13 @@ export default async function Page(props: { params: { path: string[] } }) {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{meta?.is_functor && (
|
||||
<Chip
|
||||
label={"Functor"}
|
||||
color="warning"
|
||||
sx={{ ml: "auto", maxWidth: "10rem" }}
|
||||
/>
|
||||
)}
|
||||
<ShareButton />
|
||||
</Box>
|
||||
<Divider flexItem sx={{ mt: 2 }} />
|
||||
@ -304,7 +311,9 @@ export default async function Page(props: { params: { path: string[] } }) {
|
||||
<MDX source={source} />
|
||||
{meta && <PositionLink meta={meta} content={item?.content} />}
|
||||
<div data-pagefind-ignore="all">
|
||||
{(!!meta?.aliases?.length || (!!signature && !meta?.signature)) && (
|
||||
{(!!meta?.aliases?.length ||
|
||||
(!!signature && !meta?.signature) ||
|
||||
meta?.is_functor) && (
|
||||
<>
|
||||
<Divider flexItem />
|
||||
<Typography
|
||||
@ -321,6 +330,15 @@ export default async function Page(props: { params: { path: string[] } }) {
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
{meta?.is_functor && (
|
||||
<>
|
||||
<Typography variant="h5" component={"div"}>
|
||||
This is a Functor
|
||||
</Typography>
|
||||
<br />
|
||||
<Link href="/md/tutorials/functors">Learn about functors</Link>
|
||||
</>
|
||||
)}
|
||||
{!!meta?.aliases?.length && (
|
||||
<>
|
||||
<Typography
|
||||
|
60
website/src/app/md/tutorials/functors/page.mdx
Normal file
60
website/src/app/md/tutorials/functors/page.mdx
Normal file
@ -0,0 +1,60 @@
|
||||
# Functors in nix
|
||||
|
||||
**Functors combine functions and attribute sets**
|
||||
|
||||
## Understanding Functors
|
||||
|
||||
A functor is a polymorphic data type that can represent both a
|
||||
**lambda function** (`x: x`) and an **attribute set** (`{ key = value; }`).
|
||||
|
||||
This means that the Atribute set can hold data in the form of attributes.
|
||||
|
||||
And also be a lambda function that can operate on that data.
|
||||
|
||||
-> The lambda function can access the attributes of the attribute set often called `self`.
|
||||
|
||||
## Examples of Functors
|
||||
|
||||
In the following example, `build` is both an attribute set and a lambda.
|
||||
`__functor` is a reserved attribute name that turns the attribute set `build` into a **functor**.
|
||||
|
||||
```nix
|
||||
{
|
||||
build = {
|
||||
foo = 1;
|
||||
__functor = self: _arg: self.foo;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
The attribute set `build` can now be used as a lambda via `function application`.
|
||||
|
||||
```nix
|
||||
nix-repl> build "linux"
|
||||
=> 1
|
||||
```
|
||||
|
||||
But at the same time `build` is still an Attribute set.
|
||||
|
||||
```nix
|
||||
nix-repl> build
|
||||
=> { __functor = «lambda»; foo = 1; }
|
||||
```
|
||||
|
||||
## Applications of Functors
|
||||
|
||||
Functors find practical applications including some in nixpkgs:
|
||||
|
||||
- `lib.makeOverridable`
|
||||
- `lib.setFunctionArgs`
|
||||
- `lib.mirrorFunctionArgs`
|
||||
- `lib.types` and `lib.options`
|
||||
- and many more.
|
||||
|
||||
## When to use a functor
|
||||
|
||||
(Noogle opinion)
|
||||
|
||||
The use of functor should be avoided and is often **unnecessary**.
|
||||
|
||||
Using them can add up in **complexity** and makes is hard to learn and maintain a certain piece of code.
|
@ -86,28 +86,52 @@ export const PositionLink = ({
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
{!contentPosition && position && (
|
||||
{!contentPosition && (
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Link
|
||||
target="_blank"
|
||||
href={getSourcePosition(
|
||||
"https://github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments",
|
||||
position
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
data-pagefind-ignore="all"
|
||||
variant="text"
|
||||
sx={{
|
||||
textTransform: "none",
|
||||
my: 1,
|
||||
placeSelf: "start",
|
||||
}}
|
||||
startIcon={<LinkIcon />}
|
||||
{attr_position && (
|
||||
<Link
|
||||
target="_blank"
|
||||
href={getSourcePosition(
|
||||
"https://github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments",
|
||||
attr_position
|
||||
)}
|
||||
>
|
||||
Underlying function
|
||||
</Button>
|
||||
</Link>
|
||||
<Button
|
||||
data-pagefind-ignore="all"
|
||||
variant="text"
|
||||
sx={{
|
||||
textTransform: "none",
|
||||
my: 1,
|
||||
placeSelf: "start",
|
||||
}}
|
||||
startIcon={<LinkIcon />}
|
||||
>
|
||||
Attribute position
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
{lambda_position && (
|
||||
<Link
|
||||
target="_blank"
|
||||
href={getSourcePosition(
|
||||
"https://github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments",
|
||||
lambda_position
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
data-pagefind-ignore="all"
|
||||
variant="text"
|
||||
sx={{
|
||||
textTransform: "none",
|
||||
my: 1,
|
||||
placeSelf: "start",
|
||||
}}
|
||||
startIcon={<LinkIcon />}
|
||||
>
|
||||
Underlying function
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
{!!count_applied && count_applied > 0 && (
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
|
@ -35,6 +35,7 @@ export type DocMeta = {
|
||||
path: ValuePath;
|
||||
aliases?: ValuePath[];
|
||||
is_primop?: boolean;
|
||||
is_functor?: boolean;
|
||||
primop_meta?: PrimopMatter;
|
||||
attr_position?: FilePosition;
|
||||
lambda_position?: FilePosition;
|
||||
|
Loading…
Reference in New Issue
Block a user