beginner's question

D

Dave Slayton

Ok, let's see if I may ask a fairly basic question (as opposed to an
advanced one) and get a useful answer. I hope so.

I see that this:

*PI = \3.14159265358979;

will create a constant that I may not change. Sure, why change $PI anyway,
even if you could, otherwise why set up the constant in the first place?

But, if I understand, it only modifies the scalar entry in the *PI typeglob,
making it refer now to some address in memory that holds this value for pi.
So I don't see why it should be IMPOSSIBLE to change its value, unless
there's something I don't yet understand about typeglobs. It would make
sense if it's merely POLICY, and if, for instance, it's implemented by Perl
underneath as a pointer to constant, once Perl notices it's a reference to a
scalar literal. Would someone please offer me a little guidance on this
issue? Thanks!
 
D

Dave Slayton

Sherm Pendley said:
Why do you imagine you wouldn't? This group can be harsh to those who ask
FAQs, or ignore the guidelines, but that's in response to rude behavior,
not just random flames.

Ok! (But I'm unsure what the guidelines might be, beyond trying as hard as
one can to search the FAQs before
coming here to ask questions.)
I'm not sure why you'd do it that way. The "normal" way of creating
constants
in Perl is the constant module. For example:

use constant PI => 3.14159265358979;

because it's on page 295 of Programming Perl (as is the solution you
offered), which I'm reading and
trying to absorb and understand...my purpose is not so much to define a
constant as to understand
how it all works
Constants declared this way are evaluated at compile-time, and their value
treated as if it were a literal value in your code. You can see that by
using
the B::Deparse module to turn the compiled bytecodes back into Perl
source:

sherm:~ sherm$ perl -MO=Deparse -e 'use constant PI=>3.14; print PI'
use constant ('PI', 3.14);
print 3.14;
-e syntax OK

Note the deparsed print statement - it's not printing the value of a
variable,
it's printing a literal value.

Also, note that PI is PI - not $PI. Constants aren't variables, and you
don't
need a type identifier when you use them.


It's impossible to change because the thing the typeglob is now referring
to
is a literal, which can't be changed. On the other hand, you *can* change
the
typeglob itself, so that it refers to something else, or if you declare it
as
a reference to a variable, you can change that variable's value:

Ok, well it's sounding more and more like if I knew where to look in the
Perl source code,
I'd find the literal placed in a memory location defined as something like
double *const hisliteralvalue;
thus forbidding it to be changed...otherwise, why couldn't it be changed?
the value has
to be stored in memory somewhere...maybe it boils down to the underlying
implementation
of lvalues and rvalues, which I'm also unsure of...
I see it doesn't have anything to do with the fact it's part of a typeglob,
because I see
that
$huh = \3.14159;
$$huh = \2.71828;
is likewise disallowed.

Anyhow, thanks for answering.
 
D

DJ Stunks

Subject: beginner's question

Please put the subject of your post in the Subject of the post.
I'm not sure why you'd do it that way. The "normal" way of creating constants
in Perl is the constant module. For example:

use constant PI => 3.14159265358979;

And the new "normal" way is to use Readonly, which allows constants to
be interpolated, allows the creation of complex constants (like
hashes, arrays, HoAs, HoHs, etc) and allows the creation of lexical
constants (among other advantages).

use Readonly;
Readonly my $PI => 3.14159265358979;

Although I suppose if I just wanted pi, I might use Math::Trig which
defines pi.

:)

-jp
 
M

Mark Clements

DJ said:
Please put the subject of your post in the Subject of the post.


And the new "normal" way is to use Readonly, which allows constants to
be interpolated, allows the creation of complex constants (like
hashes, arrays, HoAs, HoHs, etc) and allows the creation of lexical
constants (among other advantages).

Just to nitpick: use constant also allows you to define complex constants.

F:\Documents and Settings\Mark3>cat testconstant.pl
use strict;
use warnings;

use Data::Dumper;

use constant HoH => {
abcd => {
a=> 10,
b=> 20,
},
efgh => {
c => 30,
d => 40,
},

};

print Dumper HoH;

print HoH->{abcd}->{b}."\n";


F:\Documents and Settings\Mark3>perl testconstant.pl
$VAR1 = {
'efgh' => {
'c' => 30,
'd' => 40
},
'abcd' => {
'a' => 10,
'b' => 20
}
};
20


F:\Documents and Settings\Mark3>perl -v

This is perl, v5.8.8 built for MSWin32-x86-multi-thread

Admittedly I can't get it to work for hash slices :)


Mark
 
M

Mark Clements

Mark said:
Just to nitpick: use constant also allows you to define complex constants.
Admittedly I can't get it to work for hash slices :)
.... and it won't work with hash operators eg keys, values.

I knew there was a reason why I rarely use this in anger.

Mark
 
P

Peter J. Holzer

No, I weren't! But now that you wrote this... c'mon, please explain!!

In FORTRAN (like in perl) arguments are passed to subroutines by
reference. If you pass a literal to a subroutine, the compiler puts the
literal into a temporary variable and passes a reference to that
variable to the subroutine. Conceptionally the argument is read-only in
this case, and must not be modified. However, the compiler isn't
required to assure this (FORTRAN, like C, is one of those languages
where just about any programming error leads to undefined behaviour).

Also, since FORTRAN was developed at a time when memory was very tight,
most FORTRAN compilers fold all occurrences of a given constant into
one.

