conversion of and operation having a function from c# to tcl - tcl

how to do the and operation given as one line statement in tcl in tcl where pcieDeviceControlRegister is a function given as in the code:
code:
pcieDeviceControlRegister = cfgSpace.pcieDeviceControlRegister & (~((uint)0xF));
Reference for pcieDeviceControlRegister function is :
public uint pcieDeviceControlRegister
{
get
{
if (pcieCapabilityOffset != 0)
return (ReadDW((int)(pcieCapabilityOffset + 8) / 4, 0xF)) & 0xFFFF;
else
return 0;
}
set
{
if (pcieCapabilityOffset != 0)
{
uint val = ReadDW((int)(pcieCapabilityOffset + 8) / 4, 0xF)& 0xFFFF0000;
val |= value;
// write should be done with byte enables !!!
WriteDW((int)(pcieCapabilityOffset + 8) / 4, val, 0xF);
}
}
}

You'll have to arrange for the mapping of ReadDW and WriteDW into Tcl, probably by writing a little C or C++ code that makes commands (with the same names) that do those operations. I'm assuming that you've already done that. (SWIG can generate the glue code if you need it.)
Then, we define a command like this:
proc pcieDeviceControlRegister {{newValue ""}} {
global pcieCapabilityOffset
# Filter the bogus setup case early; if this is really an error case though,
# it is better to actually throw an error instead of struggling on badly.
if {$pcieCapabilityOffset == 0} {
return 0
# error "PCIE capability offset is zero"
}
set offset [expr {($pcieCapabilityOffset + 8) / 4}]
if {$newValue eq ""} {
# This is a read operation
return [expr {[ReadDW $offset 0xF] & 0xFFFF}]
} else {
# This is a write operation
set val [expr {[ReadDW $offset 0xF] & 0xFFFF0000}]
# Note that we do the bit filtering HERE
set val [expr {$val | ($newValue & 0xFFFF)}]
WriteDW $offset $val 0xF
return
}
}
With that, which you should be able to see is a pretty simple translation of the C# property code (with a bit of minor refactoring), you can then write your calling code like this:
pcieDeviceControlRegister [expr {[pcieDeviceControlRegister] & ~0xF}]
With Tcl, you don't write casts to different types of integers: Tcl just has numbers (which are theoretically of infinite width) so instead you need to do a few more bit masks in key places.
The conversion of the above code to a method on an object is left as an exercise. It doesn't change very much…

Related

solving an exponential equation in Raku

I'm trying to solve this exponential equation like this:
my ($l,$r);
for (1 .. 100) -> $x {
$l = $x * e ** $x;
$r = 5 * (e ** $x - 1);
say $x if $l == $r;
}
But it doesn't work. How to solve it in a straightforward and comprehensive fashion?
Sorry for the double-answering.
But here is a totally different much simpler approach solved in Raku.
(It probably can be formulated more elegant.)
#!/usr/bin/env raku
sub solver ($equ, $acc, $lower0, $upper0) {
my Real $lower = $lower0;
my Real $upper = $upper0;
my Real $middle = ($lower + $upper) / 2;
# zero must be in between
sign($equ($lower)) != sign($equ($upper)) || die 'Bad interval!';
for ^$acc { # accuracy steps
if sign($equ($lower)) != sign($equ($middle))
{ $upper = $middle }
else
{ $lower = $middle }
$middle = ($upper + $lower) / 2;
}
return $middle;
}
my $equ = -> $x { $x * e ** $x - 5 * (e ** $x - 1) }; # left side - right side
my $acc = 64; # 64 bit accuracy
my Real $lower = 1; # start search here
my Real $upper = 100; # end search here
my $solution = solver $equ, $acc, $lower, $upper;
say 'result is ', $solution;
say 'Inserted in equation calculates to ', $equ($solution), ' (hopefully nearly zero)'
For Perl 5 there is Math::GSL::Roots - Find roots of arbitrary 1-D functions
https://metacpan.org/pod/Math::GSL::Roots
Raku has support for using Perl 5 code or can access the GSL C library directly, can't it?
$fspec = sub {
my ( $x ) = shift;
# here the function has to be inserted in the format
# return leftside - rightside;
return ($x + $x**2) - 4;
};
gsl_root_fsolver_alloc($T); # where T is the solver algorithm, see link for the 6 type constants, e.g. $$gsl_root_fsolver_brent
gsl_root_fsolver_set( $s, $fspec, $x_lower, $x_upper ); # [$x_lower; $x_upper] is search interval
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
gsl_root_fsolver_iterate($s);
my $result = gsl_root_fsolver_root($s);
gsl_root_fsolver_free (s);
There are enhanced algorithms available (gsl_root_fdfsolver_*), if the derivative of a function is available.
See also https://www.gnu.org/software/gsl/doc/html/roots.html#examples for general usage

