Re: What's so wrong with this (dereferencing)code? (Symbolic Refs)
by LanX (Saint) on Jun 26, 2024 at 10:31 UTC
|
You are trying to use symbolic references which are forbidden under strict refs
In most cases it's better to just use hash values.
hash slices make this easy:
my %time;
@time{ qw(sec min hour ...) } = localtime(time);
Edit
or
my %time;
my @pad = qw (sec min hour day month);
@time{ @pad } = localtime(time);
Please note how this is more DRY than your redundant code.
The reason why symbolic references are deactivated by default "strictness" is that they result in very hard to spot errors.°
If you really need this kind of meta programming, you can still reactivate it with no strict 'refs' within the local scope.¹
Update
And to why it doesn't work with private lexicals, I suppose it has to do with the history of Perl 4 to 5, the former didn't have strict or lexical vars.
°) Especially people inexperienced to hashes are prone to this.
FWIW: I've seen languages where this was the only way to emulate hashes, but Perl is not one of them.
¹) though you can already do all of this with %package:: stash or PadWalker or eval constructs | [reply] [d/l] [select] |
|
I'm not 100% sure what you mean by DRY here, but I'll concede my code is only elegant from the perspective of the programmer not wanting to rewrite already written code rather than future readers. Now
$_ = zeropad($_) for $sec, $min, $hour, $day, $month; OTOH? That's what I'm talking about! One added line, understandable at first glance and I've learnt a new construct. I'm also pleased to have learnt about hash slices of course but kind of overkill for solving this specific problem.
| [reply] [d/l] |
|
DRY = Don't repeat yourself
Symbolic references are just implicit hash lookups, doing them explicitly is better in the vast majority of cases.
The for-solution you showed is aliasing which has similarities to referencing, but should not be confused.
Update
> Now $_ = zeropad($_) for $sec, $min, $hour, $day, $month;
> OTOH? That's what I'm talking about!
No you weren't.
But FWIW, aliasing it's also feasible with hash values.
Consider
$_ = zeropad($_) for values %time
and revaluate the clarity of concise code.
| [reply] [d/l] [select] |
|
|
|
Re: What's so wrong with this (dereferencing)code?
by kikuchiyo (Hermit) on Jun 26, 2024 at 09:14 UTC
|
If you want to generate timestamps, then generate timestamps:
use POSIX qw( strftime );
my $timestamp = strftime('%Y-%m-%d %H:%M:%S', localtime);
| [reply] [d/l] |
|
Timestamps are just one function of the function and I'm actually trying to deepen my knowledge of Perl rather than accomplish a specific task. For example why does this code work?
use POSIX;
$now = POSIX::strftime("%a, %e %b %Y %T GMT",gmtime($now));
And this code doesn't?
require POSIX;
$now = POSIX::strftime("%a, %e %b %Y %T GMT",gmtime($now));
I will be using strftime instead of rolling my own templates as even my frippery has it's limits but sometimes reinventing the wheel gets you a more efficient wheel. But once again I'm being bitten by Perls mind boggling inconsistency. | [reply] [d/l] [select] |
|
| [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in.
|
|
POSIX docs warn that it imports everything by default, so either give it an import list, or give it an empty import list and fully qualify the functions:
use POSIX 'strftime';
$now = strftime("%a, %e %b %Y %T GMT",gmtime($now));
use POSIX ();
$now = POSIX::strftime("%a, %e %b %Y %T GMT",gmtime($now));
Time::Piece docs say to use its version of strftime and strptime "without the overhead of the full POSIX extension". | [reply] [d/l] |
Re: What's so wrong with this (dereferencing)code?
by etj (Priest) on Jun 26, 2024 at 11:46 UTC
|
${$varname} works by looking in the local package for that variable name. Since you've used my, your variables won't be found there.
To achieve your stated immediate aim here of assigning to the variables you just assigned to (this "zero padding" is itself not a great idea, use the proper timestamp idea instead), you'd do:
$_ = zeropad($_) for $sec, $min, $hour, $day, $month;
But that itself won't affect the "timestamp" (how could it?). If you wanted a Unix timestamp with zeroes for those values, you'd just do something like:
my ((undef) x 5, $year, $wday, $yday, $isdst) = localtime(time);
my $zeroed_ts = timelocal((0) x 5, $year, $wday, $yday, $isdst);
| [reply] [d/l] [select] |
|
That line was exactly what I was looking for. Much elegance! As for affecting the time stamp I'm talking about using it an integer with no separators not a string. It currently returns as..
get_date('timestamp');
20240626204609
get_date('timestamp', { sep=>':' });
2024:6:26:20:46:9
I'm not doing any padding in the second case (although I note even the POSIX function pads with spaces by default). I could probably just use the output of time for the first case but it's human readable and happens to be the way I've always used time stamps when typing them by hand. | [reply] [d/l] [select] |
Re: What's so wrong with this (dereferencing)code?
by harangzsolt33 (Deacon) on Jun 27, 2024 at 11:38 UTC
|
I'm looking to create a definable timestamp from the value of localtime and I realised I needed to zero pad several values to make the timestamps numerically sortable.
If your goal is to sort dates, then you can actually skip the localtime conversion and just take "time" which gives you an integer, and pad it with zeros and sort that or just sort them as numbers. You don't have to create a timestamp or use localtime to break up the time into years, months, days, hours, minutes, and seconds. If your program saves the time by recording whatever "time" returns, then you can sort those integers very easily. You might not even have to zero pad them, just do:
my @times = ... # list of times
@times = sort {$a <=> $b} @times;
Note: The "time" function returns the number of seconds since Jan 1, 1970 except on MacOS, where it returns the seconds since Jan 1, 1904. | [reply] [d/l] |
|
$ uname ; perl -E 'say time()' ; ssh bloop.local uname \; perl -E "'sa
+y time()'"
Darwin
1719488881
Linux
1719488881
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] |
|
Sorry! I read this from an outdated perl manual. X_X
| [reply] |
|
|
|
|
| [reply] |