Re: Divide by 0? Was: Re: Introduction Letter

2005-03-01 Thread Austin Schutz
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

2005-03-01 Thread Eric Wilhelm
# 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

2005-03-01 Thread Ofer Nave
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

2005-03-01 Thread Eric Wilhelm
# 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

2005-03-01 Thread Austin Schutz
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

2005-03-01 Thread Eric Wilhelm
# 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

2005-03-01 Thread Eric Wilhelm
# 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

2005-03-01 Thread Ofer Nave
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 (?)

2005-03-01 Thread Linda W
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

2005-03-01 Thread A. Pagaltzis
* 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

2005-03-01 Thread A. Pagaltzis
* 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

2005-03-01 Thread A. Pagaltzis
* 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;