# Can I embed subroutines? - Page 2

•  Subject
• Author
• Posted on

## Re: Can I embed subroutines?

On 08/04/2015 03:00 AM, Rainer Weikusat wrote:

I am as I write this.  It has syntax errors.

## Re: Can I embed subroutines?

On 08/07/2015 04:20 PM, T wrote:

Found the missing semicolon

## Re: Can I embed subroutines?

On 08/07/2015 06:08 PM, T wrote:

Subs don't terminate with a semicolon, but variable
declarations do.

## Re: Can I embed subroutines?

The code I posted didn't. It compiles with perl -cw -Mstrict without
errors and prints the first 16 Fibonacci numbers when executed.

## Re: Can I embed subroutines?

On 08/08/2015 04:44 AM, Rainer Weikusat wrote:

Found a fixed and learned something.

I was just confused as to were you got your Fibonacci
chain from.  And, where did you apply the seed, if
any?

## Re: Can I embed subroutines?

sub make_fibber
{
my (\$v0, \$v1);

return sub {
my \$next = \$v0 + \$v1 || 1;

\$v0 = \$v1;
\$v1 = \$next;

return \$next;
};
}

The important thing to note here is that make_fibber returns a newly
created subroutine which will retain access to the \$v0 and \$v1 which
existed at the time the subroutine was created and which are going to be
used to hold the last two Fibonacci numbers which are needed in creating
the next one. Initially, they have no value which counts as 0 when used
as a number. I consider this a feature. Outputs are calculated as

my \$next = \$v0 + \$v1 || 1;

This means 'The next Fibonacci number is the sum of \$v0 and \$v1 unless
this sum is 0. In this case, use 1'. The second case occurs only when
the returned closure is called for the first time.

## Re: Can I embed subroutines?

It's probably a lot simpler to intuitively grok what things
like this mean if you have a background in C - quite a bit
of Perl's syntax is derived from C. And if you know C you'll
feel comfortable with pointers.

The most trivial notion of what a pointer is is that it's just
a variable with the address of something else. That's in part
correct and part short of the mark: a pointer isn't just a
what's pointing to. You can have pointers to integers, poin-
ters to floating point numbers, pointers to strings, pointers
to functions (or even pointers to pointers) - and what it
points to makes a difference in how it can be used (though,
in C a pointer also can be "reduced" to a mere adress if
needed for some reasons).

Perl extends this concept a bit further and thus calls pointers
'references'. E.g., in C a pointer to an array is just a pointer
to the first element of the array and does not carry also the
information about the size of the array, while a Perl reference
to an array contains that additional information.

Perl also uses the '->' operator from C. In C it's only used in
connections with so-called structures, which are basically just
collections of data fields with names. In C you may have e.g.

struct MyStruct {
int    x;
double y;
};

That's a user-defined type, here a collection two data fields,
one for an integer, named 'x', and one for a floating point
value, named 'y'. If you need an instance of such a structure,
named 'z', you'd write

struct MyStruct z;

You then can assign to the fields of 'z' with e.g.

z.x = 42;
z.y = 3.14159265359;

Of course, you can also create pointers to instances of such
tructures - you'd create one to 'z' by writing

struct MyStruct * pz = &z;

This is just saying 'pz' is a new variable that is a pointer
to a struct of type MyStruct, and it's initialized to the
rator" - similar to how the backslash is used in Perl for
creating a reference).

Now, given such a pointer to a structure, how do you get at
its data fields? The most convenient way is to use the '->'
operator. So if you want to change the integer field called
'x' of the MyStruct structure pointed to by 'pz' you can
write

pz->x = 17;

And Perl has incorporated that concept (and did run with it,
boldly using it in places never considered in C): whenever
you have a reference to something with an "inner structure"
you can use '->' to get at the innards of what the reference
is referencing.

The simplest example is probably an array:

my @arr = ( 1, 2, 3 );
my \$arr_ref = \@arr;
print \$arr_ref->[ 0 ], "\n";

