|
Triple Tech posted:Be careful of using || as the "default" operator. What you really want is "defined-or" which was introduced in 5.10 as // (they lean). That actually solves a problem for me (in the cases where I could conceive of someone passing 0, I was checking manually which was trash), guess I can put a big fat using 5.10.0 up above my includes now e:
|
# ? Aug 11, 2009 00:55 |
|
|
# ? Jun 7, 2024 21:27 |
|
Erasmus Darwin posted:What you want here is to use \%little_hash instead of just %little_hash. With the slash there, $daddy_hash{little_hash} will contain a hash reference to %little_hash. Without the \, the contents of %little_hash get flattened into the list being used to define %daddy_hash, which throws things off since you've effectively doing this: So once the function exits, the data from %little_hash will still be there, but the original reference "%little_hash" won't be? Will it still be a hash? Or did it transmute into something else? What I'm really looking for is a way to put a hash into another one, so yeah, nested hashes.
|
# ? Aug 11, 2009 14:34 |
|
Captain Frigate posted:So once the function exits, the data from %little_hash will still be there, but the original reference "%little_hash" won't be? Correct. As long as there's a reference to the hash data (in this case via $test{little_hash}), Perl will keep the data around. That's the magic of garbage collection. quote:Will it still be a hash? For the most part, yes. Technically, $test{little_hash} is a hash reference rather than a hash. That's actually a special scalar value that gets dereferenced (via the -> or % operators) to get at the underlying hash structure. However, the dereferencing is sometimes implicit since Perl knows that a nested structure has to be a reference (since that's the only way to stick an array or hash within another array or hash). And to cut through that confusing bit of text, here are some examples: code:
quote:What I'm really looking for is a way to put a hash into another one, so yeah, nested hashes. In addition to using a reference to a hash variable (i.e. when we did \%little_hash back in the make_hashes function), you can also create anonymous hash references with brackets { }. For example: my %test = ( little_hash => { foo => 0, bar => 0 }, thing_1 => 0, thing_2 => 0 ); (Note that parentheses are used for the outer enclosing punctuation and brackets are used for the subhash.) Also, I'd recommend taking a look at the perlref, perllol, and perldsc manpages. They're a little on the dense side, and they'll cover some stuff that's likely to make your eyes glaze over, but they do cover the whole mess in detail. It's not a bad system once you're used to it (especially if you've got experience in dealing with pointers in other languages), but it does take a bit for it to all sink in.
|
# ? Aug 11, 2009 15:06 |
|
So, ultimately, what I have looks like this:code:
code:
|
# ? Aug 11, 2009 16:20 |
|
Pretty much...
|
# ? Aug 11, 2009 16:42 |
|
Close. You want a dollar-sign in front of test, not a percent. So it's: $false_thing=$test{little_hash}{foo};
|
# ? Aug 11, 2009 16:43 |
|
Erasmus Darwin posted:Close. You want a dollar-sign in front of test, not a percent. So it's: Great, thanks.
|
# ? Aug 11, 2009 18:12 |
|
Wait, one more small question: if I set up the hash that way, do I still have to put the key in quotes? EDIT: Do I have to make any changes if I want to make one of the members an array? Captain Frigate fucked around with this message at 19:52 on Aug 11, 2009 |
# ? Aug 11, 2009 19:19 |
|
Captain Frigate posted:Wait, one more small question: if I set up the hash that way, do I still have to put the key in quotes? Perl generally lets you omit the quotes around a hash key when it's inside braces like that. That works with any hash -- you don't need a special setup to do that. However, depending on what sort of symbols you've got in the key, you might have to use quotes. For example, if you've got spaces in there, you'll need to quote it. quote:EDIT: Do I have to make any changes if I want to make one of the members an array? Nope. It works the same way. The only difference would be using \@litte_array instead of \%little_hash. Or, if you go the anonymous route, use brackets [] instead of braces {}.
|
# ? Aug 11, 2009 20:08 |
|
Erasmus Darwin posted:Close. You want a dollar-sign in front of test, not a percent. So it's: Older versions of ActivePerl were buggy when using this syntax (referencing nested hashes without the arrow operator). Because of that, and the inconsistent (to new developers) quoting rules for hash keys, I find it's better to write $false_thing = $test{'little_hash'}->{'foo'}, though it may never matter for you.
|
# ? Aug 13, 2009 08:02 |
|
To answer the original namespaces in perl bit, now that you've got a better understanding of references, the rule of thumb is that anything passed into a subroutine or function via arguments or passed out via returns is done so as a straight list of scalars. Since perl will automatically try to convert these lists into whatever context you try using them in, you need to watch how you pass variables. For example, this will not work as you might expect: code:
code:
code:
|
# ? Aug 14, 2009 07:24 |
|
Roseo posted:To answer the original namespaces in perl bit, now that you've got a better understanding of references, the rule of thumb is that anything passed into a subroutine or function via arguments or passed out via returns is done so as a straight list of scalars. Since perl will automatically try to convert these lists into whatever context you try using them in, you need to watch how you pass variables. Does this hold when I'm doing the opposite process, i.e. sending a hash to a function to either operate on it or print it out or something? Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element? Double Edit: Or would that just be: code:
Captain Frigate fucked around with this message at 15:59 on Aug 14, 2009 |
# ? Aug 14, 2009 15:20 |
|
Captain Frigate posted:Does this hold when I'm doing the opposite process, i.e. sending a hash to a function to either operate on it or print it out or something? Yep. If you're sending one hash or one array, it won't be a problem. But sending two will combine them, perhaaps messily. And trying to assign a scalar after a hash would be an issue: code:
quote:Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element? I believe that works, but I usually use %hash = %$href; when I HAVE to have an actual hash instead of an href. Dereferencing it is easy enough, though, so I usually don't bother. If it helps, http://www.perlmeme.org/howtos/using_perl/dereferencing.html is a decent reference on deref syntax. Roseo fucked around with this message at 18:52 on Aug 14, 2009 |
# ? Aug 14, 2009 18:50 |
|
Captain Frigate posted:Edit: Is there a way to just straight up dereferencing a hash reference into another hash? Or would I have to go element by element? Right, you are dereferencing $href to a hash, which evaluates in a list context. Since evaluating %hash supplies a list context, the assignment is a list assignment. Try this out... code:
It is also important to understand what a scalar is and what a list is. A scalar is Perl's data structure for holding an opaque thing. A scalar's "thing" can be a string, a number, or a reference to another thing*. A scalar is one thing. A list is a stack of one or more scalars**. A list has no value. Here are examples of expressions that result in scalars: code:
code:
code:
S133460 fucked around with this message at 14:43 on Aug 15, 2009 |
# ? Aug 15, 2009 14:38 |
|
Alright, one final question about hashes and functions: If I have one function which returns a reference to a small hash, that I might want to use in other hashes, which also are generated by functions, would it look like this? code:
Captain Frigate fucked around with this message at 19:54 on Aug 17, 2009 |
# ? Aug 17, 2009 19:46 |
|
We don't say pointer, we say reference. You don't have to copy the hash to "talk to it". You can just drop it in place, but make sure to dereference it. code:
|
# ? Aug 17, 2009 19:51 |
|
Triple Tech posted:We don't say pointer, we say reference. Haha, my bad. My origins are showing through, and as I said earlier, I am completely new to perl as of about a month and a half ago. Anyway, as long as the above works like I would think, I thank you all for all of your help, but I can't promise that I won't be back in the future
|
# ? Aug 17, 2009 19:56 |
|
Captain Frigate posted:
This is fine, except for some minor syntax errors (missing dollar signs in front of input_1 and input_2, and a missing underscore in input_2 in the 'my' statement). But your understanding of what's going on seems fine. quote:
First, "%{$temp}" can be written as "%$temp" since the "{}" in this case are just acting like parentheses (i.e. controlling order of operation) with regard to how Perl processes the data type. Second, "%$temp" (and the equivalent "%{$temp}") is incorrect anyway because you need a hash reference as the value to store in the hash. So you just want "$temp". (Or, if you were crazy, you could do "\%$temp".)
|
# ? Aug 17, 2009 20:45 |
|
Captain Frigate posted:Alright, one final question about hashes and functions: Not quite. You shouldn't be dereferencing $temp in bar(). Doing so expands it to a list when used in hash assignment context, so: code:
code:
You should be doing this instead: code:
code:
|
# ? Aug 17, 2009 21:08 |
|
Ok, so then since the hash can only store the scalar, I have to dereference the reference whenever I want to access parts of it, right? So would I use: code:
|
# ? Aug 17, 2009 21:37 |
|
right, but the -> is implied between key blocks.code:
Edit: Never use % when you want a scalar back. To access individual daya, use a scalar sigil. You'd use a hash in something like: my %user_data = %{$users{'jdoe'}}; which would dereference the scalar at $users{'jdoe'} and assign the hash there to %user_data, containing 'email' and 'pw' keys that could then be accessed with: $user_data{'email'}; Roseo fucked around with this message at 21:45 on Aug 17, 2009 |
# ? Aug 17, 2009 21:42 |
|
Roseo posted:right, but the -> is implied between key blocks. Ok, great. I think I've got it.
|
# ? Aug 17, 2009 21:47 |
|
This is a stupid question that I figured I'd ask here because cowsay is written in Perl. A while ago I was goofing around with cowsay and I got to the point where I had a cow on the screen updating constantly saying the most recent line of a certain server log. I forget how I did this, and it's driving me crazy. I thought it was something as simple as `tail -f logfile | cowsay` but that isn't working. Does anyone know how I might've done this?
|
# ? Aug 19, 2009 18:24 |
|
Does tail -f logfile | xargs -n 1 cowsay work?
|
# ? Aug 19, 2009 18:27 |
|
Vanadium posted:Does tail -f logfile | xargs -n 1 cowsay work? It does, but I seem to remember it just being one cow and the text inside the bubble changing. Maybe I made a shell script or something that was like while true; do tail -n 1 logfile | cowsay; sleep 3; clear; done; edit: fixed typo checkeredshawn fucked around with this message at 18:34 on Aug 19, 2009 |
# ? Aug 19, 2009 18:32 |
|
This works a little nicer, it leaves each message on screen for at least one second and leaves it there until another arrives: code:
|
# ? Aug 19, 2009 18:43 |
|
On a system that doesn't support 64 bit ints ("Q" and "q" aren't valid pack templates), how would you write one to a file? I ask this because if I just try:code:
code:
EDIT: I figure it would be easiest to just divide by powers of ten equal to the number of additional zeros, but I'm not sure how many zeros are likely to show up. I don't think it's padding equal up to enough digits to hold a 64-bit value, because I gave it 2**45 and I ended up with two zeros padded to the right (instead of six, if it were padding to hold a 64-bit value). Any insights? Captain Frigate fucked around with this message at 22:00 on Aug 20, 2009 |
# ? Aug 20, 2009 18:20 |
|
I don't know if this belongs here or in the Coding Horrors thread, but I just discovered the ternary lvalue:code:
|
# ? Aug 21, 2009 01:22 |
|
With parentheses, it's not so bad..
|
# ? Aug 21, 2009 01:36 |
|
The only other way to achieve the same effect, without resorting to using a string eval, is with references and an if block of sorts, so it's definitely a bit more concise.
|
# ? Aug 21, 2009 03:52 |
|
I don't know if you guys know this but branching in Perl actually takes a lot of time (since it's an interpreted language). The fastest, aka best, way to do this is:code:
|
# ? Aug 21, 2009 04:01 |
|
Filburt Shellbache posted:I don't know if you guys know this but branching in Perl actually takes a lot of time (since it's an interpreted language). The fastest, aka best, way to do this is: I'm not sure if that is true versus the conditional op as an lvalue. Perl speed is based on how many ops are performed, and I believe your code probably results in more ops than what CanSpice posted (because the ${} implies a scope op, there's an array access, !! is two ops, etc). I'm usually wrong though.
|
# ? Aug 21, 2009 13:38 |
|
Captain Frigate posted:I figure it would be easiest to just divide by powers of ten equal to the number of additional zeros, but I'm not sure how many zeros are likely to show up. I don't think it's padding equal up to enough digits to hold a 64-bit value, because I gave it 2**45 and I ended up with two zeros padded to the right (instead of six, if it were padding to hold a 64-bit value). Any insights? Alternately, is there a way to use sprintf for numbers longer than the supported int size?
|
# ? Aug 21, 2009 15:23 |
|
Captain Frigate posted:Alternately, is there a way to use sprintf for numbers longer than the supported int size?
|
# ? Aug 21, 2009 15:37 |
|
Mithaldu posted:Not sure if that helps you, but you might want to have a look at bignum and bigrat. If you make use of them, be aware though that they'll slow your stuff the gently caress down. Is there a way to only use bignum ints after a certain point? Like, if I have a main loop that doesn't need them, but some minor calculations afterward that do, could I put the "use" statement after the main loop and have it not take a day to process my data?
|
# ? Aug 21, 2009 15:46 |
|
Just do:code:
|
# ? Aug 21, 2009 15:50 |
|
Mithaldu posted:Just do: Oh neat, I didn't know about the "no" statement. Very nice. Thank you!
|
# ? Aug 21, 2009 15:52 |
|
You can also use Math::BigInt and then just explicitly use a Math::BigInt object for the items that will hold large values. Also, here's a quick and dirty attempt at emulating "pack('Q', $num)" using Math::BigInt. My morning coffee hasn't kicked in, and I made it work by comparing the binary representations and just fiddling with it until it matched, so I may have screwed something up. So standard disclaimers apply. Oh, and it's little endian only. Anyway, here's the code: code:
|
# ? Aug 21, 2009 16:00 |
|
Erasmus Darwin posted:You can also use Math::BigInt and then just explicitly use a Math::BigInt object for the items that will hold large values. Yes, I remember someone (you?) suggesting something along these lines for getting around the my lack of "q" support a couple pages back, and I have been using this for a lot of my packing and unpacking needs. Also, it appears that I am a colossal idiot, because I forgot I was dealing with filesizes and was only getting issues with numbers larger than ~2**45, which is still larger than any file has any right to be.
|
# ? Aug 21, 2009 16:59 |
|
|
# ? Jun 7, 2024 21:27 |
|
Captain Frigate posted:Yes, I remember someone (you?) suggesting something along these lines for getting around the my lack of "q" support a couple pages back, and I have been using this for a lot of my packing and unpacking needs. Yep, that was me. I took a peek at my previous code and used it as a cheat sheet for getting this to work.
|
# ? Aug 21, 2009 18:59 |