Related
I have been assigned such a problem in my software development course. So, the normal way is to check each procedure one by one and remember each call by each subprogram, however, I am a bit lazy programmer and I have decided to take a shortcut by implementing given pseudocode in an actual programming language.
Problem statement:
procedure Main is
X, Y, Z : Integer;
procedure Sub1 is
A, Y, Z : Integer;
begin
...
end;
procedure Sub2 is
A, B, Z : Integer;
begin
...
procedure Sub4 is
A, B, W : Integer;
begin
...
end;
end;
procedure Sub3 is
A, X, W : Integer;
begin
...
end;
begin
...
end;
Consider the program above. Given the following calling sequences and assuming that
dynamic scoping is used, what variables are visible during the execution of the last subprogram
activated? Include with each visible variable the name of the unit where it is declared (e.x. Main.X).
Main calls Sub1; Sub1 calls Sub3; Sub3 calls Sub2;
My Attempt:
$x = 10;
$y = 20;
$z = 30;
sub Sub2
{
return $x;
}
sub Sub1
{
local $x = 9;
local $y = 19;
local $z = 29;
return Sub2();
}
print Sub1()."\n";
I'm stuck at this point and have no idea how to change the code so that it shows me the variables. I see that solution is obvious, but I've coded in C++ and Java so far.
It would be nice if you've spent the time you used on asking this question on watching tutorials. However, we all have been there at one point, being confused exploring new languages. Try not to ask for the answer to your homework next time.
So, I see you'd like to use Perl, a good choice. I myself have done a similar task recently, here is my approach.
As R. Sebesta (2019) writes in the book named "Concepts of Programming
Languages" (12 ed.), the best examples of dynamic scoping are Perl and
Common Lisp.
Basically, it is based on the sequence of subprogram calls which are determined only at run time.
The following program shows how the subprogram calls affect variable value:
$x = 0;
$y = 0;
$z = 0;
sub sub1
{
local $a = 1;
local $y = 1;
local $z = 1;
return sub3();
}
sub sub2
{
local $a = 2;
local $b = 2;
local $z = 2;
sub sub4
{
local $a = 4;
local $b = 4;
local $w = 4;
}
return "Sub".$a.".A, "."Sub".$b.".B, "."Sub".$w.".W, "."Sub".$x.".X,
"."Sub".$y.".Y, "."Sub".$z.".Z";
}
sub sub3
{
local $a = 3;
local $x = 3;
local $w = 3;
return sub2();
}
print sub1()."\n";
Output: Sub2.A, Sub2.B, Sub3.W, Sub3.X, Sub1.Y, Sub2.Z
Note: Sub0 is just Main subprogram scope.
If you want to check the values of the variables in each subroutine you would dump them out with a module like Data::Dump or Data::Dumper.
sub foo {
printf "foo() current values are %s\n\n",
Data::Dumper::Dumper($a, $b, $c, $x, $y, $z);
}
If you want to see the call stack of the current subroutine you would use the Carp module.
use Carp;
sub foo { Carp::cluck("foo() here"); }
sub bar { foo() }
&bar;
# Output
foo() here at (eval 284) line 1.
W::foo() called at (eval 284) line 1
W::bar() called at (eval 285) line 1
eval 'package W; bar' called at script.pl line 116
console::_console called at script.pl line 473
I want to use perl to build a document graph as readably as possible. For re-use of nodes, I want to refer to nodes using variables (or constants, if that is easier). The following code works and illustrates the idea with node types represented by literals or factory function calls to a and b. (For simple demo purposes, the functions do not create nodes but just return a string.)
sub a (#) {
return sprintf "a(%s)", join( ' ', #_ );
}
sub b (#) {
return sprintf "b(%s)", join( ' ', #_ );
}
printf "The document is: %s\n", a(
"declare c=",
$c = 1,
$e = b(
"use",
$c,
"to declare d=",
$d = $c + 1
),
"use the result",
$d,
"and document the procedure",
$e
);
The actual and expected output of this is The document is: a(declare c= 1 b(use 1 to declare d= 2) use the result 2 and document the procedure b(use 1 to declare d= 2)).
My problem arises because I want to use strict in the whole program so that variables like $c, $d, $e must be declared using my. I can, of course, write somewhere close to the top of the text my ( $c, $d, $e );. It would be more efficient at edit-time when I could use the my keyword directly at the first mention of the variable like so:
…
printf "The document is: %s\n", a(
"declare c=",
my $c = 1,
my $e = b(
"use",
$c,
"to declare d=",
my $d = $c + 1
),
"use the result",
$d,
"and document the procedure",
$e
);
This would be kind of my favourite syntax. Unfortunately, this code yields several Global symbol "…" requires explicit package name errors. (Moreover, according to documentation, my does not return anything.)
I have the idea of such use of my from uses like in open my $file, '<', 'filename.txt' or die; or in for ( my $i = 0; $i < 100; ++$i ) {…} where declaration and definition go in one.
Since the nodes in the graph are constants, it is acceptable to use something else than lexical variables. (But I think perl's built-in mechanims are strongest and most efficient for lexical variables, which is why I am inclined into this direction.)
My current idea to solve the issue is to define a function named something like define which behind the scenes would manipulate the current set of lexical variables using PadWalker or similar. Yet this would not allow me to use a natural perl like syntax like $c = 1, which would be my preferred syntax.
I am not certain of the exact need but here's one simple way for similar manipulations.
The example in the OP wants a named variable inside the function call statement itself, so that it can be used later in that statement for another call etc. If you must have it that way then you can use a do block to work out your argument list
func1(
do {
my $x = 5;
my $y = func2($x); # etc
say "Return from the do block what is then passed as arguments...";
$x, $y
}
);
This allows you to do things of the kind that your example indicates.†
If you also want to have names available in the subroutine then pass a hash (or a hashref), with suitably chosen key names for variables, and in the sub work with key names.
Alternatively, consider normally declaring your variables ahead of the function call. There's no bad thing about it while there are many good things. Can throw in a little wrapper and make it look nice, too.
† More specifically
printf "The document is: %s\n", a( do {
my $c = 1;
my $d = $c + 1;
my $e = b( "use", $c, "to declare d=", $d );
# Return a list from this `do`, which is then passed as arguments to a()
"declare c=", $c, $e, "use the result", $d,"and document the procedure", $e
} );
(condensed into fewer lines for posting here)
This do block is a half-way measure toward moving this code into a subroutine, as I presume that there are reasons to want this inlined. However, since comments indicate that the reality is even more complex I'd urge you to write a normal sub instead (in which a graph can be built, btw).
according to documentation, my does not return anything
The documentation doesn't say that, and it's not the case.
Haven't you ever done my $x = 123;? If so, you've assigned to the result of my $x. my simply returns the newly created variable as an lvalue (assignable value), so my $x simply returns $x.
Unfortunately, this code yields several [strict vars] errors.
Symbols (variables) created by my are only visible starting with the following statement.
For better of for worse, it allows the following:
my $x = 123;
{
my $x = $x;
$x *= 2;
say $x; # 246
}
say $x; # 123
I want to use perl to build a document graph as readably as possible.
So why not do that? Right now, you are building a string, not a graph. Build a graph of objects that resolve to a string after the graph has been constructed. You can build those object with a tree of sub calls (declare( c => [ use( c => ... ), ... ] )). I'd give a better example, but the grammar of what you are generating isn't clear to me.
Your argument list makes two references each to $c, $d and $e. If you prefix the first reference with my, it will be out of scope by the time Perl gets around to parsing the second reference it won't be in scope until the next statement, so the second reference would refer to a different variable (which may violate strict vars).
Declare my ($c,$d,$e) before your function call. There is nothing wrong or inelegant about doing that.
I have a strange behaved (to Python programmer) subroutine, which simplified as the following:
use strict;
use Data::Dumper;
sub a {
my #x;
sub b { push #x, 1; print "inside: ", Dumper(\#x); }
&b;
print "outside: ", Dumper(\#x);
}
&a;
&a;
I found the result is:
inside: $VAR1=[ 1 ]
outside: $VAR1 = [ 1 ]
inside: $VAR1=[1, 1]
outside: $VAR1= []
What I thought is when calling &a, #x is empty array after "my #x" and has one element after "&b", then dead. Every time I call &a, it is the same. so the output should be all $VAR1 = [ 1 ].
Then I read something like named sub routine are defined once in symbol table, then I do "my $b = sub { ... }; &$b;", it seems make sense to me.
How to explain?
As per the "perlref" man page:
named subroutines are created at compile time so their lexical
variables [i.e., their 'my' variables] get assigned to the parent
lexicals from the first execution of the parent block. If a parent
scope is entered a second time, its lexicals are created again, while
the nested subs still reference the old ones.
In other words, a named subroutine (your b), has its #x bound to the parent subroutine's "first" #x, so when a is called the first time, b adds a 1 to #x, and both the inner and outer copies refer to this same version. However, the second time a is called, a new #x lexical is created, but b still points to the old one, so it adds a second 1 to that list and prints it (inner), but when it comes time for a to print its version, it prints out the (empty) brand new lexical (outer).
Anonymous subroutines don't exhibit this problem, so when you write my $b = sub { ... }, the inner #x always refers to the "current" version of a's lexical #x.
Okay so for my math class we were asked to write a program that performs and prints Newton's method until the values converge and we have a root for the function. At first I thought it would be easy. It was until I just couldn't get the values derived from the first time to be used the second time. My knowledge of the language is basic. Really basic, so what you're about to see might not be pretty.
#!usr/bin/perl
use PDL;
print "First guess? (this is x0)\n";
$xorig = <>;
do {
&fx;
} until ($fex == 0);
sub fx {
if ($xn == 0) {
$x = $xorig;
}
else {
$x = $xn;
}
print "What is the coefficient (for each factor) of your function?\n";
$fcx = <STDIN>;
push #coefficient_of_x, $fcx;
print "... times x to the (enter exponent, if no exponent, enter 1. if no x, enter 0)?\n";
$fex = <STDIN>;
push #exponent_x, $fex;
chomp ($fcx, $fex, $x, $xorig);
$factor = $fcx * ($x ** $fex);
push #fx, $factor;
}
my $fx = 0;
foreach my $variable (#fx) {
$fx = $variable + $fx #THIS PROVIDES A VALUE FOR THE GIVEN F(X) WITH A GIVEN X VALUE
}
print "f($x)=$fx\n";
do {
&fprimex;
} until ($fprimeex == 0);
sub fprimex {
if ($xn == 0) {
$x = $xorig;
}
else {
$x = $xn;
}
print "What is the coefficient (for each factor) of your derivative function?\n";
$fprimecx = <STDIN>;
push #coefficient_of_fpx, $fprimecx;
print "... times x to the (enter exponent, if no exponent, enter 1. if no x, enter 0)?\n";
$fprimeex = <STDIN>;
push #exponent_fpx, $fprimeex;
chomp ($fprimecx, $fprimeex, $x, $xorig);
$factorprime = $fprimecx * ($x ** $fprimeex);
push #fprimex, $factorprime;
}
$fprimex = 0;
foreach my $variableprime (#fprimex) {
$fprimex = $variableprime + $fprimex #THIS PROVIDES A VALUE FOR THE GIVEN F'(X) WITH THAT SAME X VALUE
}
print "f'($x)=$fprimex\n";
sub x0 {
$xn = $xorig - $fx / $fprimex; #THIS IS NEWTON'S METHOD EQUATION FOR THE FIRST TIME
push #newxn, $xn;
print "xn ia $xn\n";
}
&x0;
foreach $value (#exponent_x) {
$exponent_x = $xn ** $value;
push #part1, $exponent_x;
$part1 = #part1;
}
foreach $value2 (#coefficient_of_x) {
$part2 = $value2 * #part1;
push #final1, $part2;
}
print "#part1\n";
print "#final1\n";
Essentially what it is is I first ask for the first guess. I use this value to define the coefficients and the exponents of f(x) to get a value for f(x) in terms of the given x. I do it again for f'(x). Then I perform newton's method the first time and get the new value xn. But I'm having a hard time to get values for f(xn) and f'(xn), meaning I can't get x(n+1) and can't continue newton's method. I need help.
Welcome to Perl.
I would strongly recommend the following changes to your code:
Always include use strict; and use warnings; in EVERY Perl script.
Always chomp your input from STDIN as your taking it:
chomp( my $input = <STDIN> );
Don't needlessly create subroutines, especially for one-off scripts such as this.
Instead of using the statement modifier form of do, I would recommend using an infinite while with loop control statements to exit:
while (1) {
last if COND;
}
Finally, since the coefficients of your polynomial are all associated with an exponent for X, I would recommend using a %hash for conveniently saving those values.
As demonstrated:
#!usr/bin/env perl
use strict;
use warnings;
print "Build your Polynomial:\n";
my %coefficients;
# Request each Coefficient and Exponent of the Polynomial
while (1) {
print "What is the coefficient (for each factor) of your function? (use a bare return when done)\n";
chomp( my $coef = <STDIN> );
last if $coef eq '';
print "... times x to the (enter exponent, if no exponent, enter 1. if no x, enter 0)?\n";
chomp( my $exp = <STDIN> );
$coefficients{$exp} = $coef;
}
print "\nFirst guess? (this is x0)\n";
chomp( my $x = <> );
# Newton's Method Iteration
while (1) {
my $fx = 0;
my $fpx = 0;
while ( my ( $exp, $coef ) = each %coefficients ) {
$fx += $coef * $x**$exp;
$fpx += $coef * $exp * $x**( $exp - 1 ) if $exp != 0;
}
print " f(x) = $fx\n";
print " f'(x) = $fpx\n";
die "Slope of 0 found at $x\n" if $fpx == 0;
my $new_x = $x - $fx / $fpx;
print "Newton's Method gives new value for x at $new_x\n";
if ( abs($x - $new_x) < .0001 ) {
print "Accuracy reached\n";
last;
}
$x = $new_x;
}
I am having trouble working out what you intended with your code. The main problem seems to be that don't have it clear in your head what each of your subroutines do, as fx and fprimex ask for the data as well as evaluating the function (except for summing the terms which, oddly, is done outside the subroutine). That isn't what you want at all, as the exponents and coefficients remain constant throughout a program that has to evaluate those functions many times, and you really don't want to ask for the values again each time.
Here are some pointers to getting Perl code working in general
Write your program in tiny chunks -- a line or two at a time -- and check after each addition that the program compiles and runs and produces the expected results. Writing an entire program before you even try to run it is a recipe for disaster
Always use strict and use warnings, and declare every variable with my as close as possible to the point where it is first used. You have many undeclared variables which are therefore global, and passing information between sections of code using global variables is a good way to lose yourself in your own code. It is a good rule for a subroutine to use only parameters passed to it or variables declared within it
chomp variables as soon as they are read, either from a file or from the terminal. A useful idiom to trim input strings at source is
chomp(my $input = <>)
which will ensure that there are no stray newlines anywhere in your data
That at least should get you started.
I'm in two minds about showing this. I hope it will help you, but I really don't want to drag you into parts of Perl that you're not familiar with.
It's a program that uses the Newton–Raphson method to find the root of polynomials. I've skipped the terminal input for now, and hard-coded the data. As it stands it finds the square root of 3,000 by finding the positive root of x2 - 3000.
Note that #f and #f_prime hold the coefficients of the function and its derivative backwards from the usual order, so #f is (-3000, 0, 1). The program also calculates the coefficients of the derivative function, as it is a simple thing to do and far preferable to asking the user for another set of values.
There is just one subroutine polynomial, which takes a value for x and a list of coefficients. This is used to calculate the value of both the function and its derivative for a given value of x.
The algorithm step is in the line
my $new_x = $x - polynomial($x, #f) / polynomial($x, #f_prime);
which calculates x - f(x) / f'(x) and assigns it to $new_x. Each successive estimate is printed to STDOUT until the loop exits.
Comparing floating-point values for equality is a bad idea. The precision of computer floating-point values is, obviously, limited, and a sequence will probably never converge to the point where the last two values of the sequence are equal. The best that can be done is to check whether the absolute value of the difference between the last two values is below a reasonable delta. An accuracy of 10E12 is reasonable for 32-bit floating-point numbers. I have found that the series converges to within 10E14 quite reliably, but if you find that your program hangs in an endless loop then you should increase the margin.
use strict;
use warnings;
my #f = reverse (1, 0, -3000);
my #f_prime = map { $f[$_] * $_ } 1 .. $#f;
my $x = 0.5;
print $x, "\n";
while () {
my $new_x = $x - polynomial($x, #f) / polynomial($x, #f_prime);
last if abs($new_x - $x) < $x / 1e14;
$x = $new_x;
print $x, "\n";
}
sub polynomial {
my ($x, #coeffs) = #_;
my $total = 0;
my $x_pow = 1;
for my $coeff (#coeffs) {
$total += $x_pow * $coeff;
$x_pow *= $x;
}
$total;
}
output
0.5
3000.25
1500.62495833681
751.312062703027
377.652538627869
192.798174296885
104.179243809523
66.4878834504349
55.8044433107163
54.7818016853582
54.7722565822241
54.7722557505166
simple thing, how to print a binary number and shift it to the left?
$num = 0b00000010001;
for(0..6){
print sprintf ("%b",$num), "\n";
$num<<1;
}
problem of this code: it doesn't print the 0's before 1! the resoult of print is just "10001", and it doesn't shift the number.
the final output should be:
00000010001
00000100010
00001000100
00010001000
00100010000
01000100000
10001000000
Just tell the formatter that you need to print exactly N (11) digits in any case, and that 0 should be used as a padding symbol:
my $num = 0b00000010001;
for (0..6) {
printf("%011b\n", $num);
$num <<= 1;
}
Demo.
Two sidenotes here
First, it's obviously redundant to do print sprintf: printf will replace it quite well.
Second, in the original code you forgot to assign the result of shifting back to $num. Had you started your script with the use warnings pragma (like in my demo), you'd have been notified about it with Useless use of left bitshift (<<) in void context...