Skip to content

Commit

Permalink
Merge pull request #409 from MilesCranmer/rename-template-macro
Browse files Browse the repository at this point in the history
Rename `@template` to `@template_spec`
  • Loading branch information
MilesCranmer authored Feb 8, 2025
2 parents 6890e1d + 8eeb51f commit ffe5a31
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 41 deletions.
4 changes: 2 additions & 2 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ using MLJBase: machine, fit!, report
The key part is defining our template structure. This determines how different parts of the expression combine:

```julia
expression_spec = @template(expressions=(f, g)) do x1, x2, x3
expression_spec = @template_spec(expressions=(f, g)) do x1, x2, x3
f(x1, x2) + g(x2) - g(x3)
end
```
Expand Down Expand Up @@ -432,7 +432,7 @@ Now, define the template for the derivative operator:
```julia
using SymbolicRegression: D

expression_spec = @template(expressions=(f,)) do x
expression_spec = @template_spec(expressions=(f,)) do x
D(f, 1)(x)
end
```
Expand Down
4 changes: 2 additions & 2 deletions docs/src/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ TemplateStructure
TemplateExpressionSpec
```

You can use the `@template` macro as an easy way to create a `TemplateExpressionSpec`:
You can use the `@template_spec` macro as an easy way to create a `TemplateExpressionSpec`:

```@docs
@template
@template_spec
```

Composable expressions are used internally by `TemplateExpression` and allow you to combine multiple expressions together.
Expand Down
2 changes: 1 addition & 1 deletion examples/template_expression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ using Random: rand
using MLJBase: machine, fit!, report, predict
using Test: @test

expression_spec = @template(expressions = (f, g1, g2)) do x1, x2, x3
expression_spec = @template_spec(expressions = (f, g1, g2)) do x1, x2, x3
_f = f(x1, x2)
_g1 = g1(x3)
_g2 = g2(x3)
Expand Down
2 changes: 1 addition & 1 deletion examples/template_expression_complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ subexpression symbols we wish to learn:
structure = TemplateStructure{(:B_x, :B_y, :B_z, :F_d_scale)}(compute_force)

#=
Note that we could have also used the `@template` macro which is
Note that we could have also used the `@template_spec` macro which is
more convenient.
First, let's look at an example of how this would be used
Expand Down
4 changes: 2 additions & 2 deletions src/SymbolicRegression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export Population,
TemplateExpression,
TemplateStructure,
TemplateExpressionSpec,
@template,
@template_spec,
ValidVector,
ComposableExpression,
NodeSampler,
Expand Down Expand Up @@ -339,7 +339,7 @@ using .TemplateExpressionModule: ValidVector
using .ComposableExpressionModule: ComposableExpression
using .ExpressionBuilderModule: embed_metadata, strip_metadata
using .ParametricExpressionModule: ParametricExpressionSpec
using .TemplateExpressionMacroModule: @template
using .TemplateExpressionMacroModule: @template_spec

@stable default_mode = "disable" begin
include("deprecates.jl")
Expand Down
8 changes: 4 additions & 4 deletions src/TemplateExpressionMacro.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module TemplateExpressionMacroModule

"""
@template(
@template_spec(
parameters=(p1=10, p2=10, p3=1),
expressions=(f, g),
) do x1, x2, class
Expand All @@ -12,11 +12,11 @@ module TemplateExpressionMacroModule
The parameters are used to define constants that can be indexed, and the
expressions define the function keys for the template structure.
"""
macro template(f, args...)
return esc(template(f, args...))
macro template_spec(f, args...)
return esc(template_spec(f, args...))
end

function template(func, args...)
function template_spec(func, args...)
# Extract the parameters and expressions from the arguments
parameters = nothing
expressions = nothing
Expand Down
4 changes: 2 additions & 2 deletions test/test_parametric_template_expressions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,12 @@ end
#=
## Defining the Template
Now we'll use the `@template` macro to encode this structure, which will create
Now we'll use the `@template_spec` macro to encode this structure, which will create
a `TemplateExpressionSpec` object.
=#

## Define the template structure with sub-expressions f and g
template = @template(
template = @template_spec(
expressions=(f, g),
parameters=(p1=2, p2=2)
) do x1, x2, class
Expand Down
2 changes: 1 addition & 1 deletion test/test_template_expression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ end
@test eval_loss(ex, d, options; idx=idx) < 1e-10

# Test with template expressions
template = @template(expressions = (f,), parameters = (p=2,)) do x
template = @template_spec(expressions = (f,), parameters = (p=2,)) do x
f(x) + sum(p)
end

Expand Down
54 changes: 28 additions & 26 deletions test/test_template_macro.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
@testitem "Basic @template macro functionality" tags = [:part1, :template_macro] begin
@testitem "Basic @template_spec macro functionality" tags = [:part1, :template_macro] begin
using SymbolicRegression
using DynamicExpressions: OperatorEnum, Node

# Test basic parameter/expression handling
expr_spec =
@template(parameters = (p1=10, p2=10, p3=1), expressions = (f, g)) do x1, x2, class
return p1[class] * x1^2 + f(x1, x2, p2[class]) - g(p3[1] * x1)
end
expr_spec = @template_spec(
parameters = (p1=10, p2=10, p3=1), expressions = (f, g)
) do x1, x2, class
return p1[class] * x1^2 + f(x1, x2, p2[class]) - g(p3[1] * x1)
end

# Verify spec structure
@test expr_spec.structure isa TemplateStructure{(:f, :g),(:p1, :p2, :p3)}
Expand Down Expand Up @@ -37,52 +38,52 @@ end

@testitem "Template macro error handling" tags = [:part1, :template_macro] begin
using SymbolicRegression
using SymbolicRegression.TemplateExpressionMacroModule: template
using SymbolicRegression.TemplateExpressionMacroModule: template_spec

# Test missing expressions
@test_throws(
ArgumentError("expressions must be specified"),
template(:((x,) -> f(x)), :(parameters = (p1=1,)))
template_spec(:((x,) -> f(x)), :(parameters = (p1=1,)))
)

# Test invalid parameters format
@test_throws(
"parameters must be a tuple of parameter name-size pairs like `(p1=10, p2=10, p3=1)`",
template(:((x,) -> f(x)), :(parameters = 1), :(expressions = (f,)))
template_spec(:((x,) -> f(x)), :(parameters = 1), :(expressions = (f,)))
)

@test_throws(
"parameters must be a tuple of parameter name-size pairs like `(p1=10, p2=10, p3=1)`",
template(:((x,) -> f(x)), :(parameters = (1, 2)), :(expressions = (f,)))
template_spec(:((x,) -> f(x)), :(parameters = (1, 2)), :(expressions = (f,)))
)

# Test invalid expressions format
@test_throws(
"expressions must be a tuple of the form `(f, g, ...)`",
template(:((x,) -> f(x)), :(parameters = (p1=1,)), :(expressions = f))
template_spec(:((x,) -> f(x)), :(parameters = (p1=1,)), :(expressions = f))
)

# Test invalid function format
@test_throws(
ArgumentError("Expected a do block"),
template(:(f(x)), :(parameters = (p1=1,)), :(expressions = (f,)))
template_spec(:(f(x)), :(parameters = (p1=1,)), :(expressions = (f,)))
)

@test_throws(
ArgumentError("Expected a tuple of arguments for the function arguments"),
template(:(x -> f(x)), :(parameters = (p1=1,)), :(expressions = (f,)))
template_spec(:(x -> f(x)), :(parameters = (p1=1,)), :(expressions = (f,)))
)

# Test missing expressions (but having parameters)
@test_throws(
ArgumentError("expressions must be specified"),
template(:((x,) -> f(x)), :(parameters = (p1=1,)))
template_spec(:((x,) -> f(x)), :(parameters = (p1=1,)))
)

# Test invalid expressions format without parameters
@test_throws(
"expressions must be a tuple of the form `(f, g, ...)`",
template(:((x,) -> f(x)), :(expressions = f))
template_spec(:((x,) -> f(x)), :(expressions = f))
)
end

Expand All @@ -92,12 +93,13 @@ end
using Test

# Multi-output template with parameter reuse
template =
@template(parameters = (coeff=5,), expressions = (base, modifier)) do x, y, class
base_val = base(x, coeff[class])
modified = modifier(y, coeff[class])
return coeff[class] * x * base_val + modified
end
template = @template_spec(
parameters = (coeff=5,), expressions = (base, modifier)
) do x, y, class
base_val = base(x, coeff[class])
modified = modifier(y, coeff[class])
return coeff[class] * x * base_val + modified
end

# Verify structure
@test template.structure isa TemplateStructure{(:base, :modifier),(:coeff,)}
Expand Down Expand Up @@ -126,7 +128,7 @@ end
using DynamicExpressions: OperatorEnum, Node

# Test template without parameters
expr_spec = @template(expressions = (f, g)) do x1, x2
expr_spec = @template_spec(expressions = (f, g)) do x1, x2
return x1^2 + f(x1, x2) - g(x1)
end

Expand Down Expand Up @@ -155,12 +157,12 @@ end

@testitem "Template macro additional error handling" tags = [:part1, :template_macro] begin
using SymbolicRegression
using SymbolicRegression.TemplateExpressionMacroModule: template
using SymbolicRegression.TemplateExpressionMacroModule: template_spec

# Test setting parameters keyword twice
@test_throws(
"cannot set `parameters` keyword twice",
template(
template_spec(
:((x,) -> f(x)),
:(parameters = (p1=1,)),
:(parameters = (p2=1,)),
Expand All @@ -171,18 +173,18 @@ end
# Test setting expressions keyword twice
@test_throws(
"cannot set `expressions` keyword twice",
template(:((x,) -> f(x)), :(expressions = (f,)), :(expressions = (g,)))
template_spec(:((x,) -> f(x)), :(expressions = (f,)), :(expressions = (g,)))
)

# Test unrecognized keyword
@test_throws(
"unrecognized keyword invalid_keyword",
template(:((x,) -> f(x)), :(invalid_keyword = 1), :(expressions = (f,)))
template_spec(:((x,) -> f(x)), :(invalid_keyword = 1), :(expressions = (f,)))
)

# Test positional args after first
@test_throws(
"no positional args accepted after the first",
template(:((x,) -> f(x)), :(expressions = (f,)), :extra_arg)
template_spec(:((x,) -> f(x)), :(expressions = (f,)), :extra_arg)
)
end

0 comments on commit ffe5a31

Please sign in to comment.