Again on the tail of this question, I'm trying to make a will trait work, with this (golfed) code:
sub show-value( $a-var ) {
say "Value of {$a-var.^name} is ", $a-var.gist;
}
sub do-stuff () {
ENTER { say "Going in"; }
our $bar will enter { show-value($_) };
$bar = "baz";
LEAVE { say "Leaving"; }
}
do-stuff();
This simply prints "Going in". It (doesn't) work(s) in the same way if you do it on the global scope. Please note that this is an almost direct implementation of the documentation example.
You haven't noted your Rakudo version. It sounds like a bug introduced this year.
Running the same code using glot.io:
v2021.02.1
Going in
Value of Any is (Any)
Leaving
On 2021.07 I get:
Going in
Value of Any is (Any)
Leaving
A clearer example might be:
my $bar will enter { $_ = 42 }
say "bar = $bar"; # bar = 42
I am trying to implement a trigger on write access to a perl6 Class attribute. I cannot figure out the cause of the error...
... I got this notion from How does one write custom accessor methods in Perl6?
1 #!/usr/bin/env perl6
2
3 class MeasureSP {
4
5 has Real $!value;
6 has Str $.units;
7
8 submethod BUILD( :$!value, :$!units ) {}
9
10 method value( Real $newval? ) is rw {
11 return Proxy.new:
12 FETCH => sub ($) { $!value },
13 STORE => sub ($, $newval) { $!value = $newval },
14 }
15
16 }
17 my MeasureSP $m-sp = MeasureSP.new( value => 23, units => 'metres' );
18 say $m-sp.units; #metres
19 say $m-sp.value; #23
20 $m-sp.value = 1;
21 # Cannot assign to a readonly variable or a value
22 #in block <unit> at ./retry.p6 line 20
This behaviour seems to have changed - this code was working fine back in June 18 - but I want to be sure I am in step with the latest thinking.
Any help would be very much appreciated !
Either remove the return:
method value( Real $newval? ) is rw {
Proxy.new:
FETCH => sub ($) { $!value },
STORE => sub ($, $newval) { $!value = $newval },
}
Or use return-rw if you really want to be explicit:
method value( Real $newval? ) is rw {
return-rw Proxy.new:
FETCH => sub ($) { $!value },
STORE => sub ($, $newval) { $!value = $newval },
}
The problem is that return will strip away any item container, so just putting is rw on the method is not enough on its own.
As to why the posted code used to work, but no longer does: Rakudo releases in the last couple of months have included a fix for a bug that meant Proxy was treated differently than Scalar in routine return handling. The Proxy was not stripped in places it should have been; now it reliably is.
I want to write tests first, then write code that makes the tests pass.
I can write tests functions like this:
func TestCheckPassword(t *testing.T) {
isCorrect := CheckPasswordHash("test", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S")
if isCorrect != true {
t.Errorf("Password is wrong")
}
}
But I'd like to have more descriptive information for each test function.
For example, I am thinking about creating auth module for my app.
Now, in plain English, I can easily describe my requirements for this module:
It should accept a non-empty string as input.
String must be from 6 to 48 characters long.
Function should return true if password string fits provided hash string and false if not.
What's the way to put this information that is understandable by a non-tech business person into tests besides putting them into comments?
In Go, a common way of writing tests to perform related checks is to create a slice of test cases (which is referred to as the "table" and the method as "table-driven tests"), which we simply loop over and execute one-by-one.
A test case may have arbitrary properties, which is usually modeled by an anonymous struct.
If you want to provide a description for test cases, you can add an additional field to the struct describing a test case. This will serve both as documentation of the test case and as (part of the) output in case the test case would fail.
For simplicity, let's test the following simple Abs() function:
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}
The implementation seems to be right and complete. If we'd want to write tests for this, normally we would add 2 test cases to cover the 2 possible branches: test when x is negative (x < 0), and when x is non-negative. In reality, it's often handy and recommended to also test the special 0 input and the corner cases: the min and max values of the input.
If we think about it, this Abs() function won't even give a correct result when called with the minimum value of int32, because that is -2147483648, and its absolute value is 2147483648 which doesn't fit into int32 because max value of int32 is: 2147483647. So the above implementation will overflow and incorrectly give the negative min value as the absolute of the negative min.
The test function that lists cases for each possible branches plus includes 0 and the corner cases, with descriptions:
func TestAbs(t *testing.T) {
cases := []struct {
desc string // Description of the test case
x int32 // Input value
exp int32 // Expected output value
}{
{
desc: "Abs of positive numbers is the same",
x: 1,
exp: 1,
},
{
desc: "Abs of 0 is 0",
x: 0,
exp: 0,
},
{
desc: "Abs of negative numbers is -x",
x: -1,
exp: 1,
},
{
desc: "Corner case testing MaxInt32",
x: math.MaxInt32,
exp: math.MaxInt32,
},
{
desc: "Corner case testing MinInt32, which overflows",
x: math.MinInt32,
exp: math.MinInt32,
},
}
for _, c := range cases {
got := Abs(c.x)
if got != c.exp {
t.Errorf("Expected: %d, got: %d, test case: %s", c.exp, got, c.desc)
}
}
}
In Go, the idiomatic way to write these kinds of tests is:
func TestCheckPassword(t *testing.T) {
tcs := []struct {
pw string
hash string
want bool
}{
{"test", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", true},
{"foo", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", false},
{"", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", false},
}
for _, tc := range tests {
got := CheckPasswordHash(tc.pw, tc.hash)
if got != tc.want {
t.Errorf("CheckPasswordHash(%q, %q) = %v, want %v", tc.pw, tc.hash, got, want)
}
}
}
This is called "table-driven testing". You create a table of inputs and expected outputs, you iterate over that table and call your function and if the expected output does not match what you want, you write an error message describing the failure.
If what you want isn't as simple as comparing a return against a golden value - for example, you want to check that either an error, or a value is returned, or that a well-formed hash+salt is returned, but don't care what salt is used (as that's not part of the API), you'd write additional code for that - in the end, you simply write down what properties the result should have, add some if's to check that and provide a descriptive error message if the result is not as expected. So, say:
func Hash(pw string) (hash string, err error) {
// Validate input, create salt, hash thing…
}
func TestHash(t *testing.T) {
tcs := []struct{
pw string
wantError bool
}{
{"", true},
{"foo", true},
{"foobar", false},
{"foobarbaz", true},
}
for _, tc := range tcs {
got, err := Hash(tc.pw)
if err != nil {
if !tc.wantError {
t.Errorf("Hash(%q) = %q, %v, want _, nil", tc.pw, got, err)
}
continue
}
if len(got) != 52 {
t.Errorf("Hash(%q) = %q, want 52 character string", tc.pw, got)
}
if !CheckPasswordHash(tc.pw, got) {
t.Errorf("CheckPasswordHash(Hash(%q)) = false, want true", tc.pw)
}
}
}
If you want a test suite with descriptive texts and contexts (like rspec for ruby) you should check out ginko: https://onsi.github.io/ginkgo/
I have some classes (and will need quite a few more) that look like this:
use Unit;
class Unit::Units::Ampere is Unit
{
method TWEAK { with self {
.si = True;
# m· kg· s· A ·K· mol· cd
.si-signature = [ 0, 0, 0, 1, 0, 0, 0 ];
.singular-name = "ampere";
.plural-name = "ampere";
.symbol = "A";
}}
sub postfix:<A> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:short) {
return Unit::Units::Ampere.new( :$value );
};
sub postfix:<ampere> ($value) returns Unit::Units::Ampere is looser(&prefix:<->) is export(:long) {
$value\A;
};
}
I would like to be able to construct and export the custom operators dynamically at runtime. I know how to work with EXPORT, but how do I create a postfix operator on the fly?
I ended up basically doing this:
sub EXPORT
{
return %(
"postfix:<A>" => sub is looser(&prefix:<->) {
#do something
}
);
}
which is disturbingly simple.
For the first question, you can create dynamic subs by returning a sub from another. To accept only an Ampere parameter (where "Ampere" is chosen programmatically), use a type capture in the function signature:
sub make-combiner(Any:U ::Type $, &combine-logic) {
return sub (Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my &int-adder = make-combiner Int, {$^a + $^b};
say int-adder(1, 2);
my &list-adder = make-combiner List, {(|$^a, |$^b)};
say list-adder(<a b>, <c d>);
say list-adder(1, <c d>); # Constraint type check fails
Note that when I defined the inner sub, I had to put a space after the sub keyword, lest the compiler think I'm calling a function named "sub". (See the end of my answer for another way to do this.)
Now, on to the hard part: how to export one of these generated functions? The documentation for what is export really does is here: https://docs.perl6.org/language/modules.html#is_export
Half way down the page, they have an example of adding a function to the symbol table without being able to write is export at compile time. To get the above working, it needs to be in a separate file. To see an example of a programmatically determined name and programmatically determined logic, create the following MyModule.pm6:
unit module MyModule;
sub make-combiner(Any:U ::Type $, &combine-logic) {
anon sub combiner(Type $a, Type $b) {
return combine-logic($a, $b);
}
}
my Str $name = 'int';
my $type = Int;
my package EXPORT::DEFAULT {
OUR::{"&{$name}-eater"} := make-combiner $type, {$^a + $^b};
}
Invoke Perl 6:
perl6 -I. -MMyModule -e "say int-eater(4, 3);"
As hoped, the output is 7. Note that in this version, I used anon sub, which lets you name the "anonymous" generated function. I understand this is mainly useful for generating better stack traces.
All that said, I'm having trouble dynamically setting a postfix operator's precedence. I think you need to modify the Precedence role of the operator, or create it yourself instead of letting the compiler create it for you. This isn't documented.
I write a pecl function named sample_isset, and its code is :
PHP_FUNCTION(sample_isset) {
zval **fooval;
if(EG(active_symbol_table) == NULL) {
php_printf("the active symbol table is NULL");
}else if(zend_hash_find(EG(active_symbol_table),"foo",4,
(void **) &fooval) == SUCCESS){
php_printf("Got the value of $foo!");
} else {
php_printf("$foo is not defined!");
}
}
And I want to use this function to see if current symbol table has a $foo variable.
When I use it in global scope, it works well.
But When I use it in another function for example hello, I go a error, and see nothing .
The hello function may be like this.
function hello(){
sample_isset();
}
I don't know why I got an error.
It seems that the php function used the lazy loading, the active_symbol_table doesn't always exist, so You should use zend_rebuild_symbol_table before EG(active_symbol_table) .