Micah Smith
Micah Smith

Reputation: 4471

Combining string and expression interpolation

I'm having trouble combining expression and string interpolation. I want to do something like this:

a = [:foo, :bar]
b = [:printfoo, :printbar]

for (str, fn) in zip(a,b)
  @eval begin
    """ 
    ```
    $fn()
    ```
    Prints $str.
    """
    $fn() = println("$str")
  end 
end

My desired output are two functions, one which might look, as typed, like

"""    
```
printfoo()
```
Prints foo.
"""
printfoo() = println("foo")

Instead, I get expressions that look like this (when I use quote rather than @eval begin):

```\n$(fn)()\n```\nPrints $(str).\n" # /home/..., line 12:
    printfoo() = begin  # /home/..., line 12:
            println("$(str)")
        end

I don't understand why using the same $x syntax, interpolation is performed as I want only outside of quoted ("...") regions. I've tried some combinations of $($x) etc. but am missing some of the subtleties:

What would map to "foo"?

Thanks.

Upvotes: 2

Views: 172

Answers (1)

Dan Getz
Dan Getz

Reputation: 18217

The answer seems to be $(string(str)).

The following version worked for me, but it took some tweaking to arrive at:

a = [:foo, :bar]
b = [:printfoo, :printbar]
for (str, fn) in zip(a,b)
  @eval begin
    $fn() = println($(string(str)))
    @doc $("```\n$fn()\n```\nPrints $str.\n") $fn
  end
end

One problem with the OP code was when the function bodies interpolated the variable during execution - this would cause printfoo to annoyingly print bar.

Upvotes: 5

Related Questions