From: Pascal J. Bourguignon on
Matt <30days(a)net.net> writes:

> On Wed, 7 Jul 2010 21:06:02 -0500, osmium wrote:
>
>>Fred Nurk wrote:
>>
>><Presumed question contained in the subject line. Questioner has a very
>>busy life.>
>>
>>A computer has no notion of context or meaning. A human seeing an integer,
>>a number containing a decimal point, and a number given in scientific
>>notation immediately and automatically classifies them and would add them in
>>a way appropriate to the form used for the number. If conversion from one
>>type to another is needed, the human can even see the need and make the
>>necessary conversion. A computer must be *explicitly* told the form.
>
> The type is implicit in the operator or function used.
>
> When else does it matter what type it is?
>
> I see no need (apart from ease of memory management for the compiler,
> which shuld be transparent to, not a constraint on, the user) to care
> what type of variable the characters "1.23" are assigned to. I may
> want to use that string as a number or as text in the same program.
> Why do I need to be burdened with type conversion as a separate step
> in my program?

Again, it depends on the operations you want to apply on these data.

I agree with you that for user problems, 1.23 or "1.23" could make no
difference (and indeed, there are several languages where such
conversions are done automatically).

The problem come when you want to benefit from the floating point
operations that have been implemented in the hardware to have them
quick. Then you need the number ni floating point representation, and
as soon as you operate on them you get other floating point numbers
that may be surprizing. Eg. 1.23 / 5 = 0.24600001

This can be explained only knowing what a floating point is, how the
floating point operations work, and why this is a correct result.
These are considerations about the representation type used here.

Indeed the users would not care, but for this in general, you need
more complex data structures even for simple numbers. The fact is
there is no nake number. If I tell you 37.9 that doesn't mean
anything. We need some context to interpret this number. If I add
the context that's the temperature of a patient expressed in Celcius,
you may be worried, and the computer could know that we don't want a
resulting compution about temperature to return 37.900001.


--
__Pascal Bourguignon__ http://www.informatimago.com/
From: tm on
On 8 Jul., 08:50, Matt <30d...(a)net.net> wrote:
> On Wed, 7 Jul 2010 21:06:02 -0500, osmium wrote:
> >Fred Nurk wrote:
>
> ><Presumed question contained in the subject line. Questioner has a very
> >busy life.>
>
> >A computer has no notion of context or meaning. A human seeing an integer,
> >a number containing a decimal point, and a number given in scientific
> >notation immediately and automatically classifies them and would add them in
> >a way appropriate to the form used for the number. If conversion from one
> >type to another is needed, the human can even see the need and make the
> >necessary conversion. A computer must be *explicitly* told the form.
>
> The type is implicit in the operator or function used.
>
> When else does it matter what type it is?
>
> I see no need (apart from ease of memory management for the compiler,
> which should be transparent to, not a constraint on, the user) to care
> what type of variable the characters "1.23" are assigned to. I may
> want to use that string as a number or as text in the same program.
> Why do I need to be burdened with type conversion as a separate step
> in my program?

A type is a concept which adds a meaning to some data. Data can
be represented in different ways. E.g. the number 128 can be
represented as integer, floating point or string. You might not
care and you might want some automatic conversion but distinct
representations are a fact which cannot be discussed away.
Performance considerations led to a hardwired floating point
representation and memory considerations led to a packed
representation for strings. I wrote a little C program to show the
different representations:
====================================================================
# include "stdio.h"
# include "string.h"

int main (int argc, char *argv[])
{
int int32 = 128;
float float32 = 128.0;
char char32[4] = "128\0";

union {
int int32value;
float float32value;
char char32value[4];
} hardcast;

printf("int int32 = %d, sizeof(int32) = %d, bits in int32:
0x%08x\n",
int32, sizeof(int32), int32);
hardcast.float32value = float32;
printf("float float32 = %0.0f, sizeof(float32) = %d, bits in
float32: 0x%08x\n",
float32, sizeof(float32), hardcast.int32value);
memcpy(hardcast.char32value, char32, 4);
printf("char char32[4] = %s, sizeof(char32) = %d, bits in char32:
0x%08x\n",
char32, sizeof(char32), hardcast.int32value);
return 0;
}
====================================================================

This program writes:

int int32 = 128, sizeof(int32) = 4, bits in int32:
0x00000080
float float32 = 128, sizeof(float32) = 4, bits in float32:
0x43000000
char char32[4] = 128, sizeof(char32) = 4, bits in char32:
0x00383231

As you can see the bit patterns 0x00000080, 0x43000000 and 0x00383231
all can represent 128. The different representations have all their
assets and drawbacks. Arithmetic computations with character arrays
are much slower than doing it with integer representation. The three
representations do not describe the same possible values. E.g.
strings can contain letters also and floating point numbers can
represent rational numbers which integers cannot represent (there
are also integers which cannot be represented as floating point
of the same size).

