[1.0.0] Set cannot be called as inner value of Data Structures (macro edn!)
naomijub opened this issue · 4 comments
The macro edn!
fails when we try to call a Set
inside any other structure.
edn!([ 1 2 3 #{4 5 6}])
Gets an error of expected
[, found end of macro arguments
. Same is valid for set in set, #{ 1 2 3 #{4 5 6}}
.
What is the use case for the edn!
macro? I wasn't really thinking about it until looking closely at the README. In several places it is called "parse", but it's not really parsing; it is compile-time generation of Edn objects. Pretty neat to quickly hard-code some EDN. I'm guessing this was a common thing for the original use case of this crate? It's right on the top of the README.
Doing it like this has a lot of limitations, like this issue. This seems like an almost impossible (or at least an endless) task or it quickly reinventing all of proc_macro
, syn
, quote
, and edn-rs
.
I finally got around to learning about proc_macros this weekend. I made a proof of concept. This is not done yet. I wanted opinions before going through and doing the rest, testing it, etc. This needs to be a separate crate because it's a proc-macro
lib. This macro will handle any valid EDN, because it uses this crate's parse, at compile time.
You can see the minimal example, with this issue's original EDN here
https://github.com/Grinkers/constexpr_edn/blob/main/examples/example.rs
Eventually rust's const will be as powerful as c++'s constexpr, which should actually allow this crate's parse
to also be const. That would make this macro and my proof of concept crate no longer needed.
@naomijub Any thoughts on just removing the macro entirely from this crate and having a macro crate until parse can be const?
I made it match the current usage a bit more. I also managed to make it dependency-free. If we go this route, I'll go for 100% coverage and move over all existing tests. It seems to work with all the insanity you would expect from valid EDN
https://github.com/Grinkers/constexpr_edn/blob/main/examples/example.rs#L18
A side note, doing it this way actually gives some nice compiler warnings. For example, using my "parse" branch
let edn = edn!([42, "foobar" yaycats 42r1001]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: message: called `Result::unwrap()` on an `Err` value: EdnError { code: InvalidRadix(Some(42)), line: Some(1), column: Some(23), ptr: Some(22) }
Depending on what we do with #148 we can actually capture with a proc_macro
https://github.com/Grinkers/constexpr_edn/blob/ba130aaaca55fb4df19b4826b6782c763ad713c3/examples/example.rs#L28-L31
so it should be possible to do something like
let num = some_calc();
return edn!({:ok "ok" :num #capt num});
or maybe there's some other symbols we can use, like
edn!({:ok "ok" :num %num%})
. brackets is already used in edn, so whatever it ends up being, it won't be rust-like.
NO FURTHER DEVELOPMENT PLANNED