Uri Guttman <u...@stemsystems.com> writes:

> <forwarded to the list as i was emailed off list. no reason to keep
> this private IMO>
>
>
> On 05/24/2017 08:20 PM, lee wrote:
>> Uri Guttman <u...@stemsystems.com> writes:
>>
>>
>> you can get an array of hashes, where each hash is one row.
>>
>> learning dereferencing will do you much more good than using eval
>> EXPR. references are key to deeper data structures in perl and are
>> used all over the place. it is a core skill you should focus on as it
>> will solve your current problem and many to come.
>> Since when are there any data structures in perl?  Variables are even
>> virtually typeless.
>
> since when is a variable a data structure? :)

It is when it has a type.


typedef struct {
  unsigned long MemTotal;
  unsigned long MemFree;
  unsigned long Buffers;
} meminfo;


meminfo test;
meminfo foo[20];

int bar;
int baz[20];


The difference between 'int' and 'meminfo' is that 'int' is pre-defined
while 'meminfo' is defined by the programmer.  Both are data types of
which you can declare variables.  The variables you declare are
instances of the data structures that correspond to the type of the
variable.  For practical purposes, the variables 'test', 'foo[]', 'bar',
'baz[]' are all data structures.

Perl doesn't have data structures, so variables in perl are not data
structures.  That is unfortunate.

> the key is again references which still seems to confuse you. a scalar
> can hold only one thing.

A scalar can hold many different things, like an integer, a float, a
double, a string, and at least three different types of references.  You
never really know what it happens to be.

> a array a list of things.

a multitude of scalars, so you never know what it happens to be

> a hash can hold pairs of keys/values.

of which you never know what they happen to be

What about references to keys of hashes?

> but most real world data is made of combinations
> of those things.

That's why you can define types for variables, which you can not in
perl.

> an array of hashes is like a list of records. a hash of
> hashes can be keyed by names and then each subhash has data about its
> name. you can't make those without references.

Why would I need a reference to put a hash into an array or into a hash?
Perl may need that internally, which isn't relevant to the programmer in
the first place.

>>> if you need help with references, this list is the place to ask.
>> Why is it so awfully difficult to dereference a reference to an array
>> that contains references to arrays, and why does DBI, for example,
>> provide a function that returns such a reference?  It involves holding
>> the data in memory, so what is the supposed advantage of using cascaded
>> references?
> how will you organize the data without references?

I put it into a database.

> they are the branches in the tree of data. returning a single
> reference is much more efficient than returning the whole array or
> hash. that would involve copying the array/hash onto the stack and
> then copying it again to a variable in the caller. that is very slow.

Programming is even slower when you have to mess around with nested
references, trying to figure out how to de-reference them correctly.  I
did spent hours with that ...

> you say cascaded references. i call that a data tree.

Arrays do not look like trees to me, they look like rows.

> it is incredibly valuable and used all over the place.

I'm avoiding it as much as I can.

> as i said above most real world data is more complex than what a
> single hash or array can hold. think about something like what is
> needed to manage an editor or word processor. they need complex data
> trees (usually in c/c++ but the same idea). so references aren't an
> evil to be handled but the key to better management of data.

In perl, references are evil.  This is not for their technical aspects
and advantages but for the lack of data structures, the typelessness of
variables and the lack of decent ways to de-reference references in
perl.

A C compiler will tell you when you mistakenly pass a variable as an
argument to a function rather than a reference to a variable.  Perl
tells you nothing.

> any single slot in an array or hash can hold another
> array or hash via a reference. that is building up data.

That's building up a mess because you never know how to interpret what
the array or the hash are holding :)

> a phrase i use is compleity arises from layers of simplicity. a single
> hash is simple, a large data tree which is made from simple hashes can
> be very complex. references are how that works.

How do you manage that?

>> The program(mer) will want to work with the data rather than with
>> cascaded references to it, and in the unlikely case cascaded references
>> would be wanted, they could still be created.  The references are merely
>> an obstacle.
> then how will you organize that data without references? think about it
> for a minute. there is no good answer to that question. if you think
> refs are obstacles, you have plenty to learn. data is complex so they
> they complex structures. life can't live in single hashes.

Like I said, I put it into a database.  That allows me to work on a very
simple layer with just the data I need to work with, saving me all
problems with organizing the data because I can leave that to the
database.

Of course, I need to design the database in a suitable and reasonable
way.  That isn't too difficult.

A reference to an array holding references to arrays holding the data is
an obstacle because I need to work with the data, not with the
references to it, and I'm having lots of trouble to de-reference a mess
like that to finally get at the data.

>> They are also inherently dangerous because it is never obvious if some
>> variable is a reference to something or not, and that variables are
>> virtually typeless contributes to that.  Otherwise, references could be
>> helpful for passing data to functions.
> it is easy to tell. use the ref function.

That is another obstacle.  Am I seriously supposed to run tests with
'ref' against every parameter passed to every function I might write?
That is something perl should do for me, just like a C compiler does.

> and if you design your structures cleanly,

I do not design data structures in perl.  That is hardly possible when
everything is typeless and when the language doesn't have any support
for it.

> you generally know when a value should be a ref or a regular value.

