Is there a technique to pass along the default value of a hash when slipped into a sub call?
my %hash is default(222)=(a=>0,b=>111);
sub test {say %_.default}; #using automatic parameter
sub test2(%h) {say %h.default}; #explicit position parameter
test |%hash; #outputs (Any)
test2 %hash #outputs 222
The default of the input %hash is lost when slipped into the sub test. Is it possible to have the default in the slip? Cheers
my %hash is default(222)=(a=>0,b=>111);
sub test {say %_.default}; #using automatic parameter
test |%hash; #outputs (Any)
Slipping by definition means turning a container into a list of its elements. So you're not passing the hash, but instead its contents.
%_ collects copies of the passed named arguments. It's a hash local to the block its in with no relationship to a hash used to slip arguments in. Its default is the default default, which is Any, just like it is with a my declared hash:
my %foo;
say %foo.default; # (Any)
Is there a technique to pass along the default value of a hash when slipped into a sub call?
You could do this:
my %hash is default(222)=(a=>0,b=>111);
sub test {say %_<hash-default-for-test>}
test |%hash, :hash-default-for-test(%hash.default); #outputs 222
I picked the key string 'hash-default-for-test' because that's unlikely enough to occur as a normal key for any hash that it's reasonable to take the theoretical risk of accidental key collision.
Related
That is, variables like $*scalar, #*array and %*hash.
I'm asking this question mainly because I want to have an idea of how much of a burden they are on the overall performance of the grammar/regex engine.
To add a bit of precision to my question, I would like to know what happens :
on lookup,
my $var-1 = $*scalar
my $var-2 = #*array[3]
my $var-3 = %*hash<key>
and on insertion,
$*scalar = "new value 1"
#*array[3] = "new value 2"
%*hash{"existing key"} = "new value 3"
%*hash{"new key"} = "new value 3"
in relationship with the symbol table, the call stack, or any data structure involved like a special stack for handling dynamical scoping, or maybe a hash table of stacks.
My main interest is with array and hashes, and if they are both entirely duplicated each time we push/pop/modify/insert an array element or insert/modify/delete a key/value pair of a hash.
EDIT:
My assumptions about dynamical scoping was wrong. I thought that, when modifying a dynamically scoped hash, the changes would be undone at the end of the lexical scope in which the change has been made, similar to what happens in Perl with the local keyword and its associated "temporaries stack", hence my "Is the data structure duplicated ?" question. But this is not what dynamically scoped means it seems.
My assumption was that this following Raku code was equivalent to the following Perl code.
Instead, to replicate the behavior of the Perl code, we must do what the 2nd piece of Raku code do.
Raku 1:
my %*hash = (key => "value");
sub test() {
say "test() start";
say "\t", %*hash;
%*hash<key>="new value";
say "\t", %*hash;
say "test() end";
}
say %*hash;
test();
say %*hash;
OUTPUT:
{key => value}
test() start
{key => value}
{key => new value}
test() end
{key => new value}
Perl
our %hash=(key => "value");
sub test {
local %hash=%hash;
say "test() start";
say "\t", %hash;
$hash{key}="new value";
say "\t", %hash;
say "test() end"
}
say %hash;
test();
say %hash;
OUTPUT:
keyvalue
test() start
keyvalue
keynew value
test() end
keyvalue
Raku 2:
my %*hash = (key => "value");
sub test() {
my %*hash=CALLERS::<%*hash>;
say "test() start";
say "\t", %*hash;
%*hash<key>="new value";
say "\t", %*hash;
say "test() end";
}
say %*hash;
test();
say %*hash;
OUTPUT:
{key => value}
test() start
{key => value}
{key => new value}
test() end
{key => value}
The costs of looking up a dynamically scoped variable are independent of the sigil. For the purposes of lookup, the sigil is just part of the variable name to locate. The compilation of #a[3] = $x and #*a[3] = $x are identical except for the lookup of the #a/#*a - that is, they both result in a call to postcircumfix:<[ ]>, passing the resolved variable, the index, and the value to assign, and that leads to the assignment.
Arrays and hashes are implemented as mutable data structures; the only significant copying that would take place is if the dynamic array has to grow or the hash table needs its backing storage to grow to continue to provide efficient lookup.
Putting aside the fallback to GLOBAL and PROCESS, dynamic variables are stored in lexical symbol tables (thus their declaration with my). In MoarVM, the term "frame" is used for a record on the callstack, conceptually [1] created at the entry to a sub or block and destroyed at its exit. The term "static frame" is used for a data structure that represents all the things that are invariant over invocations of a sub or block. (So, if one writes a recursive sub and call it, there are many frames, but only one static frame). So far as lexical storage goes, the static frame contains a hash table mapping lexical variable names (strings) into integers. The values of a lexical are stored in the frame, as an array with the indices mapped by the static frame's hash table.
Most lexical variable lookups ($a) entirely bypass doing named lookups, being resolved at compile time to the applicable index.
By contrast, dynamic variable lookups ($*a) do use the static frame's lookup table. Dynamic variable lookup proceeds by walking the callstack, doing a lookup in the static frame's hash of lexicals to see if such a variable is declared, and if so the index is used to resolve it in the frame. There are some generic mechanisms and one special-case mechanism to improve performance here.
The generic ones are:
Strings have their hash codes cached, so the string $*a won't have to be repeatedly hashed; the integer hash code is just there and ready for the hash table lookup.
Strings are interned within a compilation unit, so if the declaration and usage of a dynamic variable occur within the same file, then the string comparison can short-circuit at pointer equality.
The special case mechanism consists of a dynamic variable lookup cache that can be established on any frame. This stores a name together with a pointer to where the dynamic variable is stored on the callstack. This provides a "shortcut" that can be especially valuable for frequently accessed dynamic variables that are declared a huge number of frames down the callstack. See this code for more details on how the cache entries are installed. (They are invalidated inside of the sliced frames when a continuation is taken; they used to also be broadly invalidated during deoptimization, but that changed with the adoption of lazy deoptimization on stack unwind a year or so ago.)
[1] Many Raku programs running on MoarVM enjoy a relatively high rate of inlining, which eliminates the cost of creation/destruction of a frame.
I've got this function here:
my #modifiers = <command option>;
sub triple(|c(Str:D $app1!, Str:D $app2!, Str:D $key! where .chars == 1, Str:D $mod where ($mod ~~ any #modifiers) = 'command' )) {
print_template(|c);
}
sub print_template(*#values) {
...work done here...
}
The problem I'm having is if I call it without the 4th argument, with something like triple 'App1', 'App2', 'p';, the default $mod argument does not get passed on to the print_template argument.
Is there a way to accomplish this?
For full context, this is the toy program here: https://paste.debian.net/1226675/
TL;DR 1. An explanation of the problem. 2. A DRY solution. 3. The DRYest solution: a parameters-capture function.
An explanation of the problem
A call proceeds in two steps:
Construct a call, without knowing what routine will hear the call. This includes constructing a capture of the call arguments. This capture is already done and dusted, immutable, before step 2.
See what routine candidates there are that might bind to the call. Try to bind the capture to their signatures. Some parameters in a routine's signature might specify defaults in case an argument is missing.
So, given a capture c, you can't alter it to make up for any arguments that aren't in it, and Raku doesn't automatically create a new capture that pretends any arguments that aren't in it are now in it. Instead you're going to have to manually add the missing values.
A DRY solution
The string 'command' appears twice in the suggested solution in your answer.
One way to write a DRY solution is to use the whole capture, which will include all the passed arguments, and then append any parameters for which corresponding arguments were not passed. That is to say, instead of:
my \d = \(|c[0..2], c[3] // 'command');
write this:
my \d = \(|c, |($mod if not c[3]));
The DRYest solution: a parameters-capture function
Ultimately what your scenario calls for is a function which completely ignores the arguments used to call a routine and instead just creates a new capture consisting of all of a routine's parameters. Then one could just write, say:
print_template(|parameters-capture);
That strikes me as pretty non-trivial. It would mean walking a routine's parameter data. This would presumably go via something like &?ROUTINE.signature.params. But &?ROUTINE is a compile-time variable and is relative to the current routine, so how do you get to that in a function you've called from the routine whose parameters you're interested in? And even if you can get to it, how do you get from compile-time parameter data structures to the run-time values that end up bound to the parameters? It's all way past my paygrade. It's perhaps a lot easier to do this sort of guts coding than it is in, say, the Perl world, where it means C coding, but still.
OK, based on responses in IRC, this does not appear to be possible. One suggested workaround:
sub triple(|c(Str:D $app1!,
Str:D $app2!,
Str:D $key! where .chars == 1,
Str:D $mod where ($mod ~~ any #modifiers) = 'command' )) {
my \d = \(|c[0..2], c[3] // 'command');
print_template(|d);
}
Another way to get to the same overall result (and probably the way I'd go) would be to split this out into a multi and dispatch based on the number of parameters. Here's one way that could look (with validation of the shared params moved to the proto:
my #modifiers = <command option>;
proto triple(Str:D, Str:D, Str:D $ where .chars == 1, $?) {*}
multi triple(|c($, $, $, Str:D $ where any #modifiers)) { print_template |c }
multi triple(|c($, $, $)) { print_template |c, 'command' }
sub print_template(*#values) {
# work done here
}
say triple 'App1', 'App2', 'p';
In reference to this question / answer, perl6 multi defaults to sub.
No such method <name> for invocant of type <class>
I would have expected it to default to method. Please could someone explain the rationale for this?
A multi declarator (multi, proto, or only) that is not followed by some other kind of declarator, but instead a routine name, will always be short for the sub declarator.
Perl 6 is keen on lexical scoping, and especially keen on making code easy to refactor.
Making the shortest way to declare a multi take the most narrowly scoped option - lexical scope - encourages keeping things as narrowly scoped as possible.
Making multi without a declarator have a consistent meaning aids refactoring, by allowing one to confidently move the code to the narrowest scope in which it is required. Having it suddenly change meaning just because it was moved into a class would be a refactoring frustration.
Finally, it's worth noting that sub in Perl 6 can be seen as filling the same niche as private static in various other languages, that multiple dispatch is generally useful, and thus a multiple dispatch sub can therefore be useful inside of a class body.
Sometimes special cases are justified. Like natural languages, Perl 6 will make them when it's really worth it, but the default is to avoid them. The argument for multi meaning something else inside of a class (and presumably role) just isn't strong enough for a special case.
A sub can occur anywhere and defaults to lexical scoping rules (my).
A method usually occurs only in a class definition and it defaults to being scoped to a class (has).
my multi sub foo (){…}
multi foo (){…} # identical
my multi method foo (){…} # must be forced to my declaration
class :: {
my multi sub foo (){…}
multi foo (){…} # identical
has multi method bar (){…}
multi method bar (){…} # identical
}
sub :: () {
my multi sub foo (){…}
multi foo (){…} # identical
my multi method foo (){…} # must be forced to my declaration
}
method :: () {
my multi sub foo (){…}
multi foo (){…} # identical
my multi method foo (){…} # must be forced to my declaration
}
Since a sub can, and does occur everywhere, it makes more sense for multi to imply a sub rather than method.
While you may think that it would make sense for multi to imply a method in a class definition; that would make it so that multi implies two different things (times two) depending on context. It would imply my sub outside of a class, and has method inside of a class. (It would also go back to my sub inside of a method inside of a class.)
That is it would be a special case. One of the design goals of Perl 6 is to reduce the number of special cases.
I have a shuffle function for Array:
shuffle:: forall e. Array -> Eff (random :: RANDOM | e) Array
It shuffles an array in a Control.Monad.Eff.Random monad and returns the wrapped one. I want to test the array is shuffled, like to compare the result is different, so I write QuickCheck code like:
quickCheck \arr -> isShuffled (shuffle arr)
However, I'm not sure how to write isShuffled to match type definitions. Since:
There is no unwrapping function like fromJust in Maybe, so it must accept Random Array and return Random Boolean, while I put the checking code in the Monadic expression.
Therefore, the result of isShuffled will not be plain Boolean, but like m Boolean
There is no suitable Testable in purescript-quickcheck for m Boolean, so I may need to create one instance for it, while the comment in QuickCheck refers:
A testable property is a function of zero or more Arbitrary arguments, returning a Boolean or Result. (code)
However, again, I cannot extract/unwrap a value from Random monad, I don't know how to access the boolean inside it and to implement like testableRandomArray to have Boolean or Result from a Random Boolean, unless I use some unsafe features.
I think I should "embed" the line of quickCheck inside a Random monad so I can access the pure Array it shuffled. However, since it is quickCheck to generate the test fixtures, I feel this is weird and no way to do that.
i'd like to know if there is any possibility to read out dynamic variable names?
Since the programm that passes the variables to my script calls them just "in1, in2, in3" etc.
Hopefully there is any way to make a loop, because it is pretty annoying to handle every input separately...
Here is what i've tried so far, but it just gives me an error.
for i=1,19,2 do
myvar[i] = ["in"..i]
end
I'm quite new to Lua, but i hope the solution is not that difficult :D
Edit:
Oh I'll try to give you some more information. The "Main" Program is no not written in Lua and just set theese "in1 ... " variables. It is a kind of robotic programmic software and has a lot of funktions build in. Thats the whole thing so i can not simply use other variable names or an array. So it is not a function or anything else related to Lua...
Here is a little Screenshot http://www.bilderload.com/daten/unbenanntFAQET.jpg
At the moment the Lua script just passes the the first input.
It depends on what you mean by "dynamic variable names."
The names of local variables do not exist. Local variables are any variable declared as a function parameter or with the local keyword. Local variables are compiled into offsets into the Lua stack, so their names don't exist. You can't index something by name to get them.
Global variables are members of the global table. Therefore, these ways to set a global variable are equivalent:
globalVar = 4
_G.globalVar = 4
_G["globalVar"] = 4
Since the programm that passes the variables to my script calls them just "in1, in2, in3" etc.
The program that passes variables to your script doesn't get to name them. A variable is just a placeholder for a value. It has no ownership of that value. When your function gets arguments, your function gets to name them.
You haven't said much about the structure of your program, so I can't really give good advice. But if you just want to take some number of values as parameters and access them as inputs, you can do that in two ways. You can take a table containing values as a parameter, or you can take a varargs:
function MyFunc1(theArgs)
for i, arg in ipairs(theArgs) do
--Do something with arg.
end
end
function MyFunc2(...)
for i, arg in ipairs({...}) do
--Do something with arg.
end
end
MyFunc1 {2, 44, 22} --Can be called with no () because it takes a single value as an expression. The table.
MyFunc2(2, 44, 22)
Whoever wrote the code that spits out these "dynamic variables" didn't do a good job. Having them is a bad habit, and might result in data loss, cluttering of the global name space, ...
If you can change it, it'd be much better to just output a table containing the results.
That said, you're not to far off with your solution, but ["in"..i] is no valid Lua syntax. You're indexing into nothing. If those variables are globals, your code should read:
for i=1,19,2 do
myvar[i] = _G["in"..i]
end
This reads the values contained by your variables out of the global table.
Try this
myvar={ in1, in2, in3, in4, in5, in6, in7, in8, in9, in10, in11,
in12, in13, in14, in15, in16, in17, in18, in19 }
if the variables are passed as global variables, or this
myvar = {...}
if the variables are passed as arguments to the script.