Unblessed reference.

J

Justin C

I'm using Spreadsheet::WriteExcel, and (I think) I've created a
reference to the worksheet. When I try to use this elsewhere I get:
Can't call method ... on unblessed reference at ...

This is the minumum I've been able to cut the code down to (sorry it's
not shorter). The problem line is 26. As per the Spreadsheet::WriteExcel
documentation I've created the object, and it's a reference to that
object that I've passed from a subroutine to Main:: to pass on to other
subroutines.

I'm slowly getting to grips with references, I seem to be OK (mostly)
with scalar, array, and harh refs, but what is this? An object
reference? I'm working on it but I haven't got it yet. Anyway, here's
the code.

#!/usr/bin/perl

use warnings;
use strict;
use Spreadsheet::WriteExcel;

my ($worksheet, $format) = create_excel_file();

artist_chart() ;

sub artist_chart {
my ($position, $last_month, $artist) = ('7', '4', 'Banksy');
populate_spreadsheet(0, $position, $last_month, $artist);
}
sub create_excel_file {
my $fname = "/var/local/chart/boris.xls";
my $workbook = Spreadsheet::WriteExcel->new($fname);
my $ws = $workbook->add_worksheet();
my $format = set_sheet_table_borders($workbook);
return (\$ws, \$format);
}
sub populate_spreadsheet {
my $start_col = shift;
my $items = \@_;
my $row = $_[0] + 1;
$worksheet->write_row($row,$start_col,$items,$format);
}
sub set_sheet_table_borders {
my $wb = shift;
my $format = $wb->add_format(
border => 7,
);
return $format;
}

__END__


Thank you for any help you can give with this.

Justin.
 
D

DouglasG.Wilson

I'm using Spreadsheet::WriteExcel, and (I think) I've created a
reference to the worksheet. When I try to use this elsewhere I get:
Can't call method ... on unblessed reference at ...

This is the minumum I've been able to cut the code down to (sorry it's
not shorter). The problem line is 26. As per the Spreadsheet::WriteExcel
documentation I've created the object, and it's a reference to that
object that I've passed from a subroutine to Main:: to pass on to other
subroutines.

I'm slowly getting to grips with references, I seem to be OK (mostly)
with scalar, array, and harh refs, but what is this? An object
reference? I'm working on it but I haven't got it yet. Anyway, here's
the code.


my ($worksheet, $format) = create_excel_file();

You're returning references to the worksheet and format objects here:
    return (\$ws, \$format);}
Just return the objects:
return ($ws, $format);}

Then this should work:
    $worksheet->write_row($row,$start_col,$items,$format);}

HTH,
- Douglas Wilson
 
J

Jens Thoms Toerring

Justin C said:
I'm using Spreadsheet::WriteExcel, and (I think) I've created a
reference to the worksheet. When I try to use this elsewhere I get:
Can't call method ... on unblessed reference at ...
This is the minumum I've been able to cut the code down to (sorry it's
not shorter). The problem line is 26. As per the Spreadsheet::WriteExcel
documentation I've created the object,

You asked for an object to be created and what you get back is
already a reference - objects are references, just, due to being
bless'ed, with some extra magic attached (and you shouldn't need
to care what that reference points to, that's what objects are
all about). Thus you add one unnecessary level of indirection
when you return a reference to what you got from the functions
that created the objects.
and it's a reference to that
object that I've passed from a subroutine to Main:: to pass on to other
subroutines.

And that's not the right thing to do, in the routine the reference
to the object gets passed to you need the object (a blessed refe-
rence) itself.
I'm slowly getting to grips with references, I seem to be OK (mostly)
with scalar, array, and harh refs, but what is this? An object
reference? I'm working on it but I haven't got it yet. Anyway, here's
the code.

use warnings;
use strict;
use Spreadsheet::WriteExcel;
my ($worksheet, $format) = create_excel_file();
artist_chart() ;
sub artist_chart {
my ($position, $last_month, $artist) = ('7', '4', 'Banksy');
populate_spreadsheet(0, $position, $last_month, $artist);
}
sub create_excel_file {
my $fname = "/var/local/chart/boris.xls";
my $workbook = Spreadsheet::WriteExcel->new($fname);

First object created.
my $ws = $workbook->add_worksheet();

And a "worksheet" object.
my $format = set_sheet_table_borders($workbook);

And here you create a "format" object.
return (\$ws, \$format);

And here you pass back references to two to of the objects which
already are references. That's verkill and it doesn't look as if
it is what you really want to do. Leave it at

return ( $ws, $format );

and you rather likely will be fine, especially since the
way you use them looks very much as if you need the object
itself and not a reference to it. I.e. when you later do
sub populate_spreadsheet {
my $start_col = shift;
my $items = \@_;
my $row = $_[0] + 1;
$worksheet->write_row($row,$start_col,$items,$format);
}

you need a "worksheet" object and not a reference to such
an object - or you would need to dereference $worksheet at
this place to get back the object itself.
sub set_sheet_table_borders {
my $wb = shift;
my $format = $wb->add_format(
border => 7,
);
return $format;
}
Regards, Jens
 
S

sln

I'm using Spreadsheet::WriteExcel, and (I think) I've created a
reference to the worksheet. When I try to use this elsewhere I get:
Can't call method ... on unblessed reference at ...

This is the minumum I've been able to cut the code down to (sorry it's
not shorter). The problem line is 26. As per the Spreadsheet::WriteExcel
documentation I've created the object, and it's a reference to that
object that I've passed from a subroutine to Main:: to pass on to other
subroutines.