CRC16 calculation in Tcl

Im trying to compute the CRC16 of a binary file.
I started by reading 2 Bytes from the Binary file and compute a CRC16 with a Polynome= 1021 and 0xFFFF Initial Value. I used a C code and tried to translate it to TCL. I couldnt use the bytes format because i get by the computation an error about using non numeric string. So i converted the bytes to strings.
proc main {}{
# open binary file
set file_read [open "$input_file" rb]
while {1} {
if {! [eof $fr]} {
append binary_data [read $file_read 2]
}
binary scan [string range $binary_data 0 1] H4 str_bin_data
set CRC_data [CRC_calculation $str_bin_data]
puts " CRC_data := $CRC_data"
}
}
proc CRC_calculation {str_bin_data} {
set Polynome 0x1021
set Highbit 0x8000
set CRC_data 0xFFFF
set byte 0
set bit 0
set data_ln [string length $str_bin_data]
# puts " data_ln := $data_ln"
for {set byte 0} {$byte < $data_ln} {incr byte} {
set CRC_data [ expr {$CRC_data ^ ([lindex $str_bin_data $byte] << 8)} ]
for {set bit 8} {$bit > 0} {incr bit -1} {
if {($CRC_data && $Highbit)} {
set CRC_data [expr {($CRC_data << 1) ^ $Polynome}]
} else {
set CRC_data [expr {$CRC_data << 1}]
}
}
puts " byte_index := $byte"
puts " CRC_data := $CRC_data"
}
return $CRC_data
}
In C when i define a byte array example( first 8 Bytes in the binary file):
unsigned char bytes[3]= {0x55,0x55,0x55,0x55};
then CRC = 0x82b8
In Tcl I dont get the correct value not even a 32 bit CRC value.
Here the C code that i m using:
#include<stdio.h>
#define Polynom 0x1021
#define Highbit 0x8000
unsigned short getCRC(const unsigned char data[])
{
unsigned short rem = 0xFFFF;
unsigned long byte = 0;
int bit = 0;
for (byte = 0; byte < 3; ++byte)
{
rem ^= (data[byte]<< 8);
for (bit = 8; bit > 0; --bit)
{
if (rem & Highbit)
rem = (rem << 1) ^ Polynom;
else
rem = (rem << 1);
}
}
return (rem);
}
int main() {
int rem ;
unsigned char data[]= {0x55,0x55,0x55,0x55};
rem = getCRC (data);
printf("%x", rem);
}
There's a few problems. Firstly, and most importantly, the scanning of the binary data isn't right as we want to end up with unsigned bytes (for parallel operation with that C) and not hex characters. You'd be better with:
# I'm assuming you've got Tcl 8.6, this is how you read 2 bytes as unsigned chars
binary scan [read $file_read 2] "cu*" str_bin_data
# Process the list of parsed byte data here; I'm not sure if you want this in the loop or not
The other big problem is that your CRC calculation isn't correct.
proc CRC_calculation {str_bin_data} {
set Polynom 0x1021
set Highbit 0x8000
set MASK 0xFFFF; # 16 bit mask; for clamping to C unsigned short range
set rem 0xFFFF
# Assume str_bin_data holds a list of unsigned char values
foreach byte $str_bin_data {
set rem [expr {$rem ^ ($byte << 8)}]
foreach _ {7 6 5 4 3 2 1 0} {
set rem [expr {
(($rem << 1) ^ ($rem & $Highbit ? $Polynom : 0)) & $MASK
}]
}
}
return $rem
}
Key observation here? Tcl's numbers are arbitrary precision integers (and IEEE doubles, though not relevant here). This means that you need to clamp the range. Minimally, that would be an AND with 0xFFFF (16-bit mask) after any operation that can increase the number of bits in use, which is just << in this algorithm. That, plus the problems with converting the binary data in the first place, are why things weren't working for you. I've also switched to using foreach as that's fast and clearer for operations where “do every one of them” is the fundamental idea, and merged the inner bits into a single expr (yes, expr expressions can be multiline if you want).
The biggest single problem was that you were passing entirely the wrong thing to the CRC_calculation code. Changing the binary scan is vital.

