@@ -4355,62 +4355,146 @@ let f = NoSpecClosure.K(1)
43554355 @test typeof (f). parameters == Core. svec ()
43564356end
43574357
4358- @testset " Expr(:thisfunction)" begin
4359- # regular functions can use Expr(:thisfunction) to refer to the function itself
4360- @eval regular_func () = $ (Expr (:thisfunction ))
4361- @test regular_func () === regular_func
4362-
4363- # This also works in callable structs, which refers to the instance
4364- struct CallableStruct
4365- value:: Int
4358+ @testset " @__FUNCTION__ and Expr(:thisfunction)" begin
4359+ @testset " Basic usage" begin
4360+ # @__FUNCTION__ in regular functions
4361+ test_function_basic () = @__FUNCTION__
4362+ @test test_function_basic () === test_function_basic
4363+
4364+ # Expr(:thisfunction) in regular functions
4365+ @eval regular_func () = $ (Expr (:thisfunction ))
4366+ @test regular_func () === regular_func
43664367 end
4367- @eval (obj:: CallableStruct )() = $ (Expr (:thisfunction ))
4368- @eval (obj:: CallableStruct )(x) = $ (Expr (:thisfunction )). value + x
43694368
4370- let cs = CallableStruct (42 )
4371- @test cs () === cs
4372- @test cs (10 ) === 52
4369+ @testset " Recursion" begin
4370+ # Factorial with @__FUNCTION__
4371+ factorial_function (n) = n <= 1 ? 1 : n * (@__FUNCTION__ )(n - 1 )
4372+ @test factorial_function (5 ) == 120
4373+
4374+ # Fibonacci with Expr(:thisfunction)
4375+ struct RecursiveCallableStruct; end
4376+ @eval (:: RecursiveCallableStruct )(n) = n <= 1 ? n : $ (Expr (:thisfunction ))(n- 1 ) + $ (Expr (:thisfunction ))(n- 2 )
4377+ @test RecursiveCallableStruct ()(10 ) === 55
4378+
4379+ # Anonymous function recursion
4380+ @test (n -> n <= 1 ? 1 : n * (@__FUNCTION__ )(n - 1 ))(5 ) == 120
43734381 end
43744382
4375- struct RecursiveCallableStruct; end
4376- @eval (:: RecursiveCallableStruct )(n) = n <= 1 ? n : $ (Expr (:thisfunction ))(n- 1 ) + $ (Expr (:thisfunction ))(n- 2 )
4377-
4378- @test RecursiveCallableStruct ()(10 ) === 55
4383+ @testset " Closures and nested functions" begin
4384+ # Prevents boxed closures
4385+ function make_closure ()
4386+ fib (n) = n <= 1 ? 1 : (@__FUNCTION__ )(n - 1 ) + (@__FUNCTION__ )(n - 2 )
4387+ return fib
4388+ end
4389+ Test. @inferred make_closure ()
4390+ closure = make_closure ()
4391+ @test closure (5 ) == 8
4392+ Test. @inferred closure (5 )
4393+
4394+ # Complex closure of closures
4395+ function f1 ()
4396+ function f2 ()
4397+ function f3 ()
4398+ return @__FUNCTION__
4399+ end
4400+ return (@__FUNCTION__ ), f3 ()
4401+ end
4402+ return (@__FUNCTION__ ), f2 ()...
4403+ end
4404+ Test. @inferred f1 ()
4405+ @test f1 ()[1 ] === f1
4406+ @test f1 ()[2 ] != = f1
4407+ @test f1 ()[3 ] != = f1
4408+ @test f1 ()[3 ]() === f1 ()[3 ]
4409+ @test f1 ()[2 ]()[2 ]() === f1 ()[3 ]
4410+
4411+ # In closures, var"#self#" should refer to the enclosing function,
4412+ # NOT the enclosing struct instance
4413+ struct CallableStruct2; end
4414+ @eval function (obj:: CallableStruct2 )()
4415+ function inner_func ()
4416+ $ (Expr (:thisfunction ))
4417+ end
4418+ inner_func
4419+ end
43794420
4380- # In closures, var"#self#" should refer to the enclosing function,
4381- # NOT the enclosing struct instance
4382- struct CallableStruct2; end
4383- @eval function (obj:: CallableStruct2 )()
4384- function inner_func ()
4385- $ (Expr (:thisfunction ))
4421+ let cs = CallableStruct2 ()
4422+ @test cs ()() === cs ()
4423+ @test cs ()() != = cs
43864424 end
4387- inner_func
43884425 end
43894426
4390- let cs = CallableStruct2 ()
4391- @test cs ()() === cs ()
4392- @test cs ()() != = cs
4427+ @testset " Do blocks" begin
4428+ function test_do_block ()
4429+ result = map ([1 , 2 , 3 ]) do x
4430+ return (@__FUNCTION__ , x)
4431+ end
4432+ # All should refer to the same do-block function
4433+ @test all (r -> r[1 ] === result[1 ][1 ], result)
4434+ # Values should be different
4435+ @test [r[2 ] for r in result] == [1 , 2 , 3 ]
4436+ # It should be different than `test_do_block`
4437+ @test result[1 ][1 ] != = test_do_block
4438+ end
4439+ test_do_block ()
43934440 end
43944441
4395- # Keywords
4396- let
4397- @eval f2 (; n= 1 ) = n <= 1 ? n : n * $ (Expr (:thisfunction ))(; n= n- 1 )
4398- result = f2 (n= 5 )
4399- @test result == 120
4442+ @testset " Keyword arguments" begin
4443+ # @__FUNCTION__ with kwargs
4444+ foo (; n) = n <= 1 ? 1 : n * (@__FUNCTION__ )(; n = n - 1 )
4445+ @test foo (n = 5 ) == 120
4446+
4447+ # Expr(:thisfunction) with kwargs
4448+ let
4449+ @eval f2 (; n= 1 ) = n <= 1 ? n : n * $ (Expr (:thisfunction ))(; n= n- 1 )
4450+ result = f2 (n= 5 )
4451+ @test result == 120
4452+ end
44004453 end
44014454
4402- # Struct constructor with thisfunction
4403- let
4404- @eval struct Cols{T<: Tuple }
4405- cols:: T
4406- operator
4407- Cols (args... ; operator= union) = (new {typeof(args)} (args, operator); string ($ (Expr (:thisfunction ))))
4455+ @testset " Callable structs" begin
4456+ # @__FUNCTION__ in callable structs
4457+ @gensym A
4458+ @eval module $ A
4459+ struct CallableStruct{T}; val:: T ; end
4460+ (c:: CallableStruct )() = @__FUNCTION__
4461+ end
4462+ @eval using .$ A: CallableStruct
4463+ c = CallableStruct (5 )
4464+ @test c () === c
4465+
4466+ # Expr(:thisfunction) in callable structs
4467+ struct CallableStruct3
4468+ value:: Int
4469+ end
4470+ @eval (obj:: CallableStruct3 )() = $ (Expr (:thisfunction ))
4471+ @eval (obj:: CallableStruct3 )(x) = $ (Expr (:thisfunction )). value + x
4472+
4473+ let cs = CallableStruct3 (42 )
4474+ @test cs () === cs
4475+ @test cs (10 ) === 52
44084476 end
4409- result = Cols (1 , 2 , 3 )
4410- @test occursin (" Cols" , result)
44114477 end
44124478
4413- let @generated foo () = Expr (:thisfunction )
4414- @test foo () === foo
4479+ @testset " Special cases" begin
4480+ # Generated functions
4481+ let @generated foo () = Expr (:thisfunction )
4482+ @test foo () === foo
4483+ end
4484+
4485+ # Struct constructor with thisfunction
4486+ let
4487+ @eval struct Cols{T<: Tuple }
4488+ cols:: T
4489+ operator
4490+ Cols (args... ; operator= union) = (new {typeof(args)} (args, operator); string ($ (Expr (:thisfunction ))))
4491+ end
4492+ result = Cols (1 , 2 , 3 )
4493+ @test occursin (" Cols" , result)
4494+ end
4495+
4496+ # Error upon misuse
4497+ @gensym B
4498+ @test_throws ErrorException @eval (module $ B; @__FUNCTION__ ; end )
44154499 end
44164500end
0 commit comments