I'm slowly getting to grips with references, I seem to be OK (mostly)
with scalar, array, and harh refs, but what is this? An object
reference? I'm working on it but I haven't got it yet. Anyway, here's
the code.

#!/usr/bin/perl

use warnings;
use strict;
use Spreadsheet::WriteExcel;

my ($worksheet, $format) = create_excel_file();
^^^^^^^^^^^^^^^^^^^
Never worked with this module, just guessing.
You return reference's (\$ws, \$format).
$workbook->add_worksheet(); and
$wb->add_format(), return references, then you
are returning references to references.
When you dereference by adding the '->' arrow,
$worksheet->'something', it is looking for a method
of a class, an array, hash, ... not another reference.

What happened to $workbook? Don't need it anymore?
Its never stored. Unless of course $workbook->add_worksheet();
creates worksheet object as a wrapper and stores itself ($self)
in a variable of the worksheet object. But that seems unlikely.
artist_chart() ;

sub artist_chart {
my ($position, $last_month, $artist) = ('7', '4', 'Banksy');
populate_spreadsheet(0, $position, $last_month, $artist);
}
sub create_excel_file {
my $fname = "/var/local/chart/boris.xls";
my $workbook = Spreadsheet::WriteExcel->new($fname);
my $ws = $workbook->add_worksheet();
my $format = set_sheet_table_borders($workbook);
^^^^^^^^^
Goes away, lost forever!
return (\$ws, \$format);
}
sub populate_spreadsheet {
my $start_col = shift;
my $items = \@_;
my $row = $_[0] + 1;
$worksheet->write_row($row,$start_col,$items,$format);
^^^^^^
@_ appears to be singularly scoped to each function, so this
cannot be itterated. Its no big deal, but generally, create
an independent (new) array reference everytime this gets
called .. my $items = [@_];

Also, I'm sure you are aware that when items is assigned, @_
contains ($position, $last_month, $artist).
}
sub set_sheet_table_borders {
my $wb = shift;
^^
Here you pass in workbook object, then later it is discarded.
In the function populate_spreadsheet(),
you use the global variables ($worksheet, $format).
This does not have general portability and its hard to tell
where/what these variables are.
I would try to consistently generalize helper functions without
the use/need of globals.

If you have groups of global variables specific to each other,
as some result of making multiple objects, maybe you could store
them in an array of hashs'.

-sln
 
J

Justin C

An object is already a reference. You don't need to take another layer
of reference, just return the object.

I think I'm getting the hang. I've been using references for ages,
hashrefs, arrayrefs, but whenever I use objects I get a bit confused.
It's coming together slowly now that I'd started working through the OO
documentation.

Don't pass parameters to subs through globals. It's very confusing.

artist_chart($worksheet, $format);

OK, sounds sensible - I really should re-read perlstyle.

Thank you for the suggestions.

Justin.
 
J

Justin C

^^^^^^^^^^^^^^^^^^^
Never worked with this module, just guessing.
You return reference's (\$ws, \$format).
$workbook->add_worksheet(); and
$wb->add_format(), return references, then you
are returning references to references.
When you dereference by adding the '->' arrow,
$worksheet->'something', it is looking for a method
of a class, an array, hash, ... not another reference.

What happened to $workbook? Don't need it anymore?
Its never stored. Unless of course $workbook->add_worksheet();
creates worksheet object as a wrapper and stores itself ($self)
in a variable of the worksheet object. But that seems unlikely.

I admit that this is all a grey area to me, but I'm following examples
in the module, and that's how it says to do it. I think $worksheet
contains some reference back to the $workbook (so that it knows which
workbook it is, as there could be more than one).

^^^^^^^^^
Goes away, lost forever!

Other than to put a worksheet in it, and add formatting to it, it's not
needed - unless I want to explicitly close it.

return (\$ws, \$format);
}
sub populate_spreadsheet {
my $start_col = shift;
my $items = \@_;
my $row = $_[0] + 1;
$worksheet->write_row($row,$start_col,$items,$format);
^^^^^^
@_ appears to be singularly scoped to each function, so this
cannot be itterated. Its no big deal, but generally, create
an independent (new) array reference everytime this gets
called .. my $items = [@_];

Also, I'm sure you are aware that when items is assigned, @_
contains ($position, $last_month, $artist).

The ->write_row function (?) will populate a spreadsheet row, starting
at row $row, column $start_col and write each of @{$items} across the
columns until it runs out of @{$items}. For some reason it wants an
arrayref, not the array (according to the documentation).
^^
Here you pass in workbook object, then later it is discarded.
In the function populate_spreadsheet(),
you use the global variables ($worksheet, $format).
This does not have general portability and its hard to tell
where/what these variables are.
I would try to consistently generalize helper functions without
the use/need of globals.

If you have groups of global variables specific to each other,
as some result of making multiple objects, maybe you could store
them in an array of hashs'.

I readed perlref from time to time, each time I understand a little
more. I have a feeling that now I'm looking more at OO programming, and
using objects, I'm going to understand a bit more. I'll give it another
read, and also perlreftut.

It's all going in slowly. I love it when I go back to my old code and
replace twenty lines with just a couple. Even though I've a long way to
go, I feel that I have still come quite far.

Thanks for the help. Also, thanks to others who replied but to whom I
have not followed up, repetition helps get the information to stick!

Justin.
 
J

Justin C

Justin C said:
[ snip passing args instead of using globals ]
Unfortunately that wasn't part of my education, all my programming was
learnt post academia, under my own steam. If I'm lacking some of these
fundamentals it's because the sources I leaned from didn't cover them
adequately (or I haven't got there yet).


You might benefit from:

http://en.wikipedia.org/wiki/Global_variable
http://en.wikipedia.org/wiki/Action_at_distance_(computer_science)

I did take 'computer studies' at school, I remember lots of punched
cards,

[snip other nostalgia]

I was light on fundamentals too, as my undergrad was in Electrical Engineering
rather than Computer Science or Software Engineering.

After I switched from "hardware" to "software" work, I eventually
noticed that my projects would get to 80-90% complete, and then
stall in insurmountable cross-dependencies, or bad design decisions
made too long ago to undo.

I was fortunate enough to be able to go back to school and pick up
my missing fundamentals.

I'll share with you the most important thing I learned in slogging
through seven years (part time) of grad school:

Think before you code!

A quick google search leads me to recommend

http://www.codewalkers.com/c/a/Programming-Basics/Coding-Best-Practicesor-at-least-Better-Practices/

since they get to that right near the beginning.

Thank you. I've forwarded this to self@home where I will have time to
study the information.

Justin.
 
J

Justin C

Maybe you need to read perlboot. In simple terms, an object is just a
refrence with a bit of magic attached. Here is how you make an object:

I think, now that I'm looking more at OO that perlboot and perltoot (I'm
sure there's a third too) I'll find these two more accessible, and
therfore probably useful. Will add them to my reading list (again).

my $obj = { a => 1 }; # an ordinary hashref
bless $obj, "My::Class"; # now it's an object

You can still deref this object with $obj->{a}, just like any other
hashref, but it's considered bad style to do so from outside the class
that defined it. (The author of the class is entitled to change the
internals in the next release, without warning you.)

However, you can also call a method on it, with $obj->method(...). This
is where 'My::Class' comes in: that is the package Perl will search
first for the method.

Yup, this is where you're losing me. I'll go to the documentation, I
fear it's going to take a little time reading, re-reading, and
re-re-reading to get some of this stuff. As I'm getting older I find
that practical (physicla) stuff goes in more easily, and abstract stuff
is getting harder to understand... that's no fun when the practical
stuff is no longer easy to do!

Justin.
 
S

sln

On 12/10/2009 07:34 AM, Justin C wrote: [snip]
Yup, this is where you're losing me. I'll go to the documentation, I
fear it's going to take a little time reading, re-reading, and
re-re-reading to get some of this stuff. As I'm getting older I find
that practical (physicla) stuff goes in more easily, and abstract stuff
is getting harder to understand... that's no fun when the practical
stuff is no longer easy to do!

Justin.

A popular phrase floating around is that Perl's OO is "bolted on".
That's actually a good way of looking at it. A perl object is just a
hash (usually) on to which you bolt some subs.

That's really all =)

Like using a glue gun to attach a pinwheel to your cell phone ... now
you can do $phone->spin()

-Sir
I get what you mean but, I always thought a Perl object
was an instance of a class with data and subs.

C++ an object is as little as an instance of a structure
where functions can be added or not. Of course there are
many more capabilities.

I wonder if Perl uses vtable like logic? Don't know.

-sln
 

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
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top