I created a simple test module ./mods/My/Module.pm6:
unit module My::Module;
use v6;
sub hello () is export {
say "Hello";
}
Then, I have a test script ./p.p6:
#! /usr/bin/env perl6
use v6;
use My::Module;
My::Module::hello();
Then I set PERL6LIB to include the folder ./mods, and then run the script:
$ ./p.p6
Could not find symbol '&hello'
in block <unit> at ./p.p6 line 7
However, if I replace the line My::Module::hello() in the script with hello() it works fine. What am I missing here?
If you export hello you can simply use it
use v6;
use lib <lib>; # hint: no need to tinker with the environment
use My::Module;
hello();
If you really WANT to use a fully qualified name, you have to use the our keyword.
our sub hello () is export {
say "Hello";
}
Related
I am trying to use multi in my Raku code that wraps a function in C.
Here I am calling lchoose function in shared libray Rmath.
This is my code which works:
use NativeCall;
constant RMATH = "./Rmath"; # shared library
sub lchoose(num64, num64) returns num64
is native( RMATH ) { * };
# The C function signature is
# double lchoose(double, double);
sub r_lchoose($n,$r) {
return lchoose($n.Num, $r.Num)
}
say r_lchoose(9,8) # 2.1972245773362196
But this does not work. The code keeps on running/hanging. Neither dies nor throws any output:
use NativeCall;
constant RMATH = "./Rmath"; # shared library
multi lchoose(num64, num64) returns num64
is native( RMATH ) { * };
multi lchoose($n,$r) {
lchoose($n.Num, $r.Num)
}
say lchoose(9,8) # Neither dies nor throws any output
My expectation is when I call lchoose(9,8) it should call second multi as the arguments are definitely not num64. If it had used second function, then it would have called the first function and given the output.
Or atleast I expected the program to throw error rather than hang.
OS information
Windows 11 64-bit
Raku information
Welcome to Rakudo™ v2022.04.0000.1.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.04-3-ga9fcd5a74.
A num64 in a signature indicate that it MUST have a num64 for a multi dispatch to work. Otherwise you could not set up candidates for a Num:D and have a candidate for num64 or num32.
And because there is no candidate for Num in your example, it will dispatch back to the original candidate, causing the infiniloop.
I would therefore write the "catch-all" lchoose candidate as:
multi lchoose(Num() $n, Num() $r) {
lchoose(my num64 $ = $n, my num64 $ = $r)
}
In the signature we convert everything to Num, and then we assign these to nameless native num64 variables in the call the other candidate (which will now dispatch correctly).
I need to export a label pointing to a function like
(func $can_sayhello (export "can sayhello") (type $t3)
The closest I can get is:
(export "can_sayhello" (func $assembly/index/can_sayhello))
using this AssemblyScript
#external("can sayhello")
export declare function can_sayhello(): void;
What I really want to do is change the label of this function
function sayhello() : void {
}
//output in wat
(export "sayhello" (func $assembly/index/sayhello))
to be
(export "can sayhello" (func $assembly/index/sayhello))
I'm new to assembly script and I really cant figure this out, if you have any questions let me know.
It's pretty unusual for any language to have function names with spaces, but it is possible!
I wrote a simple transformation pass that allows you have any string for named exports.
It is here https://github.com/willemneal/visitor-as/blob/master/src/examples/exportAs.ts
You need to add visitor-as as a dependency for your project then either in your asconfig.json or cli add the exportAs transformer.
e.g.
#exportAs("can sayhello")
export function main(): u32 {
return 42;
}
Then compile like
asc assembly/index.ts --transform visitor-as/dist/examples/exportAs
I can call the gist method on the say built-in function:
&say.gist
sub say (| is raw) { #`(Sub|54790064) ... }
Why can't I call gist on while?
&while.gist
===SORRY!=== Error while compiling <unknown file>
Undeclared routine:
while used at line 1
Obviously while isn't a "routine" but say is. But I thought that all of the built-ins in Perl 6 were really functions that we could redefine.
I thought that all of the built-ins in Perl 6 were really functions that we could redefine.
while is not a routine or macro, but part of the syntax, defined in Perl6's grammar.
If you wanted to redefine it, you would have to create your own slang, which currently involves black magic.
For some reason I have yet to figure out, it only works when done in a module (otherwise, %*LANG seems not to be defined).
Let's call the module froop.pm6:
use nqp;
sub EXPORT {
nqp::bindkey(%*LANG, 'MAIN', nqp::atkey(%*LANG, 'MAIN').^mixin(role {
rule statement_control:sym<while> {
[$<sym>=froop{
$/.hash<sym>.^mixin: role {
method Str { 'while' }
}
}|$<sym>=until]<.kok> {}
<xblock>
}
}));
once Map.new
}
This replaces the while keyword (in statement position) with froop, eg
use froop;
my $i = 0;
froop $i < 5 { say $i++ }
I have two modules in separate files within the same crate, where the crate has macro_rules enabled. I want to use the macros defined in one module in another module.
// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)
// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
I currently hit the compiler error "macro undefined: 'my_macro'"... which makes sense; the macro system runs before the module system. How do I work around that?
Macros within the same crate
New method (since Rust 1.32, 2019-01-17)
foo::bar!(); // works
mod foo {
macro_rules! bar {
() => ()
}
pub(crate) use bar; // <-- the trick
}
foo::bar!(); // works
With the pub use, the macro can be used and imported like any other item. And unlike the older method, this does not rely on source code order, so you can use the macro before (source code order) it has been defined.
Old method
bar!(); // Does not work! Relies on source code order!
#[macro_use]
mod foo {
macro_rules! bar {
() => ()
}
}
bar!(); // works
If you want to use the macro in the same crate, the module your macro is defined in needs the attribute #[macro_use]. Note that macros can only be used after they have been defined!
Macros across crates
Crate util
#[macro_export]
macro_rules! foo {
() => ()
}
Crate user
use util::foo;
foo!();
Note that with this method, macros always live at the top-level of a crate! So even if foo would be inside a mod bar {}, the user crate would still have to write use util::foo; and not use util::bar::foo;. By using pub use, you can export a macro from a module of your crate (in addition to it being exported at the root).
Before Rust 2018, you had to import macro from other crates by adding the attribute #[macro_use] to the extern crate util; statement. That would import all macros from util. This syntax should not be necessary anymore.
Alternative approach as of 1.32.0 (2018 edition)
Note that while the instructions from #lukas-kalbertodt are still up to date and work well, the idea of having to remember special namespacing rules for macros can be annoying for some people.
EDIT: it turns out their answer has been updated to include my suggestion, with no credit mention whatsoever 😕
On the 2018 edition and onwards, since the version 1.32.0 of Rust, there is another approach which works as well, and which has the benefit, imho, of making it easier to teach (e.g., it renders #[macro_use] obsolete). The key idea is the following:
A re-exported macro behaves as any other item (function, type, constant, etc.): it is namespaced within the module where the re-export occurs.
It can then be referred to with a fully qualified path.
It can also be locally used / brought into scope so as to refer to it in an unqualified fashion.
Example
macro_rules! macro_name { ... }
pub(crate) use macro_name; // Now classic paths Just Work™
And that's it. Quite simple, huh?
Feel free to keep reading, but only if you are not scared of information overload ;) I'll try to detail why, how and when exactly does this work.
More detailed explanation
In order to re-export (pub(...) use ...) a macro, we need to refer to it! That's where the rules from the original answer are useful: a macro can always be named within the very module where the macro definition occurs, but only after that definition.
macro_rules! my_macro { ... }
my_macro!(...); // OK
// Not OK
my_macro!(...); /* Error, no `my_macro` in scope! */
macro_rules! my_macro { ... }
Based on that, we can re-export a macro after the definition; the re-exported name, then, in and of itself, is location agnostic, as all the other global items in Rust 🙂
In the same fashion that we can do:
struct Foo {}
fn main() {
let _: Foo;
}
We can also do:
fn main() {
let _: A;
}
struct Foo {}
use Foo as A;
The same applies to other items, such as functions, but also to macros!
fn main() {
a!();
}
macro_rules! foo { ... } // foo is only nameable *from now on*
use foo as a; // but `a` is now visible all around the module scope!
And it turns out that we can write use foo as foo;, or the common use foo; shorthand, and it still works.
The only question remaining is: pub(crate) or pub?
For #[macro_export]-ed macros, you can use whatever privacy you want; usually pub.
For the other macro_rules! macros, you cannot go above pub(crate).
Detailed examples
For a non-#[macro_export]ed macro
mod foo {
use super::example::my_macro;
my_macro!(...); // OK
}
mod example {
macro_rules! my_macro { ... }
pub(crate) use my_macro;
}
example::my_macro!(...); // OK
For a #[macro_export]-ed macro
Applying #[macro_export] on a macro definition makes it visible after the very module where it is defined (so as to be consistent with the behavior of non-#[macro_export]ed macros), but it also puts the macro at the root of the crate (where the macro is defined), in an absolute path fashion.
This means that a pub use macro_name; right after the macro definition, or a pub use crate::macro_name; in any module of that crate will work.
Note: in order for the re-export not to collide with the "exported at the root of the crate" mechanic, it cannot be done at the root of the crate itself.
pub mod example {
#[macro_export] // macro nameable at `crate::my_macro`
macro_rules! my_macro { ... }
pub use my_macro; // macro nameable at `crate::example::my_macro`
}
pub mod foo {
pub use crate::my_macro; // macro nameable at `crate::foo::my_macro`
}
When using the pub / pub(crate) use macro_name;, be aware that given how namespaces work in Rust, you may also be re-exporting constants / functions or types / modules. This also causes problems with globally available macros such as #[test], #[allow(...)], #[warn(...)], etc.
In order to solve these issues, remember you can rename an item when re-exporting it:
macro_rules! __test__ { ... }
pub(crate) use __test__ as test; // OK
macro_rules! __warn__ { ... }
pub(crate) use __warn__ as warn; // OK
Also, some false positive lints may fire:
from the trigger-happy clippy tool, when this trick is done in any fashion;
from rustc itself, when this is done on a macro_rules! definition that happens inside a function's body: https://github.com/rust-lang/rust/issues/78894
This answer is outdated as of Rust 1.1.0-stable.
You need to add #![macro_escape] at the top of macros.rs and include it using mod macros; as mentioned in the Macros Guide.
$ cat macros.rs
#![macro_escape]
#[macro_export]
macro_rules! my_macro {
() => { println!("hi"); }
}
$ cat something.rs
#![feature(macro_rules)]
mod macros;
fn main() {
my_macro!();
}
$ rustc something.rs
$ ./something
hi
For future reference,
$ rustc -v
rustc 0.13.0-dev (2790505c1 2014-11-03 14:17:26 +0000)
Adding #![macro_use] to the top of your file containing macros will cause all macros to be pulled into main.rs.
For example, let's assume this file is called node.rs:
#![macro_use]
macro_rules! test {
() => { println!("Nuts"); }
}
macro_rules! best {
() => { println!("Run"); }
}
pub fn fun_times() {
println!("Is it really?");
}
Your main.rs would look sometime like the following:
mod node; //We're using node.rs
mod toad; //Also using toad.rs
fn main() {
test!();
best!();
toad::a_thing();
}
Finally let's say you have a file called toad.rs that also requires these macros:
use node; //Notice this is 'use' not 'mod'
pub fn a_thing() {
test!();
node::fun_times();
}
Notice that once files are pulled into main.rs with mod, the rest of your files have access to them through the use keyword.
I have came across the same problem in Rust 1.44.1, and this solution works for later versions (known working for Rust 1.7).
Say you have a new project as:
src/
main.rs
memory.rs
chunk.rs
In main.rs, you need to annotate that you are importing macros from the source, otherwise, it will not do for you.
#[macro_use]
mod memory;
mod chunk;
fn main() {
println!("Hello, world!");
}
So in memory.rs you can define the macros, and you don't need annotations:
macro_rules! grow_capacity {
( $x:expr ) => {
{
if $x < 8 { 8 } else { $x * 2 }
}
};
}
Finally you can use it in chunk.rs, and you don't need to include the macro here, because it's done in main.rs:
grow_capacity!(8);
The upvoted answer caused confusion for me, with this doc by example, it would be helpful too.
Note: This solution does work, but do note as #ineiti highlighted in the comments, the order u declare the mods in the main.rs/lib.rs matters, all mods declared after the macros mod declaration try to invoke the macro will fail.
Is there a way to get the command line arguments in go "tests",
When you call go test obviously your main is not run, so is there a way to process command line arguments,
One way would be to use the flags packages and check for the command line arguments in each test or function being tested, but that is not ideal for that you need to do this in lots and lots of places, unlike the way you to it just in main when you run the application.
One may think it is a wrong thing to do, and that it is against purity of unit-tests:
not all tests are unit tests
it is very functional not to rely on "ENV" variables and actually pass the stuff as arguments in command line,
For the record I ended up putting an init() function in one of my _test files, and set the variable that is set through flags when the main is called this way.
Environmental configs are best kept in environment variables, in my experience. You can rely on global variables like so:
var envSetting = os.Getenv("TEST_ENV")
Alternatively, if using flags is a requirement, you could place your initialization code inside a function called init().
func init() {
flags.Parse()
myEnv = *envFlag
// ...
}
An alternative approach is to make main() be a stub that merely calls into another function after arguments are processed by flag.Parse(), for example:
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help for flagname")
}
func main() {
flag.Parse()
submain(flag.Args)
}
func submain(args []string) {
...
}
Then in your tests, flag variables can be set and arguments established before calling submain(...) simulating the command line establishment of flags and arguments. This approach can be used to maximize test coverage without actually using a command line. For example, in main_test.go, you might write:
func TestSomething(t *testing.T) {
flagvar = 23
args := []string{"a", "b", "c"}
submain(args)
...
}
You can directly test main function and pass arguments.
Simple example showing a flag, and a pair of positional arguments
Note: Do NOT call it 'TestMain' that has a special meaning to the testing framework as of Go 1.8.
package main
import (
"os"
"testing"
)
func TestMainFunc(t *testing.T) {
os.Args = append(os.Args, "--addr=http://b.com:566/something.avsc")
os.Args = append(os.Args, "Get")
os.Args = append(os.Args, `./some/resource/fred`)
main()
// Test results here, and decide pass/fail.
}
os.Args[1] = "-conf=my.conf"
flag.Parse()
Notice that the config file name is hard-coded.