Apraxia
Apraxia is a pattern-based esolang created by User:Yayimhere, after being disappointed by the use of the before mentioned term. In Apraxia, every string of length >1 is valid as code. Apraxia is quite complex compared to some other languages by yayimhere, as it allows recursive functions and variables, as well as null, and a fixed point combinator. All variables in Apraxia are both sub programs/strings, and functions. As such, Apraxia is semi-functionally pure(as all strings are represented by a function).
Etymology
Apraxia's name comes from the name of lisp, as both are speech difficulties. Lisp specifically was chosen as lisp is meme-ed over being full of brackets, or in other words, being very "pattern like".
Syntax
As mentioned before, Apraxia allows all strings of symbols. As such, syntax is very generalized. Note that the last character of the command is special, and always "recognized":
- For any symbol
Xthat is not recognized(never seen before in the program up to this point): All code between this symbolXand another non recognized symbolY, is interpreted as the value ofXas a variable. ThenYis parsed in the same way, until there are no unrecognized symbols. - For any two symbols
M & Nfollowing each other, that are both recognized: This is function application of the formM(N). Note that for any length of function application, it is nested, so for the symbol setMNWit will be read asM(N(W)). - For any single symbol
Xthat is recognized, but is not in a pair is read as a variable value.
Apraxia uses the full unicode printable character space.
Semantics
First, there is the last character of the program, which is different from all others. The last character C has the function:
C(XYZ...) -> X(C(YZ...)) C() -> C C((XY)(YX)) -> X(Y(C((YX)))
This is the before mentioned fixed point combinator, to some extent. As a variable value however, it is just the symbol C. Note that C never is unrecognized, however does end the last variable definition, and is not included in that definition.
For all other variables X, their function is:
X(M) -> C((M(X))(M)) X() -> X
Then, when all variables and functions have been defined, we call the whole program as:
C(Vn-1Vn)
Where each V is one of the variables defined in the program, with Vn being the last defined. Then the whole program is evaluated. When evaluation has completed, the final result is printed.
Do note that the brackets used above are not actually present in the program in any way. As such, ( and ) are valid symbols in the program.
Note that a variable is always expanded to its actual value before anything is applied to it, unless it is being applied as a function. Also, note that this rule applies:
() ->
everywhere. A variable defined only in terms of a single copy of itself is considered a just a string, and does not expand forever.
Combinators
Here is a list of combinators/functions that may be useful. It will be listed as:
symbol - variable body - result of application
note that c will be used for the final character, and the empty string will be represented as ε. x will be used as placeholder input.
- : - ε - c((x)(x))
- . - c - c((x(c))(x))
- | - | - c((x(|))(x)(note: mostly useful for recursion, like
c(|).)
feel free to expand this list, but do not delete of this list.
Examples
XCYCC
as:
XCYCC -> C(XY) -> C(CC) -> C(C(C))
creating a copying function :(x)=c((x)(x)):
:c
1c0i?*c
replace the ? with input. This works since in the case of 1, the program calls c(c) which is a minimized version of the normal infinite loop. But on zero, it calls c() which is equal to c.
Looping counter:
||c
This works because:
c(|) -> |(c) -> c((c(|))(c))
in which the c(|) expands further like that again so it after infinite time, will look like:
c((c((c((...)(c)))(c)))(c))
This also has the interesting side effect of having c(|) ≡ |(c). Note that a trivial looping counter is one like **|*|c, however this uses trivial recursion, which is barely valid.