You wanted type conversions to take place automatically behind the
scene without your intervention. That's okay, but you must keep in
mind that you have to pay a price for this:

- The first thing is performance. Conversions cost time and you
can expect that a lot of unnecessary conversions will occur
(because the run-time system will not always guess right).
- Data loss can happen. Conversions between floats and strings
lose accuracy since floats use binary representation and
strings use decimal coding.
- Some operations may behave in an unplanned manner. E.g. Instead
of concatenating two decimal integer strings they might be
added or vice versa (when both use the same operator symbol).
- It can happen that a functions runs across a value that makes
no sense (such as dividing an integer by a string). It is
possible to define some "logic" even for such a strange case
but it is probable much wiser to consider this as program
error. With the automatic type conversions it is harder to find
errors since the cause for an error and the place where it pops
up can be a long way away from each other.

More info about this problems can be found here:

http://seed7.sourceforge.net/faq.htm#static_type_checking

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
From: Malcolm McLean on
Many high-level languages carry type information about with them.

Whilst in some ways this makes programming easier, in many ways it
makes it harder. Many variables must inherently be integers, or
scalars, or strings. Expicit typing acts as a sort of documentation of
this, and attempts to, as ypu say, divide an integer by a string will
be caught at compile time.



From: tm on
On 9 Jul., 03:20, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:
> Malcolm McLean <malcolm.mcle...(a)btinternet.com> writes:
> > Many high-level languages carry type information about with them.
>
> > Whilst in some ways this makes programming easier, in many ways it
> > makes it harder. Many variables must inherently be integers, or
> > scalars, or strings. Expicit typing acts as a sort of documentation of
> > this, and attempts to, as ypu say, divide an integer by a string will
> > be caught at compile time.
>
> But many other variables have no inherent type, and could be as well
> any number or of any other kind.
> See my factorial example in another answer!

When you use a dynamic typed solution for the 'fact' function
the following can happen:

- fact(15/4) might be wrong since for x < 1 you return 1, but
some people might prefer x instead (This might be a problem,
but lets assume that your definition of 'fact' is the right one).

- fact("abcd") will, in the optimal case, give you a run-time
error and in the not so optimal case some implied automatic type
conversion rule (or a "clever" * or - function) will give you a
wrong result which later leads to severe problems.

Why not make it explicit that you intend to reuse a function for
several types and specify exactly for which types you will do that.

In Seed7 you do exactly that: Specify a template which defines the
function 'fact' for the given type 'aType' (Note that the Seed7
template below is just a function with type parameter which contains
definitions in the body). After the template is defined it is
instantiated explicitly. This explicit instantiation is done on
purpose to improve the readability of the program. Please don't
praise implicit template instantiations since they save just one
line per instantiation.

====================================================================
$ include "seed7_05.s7i";
include "float.s7i";
include "bigint.s7i";
include "bigrat.s7i";
include "complex.s7i";

const proc: FACT_DECL (in type: aType) is func
begin

const func aType: fact (in var aType: argument) is func
result
var aType: result is aType conv 1;
begin
if argument >= (aType conv 1) then
result := argument * fact(argument - aType conv 1);
end if;
end func;

end func;

FACT_DECL(integer);
FACT_DECL(float);
FACT_DECL(bigInteger);
FACT_DECL(bigRational);
FACT_DECL(complex);

const proc: main is func
begin
noop;
end func;
====================================================================

When you try this program you will get the compile time error:

fact3.sd7(14):51: Match for {argument >= {complex conv 1 } } failed
if argument >= (aType conv 1) then

It tells you that >= is not defined for the type 'complex'.

*** SURPRISE, SURPRISE ***

Mathematicians will tell you >= cannot be defined reasonable for
'complex' values.

You get this error at compile time for free without heavy testing.

Now you can define >= for 'complex' or decide for something else.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
From: Paul N on
On 9 July, 13:14, blm...(a)myrealbox.com <blm...(a)myrealbox.com> wrote:
> In article <87y6dnexi1....(a)kuiper.lan.informatimago.com>,
> Pascal J. Bourguignon <p...(a)informatimago.com> wrote:
>
> > Paul N <gw7...(a)aol.com> writes:
>
> > > Incidentally, I would be a bit surprised if a language actually
> > > provided a type for real numbers.
>
> > This is not impossible, using the right representation.  Eg. continued
> > fractions.  There are libraries, that you could integrate like gmp in
> > a given language.
>
> Are there libraries that allow representing *all* real numbers,
> including the irrationals?  I'm trying to imagine how that could
> work .... ?

As I understand it, for the majority of real numbers, it would take an
infinite amount of space just to store one number. Which is why I
expressed my doubts. On the other hand, if it's a number that you are
interested in, it's probably one of the tiny minority that *can* be
represented in a finite space.

Of course, any computer using a fixed size for numbers can only store
a tiny minority of the integers and a tiny minority of the floating
point numbers, so we're used to getting half measures anyway.