What is "await do" in Perl 6? - raku

I see the following code in Perl 6:
await do for #files -> $file {
start {
#do something ... }
}
which runs in async mode.
Why does the above code need do? What is the purpose of do in PerlĀ 6? Could someone please explain the above code in detail?
Also is there are an option to write something like this:
for #files -> $file {
start {
#do something ... }
}
and await after the code for the promises to be fulfilled?

The purpose of do
The for keyword can be used in two different ways:
1) As a stand-alone block statement:
for 1..5 { say $_ }
2) As a statement modifier appended to the end of a statement:
say $_ for 1..5;
When the bare for keyword is encountered in the middle of a larger statement, it is interpreted as that second form.
If you want to use the block form inside a larger statement (e.g. as the argument to the await function), you have to prefix it with do to tell the parser that you're starting a block statement here, and want its return value.
More generally, do makes sure that what follows it is parsed using the same rules it would be parsed as if it were its own statement, and causes it to provide a return value. It thus allows us to use any statement as an expression inside a larger statement. do if, do while, etc. all work the same way.
Explanation of your code
The code you showed...
await do for #files -> $file {
start {
#do somthing ... }
}
...does the following:
It loops of over the array #files.
For each iteration, it uses the start keyword to schedule an asynchronous task, which presumably does something with the current element $file. (The $*SCHEDULER variable decides how the task is actually started; by default it uses a simple thread pool scheduler.)
Each invocation of start immediately returns a Promise that will be updated when the asynchronous task has completed.
The do for collects a sequence of all the return values of the loop body (i.e. the promises).
The await function accepts this sequence as its argument, and waits until all the promises have completed.
How to "await after the code"
Not entirely sure what you mean here.
If you want to remember the promises but not await them just jet, simply store them in an array:
my #promises = do for #files -> $file {
start {
#do something ... }
}
#other code ...
await #promises;
There is no convenience functionality for awaiting all scheduled/running tasks. You always have to keep track of the promises.

Related

Async Wait Efficient Execution

