Skip to content

Commit 8e53041

Browse files
authored
Merge pull request #13 from MasonProtter/saner-closure-handling
Fix closure perf problem, removed MLStyle, use GithubActions
2 parents ef8c173 + 234a98a commit 8e53041

9 files changed

Lines changed: 90 additions & 225 deletions

File tree

.travis.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

Project.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
name = "LegibleLambdas"
22
uuid = "f1f30506-32fe-5131-bd72-7c197988f9e5"
33
authors = ["MasonProtter <mason.protter@gmail.com>", "Roger-luo <hiroger@qq.com>"]
4-
version = "0.2.1"
4+
version = "0.3.0"
55

66
[deps]
7-
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
87
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
98

109
[compat]
11-
julia = "~1.0.0"
12-
MLStyle = "~0.3"
13-
MacroTools = "~0.5"
10+
julia = "1"
11+
MacroTools = "0.5"
1412

1513
[extras]
1614
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ julia> g = @λ(x -> x + 1)
3232
(x -> x + 1)
3333
```
3434

35-
If you use julia **v1.1+**, anonymous returned by other functions will also benefit from increased legibility
36-
35+
This 'just works' inside most closures too!
3736
```julia
3837
julia> D(f, ϵ=1e-10) = (x -> (f(x+ϵ)-f(x))/ϵ)
3938
D (generic function with 2 methods)
4039

4140
julia> D(sin)
42-
(x -> (sin(x + 1e-10) - sin(x)) / 1e-10)
41+
(x -> ((sin)(x + 1e-10) - (sin)(x)) / 1e-10)
42+
43+
julia> D(sin, 0.01)
44+
(x -> ((sin)(x + 0.01) - (sin)(x)) / 0.01)
4345
```
4446

4547
## License

src/LegibleLambdas.jl

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,90 @@ julia> @λ(x -> g(x)/3)
1515
(x -> g(x)/3)
1616
```
1717
"""
18-
:()
19-
20-
# NOTE: Base.@locals is in v1.1
21-
@static if VERSION < v"1.1.0"
22-
# NO Base.@locals
23-
include("no_local.jl")
24-
else
25-
# With Base.@locals
26-
include("local.jl")
18+
macro λ(ex)
19+
return parse_lambda(ex)
2720
end
2821

2922
eval(:(const $(Symbol("@lambda")) = $(Symbol(""))))
3023

31-
include("replace_variable.jl")
32-
include("expr_printing.jl")
24+
"""
25+
parse_lambda(ex)
26+
27+
Parse a lambda expression to `LegibleLambda` constructor expression.
28+
"""
29+
function parse_lambda(ex)
30+
if ex.head == :(->)
31+
:(LegibleLambda($(QuoteNode(ex)), $(esc(ex))))
32+
else
33+
throw("Must be called on a Lambda expression")
34+
end
35+
end
36+
37+
#------------------------------------------------------------------------------------
38+
39+
struct LegibleLambda{F <: Function} <: Function
40+
ex::Expr
41+
λ::F
42+
end
43+
44+
(f::LegibleLambda)(args...) = (f.λ)(args...)
45+
46+
function Base.show(io::IO, f::LegibleLambda)
47+
show(io, MIME"text/plain"(), f)
48+
end
49+
50+
function Base.show(io::IO, ::MIME"text/plain", f::LegibleLambda)
51+
l_names = propertynames(f.λ)
52+
ex = f.ex
53+
foreach(l_names) do name
54+
ex = postwalk(ex) do s
55+
s === name ? getfield(f.λ, name) : s
56+
end
57+
end
58+
ex_cut = ex |> (ex -> postwalk(cutlnn, ex)) |> (ex -> postwalk(cutblock, ex))
59+
name = replace((repr(ex_cut |> pretty_kwargs)[2:end]), "->" => " -> ")
60+
print(io, name)
61+
end
62+
63+
#------------------------------------------------------------------------------------
64+
65+
cutlnn(x) = x
66+
function cutlnn(ex::Expr)
67+
Expr(ex.head, ex.args[[!(arg isa LineNumberNode) for arg in ex.args]]...)
68+
end
69+
70+
cutblock(x) = x
71+
function cutblock(ex::Expr)
72+
if (ex.head == :block) && (length(ex.args)==1)
73+
ex.args[1]
74+
else
75+
ex
76+
end
77+
end
78+
79+
tupleargs(x::Symbol) = (x,)
80+
function tupleargs(ex::Expr)
81+
if ex.head == :tuple
82+
Tuple(ex.args)
83+
else
84+
throw("expression must have head `:tuple`")
85+
end
86+
end
87+
88+
pretty_kwargs(x::Symbol) = x
89+
function pretty_kwargs(ex)
90+
if ex.args[1] isa Expr
91+
if ex.args[1].head == :block
92+
exout = copy(ex)
93+
exout.args[1].head = :tuple
94+
exout
95+
else
96+
ex
97+
end
98+
else
99+
ex
100+
end
101+
end
102+
33103

34104
end

src/expr_printing.jl

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/local.jl

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/no_local.jl

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/replace_variable.jl

Lines changed: 0 additions & 62 deletions
This file was deleted.

test/runtests.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ end
2020
@testset "Closures" begin
2121
D(f, ϵ=1e-10) = (x -> (f(x+ϵ)-f(x))/ϵ)
2222

23-
if VERSION < v"1.1.0"
24-
@test repr(D(sin)) == "(x -> (f(x + ϵ) - f(x)) / ϵ)"
25-
else
26-
@test repr(D(sin)) == "(x -> ((sin)(x + 1.0e-10) - (sin)(x)) / 1.0e-10)"
27-
end
23+
@test repr(D(sin)) == "(x -> ((sin)(x + 1.0e-10) - (sin)(x)) / 1.0e-10)"
2824

2925
@test D(sin)(π) == -1.000000082740371
3026
end

0 commit comments

Comments
 (0)