https://github.com/masonprotter/simpleunderscores.jl
Because there weren't enough of these packages already
https://github.com/masonprotter/simpleunderscores.jl
Last synced: 3 months ago
JSON representation
Because there weren't enough of these packages already
- Host: GitHub
- URL: https://github.com/masonprotter/simpleunderscores.jl
- Owner: MasonProtter
- License: mit
- Created: 2023-02-20T23:10:43.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2023-02-24T20:30:46.000Z (almost 3 years ago)
- Last Synced: 2025-09-23T22:51:34.344Z (4 months ago)
- Language: Julia
- Size: 17.6 KB
- Stars: 11
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SimpleUnderscores.jl
SimpleUnderscores.jl aims to provide yet another way to locally construct anonymous functions where the arguments do not need to be listed before they are used in the body, but taking an approach that differents from [Underscores.jl](https://github.com/c42f/Underscores.jl) with less complicated scoping rules. See also [JuliaLang/julia/issues/38713](https://github.com/JuliaLang/julia/issues/38713).
By default, it exports one macro, `@>`. An expression acted on by `@>` interprets underscores `_` as a placeholder for a function argument. Hence, `@> _ + 1` means the same thing as `x -> x + 1`. A bare underscore `_` always is the first argument to the function:
``` julia
julia> using SimpleUnderscores
julia> map(@> _ + _, [1,2,3])
3-element Vector{Int64}:
2
4
6
```
### Multiple Arguments
Click to expand
If you want to write a function acting on multiple arguments, you can write for instance `_4` to mean the fourth argument. The function returned will take as many arguments as the highest argument placeholder number specified.
``` julia
julia> λ = @> _ + _3;
julia> λ(5, 6, 7)
12
julia> λ(5,6)
ERROR: MethodError: no method matching (::var"#23#24")(::Int64, ::Int64)
Closest candidates are:
(::var"#23#24")(::Any, ::Any, ::Any)
```
```julia
julia> map(@> _1.a + _2.b, [(;a=1,), (;a=2)], [(;b=3), (;b=4)])
2-element Vector{Int64}:
4
6
```
You can also use `__` to signify varargs:
``` julia
julia> f = @> _ + __[end];
julia> f(1,2,3,4,5,6,7,8,9)
10
```
### Main limitation: dealing with tuples and commas
Click to expand
Because the parser is such that [commas parse tighter than macros](https://github.com/JuliaLang/julia/issues/36547#issuecomment-1437406477), when you write code like
``` julia
map(@> _ + _, [1, 2])
```
this will actually get parsed as `map(@>(((_ + _), [1, 2])))` rather than `map(@>(_ + _), [1, 2])`, but SimpleUnderscores will then macroexpand this to something like `map(((x -> x + x), [1, 2])...,)` so that we get the desired behaviour.
Unfortunately though, SimpleUnderscores.jl cannot tell the difference between `@> (_, 1)` and `(@> _, 1)`, which means that if you want to write an anonymous function using SimpleUnderscores.jl that returns a `Tuple`, you need to write something like `@> tuple(_, 1)`. The potential for fixing this is being discussed here: [JuliaLang/julia/issues/36547](https://github.com/JuliaLang/julia/issues/36547).
This parsing behaviour also unfortunately means that a somewhat confusing error gets thrown if you try to construct a `Tuple` at the top level containing `@>`:
``` julia
julia> @> _, [1] # Doesn't work :(
ERROR: syntax: "..." expression outside call around REPL[39]:1
julia> (@> _, [1]) # Also doesn't work :(((
ERROR: syntax: "..." expression outside call around REPL[40]:1
julia> ((@> _, [1]),) # At least this works.
(var"#31#32"(), [1])
```
but you should probably just use `@>( ... )` instead in these case. Follow this PR for any news on a potential fix: [JuliaLang/julia/pull/48750](https://github.com/JuliaLang/julia/pull/48750)
### Nested macros
Click to expand
Macros appearing inside a `@>` macro are recursively hit with `macroexpand` in the approporiate module, this is to make sure that things like `@> filter(@> _.a > 1, _)` correctly work.
### Other names
Click to expand
There's two other, unexported macros inside the package, `@->` and `@_` which are the exact same as `@>` but some people may prefer the other names. If you prefer that, then you can simply do `using SimpleUnderscores: @_` or `using SimpleUnderscores: @->`.