Skip to content

Commit 697de8a

Browse files
committed
Fix infinite recursion error in MonteCarloHash construction.
1 parent 947895a commit 697de8a

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

src/function_hashing/chebhash.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@ end
3333
ChebHash(similarity, args...; kws...) =
3434
ChebHash(SimilarityFunction(similarity), args...; kws...)
3535

36-
for (discrete_sim, fn_sim) in zip([ℓ2, cossim], [L2, cossim])
36+
const _valid_ChebHash_similarities = (
37+
# Function space similarities
38+
(L2, cossim),
39+
# Discrete-space similarities corresponding to function space similarities
40+
(ℓ2, cossim),
41+
)
42+
43+
for (fn_sim, discrete_sim) in zip(_valid_ChebHash_similarities...)
3744
quote
3845
# Add an implementation of ChebHash that dispatches on the similarity
3946
# function fn_sim
@@ -49,11 +56,18 @@ for (discrete_sim, fn_sim) in zip([ℓ2, cossim], [L2, cossim])
4956
end
5057

5158
# Implementation of ChebHash for invalid similarity functions. Just throws
52-
# a TypeError. Necessary because otherwise the first external ChebHash
53-
# constructor will go into an infinite loop when it receives an invalid
54-
# similarity function.
55-
ChebHash(sim::SimilarityFunction, args...; kws...) =
56-
ErrorException("similarity must be ℓ2 or cossim") |> throw
59+
# a error.
60+
# Necessary because otherwise the first external ChebHash constructor
61+
# will go into infinite recursion if it receives an invalid similarity
62+
# function.
63+
function ChebHash(sim::SimilarityFunction, args...; kws...)
64+
valid_sims = _valid_MonteCarloHash_similarities[1] .|>
65+
string |>
66+
collect |>
67+
sort!
68+
valid_sims = join(valid_sims, ", ", " or ")
69+
ErrorException("similarity must be $(valid_sims)") |> throw
70+
end
5771

5872
#========================
5973
Helper functions for ChebHash

src/function_hashing/monte_carlo.jl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,16 @@ end
5151
MonteCarloHash(similarity, args...; kws...) =
5252
MonteCarloHash(SimilarityFunction(similarity), args...; kws...)
5353

54-
for (simfn, fn_space_simfn, p) in zip([ℓ1,ℓ2,cossim], [L1,L2,cossim], [1,2,2])
54+
const _valid_MonteCarloHash_similarities = (
55+
# Function space similarities
56+
(L1, L2, cossim),
57+
# Discrete-space similarities corresponding to function space similarities
58+
(ℓ1, ℓ2, cossim),
59+
# Order of L^p space that the similarity applies to
60+
(1, 2, 2),
61+
)
62+
63+
for (fn_space_simfn, simfn, p) in zip(_valid_MonteCarloHash_similarities...)
5564
quote
5665
# Add dispatch for case in which we specify the similarity function
5766
# to be $fn_space_simfn
@@ -65,6 +74,19 @@ for (simfn, fn_space_simfn, p) in zip([ℓ1,ℓ2,cossim], [L1,L2,cossim], [1,2,2
6574
end |> eval
6675
end
6776

77+
# Implementation of MonteCarloHash for invalid similarity functions. Just throws
78+
# an error.
79+
# Necessary because otherwise the first MonteCarloHash constructor will go into
80+
# infinite recursion if it receives an invalid similarity function.
81+
function MonteCarloHash(sim::SimilarityFunction, args...; kws...)
82+
valid_sims = _valid_MonteCarloHash_similarities[1] .|>
83+
string |>
84+
collect |>
85+
sort!
86+
valid_sims = join(valid_sims, ", ", " or ")
87+
ErrorException("similarity must be $(valid_sims)") |> throw
88+
end
89+
6890
#========================
6991
MonteCarloHash helper functions
7092
========================#

test/function_hashing/test_chebhash.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Tests
3535
@test_throws(ErrorException, ChebHash(L1))
3636
@test_throws(ErrorException, ChebHash(ℓ2))
3737

38-
# Construct a hash function (with valid similarity_ in the same
38+
# Construct a hash function (with valid similarity) in the same
3939
# manner as we did above in case the ChebHash API ever changes.
4040
# This ensures that we won't forget to update these tests.
4141
_ = ChebHash(L2)

test/function_hashing/test_monte_carlo.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ Tests
2828
@test hashtype(hashfn) == hashtype(LSHFunction(ℓ1))
2929
end
3030

31+
@testset "Pass invalid similarity function" begin
32+
# Attempt to construct a MonteCarloHash with an invalid
33+
# similarity function.
34+
μ() = rand()
35+
36+
@test_throws(ErrorException, MonteCarloHash(ℓ1, μ))
37+
@test_throws(ErrorException, MonteCarloHash(ℓ2, μ))
38+
@test_throws(ErrorException, MonteCarloHash(jaccard, μ))
39+
40+
# Construct a hash function (with valid similarity) in the same
41+
# manner in case the MonteCarloHash API ever changes.
42+
# This ensures that we won't forget to update these tests.
43+
_ = MonteCarloHash(L2, μ)
44+
end
45+
3146
#==========
3247
Cosine similarity hashing
3348
==========#

0 commit comments

Comments
 (0)