asc-community / asc-community/AngouriMath
Lambdas & functions as entities
- Dominant language
- C#
- Stars
- 831
- Forks
- 79
- Avg merge
- 3h 23m
- Merged PRs (30d)
- 309
Description
# Lambdas and function entities
This was planned for 1.6, but may be implemented much sooner (as soon as it's clear what we are going to do).
The plan consists of two key points: `apply` node and `lambda` node.
## Apply node
This node indicates that something is applied to something.
### Declaration
```cs
record Application(Entity Expression, LList Arguments);
```
`LList` is a linked list from Honk# 1.0.3+.
### Syntax
It will have syntax `apply(expr, ...)`, for example,
```
apply(a, x)
apply(a, x, y, z)
apply(1 + sqrt(y), x)
apply(y + y, y + y)
apply(y + y, y + y, apply(y + y, y + y))
```
etc.
With implicit parsing disabled by default, it will create an apply node for cases when an expression follows another expression, for example,
```
x x
a 5
sin x
f a b
```
but with priority higher than operators:
```
f a b = apply(apply(f, a), b)
f a b * 2 = apply(apply(f, a), b) * 2
```
The priority is higher than all others except for `Leaf` and is defined as
```
Func = 80 | NumericalOperation,
```
(this existed before for functions, no additional is added for application)
Comma-separated arguments are still allowed:
```
f a b
```
is the same as
```
f(a, b)
```
## Relaxing syntax for calling built-in functions
Currently you cannot have spaces between parentheses when calling a built-in function: `sin(x)` is valid,
but `sin (x)` will be interpreted as `sin * x`.
Now it won't be so with implicit parsing disabled. `sin (x)` will be interpreted as `sin(x)`.
Moreover, there will be no need to set parentheses. `sin x` will be equal to `sin(x)`. In this case, operator has a lower priority (that is, `sin x * x` is `(sin x) * x`).
## Lambda node
This node is for declaration lambdas. All logic about lambdas is going to be borrowed from lambda-calculus.
### Declaration
```cs
record Lambda(Variable Var, Entity Body);
```
### Syntax
List of variables separated by space, followed by `=>`, followed by the lambda's body. For example,
```
a => a + 3
a => a + b
a b => a + b (the same as a => b => a + b)
a b c => 3 (the same as a => b => c => 3)
a 3 => 3 Invalid
```
As synonym, `lambda` can be used:
```
lambda(x, x + 3)
lambda(x, y, x + 3)
lambda() // error
lambda(x) // error
```
#### Parameters syntax
Identifiers (variables), separated by space, before `=>`, substitute lambdas' parameters, so it reads from the right to the left. A non-variable interrupts it.
```
2 + a => 3 (the same as 2 + (a => 3), will be parsed to the left starting from =>)
a b quack c => 3
a + b * c => a + b (the same as a + b * (c => a + b))
```
The priority of `=>` will be lower than `provided` (and hence, lower than any other operator and construction).
### Logic
When simplifying, apply of lambda and something will result in lambda's body substituted with the argument:
```
(a b => a + b) 4
becomes
b => a + 4
```
When substituting, lambda may be alpha-converted on demand. For example:
```
(a b => a + b) b
```
will become
```
c => b + c
```
Derivative, integral, limit do not affect lambdas, if the latter are passed as parameters.
**Currying** of built-in functions is allowed via lambdas:
```
derivative (x + a)
```
is inner simplified to
```
y => derivative (x + a) y
```
## Differentiation and integration
Derivative and integral of an applied function now can be reduced by corresponding rules, for example:
```
derivative(f (x ^ 2), x)
```
will be reduced to
```
derivative(f (x ^ 2), x ^ 2) * derivative(x ^ 2, x)
```
## Breaking changes
By default, implicit parsing is enabled currently. To enable proper application syntax, it will be disabled (but remains as an option in the settings).
Contributor guide
Assessment
This issue has not been assessed yet.