Modify string interpolation

Is it possible to modify string interpolation using type-specific rules restricted to a specific context?

"""SELECT * WHERE {
?s <$(ns.aa.__str__())> ?o)
}
"""

outputs
"SELECT * WHERE {\n?s <http://example.org/aa> ?o)\n}\n"

but it would be more fun if I could only write something like

sparql""“SELECT * WHERE {
?s $(ns.aa) ?o)
}
“””

Any thoughts on how to achieve this?

complete example below:

using PyCall

begin
	rdflib = pyimport_conda("rdflib","rdflib")
end;

begin
struct NameSpace
		_ns
		NameSpace(s::String) = new(pycall(rdflib.Namespace, PyObject, s))
end
	Base.getproperty(thens::NameSpace, s::Symbol) = 
		pycall(rdflib.Namespace.term, PyObject, getfield(thens, :_ns), string(s))
end

ns = NameSpace("http://example.org/")

s = """SELECT * WHERE {
?s <$(ns.aa.__str__())> ?o)
}
"""

println(s)

Julia will use the show mechanism to determine the string representation of your inserted variable during interpolation. So it is possible to define how certain types will be interpolated in your string. However i don’t no pycall therfore i don’t know about the type of ns.aa. You should own the type in order to define new show methods on it, otherwise this would be considered type piracy.

Here is a small example how to do this for your own types

julia> struct Foo
           x
       end
julia> f = Foo(4)
julia> Base.show(io::IO, f::Foo) = print(io, "This is my custom representation of $(f.x) wrapped in Foo")
julia> "longer string with interpolated $f"
"longer string with interpolated This is my custom representation of 4 wrapped in Foo"

PS: You can also define non-standard string literals such as sparql"..." where you can parse and modify the string however you want but I guess hooking into the show mechanism is the simpler solution…

2 Likes

I’m not sure where the sparql macro comes from, but my guess is that it doesn’t allow string interpolation, which seems to be what you want. This can be incorporated, but it requires some effort, as it isn’t the default behaviour. The code in HypertextLiteral might show you how.

Yes. Two options:

  1. Write a custom string macro foo"...". Then you can interpret $ any way you want. For example, PyCall does this for py"..." (defined here) to make $x interpolate a value as a Python object rather than as a string.
  2. Wrap a value in your own type, and define a custom show(io, x) method, since string interpolation uses show to convert values to strings.
1 Like

There is no sparql macro yet, I was contemplating writing one. I am learning rdflib (python library) and Julia at the same time.