Comments (5)
I tried to prototype a way to include that type information in the macro and was "partially successful". But there is a very odd issue about how the code emitted by the macro was evaluated that prevented it from being successful. I don't yet understand enough about how evaluation in Julia works to figure this out. Here's an MWE of the issue I encountered during prototyping:
using MacroTools
# crude version of aagent for prototype
macro make_type(name, fields)
param_tnames = map(name.args[2:end]) do x
if x isa Symbol
return x
else
return x.args[1]
end
end # like T,L
param_tnames_constraints = :({$(name.args[2:end]...)}) # like T<:Number,L<:Real
tname = :($(name.args[1]){$(param_tnames...)})
define_type(name, fields, __module__, quote
function $(tname)() where $(param_tnames_constraints)
m = new()
m
end
end)
end
# crude version of define_agent for prototype
function define_type(name, fields, __module, constructor)
fields = MacroTools.striplines(fields)
quote
let
name = $(QuoteNode(name))
additional_fields = $(QuoteNode(fields.args))
additional_fieldnames = [Meta.isexpr(f, :(::)) ? f.args[1] : f for f in $(QuoteNode(fields.args))]
expr = quote
mutable struct $name
$(additional_fields...)
$$(QuoteNode(constructor))
end
end
println("returned expr: ", expr)
Core.eval($(__module), expr)
end
end
end
Calling the above results in an error:
julia> @make_type MyAgent{T<:AbstractString} begin
myname::T
end
returned expr: begin
#= /Users/wusea/Desktop/misc/agentypes.jl:89 =#
mutable struct MyAgent{T <: AbstractString}
#= /Users/wusea/Desktop/misc/agentypes.jl:90 =#
myname::T
#= /Users/wusea/Desktop/misc/agentypes.jl:91 =#
begin
#= /Users/wusea/Desktop/misc/agentypes.jl:73 =#
function MyAgent{T}() where {T <: AbstractString}
#= /Users/wusea/Desktop/misc/agentypes.jl:73 =#
#= /Users/wusea/Desktop/misc/agentypes.jl:74 =#
m = new()
#= /Users/wusea/Desktop/misc/agentypes.jl:75 =#
m
end
end
end
end
ERROR: syntax: invalid variable expression in "where" around /Users/wusea/Desktop/misc/agentypes.jl:89
Stacktrace:
[1] top-level scope
@ none:1
Now, the very weird part is that if you just copy and paste the returned code into the REPL it works just fine:
julia> mutable struct MyAgent{T <: AbstractString}
#= /Users/wusea/Desktop/misc/agentypes.jl:90 =#
myname::T
#= /Users/wusea/Desktop/misc/agentypes.jl:91 =#
begin
#= /Users/wusea/Desktop/misc/agentypes.jl:73 =#
function MyAgent{T}() where {T <: AbstractString}
#= /Users/wusea/Desktop/misc/agentypes.jl:73 =#
#= /Users/wusea/Desktop/misc/agentypes.jl:74 =#
m = new()
#= /Users/wusea/Desktop/misc/agentypes.jl:75 =#
m
end
end
end
julia> alice = MyAgent{String}()
MyAgent{String}(#undef)
from algebraicagents.jl.
Got it! It seems to me that Julia applies some extra expression "normalisation" when you run the code from REPL; when you construct an expression manually and eval it, you need to be more careful.
In this case, the braces around parameter constraints are redundant. We need the following:
# in make_type
param_tnames_constraints = name.args[2:end] # like T<:Number,L<:Real`
# in define_type
function $(tname)() where $(param_tnames_constraints...)
from algebraicagents.jl.
I refined the support for parametric types in @aagent
.
from algebraicagents.jl.
Consider
@aagent struct MyAgent{T <: Real, P <: Real}
myname1::T
myname2::P
end
a = MyAgent{Float64, Int}("myagent", 1, 2)
@test a isa MyAgent{Float64, Int}
from algebraicagents.jl.
Cool! I think this issue can be closed.
from algebraicagents.jl.
Related Issues (15)
- Register HOT 81
- fix agent syncing
- Opera docs/tests HOT 1
- ci (tests, docs, tagbot) HOT 4
- change `_step!(agent, time)` to `_step!(agent)`
- TagBot trigger issue HOT 21
- fix `Opera` docs HOT 1
- redundant tutorials HOT 1
- how to use `ports_in`? HOT 2
- suggestion for `getobservable` HOT 2
- `@aagent` throws segfault during precompilation
- saving and loading agent hierarchies
- mutability of agent structs HOT 3
- undefined additional fields HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from algebraicagents.jl.