ANN: CBOOCall

From the README of CBOOCall.jl:

split(",", "a,b,c") is not really the right way to do it.
split only works with strings, so it should be a class method.
We should be able to do ",".split("a,b,c").
There’s even a mnemonic. Think of “comma-separated values”.
Well this is a “comma split string”.

Now there is a way with CBOOCall.jl:

julia> @eval Base import CBOOCall;
julia> @eval Base CBOOCall.@cbooify String (split,)

Then we have

julia> ",".split("a,b,c")
1-element Vector{SubString{String}}:
 ","

… uh, we can fix that

julia> @eval Base CBOOCall.@cbooify String (split=(x,y) -> split(y, x),)
julia> ",".split("a,b,c")
3-element Vector{SubString{String}}:
 "a"
 "b"
 "c"

Ahhhh… That’s much better than split("a,b,c", ",")! …
I mean split(",", "a,b,c").

… wait …, is, … it’s the other way around, right? Let’s consult the Zen of CBOO.

>>> spl[TAB, TAB] # Bonk! Bonk! It's not there.
>>> from string import spl[TAB, TAB] # Bonk! Bonk! Not there either. Good.
>>> ','.split("a,b,c")
[',']
>>> 'a,b,c'.split(",")
['a', "b", 'c']

So the first way was correct. In any case, this is clearly the superior, intuitive, syntax for splitting strings.

Of course, you have to pay for this with a performance hit, right? How much is it?

Let’s pick a fast operation, and put it in the middle of a list, and swap parameter order for no reason.

julia> @eval Base CBOOCall.@cbooify Int64 (+, /, length, xor=(x,y)->xor(y,x), floor, rand)

The usual way

julia> @btime sum(xor(x,y) for (x, y) in zip(1:100, 101:200))
  2.134 ns (0 allocations: 0 bytes)
16856

The way of CBOO

julia> @btime sum(x.xor(y) for (x, y) in zip(1:100, 101:200))
  2.134 ns (0 allocations: 0 bytes)
16856

Why does this work ? Someone made searching for a literal Symbol in a Tuple of Symbols very fast in order to make NamedTuples fast.

julia> @btime in(3, (1,2,3))
  1.442 ns (0 allocations: 0 bytes)
true

julia> @btime in(:a, (:b, :c, :a))
  0.020 ns (0 allocations: 0 bytes)
true

(The for-real README gives the real motivation, which is to avoid namespace pollution)

2 Likes

I think I get what the package does, just not the reasoning for the name CBOO[Call] and “@cbooify

which allows you to write the function call f(a::A, args…) as a.f(args…) as well. You can use it by adding a single line to your module. Using the alternative call syntax incurs no performance penalty.

This looks to me more like C++ [OO] syntax (I read it as CB - OO, still unclear why CB). Is it really better to abandon the usual multiple dispatch syntax? And why do you state:

For example, in building quantum computing circuits programmatically, people really want to write circ.x(1)

just not the reasoning for the name CBOO

Google this: cboo julia language

Is it really better to abandon the usual multiple dispatch syntax

I was 1000% certain that would be in the first reply to this post. I forgot to add some sort of redirection channel to the post: There are several posts and probably hundreds of comments on why it’s not a good idea (and maybe a few in favor) to do this. I invite anyone who is interested to find those threads and read them and perhaps add any new insights they have. But, I respectfully request that comments in this post refrain from pursuing this topic. It would be a distraction… I don’t know, if someone really feels like they have to save the uninitiated from perdition, then a comment here with a link to such a discussion might be reasonable.

And why do you state

That’s a good point. I could have been more thorough in the readme with a link to some of the many quantum-circuit building packages that do this. You could check out the software for building circuits from IBM, Google, AWS, Microsoft, etc.

EDIT: What I do think is on topic here is concrete proposals to solve the motivating problem given in the README in a different way. Other ideas have been suggested. For example, for the particular application linked there, we tried several. You can certainly argue over the merits of the different approaches.

EDITED EDIT: I think more context will help: I don’t know if @cbooify will work out for QuantumCircuits.jl in the end. But, I wanted a package with a very simple interface in order to quickly switch it on and off.

This is exactly what I want. Thanks!