Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename @template to @template_spec #409

Merged
merged 2 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading