Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re^3: The error says the value is uninitialized, but it works anyway

by afoken (Canon)
on Aug 18, 2019 at 07:35 UTC ( #11104641=note: print w/replies, xml ) Need Help??


in reply to Re^2: The error says the value is uninitialized, but it works anyway
in thread The error says the value is uninitialized, but it works anyway

We haven't learned "map" or "grep" yet.

Is that a royal we? ;-)

Yes, learning in groups is ok, also the classic school "class and teacher" approach. But that's not all. Don't think that's the only way to learn. There are so many other ways, and some of them make learning so easy that you don't even feel like you are learning.

Feel free to learn new things outside the group. The group won't always be there when you need to learn something new, so you better learn how to learn on your own.

To learn a computer language, read other people's code and try to understand what their code does. Especially in the early learning process, you will find new things in almost every line of code, and what you read looks more line line noise or a cat trampling over the keyboard than anything else. But things will soon start to make sense. You will recognize some constructs you've seen before. And very soon after that, you will know the most common constructs. Programs look like buildings made from Lego, and you know the Lego bricks quite well. Then, one day, you will see a car made from those building blocks. A program that uses the same building blocks that you already know, plus a single new building block that you have never seen before. That will happen several times, and you will get used to people building cars, trucks, railway systems, space ships, boats from the Lego bricks. Way before that, you have build your own little buildings, perhaps a little bit wonky, but they did the job. Your first "car" may have five wheels and a spaceship canon, but hey, it moved! And the next one will roll on an even number of wheels.

One day, you will find an artistic, huge bouquet of flowers, large and tiny, all made from the same Lego blocks you use to build ugly cars. And you will enjoy not only the look, but also the way it was built. That's why Perl has an "artistic" license.

The great thing about computer languages is that you can do experiments with them without really breaking anything. Take any program you find, make it run un your computer. Then try to change it a little bit. If if did additions of two numbers, make it subtract instead. Extend it to three numbers. You will make errors, Things will break. Your code will look like a mess. That's expected. And if you have messed up the code to the point were nothing works, you can easily revert to the original program simply by renaming your source file to something different and copying in the original file.

There are tools for exactly that, taking, breaking, and reverting code. But they also need some time to learn. Subversion and Git are two famous ones, and once you have learned how to make your computer manage your files, you won't want to go back. But that's a diffferent story, and for your first steps, renaming and copying files is ok. Once you can write software on a level above hello world and the classic calculator example, take some time to learn Subversion. It comes with a really good book, from which you really need only one or two chapters to get up and running.

When I look things up, it feels like I'm diving into the deep end and I can't see the shore.

I know that feeling. But believe me, you've just got your toes wet, and the beach is right behind you. I have that feeling at work with every new product that we develop (embedded systems for medical applications, aerospace, and other industries). Every time, I feel like knowing nothing about the product environment. It takes a few weeks, then I think I've understood what the product will do. Then, our client explains what the product really does, with some of the edge cases, and I see that I'm still near the beach, and the water just reaches the belly button. I'm nowhere near the deep see that I thought I was swimming in. Get used to it. You can't know everything.

We have covered hashes only in the most basic sense so far.

Hashes are easy. There is some math involved in the background, and that's the difficult part of hashes, but you don't have to know that to work with hashes. First, hashes are like arrays, with some little differences:

  • Hashes aren't ordered like arrays, they will enumerate their keys and values in a random order that changes with every run of your program.
  • Hashes don't use positive integers to find the location of an entry, but instead, they use any strings you like.
  • Hashes use % instead of @, and {} instead of [].

Then, there are some functions to help you with hashes: To get a list of keys, use keys. To get a list of values, use values. To get a stream of key-value-pairs, use each in a while loop. To find out if a key exists in a hash, use exists.

For instance in a previous assignment, I really wanted to take a user input and force it to be a floating point number not a string (for math equations), but I could only find a way to take user input and make it an integer "int(<STDIN>)", but what if they enter a number with a decimal? Why is it basically impossible to easily force user input to be a number if it's not a whole number?

Good questions. It's all in the documentation, but perl has a lot of documentation, and in some cases, it's a little bit messy. Reading documentation is another thing you have to learn.

But your feeling is right. Making a number from a string of user input should be easy, and in fact it is easy. Perl's scalars can store strings or numbers, and perl automatically converts them when needed. You don't have to do anything!

Now, input from STDIN usually has a trailing newline that needs to be removed, see chomp. After that, if the user input looks like a number in a format understood by perl (i.e. not roman or klingon numbers), perl can use it like a number.

There are a few ways to trigger automatic conversion, like adding 0 to force numeric context or appending an empty string to force string context. You will see that in other peoples code, and with a little bit of luck, you will also find it in the documentation.

Now, I know that you guys who know this stuff well probably have the answer to this readily at hand, but for me, trying to find an Easy answer for something that I think is a simple question, was not easy to understand at all. Obviously I don't expect that to be answered now, but just explaining how I'm still learning, and I don't always understand what I see online when I look things up.

It looks like Perl is your first or second computer language, That makes things a little bit hard. To stay with the Lego bricks picture: you start with lego bricks, you have never had wood blocks to play with. That makes it a little bit harder to understand stacking of blocks to build simple houses. But do not fear, everyone but Larry Wall had to learn Perl.

Learning new computer languages will become easier, because they share many of the same concepts. Their syntaxes may differ wildly, but things like strings, arrays, references/pointers, loops, if/then/else are quite universal. Your building blocks look a little bit different, but building things works using the same prinicples.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
  • Comment on Re^3: The error says the value is uninitialized, but it works anyway

Replies are listed 'Best First'.
Re^4: The error says the value is uninitialized, but it works anyway
by afoken (Canon) on Aug 18, 2019 at 08:22 UTC

    Another point. Computer languages are not just words and some funny interpuction. There are phrases, and you are rarely told explicitly that they exist. Phrases just appear in the documentation, and everyone uses them.

    I learned several computer languages until I really understood that. I was learning MUMPS at that time, a language older than C, originally running on the bare metal of 1960s hardware, now running in its own integrated environment on top of common operating systems. MUMPS is a small, but very powerful language. To me, it feels very much like 1960s version of Perl, restricted only by the limited resources of the old hardware.

    Because MUMPS is such a small language, many things you do don't just require one command, but a combination of commands. For example, writing a file:

    OPEN 51:("FOOBAR":"W") ELSE GOTO FAILED USE 51:("FOOBAR":"W") WRITE "HELLO WORLD" USE 0 CLOSE 51

    Or shorter:

    O 51:("FOOBAR":"W") E G FAILED U 51:("FOOBAR":"W") W "HELLO WORLD" U 0 C 51

    Yes, white space is significant. Opening files differes wildly between various implementations. And you don't write out commands at all. You use their one-letter equivalent, because you don't have memory for all of those redundant letters. You put as much code into a single line as possible, because the code is read and interpreted line by line. Using as few lines as possible makes your code run faster on ancient machines.

    The equivalent perl code looks like this:

    open HANDLE,'>','FOOBAR' or die; select HANDLE; print "HELLO WORLD"; select STDOUT; close HANDLE;

    The great thing about MUMPS is that it has associative arrays, and you can use them as in Perl.

    for my $key (sort keys %hash) { print $key,"\n"; }

    In MUMPS:

    SET KEY="" FOR SET KEY=$ORDER(^HASH(KEY)) QUIT:KEY="" D .WRITE ^HASH(KEY),!

    Short form:

    S KEY="" F S KEY=$O(^HASH(KEY)) Q:KEY="" D .W ^HASH(KEY),!

    The equivalent perl code requires an imaginary nextkey function:

    my $key=''; while (($key=nextkey(\%hash,$key)) ne '') { print $hash{$key},"\n"; }

    My point here is the phrase: There is only this way to enumerate all keys of a hash. You set the current key to the empty string. Then you run an infinite loop, in which you call the $ORDER() function to get the next key of a hash (or the first key, when called with the empty string). When the $ORDER() function returns an empty string, you are done and must quit the infinite loop. Only after that, you can work with the current key. And yes, the $ORDER() function is special. It should really be called with a reference to the hash and a key. Actually, it is, but it looks like it is called with the hash value of the key.

    Once you have written a sufficient amount of MUMPS code, you think "iterate over ^HASH" and automatically type S K="" F  S K=$O(^HASH(K) Q:K=""  D. You no longer think about the for loop and its abort condition. You just type that line noise from muscle memory.

    And this is true for all languages. In Perl, you think "iterate over %hash and write for my $key (sort keys %hash) { or while (my ($k,$v)=each %hash) {.

    (There may be some minor errors in the MUMPS code, as I haven't used MUMPS for a few years.)

    Update: fixed some MUMPS errors around OPEN and USE.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      Note that each in scalar context returns the next key.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        Note that each in scalar context returns the next key.

        One of the things I rarely use.

        each iterates over the keys of a hash, returning different values when called repeatedly.

        >perl -E '%h=map{ $_ => 1 } qw( a b c d e f ); while ($k=each %h) { sa +y $k }' a c d b f e >

        But the MUMPS $ORDER() function is different. Keys in MUMPS are always sorted, unlike Perl's hash keys. And keys must not be empty. $ORDER() returns the next key for the key you pass into. It does not iterate. Passing -1 as a second argument to $ORDER() returns the previous key instead of the next one. If there is no previous / next key, an empty string is returned.

        KILL ^H SET ^H("D")=1 SET ^H("E")=1,^H("F")=1 S ^H("A")=1,^H("B")=1,^H("C")=1 ; ^-- ^H now contains the keys "A", "B", "C", "D", "E", "F" ; WRITE $ORDER(^H("")),! ; ^-- writes "A", the first key (in order) of ^H ; W $O(^H("C")),! ; ^-- writes "D", the next key after "C" in ^H ; W $O(^H("F")),! ; ^-- writes "", because "F" is the last key in ^H ; W $O(^H("D"),-1),! ; ^-- writes "C", the key before "D" in ^H ; W $O(^H("A"),-1),! ; ^-- writes "", because "A" is the first key in ^H ; SET K="" FOR SET K=$ORDER(^H(K)) QUIT:K="" DO .WRITE K WRITE ! ; ^-- writes "ABCDEF", all keys of ^H in order ; S K="" F S K=$O(^H(K,-1)) Q:K="" D .W K W ! ; ^-- writes "FEDCBA", all keys of ^H in reverse order (-1 passed as + second argument to $ORDER) ; S K="B" F S K=$O(^H(K)) Q:K="" Q:K="E" D .W K W ! ; ^-- writes "CD", all keys of ^H following "B" and stopping at the +end of keys or at "E", in order ; S K="B" F S K=$O(^H(K)) Q:K="" Q:K]]"E" D .W K W ! ; ^-- writes "CDE", all keys of ^H following "B" and stopping at the + end of keys or at the first key sorting after "E", in order

        Actually, $ORDER() is a "new" (*cough*) function, it can handle negative and non-numeric keys. The original function used to iterate over keys was $NEXT(), and it was intended to be used only with positive integers, i.e. plain arrays or sparse arrays. It returns -1 if no more keys can be found. Unfortunately, -1 is a legal key. So if $NEXT() returns -1, you can not know if you found the last key or you just happen to have -1 as a key. $ORDER() fixes that problem, and $NEXT() is provided for legacy code from the dark ages.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      Wow, MUMPS is a real thing???!! I always thought TheDailyWTF made that up. Are you next going to tell me Initech is a real company?


      holli

      You can lead your users to water, but alas, you cannot drown them.
        Wow, MUMPS is a real thing???!! I always thought TheDailyWTF made that up.

        Yes, it's old, it's real, and it is still in use. Most implementations are gone, unmaintained or unsupported, but MUMPS is hidden in InterSystems Caché, and you can still write software in MUMPS in a Caché system. Another surviving implementation is GT.M. See also "Current users of MUMPS applications" in MUMPS.

        From the 1980s to 2015, a MUMPS implementation was used as the main database for producing and distributing blood products for two federal states (about 5 million people) in Germany. During the 1990s, the system was cloned to support another two federal states for a short time. Duing its last five years, working with that system paid my bills.

        That MUMPS system was replaced by a custom application written around a commercial SQL database, originally written in and for a completely different country. Not for performance reasons, but because blood services merged, and a political decision was made to use the larger system. As far as I know, the MUMPS system is still running, disconnected from all other systems, to be able to access the original records that have been ported into the new system.

        Update note: A few minutes after posting, I have removed some details that should not have been exposed.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11104641]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2019-12-13 09:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?