Yes, but using references in perl is very awkward.  I almost always pass
variables, not references to functions.  I know it's not ideal for
performance, but it's much easier to manage.

> if you have to have either type, checking with ref will
> do the trick.
>> For example:
>>
>>
>> my $foo;
>>
>>
>> Is that a reference?  An integer?  A float?  A vector of characters?  A
>> data structure?  A character?  Something else?  There is no way to
>> tell.  Pass it to a function and you have to ask again if it's a
>> reference or a variable.
> perldoc -f ref

See it from the perspective of the programmer:  They need to go to
lengths to figure out what $foo is when looking at the code.  They might
have to put in a print statement to print debugging information to see
what 'ref' has to say about $foo.  They can even get surprised because
$foo may suddenly change from an integer to a reference to an array
holding references to arrays holding references to functions.

That is evil.  Have some mercy with the programmers, please :)

> and you rarely need to know so many different types of values in one scalar.

Consider the simple case of reading data provided by users, like a CSV.
You may get all kinds of different numerical values or strings or undef
from any field where you may expect the type of data you get, or a
different type.

It's similar with data from a database, as you might change a TEXT
column into an INT column after a while because you found out only later
that all the data being held in that column is integers.

In the first case, you need to use appropriate checks to make sure you
get the kind of data you're expecting.  In the second case, you very
likely don't need to do anything.

In both cases, it suddenly becomes a tremendous advantage that variables
in perl are typeless because your program will handle the data and does
not require serious modifications, like a C program would.

Still it is crucial what types of data is being held in your scalars
because that is the very data your application does its work with.


And there's the third case of the programmers either trusting or
distrusting themselves (or each other), which would either require to
check every variable passed to a function or otherwise somewhere
appearing, or to just let it go and to assume that the variable in
question will always hold data of the expected type.

References make this worse, not any better.

>> Why don't references at least require a different notation?  An 'int
>> *foo;' tells you right away what it is.
>>
>>
>> typedef struct {
>>    unsigned long MemTotal;
>>    unsigned long MemFree;
>>    unsigned long Buffers;
>> } meminfo;
>>
> so use hungarian notation in the name. $foo_ref. not what i would do but
> it works for that.

That's assuming never making mistakes by putting an unexpected type of
data into a variable.

It requires more work from the programmers.  If there was a way to
declare types for variables, we could make use of that and receive error
messages when we made mistakes.

>> ... also tells you what it is, and when you try to misuse it, you get an
>> error message.  It is impossible to create variables of self-defined
>> types in perl because the variables don't have types to begin with.
>> That includes data structures.
> this is perl. it is designed to allow anything to be stored in a slot.
> you said it earlier, it is not strongly typed which is a win for many
> things. an array can hold different value types.

Yes, it's a big advantage.  It would be better if it was also possible
to bind variables to types.  We could even have a way to define data
structures.

> and in c you don't get deep structures without pointers and that has the
> same issues you seem to find with references.

They are so much easier to deal with in C that I like using references
there.

>> My limit with "data structures" in perl are strided lists.  They are a
>> poor clutch and I don't like them, but unfortunately, there are no data
>> structures in perl.
> you are wrong about no data structures in perl. you will have to take my
> word on that (and everyone else who teaches perl). you just haven't
> learned references yet. once you do, it will all make more sense.

So how do you define data structures in perl?

>>>> They are potentially dangerous because you might fetch huge numbers of
>>>> rows and run into memory issues which could bring down the server.  I'm
>>>> avoiding them unless they have a significant advantage and when I can be
>>>> sure not to fetch too many rows, or when I would have all the data in
>>>> the program anyway.
>>> you can get a row at a time i am sure with each row being a hash.
>> The hash would have to be transformed into an array.  Hashes are
>> difficult to debug because you don't get any error when using elements
>> that do not exist, so they are as inherently dangerous as references are
>> --- or even more dangerous because you sometimes get error messages
>> telling you that something cannot be used as reference to a an array.
> there are ways to lock hash keys so look for that. i have yet to need
> that and don't run into that problem much.

Lock them?  Like you would get an error message when trying to use a key
that doesn't exist?

I'd find that very useful because it happens often enough.

> it all comes down to experience in anything like this.

Experience is always important.  My perspective with perl is quite a bit
limited to database applications.

> you haven't used references enough to really get them so they seem
> nasty to you. i can only say you need to persevere with them. you are
> welcome to show code that bothers you and ask questions here. but
> ranting on how references are evil is not productive anywhere.

Look at the selectall_arrayref() provided by DBI[1].

How do you de-reference nested references to things?  It doesn't work to
just stack up the operators as deep as the nesting goes.

It is difficult to ask a specific question when you don't really know
what you need to ask because you will only know that once you found some
answers.

Let's say you have a table in a database and your query returns 100 rows
with 10 fields in each row.  You use selectall_arrayref() to get the
result of the query.  How do you get the content of row 25, field 5?

I guess you understand how I consider references as an obstacle with a
question like that.  I wouldn't even use selectall_arrayref() if
selectall_array() was available as documented, which it is not.


[1]: http://search.cpan.org/~timb/DBI-1.636/DBI.pm#selectall_arrayref


-- 
"Didn't work" is an error.

-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to