I need to iterate 100's of ids in parallel and collect the result in list. I am trying to do it in following way
val context = newFixedThreadPoolContext(5, "custom pool")
val list = mutableListOf<String>()
ids.map {
val result:Deferred<String> = async(context) {
getResult(it)
}
//list.add(result.await()
}.mapNotNull(result -> list.add(result.await())
I am getting error at
mapNotNull(result -> list.add(result.await())
as await method is not available. Why await is not applicable at this place? Instead commented line
//list.add(result.await()
is working fine.
What is the best way to run this block in parallel using coroutine with custom thread pool?
Generally, you go in the right direction: you need to create a list of Deferred and then await() on them.
If this is exactly the code you are using then you did not return anything from your first map { } block, so you don't get a List<Deferred> as you expect, but List<Unit> (list of nothing). Just remove val result:Deferred<String> = - this way you won't assign result to a variable, but return it from the lambda. Also, there are two syntactic errors in the last line: you used () instead of {} and there is a missing closing parenthesis.
After these changes I believe your code will work, but still, it is pretty weird. You seem to mix two distinct approaches to transform a collection into another. One is using higher-order functions like map() and another is using a loop and adding to a list. You use both of them at the same time. I think the following code should do exactly what you need (thanks #Joffrey for improving it):
val list = ids.map {
async(context) {
getResult(it)
}
}.awaitAll().filterNotNull()

How to know which line of code was being executed when a signal is received

I'm trying to do something like this
$SIG{ALRM} = sub {
print $line_number_when_alarm_went_off;
};
alarm 10;
# rest of the script
I'm using ALRM as an example, I will end up using a different signal to kill from the outside to trigger it. Is there a neat way of doing this sort of operation?
I have some slow scripts and sometimes I would like to send them a signal to know where the code is at that moment.
I want to make this as unobtrusive as possible so I could package it and add it to legacy code.
You can use caller in list context to get the package, file and line number of the place that the current sub got called from.
$SIG{ALRM} = sub {
my ($pkg, $file, $line) = caller;
CORE::say $line;
die;
};
alarm 2;
while (1) {
1;
}
This will output 11 (if I counted correctly, in my file it's 1740, and the $SIG line is 1730.
It also works with other signal handlers, like warn.
$SIG{__WARN__} = sub {
my ($pkg, $file, $line) = caller;
CORE::say $line;
};
warn 'foo';
This will output 7
Note that your code has a syntax error. You are assigning a hash reference as a signal handler, not a sub reference!

Bypassing functions that do not exist

how would it be possible to bypass functions that are not existing in DM
such that the main code would still run? Try/catch does not seem to work, e..g
image doSomething(number a,number b)
{
try
{
whateverfunction(a,b)
}
catch
{
continue
}
}
number a,b
doSomething(a,b)
Also conditioning wont work, e.g..
image doSomething(number a,number b)
{
if(doesfunctionexist("whateverfunction"))
{
whateverfunction(a,b)
}
}
number a,b
doSomething(a,b)
thanks in advance!
As "unknown" commands are caught by the script-interpreter, there is no easy way to do this. However, you can construct a workaround by using ExecuteScriptCommand().
There is an example tutorial to be found in this e-book, but in short, you want to do something like the following:
String scriptCallStr = "beep();\n"
scriptCallStr = "MyUnsaveFunctionCall();\n"
number exitVal
Try { exitVal = ExecuteScriptString(scriptCallStr ); }
Catch { exitVal = -1; break; }
if ( -1 == exitVal )
{
OKDialog("Sorry, couldn't do:\n" + scriptCallStr )
}
else
{
OKDialog( "All worked. Exit value: " + exitVal )
}
This works nicely and easy for simple commands and if your task is only to "verify" that a script could run.
It becomes clumsy, when you need to pass around parameters. But even then there are ways to do so. (The 'outer' script could create an object and pass the object-ID per string. Similarly, the 'inner' script can do the same and return the script-object ID as exit-value.)
Note: You can of course also put doesfunctionexist inside the test-script, if you do only want to have a "safe test", but don't actually want to execute the command.
Depending on what you need there might also be another workaround solution: Wrapper-functions in a library. This can be useful if you want to run the same script on different PCs with some of which having the functionality - most likely some microscope - while others don't.
You can make your main-script use wrapper methods and then you install different versions of the wrapper method script scripts as libraries.
void My_SpecialFunction( )
{
SpecialFunction() // use this line on PCs which have the SpecialFunction()
DoNothing() // use alternative line on PCs which don't have the SpecialFunction()
}
My_SpecialFunction( )
I have used this in the past where the same functionality (-stage movement-) required different commands on different machines.

How do i stop SSIS Script component to process data

i am processing a ragged semicolon delimited file using script component as transformation.
The component is able to process the data and load to oledb destination. But when error is found it should stop processing further. As i am using try catch block the component doesn't fail and continue to process till the end.
Is there any way i could stop the processing further without failing the component/package?
Let me know if any other information/details required?
sample code:
str.split(";");
if(column[0] == "H")
{
col1=Column[3];
}
if(column[0] != "T")
{
try
{
Row.col1=Column[0];
Row.col2=Column[1];
.....
}
catch
{
update the variable to check if we have error in file.
}
}
Thank you for your time.
The general idea will be that you want to use try/catch blocks to ensure the data processing itself doesn't abort. Once you know your script isn't reporting a failure back to the engine, it's a simple process to not call the AddRow()
Pseudocode
foreach(line in fileReader)
{
try
{
// perform dangerous operations here
// Only add row if you have been able to parse current line
Output0Buffer.AddRow();
Output0Buffer.Col1 = parsedContent;
}
catch
{
// Signal that we should break out of the loop
// do not propagate the error
// You might want to do something though so you know you
// have an incomplete load
break;
}
}
If you are looking to just skip the current bad line, you can substitute continue for the break above.
C# loop - break vs. continue
I didn't get any help from anywhere, But as a work around i have placed a return statement in the code. It checks the error variable if it's true then i will return without processing further. But the thing still is it processes the whole file :(. But it works!!!

optimal way of passing multiple callback functions as arguments?

I have a function that could be used in CLI or web application, that being said, there is a little difference in the process; for example: if I'm using this function for CLI it'll use a text progress bar, but that doesn't make sense if I'm using this function for a web application.
The function is basically a loop; so what i'm looking for is a way to make this function flexible by making it possible to pass code as an argument so that it'll be executed at the end of each loop cycle. So if I'm using this function in CLI; i'll pass a progress incremental function to advance the progress bar, and so on.
My current solution is to pass a progress bar object instance, which I think isn't a proper solution; because it doesn't seem flexible for the long run.
A demonstration example of what I'm already doing:
function myFunction($progressBar = null)
{
for($i = 0; $i......)
{
//Do stuff
....
//finally...
if(!empty($progressBar))
$progressBar->advance();
}
}
So, if I want to add another function at the end of the loop, I'll have to pass it as an argument and call it manually later; but as I said, it just doesn't seem right.
I'm thinking of using a callback function(an anonymous function being passed to myFunction) But what is a proper way of doing that; should I just make each callback function as an individual argument? or, to make it even more flexible, should I be grouping all callback functions in an array(if that's possible).
Yes, you can use callbacks for this.
function myFunction($progressBar = null, callable $callback = null)
{
for($i = 0; $i......)
{
//Do stuff
....
//finally...
if(!empty($progressBar))
$progressBar->advance();
}
if ($callback){ //Execute the callback if it is passed as a parameter
$callback();
}
}
Also, you can specify parameters for an anonymous function:
Example: you want to echo something at some point.
myFunction($progressBar) ; //No need yet
myFunction($progressBar, function($result){ echo $result ; }) ; //Now you want to execute it
So, handle it in an appropriate way:
if ($callback){ //Execute the callback if it is passed as a parameter
$callback("All is fine"); //Execute the callback and pass a parameter
}
Array of callbacks also may be useful in this case like:
$callbacks = array(
"onStart" => function(){ echo "started" ; },
"onEnd" => function(){ echo "ended" ; }
) ;
function myFunc($progressBar = null, $callbacks){
if (isset($callbacks["onStart"]) && is_callable($callbacks["onStart"])){
$callbacks["onStart"]() ;//Execute on start.
}
//Execute your code
if (isset($callbacks["onEnd"]) && is_callable($callbacks["onEnd"])){
$callbacks["onEnd"]() ;//Execute on end.
}
}