How to prefix/suffix identifiers within a macro? [duplicate] - macros

This question already has answers here:
Is it possible to declare variables procedurally using Rust macros?
(4 answers)
Closed 5 years ago.
When using a macro that defines a function, is it possible to add a prefix to the function?
macro_rules! my_test {
($id:ident, $arg:expr) => {
#[test]
fn $id() {
my_test_impl(stringify!($id), $arg);
}
}
}
For example, fn my_test_$id() {
I'm defining tests using an identifier which may begin with numbers, and I would like to use a common prefix.

Currently this is not supported in stable.
However there is a feature in nightly called concat_idents:
concat_idents!(my_test_, $id)
See
Rust docs
Issue
Update: it seems there aren't near-term plans to add this into stable releases, see issue.

[...] is it possible to add a prefix to the function?
No. Really, really no. Super totally not at all even in the slightest.
I would like to have use a common prefix.
Put them all in a mod instead.

As mentioned, you should use submodules for this, but remember that macros can create submodules, submodules can be nested allowing their names to overlap, submodules can provide impls, and the tests submodule is not magic.
I once submitted a pull request that avoids numerous "boiler plate names" by refactoring the code using these tricks, although the #[no_mangle] exports make it harder.

Related

Dart - How to access global scope? [duplicate]

This question already has answers here:
How can I call a function from a method of the same name?
(3 answers)
Closed 12 months ago.
The simple actual question is
How to access GLOBAL scope in Dart?
Below is just the answer why I'm looking for it.
I have a problem which requires me to learn about Dart's scope resolution from here but unfortunately I can't find the solution for my problem, not even from Google or here, which was surprising me to have to open this question.
Dart allows user to exclude the this. on member variable access within class's scope so if two potentially conflicted variables need to share the same name, they need to be differentiated with scope operator and reference.
I need to define a class with member variable print where there is also global function print being called somewhere within the class. Of course print() => print(...) will returns error so I'm expecting something as simple as print() => global.print(..) but neither that is working.
I know there's workaround to solve it but please I need a straightforward one if any. Thank you.
you could add this line at the top of your file:
import 'dart:core' as core;
Then you would be able to refer to print as core.print(...);
The problem is that now you would have to use core. for every primitives like int, example:
core.int variable = 1;
I think this is not worth it and it's better to use another name for your print method.

Is it possible to distribute the code of a class to several files?

Is it possible to distribute the code of a class to several files?
Honestly, I think the best route is to break it up into different roles that you compose into your class.
After all, how are you planning on breaking up your class?
Are you going to group methods and attributes according to similarity?
At that point you've just about come up with a role, so you might as well make it a role.
If you look at the source for Rakudo you see things like this:
class Perl6::Metamodel::ClassHOW
does Perl6::Metamodel::Naming
does Perl6::Metamodel::Documenting
does Perl6::Metamodel::LanguageRevision
does Perl6::Metamodel::Stashing
does Perl6::Metamodel::AttributeContainer
does Perl6::Metamodel::MethodContainer
does Perl6::Metamodel::PrivateMethodContainer
does Perl6::Metamodel::MultiMethodContainer
does Perl6::Metamodel::MetaMethodContainer
does Perl6::Metamodel::RoleContainer
does Perl6::Metamodel::MultipleInheritance
does Perl6::Metamodel::DefaultParent
does Perl6::Metamodel::C3MRO
does Perl6::Metamodel::MROBasedMethodDispatch
does Perl6::Metamodel::MROBasedTypeChecking
does Perl6::Metamodel::Trusting
does Perl6::Metamodel::BUILDPLAN
does Perl6::Metamodel::Mixins
does Perl6::Metamodel::ArrayType
does Perl6::Metamodel::BoolificationProtocol
does Perl6::Metamodel::REPRComposeProtocol
does Perl6::Metamodel::InvocationProtocol
does Perl6::Metamodel::ContainerSpecProtocol
does Perl6::Metamodel::Finalization
does Perl6::Metamodel::Concretization
does Perl6::Metamodel::ConcretizationCache
{
… # only 300 lines of code
}
If you do a good job of splitting up your roles, you should be able to use them in many classes.
How many classes in the Rakudo code base do you think compose in the Perl6::Metamodel::Naming role?
That role only provides a few things, and is only 45 lines long.
Here is an abbreviated version.
(All of the code in the methods has been deleted here for brevity.)
role Perl6::Metamodel::Naming {
has $!name;
has $!shortname;
method name($obj) {
…
}
method set_name($obj, $name) {
…
}
method shortname($obj) {
…
}
method set_shortname($obj, $shortname) {
…
}
}
Yes, there always is. But there us no standard supported way (yet anyway).
You can take the approach that Raku takes itself when creating the core settings: concatenate the files into a single file, and compile that. When you're building Rakudo from scratch, that's what's happening when you see the line:
+++ Generating gen/moar/foo
The generated files can be inspected in the gen/moar directory. At one point, I brought this up in a problem solving issue, but that never went anywhere. Perhaps that should be revisited.
You can use augment class. But that currently only makes sense inside a single file, because with multiple files it is creating multiple versions of the same "module" in pre-compilation. And the system is not able to determine what to resolve to what. This is when you realize that pre-compilation of Raku modules currently is creating libraries that need to be statically linkable at runtime.

Using $crate in Rust's procedural macros?

I know what the $crate variable is, but as far as I can tell, it can't be used inside procedural macros. Is there another way to achieve a similar effect?
I have an example that roughly requires me to write something like this using quote and nightly Rust
quote!(
struct Foo {
bar: [SomeTrait;#len]
}
)
I need to make sure SomeTrait is in scope (#len is referencing an integer outside the scope of the snippet).
I am using procedural macros 2.0 on nightly using quote and syn because proc-macro-hack didn't work for me. This is the example I'm trying to generalize.
Since Rust 1.34, you can use extern crate self as my_crate, and use my_crate::Foo instead of $crate::Foo.
https://github.com/rust-lang/rust/issues/54647
https://github.com/rust-lang/rust/pull/57407
(Credit: Neptunepink ##rust irc.freenode.net)
Based on replies from https://github.com/rust-lang/rust/issues/38356#issuecomment-412920528, it looks like there is no way to do this (as of 2018-08), neither to refer to the proc-macro crate nor to refer to any other crate unambiguously.
In Edition 2015 (classic Rust), you can do this (but it's hacky):
use ::defining_crate::SomeTrait in the macro
within third-party crates depending on defining_crate, the above works fine
within defining_crate itself, add a module in the root:
mod defining_crate { pub use super::*; }
In Edition 2018 even more hacky solutions are required (see this issue), though #55275 may give us a simple workaround.
You can wrap your proc-macro inside a declarative macro, and pass the $crate identifier to your proc-macro for reuse (see this commit for example). It will create a proc_macro::Ident value with the special $crate identifier.
Note that you cannot manually create such an identifier, since $ is normally invalid inside identifiers.

Sinatra coffeescript --bare?

I've done some searching on this, but I cannot find info. I'm building an application inside sinatra, and using the coffeescript templating engine. By default the compiled code is wrapped as such:
(function() {
// code
}).call(this);
I'd like to remove that using the --bare flag, so different files can access classes and so forth that I'm defining. I realize that having it more contained helps against variable conflicts and so forth, but I'm working on two main pieces here. One is the business logic, and arrangement of data in class structures. The other is the view functionality using raphaeljs. I would prefer to keep these two pieces in separate files. Since the two files wrapped as such cannot access the data, it obviously won't work. However, if you can think of a better solution than using the --bare option, I'm all ears.
Bare compilation is simply a bad practice. Each file should export to the global scope only the public objects that matter to the rest of your app.
# foo.coffee
class Foo
constructor: (#abc) ->
privateVar = 123
window.Foo = Foo # export
Foo is now globally available. Now if that pattern isn't practical, maybe you should rethink your structure a bit. If you have to export too may things, you nest and namespace things better, so that more data can be exposed through fewer global variables.
I support Alex's answer, but if you absolutely must do this, I believe my answer to the same question for Rails 3.1 is applicable here as well: Put the line
Tilt::CoffeeScriptTemplate.default_bare = true
somewhere in your application.

Using lstlisting environment withing macros?

I tried to define a macro, for me to quickly create a listing environment. The definition looked like that:
% \def \lstlistingcode[#1] { \begin{lstlisting}#1\end{lstlisting} }
which ends in an Error:
job aborted, no legal \end found
Is it possible to use environments within macros, and if yes - how?
Some environments can, e.g. alltt; however, lstlisting can't, because of how it is written (it apparently has to do with various catcode stuff that it does).
Using \def as you do is sort of outdated; \newcommand is preferred:
\newcommand \allttcode[1] { \begin{alltt}#1\end{alltt} }
...
\allttcode{test}