This is going to print out the first element (with index 0)
of the array '\$arr_ref' is a reference to.

The same works for hashes:

my %hash = ( good => 1,
my \$hash_ref = \%hash;
print \$hash_ref->{ good }, "\n";

And when '\$fibber' (that's what started the whole discussion)
is a reference to a function, then

\$fibber->( );

is just a call (with no arguments) of the function '\$fibber'
is a reference to. So you can do things like this

sub foo {
my \$a = shift;
print "In function foo, called with argument \$a\n";
}

my \$foo_ref = \&foo;
\$foo_ref->( 'bla' );

This may look arcane (or even useless;-) at the moment, but
there's a lot of places all this can be very handy.

Regards, Jens
--
\   Jens Thoms Toerring  ___      jt@toerring.de
\__________________________      http://toerring.de

## Re: Can I embed subroutines?

On 08/06/2015 04:52 PM, Jens Thoms Toerring wrote:

Hi Jens,

Wonderful way of stating it.  Very clear.  The word "pointer"
can have a specific and a general meaning.  Relating this to
"C" was beautiful.

By the way in Modula2, a pointer just points to the first element.

-T

## Re: Can I embed subroutines?

On 08/06/2015 04:52 PM, Jens Thoms Toerring wrote:

Extraordinary tutorial!  Thank you!

my @arr = ( 1, 2, 3 );
my \$arr_ref = \@arr;
print \$arr_ref->[ 0 ], "\n";

Would these two be the same thing?

print \$arr_ref->[ 0 ], "\n";
print \$\$arr_ref[ 0 ],  "\n";

-T

## Re: Can I embed subroutines?

Yes. And you can also do it with

print @\$arr_ref[ 0 ],  "\n";

As usual in Perl, there's more than one way to do it. Can

Regards, Jens
--
\   Jens Thoms Toerring  ___      jt@toerring.de
\__________________________      http://toerring.de

## Re: Can I embed subroutines?

On 08/07/2015 05:20 PM, Jens Thoms Toerring wrote:

Hi Jens,

Thank you!  I just included it in my notes.

Just out of curiosity, how are you getting away with addressing
an element in an array with "@"

print @\$arr_ref[ 0 ],  "\n";

Where ever I do it I get the finger shaken at me.

\$ perl -e 'use strict; use warnings; my @A=(11,22,33); print "@A[2]
\n";'

Scalar value @A[2] better written as \$A[2] at -e line 1.
33

It is a real pain in the butt, as it is intuitive to me
to address a value in an array with the array symbol.
And I have to go back over everything and change them.

Well, right after I insert all the missing semicolons
Bash doesn't use a semicolon at the end the line but
does use them to break up command like Perl does.  I
wonder if next time I do some more Bash programming
if I will start putting semicolons at the end of each
line.  Pavlovian response.

Thank you for the help!
-T (a.k.a. Todd)

## Re: Can I embed subroutines?

There's a difference between '@A[2]' and '@\$arr_ref[2]' - the
first one is considered a bit fishy by Perl, but the second
does not give that warning (at least for me).

If you look up the explanation for the warning in 'perldoc perldiag'
you'll find

Scalar value @%s[%s] better written as \$%s[%s]
(W syntax) You've used an array slice (indicated by @) to select a
single element of an array.  Generally it's better to ask for a
scalar value (indicated by \$).  The difference is that \$foo[&bar]
always behaves like a scalar, both when assigning to it and when
evaluating its argument, while @foo[&bar] behaves like a list when
you assign to it, and provides a list context to its subscript,
which can do weird things if you're expecting only one subscript.

On the other hand, if you were actually hoping to treat the array
element as a list, you need to look into how references work,
because Perl will not magically convert between scalars and lists
for you.  See perlref.

BTW, if you want to get that kind of explanation for every

use diagnostics;

to ypur scripts and Perl becomes a lot more verbose in these cases.

It's different for '@\$arr_ref[2]': here, given that '\$arr_ref' is
a reference, the '@' works as the "dereferencing operator", giving
you the underlying array you then can use the '[]' on - there does
not seem to be a possible problem with getting confused with an
array slice (or at least Perl didn't warn me about it;-)

Regards, Jens
--
\   Jens Thoms Toerring  ___      jt@toerring.de
\__________________________      http://toerring.de

## Re: Can I embed subroutines?

On 08/08/2015 04:18 AM, Jens Thoms Toerring wrote:

Hi Jens,

"use diagnostics;" is now in my template.  :-)

Thank you for helping me with this!
-T

## Re: Can I embed subroutines?

What does this question mean? At the highest level, it's 'calculcate
the next Fibonacci number and return it'. Somewhat below, \$fibber is
Perl scalar with a name which is a silly wordplay on 'fibonacci number
producer'. It holds the return value of make_fibber which is a reference
to a subroutine which will caluclate the next Fibonacci number and
return it whenever it is invoked (a so-called generator although other
people prefer the term iterator[*]). That's a simple example for
something working in a "non-null lexical environment" because it needs
the two most recently calculated numbers in order to do that (stored in
\$v0 and \$v1). Lastly,

\$fibber->()

calls this subroutine. '->' is another way to get from a reference to
something to this something. It could also have been written as

&\$fibber()

or even

&\$fibber

## Re: Can I embed subroutines?

On 08/04/2015 03:11 AM, Rainer Weikusat wrote:

Hi Rainer,

Thank you.

-T

Where you teasing about the Fibonacci number?

## Re: Can I embed subroutines?

As Eric Pozharski pointed out, this isn't really true anymore for
sufficiently current perls: Since 5.18, the Perl compiler supports
lexcically-scoped, named subroutines as an experimental feature. As far
as I could determine from the documentation, this means that

my sub x10 { \$_[0] * 10 };

will be translated into an equivalent of

my \$x10 = sub { \$_[0] * 10 };

and invocations of x10 in the corresponding lexical scope will call this
subroutine.

I consider this of limited usefulness because it doesn't scale much
beyond one level of nesting for text-formatting reasons and I consider
the idea that 'enforced information hiding' is necessary to stop the
morons from stepping onto the grass in place they're not supposed to
misguided --- said morons (who doubtlessly exist in droves) will find
another way to cause mayhem and an attempt to teach them something about
'enlightened self interest' would seem more useful to me.

## Re: Can I embed subroutines?

jt@toerring.de (Jens Thoms Toerring) writes:

[...]

Perl doesn't support lexically scoped declarations except when using
my. Consequently, nesting B in A in the way above is just an
obfuscation: The subroutine will still have a name in the symbol table
of the current package.

## Re: Can I embed subroutines?

On 08/01/2015 05:12 AM, Rainer Weikusat wrote:

Got it.  Thank you!

## Re: Can I embed subroutines?

jt@toerring.de (Jens Thoms Toerring) writes:

[...]

A Perl module isn't really a module in the sense the term is used in
Modula but rather what's called 'a package' in Lisp (and the keyword
used for declaring one is 'package' and not 'module'): A collection of
(usually) related named things which is linked into a global,
hierarchically structured namespace.

This is implemented as set of nested hash tables: The top-level symbol
table is %:: (or %main::) and it contains a key Package:: for every
top-level package named Package. The hash-slot of the corresponding glob holds a
reference to the symbol table (hash) for the package. And so forth for
nested packages.

Two ways to get access to the coderef corresponding with a subroutine
defined in a nested package:

------------
package Something;

package Something::Else;

sub inc { \$_[0] + 1 }

package main;

my (\$inc0, \$inc1);

\$inc0 = \&Something::Else::inc;
\$inc1 = \&->->};

print("\$inc0, \$inc1\n");
------------

## Re: Can I embed subroutines?

*SKIP*

You can do things like this with 5.20 (or something).  Yes, I understand
your motivation to stay with ancient perl.

Even with your ancient perl you can achieve this (and there will be