I tried it, and it works. But - catch :here
|| catch(:here)
- produces error.
In catchtest.cr:59:3
59 | catch :here
^----
Error: 'catch' is expected to be invoked with a block, but no block was given
In catchtest.cr:59:3
59 | catch(:here)
^----
Error: 'catch' is expected to be invoked with a block, but no block was given
But these work - catch :here {}
|| catch(:here) {}
Could make visually nicer, something like this:
Break.new(:here) -> throw :here
catch :here {} -> catch :here
Otherwise it seems to work, at lease in this example.
This definitely would have made writing the original code a snap.
I would urge adding this capability into the language!
Here’s the test code (made sozpg
simpler for testing purposes).
class Break < Exception
getter symbol : Symbol
def initialize(@symbol : Symbol)
end
end
def catch(symbol : Symbol)
begin
yield
rescue e : Break
raise e unless e.symbol == symbol
end
end
def sozpg(val)
md, rscnt = 30u64, 8
res = [7,11,13,17,19,23,29,31]
bitn = [0,0,0,0,0,1,0,0,0,2,0,4,0,0,0,8,0,16,0,0,0,32,0,0,0,0,0,64,0,128]
kmax = (val - 2) // md + 1
prms = Array(UInt8).new(kmax, 0)
prms.each_with_index do |resgroup, k|
res.each_with_index do |prm_r, i|
next if resgroup & (1 << i) != 0
prime = md * k + prm_r
Break.new(:here) if prime > Math.isqrt(val)
res.each do |ri|
kn, rn = (prm_r * ri - 2).divmod md
kpm = k * (prime + ri) + kn
while kpm < kmax; prms[kpm] |= bitn[rn]; kpm += prime end
end end end
catch :here {}
primes = [2, 3, 5] of UInt64
prms.each_with_index do |resgroup, k|
res.each_with_index do |r_i, i|
primes << md * k + r_i if resgroup & (1 << i) == 0
end end
primes
end
puts (primes = sozpg(541)).size
print primes
https://play.crystal-lang.org/#/r/cqdy