Assign random number to node in TCL script for ns-2: ERROR variable is array

I am trying to run the following tcl script but getting an error
can't set "val": variable is array
while executing
"set val [random_int $upper_limit]"
Here is my code,Please any help
proc random_int { upper_limit } {
global myrand
set myrand [expr int(rand() * $upper_limit + 1)]
return $myrand
}
set upper_limit 21
set val [random_int $upper_limit]
$ns at 0.6 "[$node($val) set ragent_] malicious"
Your current main problem is that there's an existing use of the val as an array; Tcl's variables can't simultaneously be scalars and arrays. The most expedient fix is to change the name of the variable, perhaps to value.
set value [random_int $upper_limit]
$ns at 0.6 "[$node($value) set ragent_] malicious"
Apart from that, your random number generator could be a bit sharper code. It probably doesn't need to access any global variables, and it really should have the expression put in braces (for a bunch of reasons including both speed and safety). Here's the trimmed/tuned version:
proc random_int { upper_limit } {
expr { int(rand() * $upper_limit + 1) }
}
Occasionally, I write such procedures slightly differently, like this:
proc random_int { upper_limit } {expr {
int(rand() * $upper_limit + 1)
}}
It's semantically identical, but it makes it clearer what the author is really thinking about.

Returning values from exception handlers in Perl 6

