Re: Divide by 0? Was: Re: Introduction Letter
On Tue, Mar 01, 2005 at 08:13:46AM +, Fergal Daly wrote: On Mon, Feb 28, 2005 at 07:55:36PM -0600, Eric Wilhelm wrote: I like the one where you get the mathematically-correct (or at least mathematically-useful) infinity. $perl -le 'use bigint; $x = 1/0; print $x+1' inf $perl -le 'use bigint; $x = 1/0; print 1/$x' 0 and what should these print? $perl -le 'use bigint; $x = 2/0; print $x*0' $perl -le 'use bigint; $x = 1/0; print ($x+1)-$x' $perl -le 'use bigint; $x = 1/0; print ($x*2)/$x' I don't know, but I do know that having the interpreter crap out is not helpful to most of us simpletons who find phrases like core dumped not especially user friendly. Maybe if there is a divide by zero you could set one of the cussword variables ([EMAIL PROTECTED]@#$!) in addition to returning undef or inf, whatever. Then if you mathematically correct types don't like the result you can make your own, or go back to crapping out by kill(SIGBUS,$$). I suppose I could try to create a use divide 0/undef/inf/crap pragma. Then you could do whatever you want. You'd still get a surprise if you ever forgot it though.. Austin
Re: Mail::Preconfigured
# The following was supposedly scribed by # Eric Wilhelm # on Monday 28 February 2005 10:57 pm: This is really intended for cron and other fully-automatic (webserver/daemon triggered) jobs where you want mail to be sent via an external smtp server (and don't want to mess with sendmail.) Because of the YAML config file support, you can define the owner's (your) address and smtp username/password info in a single place instead of in every script. Maybe it would be more useful if it used either Net::SMTP or Net::SMTP_auth depending on whether your config file had an 'auth' entry in it? --Eric -- Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth - http://scratchcomputing.com -
Re: Divide by 0? Was: Re: Introduction Letter
Austin Schutz wrote: I suppose I could try to create a use divide 0/undef/inf/crap pragma. Then you could do whatever you want. You'd still get a surprise if you ever forgot it though.. I think that's the best answer. Not a good idea for most programs, wonderful idea for math programs - which can simply say use infinity; or something along those lines at the top. BTW-I'm reading Perl 6 Now, and I believe there was mention there about Perl 6 having support for infinity and possibly other equally strange notions. I'm at work, though, so I don't have access to the book right now. -ofer
Re: Divide by 0 citation plea
# The following was supposedly scribed by # Ken Williams # on Tuesday 01 March 2005 11:39 am: So, is that positive or negative infinity? Sometimes that makes an awful lot of difference. Sure. I was just (sort of) playing devil's advocate by pointing out that rules are meant to be broken. If your computer science professor told you to never divide by zero and you blindly followed his advice, you would be going to a lot more trouble to compare the slopes of vertical lines than is needed. (apologies for my previous transposition of dy for dx) use bigint; my @slopes; foreach my $line (@lines) { my @d = map({$line-[1][$_] - $line-[0][$_]} 0..1); push(@slopes, $d[1]/$d[0]); } my $steepest = (sort({$slopes[$a] = $slopes[$b]} 0..$#lines))[-1]; As far as direction goes, in this case it is inherent in the conventions of slope. The point is that by breaking the rules for a second, we are able to better apply all of those other concepts that we're supposed to be using like SPOT, compactness, maintainability, clarity, etc. (It doesn't hurt that we're using the most powerful mainstream programming language either.) I would take the time to write the rule-bound example, but I think it's a safe bet to say that it would pass for C once you ran it through s/\$// (and there's a reason that I don't write everything in C.) If you don't specify the approach direction, the limit is undefined Which of course is not equal to undef(). Don't get me wrong, I'm not lobbying for pi==3 here. See also http://mathforum.org/dr.math/faq/faq.divideby0.html . The explanations get progressively more advanced as you go down the page. Yes. It's complicated and I'm not advocating that we rewrite the elementary arithmetic books. Just pointing out that once you understand how to calculate the limit as the denominator goes to zero (and the implications/assumptions involved in that) that you can use perl to solve real problems in intuitive ways. (heh. Maybe I need a Perl hacker's license and registration that says I'm authorized to divide by zero and use up to 3.7GB of memory (equivalent of deadly force and what-not.) Then we'll all put our certifications on our e-mail (and notches in our belts) so the algorithm police know whether to pull us over or not. Something like an irony meter/beware of sarcasm bumper-sticker might also be useful (just like that my speed limit is: license plate that I've always wanted.)) --Eric -- Chess is a foolish expedient for making idle people believe they are doing something very clever when they are only wasting their time. -- George Bernard Shaw - http://scratchcomputing.com -
Re: Divide by 0 citation plea
On Tue, Mar 01, 2005 at 01:45:56PM -0600, Ken Williams wrote: If you allow positive and negative infinity as part of your numerical system, then division by zero moves from undefined to indeterminate, so I suppose one could argue that division by zero should be 'nan' rather than throwing an exception. Presumably this was some backward-compatibility thing. ..which was I guess the original point of my question. Often times these exceptions happen buried in code where you are e.g. trying to find the mean value of 0 items. _generally_ the code doesn't occur inside an eval block, and no useful (to an end user) error is generated if the application isn't expecting an exception to be thrown. I don't disagree with the math issues regarding there not being a definable value, but in practice the interpreter throwing an exception has been a much greater problem for me than having a piece of errant data such as a NaN which will generally cause detectable errors later. Often (always, in my experience) they are errors which would be trapped by error detecting code which isn't expecting exceptions. Often this is caused by a module author not expecting an empty list of arguments, or similar. The author doesn't document a piece of code as capable of throwing an exception, because they don't think it is. The net result may be something like a user submitting a web form and getting a blank page in response. Interestingly, bigint sets NaN for 0/0, so it's definitely possible. I'm going to meditate on this a bit. Austin
Re: monkeys should write tests
# The following was supposedly scribed by # Austin Schutz # on Tuesday 01 March 2005 02:13 pm: Often this is caused by a module author not expecting an empty list of arguments, or similar. The author doesn't document a piece of code as capable of throwing an exception, because they don't think it is. And of course you didn't write a test for that because you thought nobody would be stupid enough to call the function with a bunch of (or not enough) garbage. Maybe that's an argument for a Test::Garbage module or a randomly generated t/Stupid.t. So, something else falls out of today's entropy (and I thought I was just wasting time.) While you're meditating: http://perl.overmeer.net/ Programming is a Dark Art, and it will always be. The programmer is fighting against the two most destructive forces in the universe: entropy and human stupidity. They're not things you can always overcome with a methodology or on a schedule. -- Damian Conway, author of Object Oriented Perl. --Eric -- Cleanliness is next to impossible. -- Unknown - http://scratchcomputing.com -
exception cases 2 to the left
# The following was supposedly scribed by # Ken Williams # on Tuesday 01 March 2005 01:45 pm: My point goes beyond this example, though: I think the reason you feel like you should be able to divide by zero in this case is that there's a point discontinuity (an exception case) at zero that you feel like should be fairly easy to fill in. Usually the best way to deal with such things, though, is to eliminate that discontinuity in the first place. Using bigint and letting $above_zero / 0 == inf does exactly that (eliminates the discontinuity.) And IMO does it without the cost of transparency that the non-dividing example carries. If a slope is defined as dy/dx, the intuitive answer for what happens when dx==0 is that dy/dx == inf (with the sign on +/-inf coming from dy (and wow! that's exactly what you get with bigint.)) I agree that your point goes beyond this example and that eliminating a discontinuity gives a more robust solution. My point is that there is more than one way to skin a dead horse. Saying that 1/(1/0) == 2/(1/0) doesn't mean that 1==2. Rather, it means that for all *practical* purposes (in the appropriate context) that two unfathomably large numbers (ie two something numbers each divided by an unfathomably nothing number) are close enough to the same thing that there is no point in going to the end of the universe with a micrometer to check their difference. --Eric -- There are three terrible ages of childhood -- 1 to 10, 10 to 20, and 20 to 30. -- Cleveland Amory - http://scratchcomputing.com -
Re: Parallel::Simple - bound args syntax
Mark Stosberg wrote: On Tue, Mar 01, 2005 at 02:40:36PM -0800, Ofer Nave wrote: # getting fancy with arg binding my @hosts = qw( foo bar baz ); prun( map { my $host = $_; sub { test_host( $host ) } } @hosts ) or die( Parallel::Simple::errplus() ); I think this is simpler, because I can guess what it does without reading more documentation. My idea of simple here is clarifying the call some: my @host_tests; for qw( foo bar baz ) { push @host_tests, sub { test_host( $_ ) }; } prun (@host_tests) or die( Parallel::Simple::errplus() ); I don't think that's going to do what you expect. The values in $_ are not going to be captured in the anonymous sub because $_ is a global variable. That's why I created a new lexical variable to capture the value on each loop inside the closure. It's not clear your code refs would interact with arguments that may already be passed into them, before they get to prun(). It's also not 'normal' to mix hash and list calling styles, or to use a code ref for a hash key. The mixed hash/list calling styles is a seperate discussion - that was already part of the initial design, and not part of the topic of this email, which is whether or not the args binding feature is an appropriate addition for the module. Also, I'm not using code refs as keys anywhere. Simply putting a code ref on the left side of a = operator won't stringify it. In summary, I don't think the suggested addition would be 'simple'. Ah, that's the real question! I'm still not convinced either way, but I'm leaning towards including it. -ofer
Re: Win32::Tie Registry / Activestate Perl problem (?)
As someone pointed out on the ActiveState list, TieRegistry may not be very robust for dealing with registry objects. There are cases where TieRegistry cannot access values under keys with weird names -- valid win32 Registry names, but names that have binary (Unicode) characters in them. It seems TieRegistry doesn't handle these cases reliably. I haven't rewritten my program using the old Win32::Registry package, but if I do (pain in the posterior interface that it is...), it may be that we should *deprecate* TieRegistry in favor of the more native Registry interface (Ug). At the very least, it should be noted in the documentation that it may not be reliable for working with some registry keys (hey, it enumerated my entire Classes key just fine). Sigh. As it is, TieRegistry certainly seems to have problems reliably accessing values under keynames where the keynames are not ascii strings. I tried adding the use UTF8 to see if it would get around the problem, but when I write out registry dumps of the keys, and read them with a multi-byte supporting editor (gvim), I get different strings where the binary is, indicating that something in the registry export feature doesn't quite translate the keynames the same under UCS-16 v. UTF-8. :-( Linda Linda W wrote: I decided to temporarily give up on the cygwin version of TieRegistry just to make some progress.
Re: Parallel::Simple - bound args syntax
* Ofer Nave [EMAIL PROTECTED] [2005-03-01 23:45]: I realize that since I can tell listrefs apart from strings and code refs, I could allow this: prun( $coderef1, $coderef2 = [ $arg1, $arg2, $arg3 ], ); Which would run $coderef1 once, but run $coderef2 three times, once for each arg. If you wanted to pass more than one arg at a time, you could create sublists: Leave it out. It looks like a great idea to you right now with the one or two examples you developed this on, but you'll get sick of it very quickly if you start to use it on a larger scale. Don't try to be too clever, it will bite you once in maintenance mode. I've done things like that several times in the past and they always end up obfuscating the code more than they help. This is really something that must be solved on the language level, à la currying and compositing operators, not on the level of individual APIs by overloading the semantics of various data types. If you feel it is really important to make this particular use case easier, use an API like this: prun( $coderef1, [ $coderef2, $arg1 ], [ $coderef2, $arg2 ], [ $coderef2, $arg3 ], ); whose meaning is reasonably easy to guess without having to study the documentation too closely. For reducing redundancy, this allows you to fall back on regular Perl idioms: prun( $coderef1, map( [ $coderef2, $_ ], $arg1, $arg2, $arg3, ), ); Now the prun() function has one fewer interface conventions, and I can understand half of what's going on with my regular Perl knowledge before I've even read your docs. There is also precedent in taking an anonymous array with a coderef in the first slot as a shortcut for call this code with these parameters; offhand I remember that Tk does it this way but there were other places I saw it. I believe that is because it is a pretty natural notation. And your code also has less to guess, because the number of arguments doesn't change depending on whether I pass arguments to some coderefs or not. For similar reasons, I would suggest that you don't allow named subs as in prun( foo = $coderef1, bar = $coderef2, ); but rather require prun( { foo = $coderef1, bar = $coderef2, } ); so that you only have to check one easily expressed condition. Except when they aren't, consistency and simplicity are very important goals, particularly for your interface. Regards, -- #Aristotle *AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}; Just-another-Perl-hacker;
Re: Parallel::Simple - bound args syntax
* A. Pagaltzis [EMAIL PROTECTED] [2005-03-02 03:25]: Except when they aren't, consistency and simplicity are very important goals, particularly for your interface. That is your in the general sense. I meant to say interfaces here. Regards, -- Aristotle If you can't laugh at yourself, you don't take life seriously enough.
Re: Parallel::Simple - bound args syntax
* Ofer Nave [EMAIL PROTECTED] [2005-03-02 03:55]: I hate to force people to create an anonymous hash when it can be implied. Plus I'm already checking for hashref as the first param to allow options to be specified, so I'd have to change that... to what, I don't know. Ah, I forgot about that. Of course the optional hash of options is usually passed last... (DBI comes to mind; I'm sure there are more? Can't think of any right now.) Regards, -- #Aristotle *AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(,$\/, )[defined wantarray]/e;$1}; Just-another-Perl-hacker;