so if you have fortran code like this

call f(5)
do 1 i=1,5
print *,i
1 continue

subroutine f(n)
n=10
return

the compiler would replace all occurences of 5 with a single internal
variable, which would be set to 10 in the subroutine f, so the loop
would run 10 times instead of 5 times.

hp
 
D

DJ Stunks

Well, this is a *slightly* flame-baiting subject: some prefer one
module, some the other. In doubt let's mention both and not start a
value attribution competition...

No flame intended, I assure you. The primary (though minor)
disadvantage of Readonly as I see it, is that you have to download
it. Maybe at some point it will make it into Perl core. Also, as the
module's author admits, it's slow, but that's why there's Readonly::XS
- the issue there being that you have to compile it.

-jp
 
B

Beliavsky

InFORTRAN(like in perl) arguments are passed to subroutines by
reference. If you pass a literal to a subroutine, the compiler puts the
literal into a temporary variable and passes a reference to that
variable to the subroutine. Conceptionally the argument is read-only in
this case, and must not be modified. However, the compiler isn't
required to assure this (FORTRAN, like C, is one of those languages
where just about any programming error leads to undefined behaviour).

Also, since FORTRAN was developed at a time when memory was very tight,
most FORTRAN compilers fold all occurrences of a given constant into
one.

so if you have fortran code like this

call f(5)
do 1 i=1,5
print *,i
1 continue

subroutine f(n)
n=10
return

the compiler would replace all occurences of 5 with a single internal
variable, which would be set to 10 in the subroutine f, so the loop
would run 10 times instead of 5 times.

The code given is not standard Fortran (as its author knows), so the
compiler is free to do what it wants. For the code

program main
call f(5)
do i=1,5
print*,i
end do
end program main

subroutine f(n)
n=10
return
end subroutine f

On Windows, the g95, Intel, and Lahey/Fujitsu compilers give output

1
2
3
4
5

I think Mr. Holzer's comments describe what Fortran compilers used to
do -- I have heard similar stories before -- but not what they do
know, fortunately.
 
J

Joe Smith

Dave said:
Ok, well it's sounding more and more like if I knew where to look in the
Perl source code,
I'd find the literal placed in a memory location defined as something like
double *const hisliteralvalue;
thus forbidding it to be changed...otherwise, why couldn't it be changed?
the value has to be stored in memory somewhere...

One of the questions on a Purity Test for programmers is:

Q1a: Have you ever changed the value of 4?
Q1b: ... In a language other than FORTRAN?

The FORTRAN compiler I worked with passed literals by reference, exactly
the same way it passed variables by reference to functions and subroutines.
If a function/subroutine modified its arguments, it would change the
constant, and the changed constant would be passed to the next
function/subroutine to be called with that same literal value.

Perl does not have this problem. Read-only variables and constants are
marked as such. Perl execution triggers a fatal error on attempt to
modify read-only data.

-Joe
 
P

Peter J. Holzer

On 03 Feb 2007 19:16:30 -0600, Lawrence Statton XE2/N1GAK
<[email protected]> wrote:
3.14159=2.71828; # Would you expect this to work?!?
You were never aFortranprogrammer, were you :)
No, I weren't! But now that you wrote this... c'mon, please explain!!

InFORTRAN(like in perl) arguments are passed to subroutines by
reference. If you pass a literal to a subroutine, the compiler puts the
literal into a temporary variable and passes a reference to that
variable to the subroutine. Conceptionally the argument is read-only in
this case, and must not be modified. However, the compiler isn't
required to assure this (FORTRAN, like C, is one of those languages
where just about any programming error leads to undefined behaviour).

Also, since FORTRAN was developed at a time when memory was very tight,
most FORTRAN compilers fold all occurrences of a given constant into
one.

so if you have fortran code like this
[horrible pseudo-fortran77 deleted]

the compiler would replace all occurences of 5 with a single internal
variable, which would be set to 10 in the subroutine f, so the loop
would run 10 times instead of 5 times.

The code given is not standard Fortran (as its author knows),

Yes, sorry. My Fortran is very rusty - I never did much Fortran
programming and the little bit I did was 15+ years ago. I get to look at
some Fortran code (mostly F77, with a few bits of F90 and Fortran IV
sprinkled into it) every year or two, though.
I think Mr. Holzer's comments describe what Fortran compilers used to
do -- I have heard similar stories before -- but not what they do
know, fortunately.

Yup. Compiler technology has come a long way in the last 20 years. It
also depends on the platform - I don't think folding integer constants
makes much sense (performance- or space-wise) on Intel processors (but
the Intel Fortran compiler I used in the late 1980's did it anyway).

hp
 
A

anno4000

Mark Clements said:
Just to nitpick: use constant also allows you to define complex constants.

Not quite. You can put a complex structure in a constant, but that
doesn't make the structure constant. With Readonly you can make
deeply immutable structures.
F:\Documents and Settings\Mark3>cat testconstant.pl
use strict;
use warnings;

use Data::Dumper;

use constant HoH => {
abcd => {
a=> 10,
b=> 20,
},
efgh => {
c => 30,
d => 40,
},

};

print Dumper HoH;

print HoH->{abcd}->{b}."\n";

Now do

HoH->{abcd}->{b} = 123;

and print it again.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,269
Messages
2,571,098
Members
48,773
Latest member
Kaybee

Latest Threads

Top