@@ -111,7 +111,30 @@ Base.promote_rule(::Type{T19714}, ::Type{Int}) = T19714
111111 @test ∘ (x -> x- 2 , x -> x- 3 , x -> x+ 5 )(7 ) == 7
112112 fs = [x -> x[1 : 2 ], uppercase, lowercase]
113113 @test ∘ (fs... )(" ABC" ) == " AB"
114+
115+ # Like +() and *() we leave ∘() undefined.
116+ # While `∘() = identity` is a reasonable definition for functions, this
117+ # would cause headaches for composition of user defined morphisms.
118+ # See also #34251
119+ @test_throws (MethodError, ∘ ())
120+
121+ @test ∘ (x -> (x, 1 ))(0 ) === (0 , 1 )
122+ @test ∘ (x -> (x, 2 ), x -> (x, 1 ))(0 ) === ((0 , 1 ), 2 )
123+ @test ∘ (x -> (x, 3 ), x -> (x, 2 ), x-> (x,1 ))(0 ) === (((0 , 1 ), 2 ), 3 )
124+ @test ∘ (x -> (x, 4 ), x -> (x, 3 ), x-> (x,2 ), x-> (x, 1 ))(0 ) === ((((0 , 1 ), 2 ), 3 ), 4 )
125+
126+ # test that user defined functors only need to overload the two arg version
127+ struct FreeMagma
128+ word
129+ end
130+ Base.:(∘ )(a:: FreeMagma , b:: FreeMagma ) = FreeMagma ((a. word, b. word))
131+
132+ @test ∘ (FreeMagma (1 )) === FreeMagma (1 )
133+ @test ∘ (FreeMagma (1 ), FreeMagma (2 )) === FreeMagma ((1 ,2 ))
134+ @test ∘ (FreeMagma (1 ), FreeMagma (2 ), FreeMagma (3 )) === FreeMagma (((1 ,2 ), 3 ))
135+ @test ∘ (FreeMagma (1 ), FreeMagma (2 ), FreeMagma (3 ), FreeMagma (4 )) === FreeMagma ((((1 ,2 ), 3 ), 4 ))
114136end
137+
115138@testset " function negation" begin
116139 str = randstring (20 )
117140 @test filter (! isuppercase, str) == replace (str, r" [A-Z]" => " " )
0 commit comments