I've been trying to write a Perl 6 expression which performs the following logic: Evaluate a subexpression and return its value, but if doing so causes an exception to be raised, catch the exception and return a fixed value instead.
For example, suppose I want to divide two numbers and have the expression evaluate to -1 if an error occurs. In Ruby I might write:
quotient = begin; a / b; rescue; -1; end
In Emacs Lisp that might be written as:
(setq quotient (condition-case nil (/ a b) (error -1))
My first Perl 6 attempt was like so:
sub might-throw($a, $b) { die "Zero" if $b == 0; $a / $b }
my $quotient = do { might-throw($a, $b); CATCH { default { -1 } } };
But here $quotient ends up undefined, regardless of whether $b is zero.
It seems that that the value returned by CATCH is ignored, or at least on the doc page that describes how exceptions work, all of the CATCH bodies only do things with side effects, like logging.
That page mentions try as an alternative. I might write for example:
my $quotient = try { might-throw($a, $b) } // -1;
I find it a rather underwhelming solution. For one thing, the expression I'm evaluating might genuinely have an undefined value, and I can't distinguish this from the case where an exception was thrown. For another, I might want to fall back to different values depending on the class of the thrown exception, but try just swallows them all. I can put my own CATCH block in the try to distinguish among the exceptions, but then I'm back at the first case above, where the value from the CATCH is ignored.
Can Perl 6's exception handling do as I've expressed I want it to be able to do above?
EDIT:
The current answers are informative, but are focusing too narrowly on the semantics of the division operator. I've rewritten the question slightly to make the main issue of exception catching more central.
The reason your catch block doesn't work is because dividing by zero isn't in and of itself an error. Perl6 will happily let you divide by zero and will store that value as a Rat. The issue arises when you want to display said Rat in a useful fashion (IE say it). That's when you get a Failure returned that becomes and Exception if not handled.
So you've a few options. You can check $b before you make $q :
$q = $b == 0 ?? -1 !! $a / $b;
Or if you want to keep the real value (note you can introspect both the numerator and the denominator of a Rat without causing the divide by Zero error) when you say it you can use the .perl or .Num versions.
Both give you the decimal representation of the Rat with .perl giving <1/0> and .Num giving Inf when you have a 0 denominator.
TL;DR The bulk of this answer introduces trys, my solution comprehensively addressing the overall issue your Q demonstrates and much more besides. The last section discusses some things happening in your attempts that others failed to address[1 2].
trys summary
A couple very simple examples:
say trys { die }, { -1 } # -1
say trys { die }, { when X::AdHoc { 42 } } # 42
trys is a single user defined routine that combines the best of the built in try and CATCH constructs. It:
Takes a list of one or more Callables (functions, lambdas, etc), each of which can play either a try role, a CATCH role, or both.
Passes the "ambient" (last) exception to each Callable as its topic.
Calls each Callable in turn until one succeeds or they all "fail" (throw exceptions or otherwise reject a result).
Returns a value, either the result of the first successful call of a Callable or a Failure that wraps the exception thrown by the last Callable (or all exceptions if optional :$all-throws is passed).
Is not a spelling mistake.[3]
The trys code
unit module X2;
our sub trys ( **#callables, #= List of callables.
:$reject = (), #= Value(s) to be rejected.
:$all-throws = False, #= Return *all* thrown exceptions?
:$HANDLED = True, #= Mark returned `Failure` handled?
) is export {
my #throws; #= For storing all throws if `$all-throws`.
$! = CLIENT::<$!>; # First callable's `$!` is `trys` caller's.
#throws.push: $! if $! && $all-throws; # Include caller's `$!` in list of throws.
my $result is default(Nil); # At least temporarily preserve a `Nil` result.
for #callables -> &callable {
$result = try { callable $! } # `try` next callable, passing `$!` from prior callable as topic.
if not $! and $result ~~ $reject.any # Promote result to exception?
{ $! = X::AdHoc.new: payload => "Rejected $result.gist()" }
#throws.push: $! if $! && $all-throws;
return $result if not $!; # Return result if callable didn't throw.
}
$! = X::AdHoc.new: payload => #throws if $all-throws;
given Failure.new: $! { # Convert exception(s) to `Failure`.
.handled = $HANDLED;
.return
}
}
Code on glot.io (includes all trys code in this answer).
trys in detail
use X2;
# `trys` tries a list of callables, short circuiting if one "works":
say trys {die}, {42}, {fail} # 42
# By default, "works" means no exception thrown and result is not a `Failure`:
say trys {die}, {fail}, {42} # 42
# An (optional) `:reject` argument lets you specify
# value(s) you want rejected if they smartmatch:
say trys :reject(Nil,/o/), {Nil}, {'no'}, {2} # 2
# If all callables throw, return `Failure` wrapping exceptions(s):
say trys :reject(Nil), {Nil} # (HANDLED) Rejected Nil
say trys {die} # (HANDLED) Died
say trys {(42/0).Str} # (HANDLED) Attempt to divide by zero
# Specify `:!HANDLED` if the returned `Failure` is to be left unhandled:
say (trys {(42/0).Str}, :!HANDLED) .handled; # False
# The first callable is passed the caller's current exception as its topic:
$! = X::AdHoc.new: payload => 'foo';
trys {.say} # foo
# Topic of subsequent callables is exception from prior failed callable:
trys {die 'bar'}, *.say; # bar
trys {fail 'bar'}, {die "$_ baz"}, *.say; # bar baz
# Caller's `$!` is left alone (presuming no `trys` bug):
say $!; # foo
# To include *all* throws in `Failure`, specify `:all-throws`:
say trys {die 1}, {die 2}, :all-throws; # (HANDLED) foo 1 2
# Note the `foo` -- `all-throws` includes the caller's original `$!`.
trys "traps"
# Some "traps" are specific to the way `trys` works:
say trys { ... } // 42; # "(HANDLED) Stub code executed"
say trys { ... }, { 42 } # 42 <-- List of blocks, no `//`.
#trys 22; # Type check failed ... got Int (22)
say trys { 22 } # 22 <-- Block, not statement.
#trys {} # Type check failed ... got Hash ({})
say trys {;} # Nil <-- Block, not Hash.
# Other "traps" are due to the way Raku works:
# WAT `False` result if callable has `when`s but none match:
say do {when rand { 42 }} # False <-- It's how Raku works.
say trys {when rand { 42 }} # False <-- So same with `trys`.
say trys {when rand { 42 }; Nil} # Nil <-- Succinct fix.
say trys {when rand { 42 }; default {}} # Nil <-- Verbose fix.
# Surprise `(Any)` result if callable's last/return value is explicitly `$!`:
$! = X::AdHoc.new: payload => 'foo';
say try {$!} # (Any) <-- Builtin `try` clears `$!`.
say $!; # (Any) <-- Caller's too!
$! = X::AdHoc.new: payload => 'foo';
say trys {$!} # (Any) <-- `trys` clears `$!` BUT:
say $!; # foo <-- Caller's `$!` left alone.
$! = X::AdHoc.new: payload => 'foo';
say try {$!.self} # foo <-- A fix with builtin `try`.
say $!; # (Any) <-- Caller's `$!` still gone.
$! = X::AdHoc.new: payload => 'foo';
say trys {.self} # foo <-- Similar fix with `trys`.
say $!; # foo <-- Caller's `$!` left alone.
Discussion of your attempts
My first Raku attempt was like so:
sub might-throw($a, $b) { die "Zero" if $b == 0; $a / $b }
my $quotient = do { might-throw($a, $b); CATCH { default { -1 } } };
A CATCH block always returns Nil. It's the last statement in the closure body so a Nil is always returned. (This is a footgun that plausibly ought be fixed. See further discussion in Actually CATCHing exceptions without creating GOTO)
I might write for example:
my $quotient = try { might-throw($a, $b) } // -1;
the expression I'm evaluating might genuinely have an undefined value, and I can't distinguish this from the case where an exception was thrown.
You could instead write:
my $quotient is default(-1) = try { might-throw($a, $b) }
What's going on here:
The is default trait declares what a variable's default value is, which is used if it's not initialized and also if there's an attempt to assign Nil. (While Nil is technically an undefined value, its purpose is to denote "Absence of a value or benign failure".)
try is defined to return Nil if an exception is thrown during its evaluation.
This may still be unsatisfactory if one wants to distinguish between a Nil that's returned due to an exception being thrown and one due to ordinary return of a Nil. Or, perhaps more importantly:
I might want to fall back to different values depending on the class of the thrown exception, but try just swallows them all.
This needs a solution, but not CATCH:
I can put my own CATCH block in the try to distinguish among the exceptions, but then I'm back at the first case above
Instead, there's now the trys function I've created.
Footnotes
[1] As you noted: "The current answers ... are focusing too narrowly on the semantics of the division operator.". So I've footnoted my summary of that aspect, to wit: to support advanced math, Raku doesn't automatically treat a rational divide by zero (eg 1/0) as an exception / error. Raku's consequent double delayed exception handling is a red herring.
[2] CATCH is also a red herring. It doesn't return a value, or inject a value, even when used with .resume, so it's the wrong tool for doing the job that needs to be done.
[3] Some might think trys would best be spelled tries. But I've deliberately spelled it trys. Why? Because:
In English, to the degree the the word tries is related to try, it's very closely related. The sheer oddness of the word choice trys is intended to remind folk it's not just a plural try. That said, the rough meaning is somewhat closely related to try, so spelling it trys still makes sense imo.
I like whimsy. Apparently, in Albanian, trys means "to press, compress, squeeze". Like try, the trys function "presses" code ("to press" in the sense of "to pressure"), and "compresses" it (as compared to the verbosity of not using trys), and "squeezes" all the exception related error mechanisms -- Exceptions, Failures, Nils, try, CATCH, .resume -- into one.
In Lithuanian, trys means "three". trys:
Rejects results of three kinds: Exceptions; Failures; and user specified :reject values.
Keeps things rolling in three ways: passes caller's $! to the first callable; calls subsequent callables with last exception as their topic; turns an exception thrown in the last block into a Failure.
Tackles one of the hardest things in programming -- naming things: trys is similar to but different from try in an obvious way; I hereby predict few devs will use the Albanian or Lithuanian words trys in their code; choosing trys instead of tries makes it less likely to clash with existing code. :)
This seems to be a design and/or implementation defect:
Rakudo happily divides an Int by 0, returning a Rat. You can .Num it (yielding Inf) and .perl it, but it will blow up if you try to .Str or .gist it.
In contrast, dividing by the Num 0e0 will fail immediately.
For the sake of consistency, integer division by zero should probably fail as well. The alternative would be returning a regular value that doesn't blow up when stringified, but I'd argue against it...
I got the following to work:
use v6;
my $a = 1;
my $b = 0;
my $quotient = $a / $b;
try {
#$quotient; # <-- Strangely, this does not work
"$quotient";
CATCH {
when X::Numeric::DivideByZero {
$quotient = -1;
}
default { fail }
}
}
say "Value of quotient: ", $quotient;
Output:
Value of quotient: -1
However, if I don't stringify $quotient in the try clause, it instead gives
Useless use of $quotient in sink context (line 9)
Attempt to divide 1 by zero using div
in block <unit> at ./p.p6 line 18
I am not sure if this can be a bug..
Edit:
To address the question of the return value from the CATCH block. You can work around the issue that it does not return a value to the outer scope by instead calling the resume method:
my $a = 1;
my $b = 0;
my $quotient = do {
my $result = might-throw($a, $b);
CATCH {
default {
say "Caught exception: ", .^name;
.resume;
}
}
$result; #<-- NOTE: If I comment out this line, it does not work
# A bug?
};
sub might-throw($a, $b) {
if $b == 0 {
die "Zero";
-1; # <-- the resume method call from CATCH will continue here
}
else {
$a / $b
}
}
So we've got a function. Sometimes it returns Any (undef) other wise is return $a / $b unless $b is 0 in which case it throws an exception.
sub might-throw($a, $b) {
return Any if (True, False, False, False, False).pick();
die "Zero" if $b == 0;
$a / $b;
}
We want quotient to be the value of the function call unless it throws an exception, in which case we want -1.
Lets make 20 random pairs and try it out :
for 1..20 {
my $a = (0..2).pick;
my $b = (0..2).pick;
my $quotient = -1;
try {
let $quotient = might-throw($a, $b);
$quotient ~~ Any|Numeric;
}
say "{$a}/{$b} is {$quotient} maybe..";
}
So we start be predefining the quotient to the error state. Then in a try block we call out function using let to set it. the let will be rolled back if the function errors or the block returns undef... Hence we test that $quotient is an Any or a Numeric.
Other answers have helpfully focused on the "why", so here's one focused just on the "how".
You asked how to rewrite
sub might-throw($a, $b) { die "Zero" if $b == 0; $a / $b }
my $quotient = do { might-throw($a, $b); CATCH { default { -1 } } };
so that it sets $quotient to the provided default when $b == 0. Here are two ways:
Option 1
sub might-throw($a, $b) { die "Zero" if $b == 0; $a / $b }
my $quotient = sub { might-throw($a, $b); CATCH { default { return -1 } } }();
Option 2
sub might-throw1($a, $b) { die "Zero" if $b == 0; $a / $b }
my $quotient = do with try might-throw1($a, $b) { $_ } elsif $! { -1 };
A few explanatory notes: CATCH blocks (and phasers more generally) do not implicitly return their last expression. You can explicitly return with the return function, but only from within a Routine (that is, a method or a sub). Option 1 wraps the block you provided in an immediately invoked anonymous sub, which gives you a scope from which to return.
Option 2 (which would be my preference) switches to try but addresses the two problems you noted with the try {…} // $default approach by taking advantage of the fact that try sets the value of $! to the last exception it caught.
You mentioned two problems with try {…} // $default. First, that you want to distinguish between an exception and a genuinely undefined value. Option 2 does this by testing whether try captured an exception – if &might-throw returned an undefined value without throwing an exception, $quotient will be undefined.
Second, you said that you "might want to fall back to different values depending on the class of the thrown exception". Option 2 could be extended to do this by matching on $! within the elsif block.
I think that creating an infix operator would make some sense.
sub infix:<rescue> ( $l, $r ) {
# return right side if there is an exception
CATCH { default { return $r }}
return $r if $l ~~ Nil; # includes Failure objects
return $r if $l == NaN;
# try to get it to throw an exception
sink $l;
sink ~$l; # 0/0
# if none of those tests fail, return the left side
return $l;
}
A quick copy of what you have into using this new operator:
my ($a,$b) = 0,0;
my $quotient = do { try { $a / $b } rescue -1 };
Which can of course be simplified to:
my $quotient = $a / $b rescue -1;
This doesn't cover the ability to have multiple typed rescue tests like Ruby.
(It wouldn't fit in with Raku if it did, plus CATCH already handles that.)
It also doesn't actually catch exceptions, so you would have to wrap the left side with try {…} if it could potentially result in one.
Of course once we get macros, that might be a whole other story.
(The best way to solve a problem is to create a language in which solving the problem is easy.)
If leave(value) were implemented you could maybe have used it in your CATCH block.
leave(value) as far as I know is supposed to be similar to return(value), which was part of the reason I used a sub.
do { might-throw($a, $b); CATCH { default { leave(-1) } } };
Though it might also not work because there are the two blocks created by CATCH {…} and default {…}.
This is all hypothetical anyway as it is not implemented.
If rescue were to actually be added to Raku, a new method might be in order.
use MONKEY-TYPING;
augment class Any {
proto method NEEDS-RESCUE ( --> Bool ){*}
multi method NEEDS-RESCUE ( --> False ){} # includes undefined
}
augment class Nil { # includes Failure objects
multi method NEEDS-RESCUE ( --> True ){}
}
# would be in the Rational role instead
augment class Rat {
multi method NEEDS-RESCUE (Rat:D: ){
$!denominator == 0
}
}
augment class FatRat {
multi method NEEDS-RESCUE (FatRat:D: ){
$!denominator == 0
}
}
augment class Num {
multi method NEEDS-RESCUE (Num:D: ){
self.isNAN
}
}
sub infix:<rescue> ( $l, $r ){
$l.NEEDS-RESCUE ?? $l !! $r
}
say 0/0 rescue -1; # -1
say 0/1 rescue -1; # 0
say NaN rescue -1; # -1

How can you emulate recursion with a stack?

I've heard that any recursive algorithm can always be expressed by using a stack. Recently, I've been working on programs in an environment with a prohibitively small available call stack size.
I need to do some deep recursion, so I was wondering how you could rework any recursive algorithm to use an explicit stack.
For example, let's suppose I have a recursive function like this
function f(n, i) {
if n <= i return n
if n % i = 0 return f(n / i, i)
return f(n, i + 1)
}
how could I write it with a stack instead? Is there a simple process I can follow to convert any recursive function into a stack-based one?
If you understand how a function call affects the process stack, you can understand how to do it yourself.
When you call a function, some data are written on the stack including the arguments. The function reads these arguments, does whatever with them and places the result on the stack. You can do the exact same thing. Your example in particular doesn't need a stack so if I convert that to one that uses stack it may look a bit silly, so I'm going to give you the fibonacci example:
fib(n)
if n < 2 return n
return fib(n-1) + fib(n-2)
function fib(n, i)
stack.empty()
stack.push(<is_arg, n>)
while (!stack.size() > 2 || stack.top().is_arg)
<isarg, argn> = stack.pop()
if (isarg)
if (argn < 2)
stack.push(<is_result, argn>)
else
stack.push(<is_arg, argn-1>)
stack.push(<is_arg, argn-2>)
else
<isarg_prev, argn_prev> = stack.pop()
if (isarg_prev)
stack.push(<is_result, argn>)
stack.push(<is_arg, argn_prev>)
else
stack.push(<is_result, argn+argn_prev>)
return stack.top().argn
Explanation: every time you take an item from the stack, you need to check whether it needs to be expanded or not. If so, push appropriate arguments on the stack, if not, let it merge with previous results. In the case of fibonacci, once fib(n-2) is computed (and is available at top of stack), n-1 is retrieved (one after top of stack), result of fib(n-2) is pushed under it, and then fib(n-1) is expanded and computed. If the top two elements of the stack were both results, of course, you just add them and push to stack.
If you'd like to see how your own function would look like, here it is:
function f(n, i)
stack.empty()
stack.push(n)
stack.push(i)
while (!stack.is_empty())
argi = stack.pop()
argn = stack.pop()
if argn <= argi
result = argn
else if n % i = 0
stack.push(n / i)
stack.push(i)
else
stack.push(n)
stack.push(i + 1)
return result
You can convert your code to use a stack like follows:
stack.push(n)
stack.push(i)
while(stack.notEmpty)
i = stack.pop()
n = stack.pop()
if (n <= i) {
return n
} else if (n % i = 0) {
stack.push(n / i)
stack.push(i)
} else {
stack.push(n)
stack.push(i+1)
}
}
Note: I didn't test this, so it may contain errors, but it gives you the idea.
Your particular example is tail-recursive, so with a properly optimising compiler, it should not consume any stack depth at all, as it is equivalent to a simple loop. To be clear: this example does not require a stack at all.
Both your example and the fibonacci function can be rewritten iteratively without using stack.
Here's an example where the stack is required, Ackermann function:
def ack(m, n):
assert m >= 0 and n >= 0
if m == 0: return n + 1
if n == 0: return ack(m - 1, 1)
return ack(m - 1, ack(m, n - 1))
Eliminating recursion:
def ack_iter(m, n):
stack = []
push = stack.append
pop = stack.pop
RETURN_VALUE, CALL_FUNCTION, NESTED = -1, -2, -3
push(m) # push function arguments
push(n)
push(CALL_FUNCTION) # push address
while stack: # not empty
address = pop()
if address is CALL_FUNCTION:
n = pop() # pop function arguments
m = pop()
if m == 0: # return n + 1
push(n+1) # push returned value
push(RETURN_VALUE)
elif n == 0: # return ack(m - 1, 1)
push(m-1)
push(1)
push(CALL_FUNCTION)
else: # begin: return ack(m - 1, ack(m, n - 1))
push(m-1) # save local value
push(NESTED) # save address to return
push(m)
push(n-1)
push(CALL_FUNCTION)
elif address is NESTED: # end: return ack(m - 1, ack(m, n - 1))
# old (m - 1) is already on the stack
push(value) # use returned value from the most recent call
push(CALL_FUNCTION)
elif address is RETURN_VALUE:
value = pop() # pop returned value
else:
assert 0, (address, stack)
return value
Note it is not necessary here to put CALL_FUNCTION, RETURN_VALUE labels and value on the stack.
Example
print(ack(2, 4)) # -> 11
print(ack_iter(2, 4))
assert all(ack(m, n) == ack_iter(m, n) for m in range(4) for n in range(6))
print(ack_iter(3, 4)) # -> 125