Consider this:
SWITCH ($mode)
{
MODE1
{
}
MODE2
{
}
MODE3
{
}
}
Can I directly call the code under MODE1, MODE2, or MODE3 without executing the entire SWITCH statement?
I have a situation where MODE3 can only run if MODE2 has been completed, and MODE2 can only run if MODE1 has been completed. I have moved all the code for each MODE into a separate function. However, the logic to determine if previous modes have completed is growing in size, duplicates code, and is confusing.
For instance:
SWITCH ($mode)
{
MODE1
{
DoMode1
if (!Mode1Complete) { Exit }
}
MODE2
{
if (!Mode1Complete) { DoMode1 }
if (!Mode1Complete) { Exit }
DoMode2
}
MODE3
{
if (!Mode2Complete)
{
if (!Mode1Complete)
{
DoMode1
if (!Mode1Complete) { Exit }
DoMode2
if (!Mode2Complete) { Exit }
}
else
{
DoMode2
if (!Mode2Complete) { Exit }
}
}
DoMode3
}
}
You can see how this will get complicated real quick!
What I want to do is this:
SWITCH ($mode)
{
MODE1
{
DoMode1
If (!Mode1Complete) { Exit }
}
MODE2
{
if (!Mode1Complete)
{
#Call MODE1
}
if (!Mode1Complete) { Exit }
DoMode2
}
MODE3
{
if (!Mode2Complete)
{
#Call MODE2
}
if (!Mode2Complete) { Exit }
DoMode3
}
}
Please note "MODEx" is just an example. The actual conditions will not be in numerical order like this. They will be different words.
Any ideas how to make this happen?
Using GetNewClosure to store state inside scriptblocks. If your code needs external variables inside scriptblocks, consider passing them as arguments to the corresponding scriptblocks.
Example:
# Setup scriptblocks for switch statement and dependencies.
# Use 'GetNewClosure' to capture variables (e.g.: $ModeComplete)
$Alpha = {
if (!$ModeComplete) {
'Alpha'
$ModeComplete = $true
}
}.GetNewClosure()
$Beta = {
. $Alpha
if (!$ModeComplete) {
'Beta'
$ModeComplete = $true
}
}.GetNewClosure()
$Gamma = {
. $Beta
if (!$ModeComplete) {
'Gamma'
$ModeComplete = $true
}
}.GetNewClosure()
# Helper scriptblock, will execute scriptblock
# from varible named as current switch condition
$ExecuteCurrentMode = {
. (Get-Variable -Name $_ -ValueOnly)
}
# Mode
$Mode = 'Gamma'
# Switch
switch ($Mode) {
'Alpha' {
. $ExecuteCurrentMode $_
}
'Beta' {
. $ExecuteCurrentMode $_
}
'Gamma' {
. $ExecuteCurrentMode $_
}
}
Result
Alpha
Beta
Gamma
Related
function emptyInputSignup($fname, $lname, $email, $username, $pwd, $pwdrepeat) {
$result = null;
if (empty($fname) || empty($lname) || empty($email) || empty($username) || empty($pwd) || empty($pwdrepeat)) {
$result = true;
} else {
$result = false;
}
return $result;
};
function invalidUid($username) {
$result = null;
if (!preg_match('/^[a-zA-Z0-9]*$/'), $username) {
$result = true;
} else {
$result = false;
}
return $result;
}
What have I donr wrong, what does it want, i literally copied the emptyInputSignup function and then wrote some regex in and vscode is confused
I've stared at it for an hour, when I google for regex not working properly, I couldn't find anyone having similar problems.
You need to put , $username inside the preg_match function parenthesis, after the regex pattern. It is in the wrong place.
It should be:
if (!preg_match('/^[a-zA-Z0-9]*$/', $username)) {
$result = true;
} else {
$result = false;
}
I have a variable that stores a switch statement
$com = '
switch ($_)
{
1 {"It is one."}
2 {"It is two."}
3 {"It is three."}
4 {"It is four."}
}
'
I am trying to pipe in the number to run the switch statement
something like:
1 | iex($com)
Your options are:
A scriptblock or function with a process block:
$com = {
process {
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
}
}
function thing {
process {
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
}
}
1..3 | & $com
1..3 | thing
A filter, exactly the same functionality:
filter thing {
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
}
1..3 | thing
Using ScriptBlock.Create method (this would require a process block in the string expression):
$com = '
process {
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
}
'
1..3 | & ([scriptblock]::Create($com))
Using ScriptBlock.InvokeWithContext method and the automatic variable $input, this technique does not stream and also requires an outer scriptblock to work, it's just to showcase and should be discarded as an option:
$com = '
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
'
1..3 | & { [scriptblock]::Create($com).InvokeWithContext($null, [psvariable]::new('_', $input)) }
Using Invoke-Expression, also requires an outer scriptblock with a process block (should be discarded - from all techniques displayed above this is the worst one, the string expression is being evaluated per item passed through the pipeline):
$com = '
switch ($_) {
1 { "one." }
2 { "two." }
3 { "three." }
}
'
1..3 | & { process { Invoke-Expression $com } }
I'm trying to write a macro that will rewrite certain Rust control flow, but I'm having difficulty matching an if expression. The problem is that the predicate is an expression, but an expr is not permitted to be followed by a block or {.
The best I've got is to use tt:
macro_rules! branch {
(
if $pred:tt
$r1:block
else
$r2:block
) => {
if $pred {
$r1
} else {
$r2
}
};
}
Which works fine with single-token or grouped predicates:
branch! {
if (foo == bar) {
1
} else {
2
}
}
But fails if the predicate was not grouped:
branch! {
if foo == bar {
1
} else {
2
}
}
error: no rules expected the token `==`
I also tried to use a repeating pattern of tt in the predicate:
macro_rules! branch {
(
if $($pred:tt)+
$r1:block
else
$r2:block
) => {
if $($pred)+ {
$r1
} else {
$r2
}
};
}
But this produces an error because it's now ambiguous whether subsequent block should match the tt too:
error: local ambiguity: multiple parsing options: built-in NTs tt ('pred') or block ('r1').
Is there a way to do this, or am I stuck with inventing special syntax to use in the macro?
You could use a TT muncher to parse the predicate:
macro_rules! branch {
{
if $($rest:tt)*
} => {
branch_parser! {
predicate = ()
rest = ($($rest)*)
}
};
}
macro_rules! branch_parser {
{
predicate = ($($predicate:tt)*)
rest = ({ $($then:tt)* } else { $($else:tt)* })
} => {
println!("predicate: {}", stringify!($($predicate)*));
println!("then: {}", stringify!($($then)*));
println!("else: {}", stringify!($($else)*));
};
{
predicate = ($($predicate:tt)*)
rest = ($next:tt $($rest:tt)*)
} => {
branch_parser! {
predicate = ($($predicate)* $next)
rest = ($($rest)*)
}
};
}
fn main() {
branch! {
if foo == bar {
1
} else {
2
}
}
}
Output:
predicate: foo == bar
then: 1
else: 2
In some cases you may want to pass in an argument to a macro which is either some text, or nothing (blank space, as if nothing was written).
Given this starting point:
macro_rules! testme {
($var:ident, $code:block) => {
for i in 0..10 {
let $var = i;
{ $code }
if $var > 5 {
println!("over 5");
}
}
}
}
fn main() {
testme!(myvar, {
println!("{}", myvar);
});
}
We may want var to optionally be mutable, assuming the macro body is larger then in the example above, its best not to duplicate the entire macro.
macro_rules! testme {
(private $var:ident, $code:block, $var_qual:tt) => {
for i in 0..10 {
// imagine this is a lot more code :)
let $var_qual $var = i;
{ $code }
if $var > 5 {
println!("over 5");
}
}
};
(mut $var:ident, $code:block) => {
testme!(private $var, $code, mut)
};
/*
($var:ident, $code:block) => {
testme!(private $var, $code, )
// ^ how to pass in a blank argument?
};
*/
}
fn main() {
testme!(mut myvar_mut, {
myvar_mut += 10;
println!("{}", myvar_mut);
});
/*
testme!(myvar_immutable, {
println!("{}", myvar_immutable);
});
*/
}
As far as I can tell there is no way to pass in a an empty argument, uncomment the /**/ comments to see the error.
Is it possible to pass in an empty argument to a macro to make an example like this work?
As far as I know its not possible to pass in blank / empty arguments.
It is possible however to pass in a locally defined macro which optionally adds a prefix.
Working example:
macro_rules! testme {
(private $var:ident, $code:block, $var_qual_macro:ident) => {
for i in 0..10 {
// imagine this is a lot more code :)
let $var_qual_macro!($var) = i;
{ $code }
if $var > 5 {
println!("over 5");
}
}
};
(mut $var:ident, $code:block) => {
macro_rules! var_qualifier { ($v:ident) => { mut $v } }
testme!(private $var, $code, var_qualifier)
};
($var:ident, $code:block) => {
macro_rules! var_qualifier { ($v:ident) => { $v } }
testme!(private $var, $code, var_qualifier)
};
}
fn main() {
testme!(mut myvar_mut, {
myvar_mut += 10;
println!("{}", myvar_mut);
});
testme!(myvar_immutable, {
println!("{}", myvar_immutable);
});
}
Take care when nesting macros like this that the name of the macro (var_qualifier in this case) is isn't the same name used inside a different macro since the name will be silently shadowed.
I am trying to use the Get-SPContentDatabase powershell command from a code behind file:
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("Get-SPContentDatabase -site http:////gBox.contoso.com");
Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
if (PSOutput.Count > 0)
{
foreach (PSObject outputItem in PSOutput)
{
if (outputItem != null)
{
lblResults.Text += outputItem.BaseObject.ToString();
lblResults.Text += outputItem.BaseObject.GetType().FullName;
lblResults.Text += "<hr>";
}
}
}
else
{
lblResults.Text = "No output found";
}
}
However, the PSOutput keeps coming back with zero objects.
The Command works great from the PowerShell window, but not from the code behind.
Any thoughts?
The command Get-SPContentDatabase is failed to execute since Microsoft.SharePoint.PowerShell module have to be loaded first:
using (var psInst = PowerShell.Create())
{
psInst.AddScript("Add-PsSnapin Microsoft.SharePoint.PowerShell");
}
Example: print ContentDb names
using (var psInst = PowerShell.Create())
{
psInst.AddScript("Add-PsSnapin Microsoft.SharePoint.PowerShell");
psInst.AddScript("Get-SPContentDatabase -site http://contoso.intranet.com/");
var result = psInst.Invoke();
foreach (var outputItem in result)
{
var contentDb = outputItem.BaseObject as SPContentDatabase;
Console.WriteLine(contentDb.Name);
}
}