Discussion:
New Seed7 Release 2006-07-07
(too old to reply)
t***@gmx.at
2006-07-07 18:20:22 UTC
Permalink
Hello,

I have released a new version of Seed7: seed7_05_20060707.tgz

In the Seed7 programming language new statements and operators
can be declared easily. Types are first class objects and therefore
templates/generics need no special syntax. Object orientation is
used when it brings advantages and not in places when other
solutions are more obvious.

Seed7 is covered by the GPL (and LGPL for the Seed7 runtime library).

Changelog:
- A little improvement of the castle example program was done.
- The drwText function of the windows graphic driver
was changed to support unicode characters.
- A new example program (planets) was added.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
goose
2006-07-10 15:01:35 UTC
Permalink
***@gmx.at wrote:
> Hello,
>
> I have released a new version of Seed7: seed7_05_20060707.tgz
>
> In the Seed7 programming language new statements and operators
> can be declared easily. Types are first class objects and therefore
> templates/generics need no special syntax. Object orientation is
> used when it brings advantages and not in places when other
> solutions are more obvious.
>
> Seed7 is covered by the GPL (and LGPL for the Seed7 runtime library).
>

I do not mean to rubbish your work as you seem to have
put a lot of effort into this but I have to ask: What
exactly is it that seed7 brings to the party that we
don't already have?

I've skimmed quickly through the manual and didn't find
a feature that I considered unique, and even found a few
that I consider "bad" for a general purpose programming
language.

<snipped>

goose,
Aaron Gray
2006-07-10 16:00:58 UTC
Permalink
> I do not mean to rubbish your work as you seem to have
> put a lot of effort into this but I have to ask: What
> exactly is it that seed7 brings to the party that we
> don't already have?
>
> I've skimmed quickly through the manual and didn't find
> a feature that I considered unique, and even found a few
> that I consider "bad" for a general purpose programming
> language.

What other language gives this mix of features.

I would be interested if there is one or two others.

Aaron
goose
2006-07-11 08:57:29 UTC
Permalink
Aaron Gray wrote:
> > I do not mean to rubbish your work as you seem to have
> > put a lot of effort into this but I have to ask: What
> > exactly is it that seed7 brings to the party that we
> > don't already have?
> >
> > I've skimmed quickly through the manual and didn't find
> > a feature that I considered unique, and even found a few
> > that I consider "bad" for a general purpose programming
> > language.
>
> What other language gives this mix of features.
>
> I would be interested if there is one or two others.
>

<from the seed7 homepage, numbered for convenience>

Features of Seed7
1 User defined statements and operators.
2 Types are first class objects (Templates and generics can be
defined easily without special syntax).
3 Predefined constructs like arrays or for-loops are declared in the
language itself.
4 Object orientation
5 Strong typing
6 exception handling
7 overloading of procedures/functions/operators/statements
8 Various predefined types like resizable arrays, hashes, bitsets,
structs, color, time, duration, etc.
9 Runs under linux and various unix versions. A windows version is
under developent
10The interpreter and the example programs use the GPL license,
while the runtime library uses the LGPL license.


Well, lets take C++ and see how it compares:
#1 - userdefined operators, although I don't think it
is possible to have used-defined statements without
clarifying what that is (I suspect it means user-defined
language constructs and not user-defined statements).
#2 templates (generics???) in C++
#3 for loops in C++ itself, stl takes care of things like arrays
#4 OO in C++
#5 also in C++
#6 C++ has this
#7 C++ has this also (don't know about "statements" - suspect
"language constructs" is what is meant).
#8 C++ has most of this AFAIK; also can define new types so can
define color, etc in a trivial manner.
#9 C++ does better than this here.
#10 See gcc.

So, C++ loses half a point (#1) and wins 2 points (#9 #10).

Lets see if Lisp has all these features:
#1 Yes, and more (macros defining mini-language facility)
#2 Yes, and more (functions are first class objects too)
#3 Yes, and they can be defined using only the language itself.
#4 Yes, with CLOS seeming to be much more powerfull than seed7
#5 Not by default, as this is considered a "bad thing" not a
"good thing" in lisp-world; but sure, you can use
typed variables if you want to.
#6 Yes, and more (signaling errors and restarting, not just
throwing exception and unwinding call-stack).
#7 Yes.
#8 Yes to most of the above, trivial to define the rest to fit in
transparently to the language.
#9 Yes (and better)
#10Yes (depending on which implementation you choose).


Lisp loses 1 point (#5) only by not having that as default
behaviour and wins #1, #2, #3, #4 (IMHO, you may think differently),
#6, #8 and #9 for a total of 7 points.

So, like I asked, what exactly is new or special about this
language?

goose,
I'd actually like to know, see?
Grzegorz Wróbel
2006-07-11 17:34:58 UTC
Permalink
goose wrote:
> <from the seed7 homepage, numbered for convenience>
>
> Features of Seed7
> 1 User defined statements and operators.
> 2 Types are first class objects (Templates and generics can be
> defined easily without special syntax).
> 3 Predefined constructs like arrays or for-loops are declared in the
> language itself.
> 4 Object orientation
> 5 Strong typing
> 6 exception handling
> 7 overloading of procedures/functions/operators/statements
> 8 Various predefined types like resizable arrays, hashes, bitsets,
> structs, color, time, duration, etc.
> 9 Runs under linux and various unix versions. A windows version is
> under developent
> 10The interpreter and the example programs use the GPL license,
> while the runtime library uses the LGPL license.
>
>
> Well, lets take C++ and see how it compares:
> #1 - userdefined operators, although I don't think it
> is possible to have used-defined statements without
> clarifying what that is (I suspect it means user-defined
> language constructs and not user-defined statements).
> #2 templates (generics???) in C++
> #3 for loops in C++ itself, stl takes care of things like arrays
> #4 OO in C++
> #5 also in C++
> #6 C++ has this
> #7 C++ has this also (don't know about "statements" - suspect
> "language constructs" is what is meant).
> #8 C++ has most of this AFAIK; also can define new types so can
> define color, etc in a trivial manner.
> #9 C++ does better than this here.
> #10 See gcc.
>
> So, C++ loses half a point (#1) and wins 2 points (#9 #10).
>
> Lets see if Lisp has all these features:
> #1 Yes, and more (macros defining mini-language facility)
> #2 Yes, and more (functions are first class objects too)
> #3 Yes, and they can be defined using only the language itself.
> #4 Yes, with CLOS seeming to be much more powerfull than seed7
> #5 Not by default, as this is considered a "bad thing" not a
> "good thing" in lisp-world; but sure, you can use
> typed variables if you want to.
> #6 Yes, and more (signaling errors and restarting, not just
> throwing exception and unwinding call-stack).
> #7 Yes.
> #8 Yes to most of the above, trivial to define the rest to fit in
> transparently to the language.
> #9 Yes (and better)
> #10Yes (depending on which implementation you choose).
>
>
> Lisp loses 1 point (#5) only by not having that as default
> behaviour and wins #1, #2, #3, #4 (IMHO, you may think differently),
> #6, #8 and #9 for a total of 7 points.
>
> So, like I asked, what exactly is new or special about this
> language?
>
> goose,
> I'd actually like to know, see?
>

What I gather, the new thing is those user defined "statements", which allows you to actually "develop your own language" by defining new syntax statement. Sound like a powerfull feature, but then if you think about the hell of going trough someone elses code... practically you would need to learn each programmers private language.

As to Lisp and it's "advantages"... well, it's a functional language. You know, all real software is done using imperative languages.

--
677265676F727940346E6575726F6E732E636F6D
Robbert Haarman
2006-07-11 18:16:26 UTC
Permalink
goose wrote:

>5 Strong typing
>
>#5 Not by default, as this is considered a "bad thing" not a
> "good thing" in lisp-world; but sure, you can use
> typed variables if you want to.

I wouldn't say that. Implementations are not required to check these
types, let alone detect type errors at compile time. Type declarations
in Common Lisp are really only there for performance enhancement, and I
think in seed7 they also catch errors.

Grzegorz Wr?bel wrote:

> What I gather, the new thing is those user defined "statements", which
> allows you to actually "develop your own language" by defining new syntax
> statement.

But Lisps have that, and so does Ocaml.

> Sound like a powerfull feature, but then if you think about the
> hell of going trough someone elses code... practically you would need to
> learn each programmers private language.

This is actually not as bad as you may expect. Sure, if someone goes and
redefines standard bindings or uses his own constructs almost
exclusively, you will have a different language to learn and it will be
bad. But this is not the way the feature is usually used; Lisp macros,
at least, are usually used to define useful new control structures or to
succinctly and elegantly write down code that would otherwise be
repetitive. For the most part, the program will still read like an
ordinary Lisp program.

> As to Lisp and it's "advantages"... well, it's a functional language. You
> know, all real software is done using imperative languages.

Wrong on two counts. First of all, Lisp isn't a functional language.
People do use the functional style a lot (because they consider it the
most elegant), but Lisp nowhere near forces you to do this. All Lisp
dialects I know sport variables, assignments, and mutable data
structures just like any other imperative language.

Secondly, if you consider Ocaml and Haskell functional languages
(both of them have imperative features), then real software is written
in functional languages: mldonkey and darcs are two that I have used.

I wouldn't be surprised to see functional languages pick up popularity
in the near future; the absence of state makes it much easier to run
functional programs in a distributed environment than imperative ones,
and with multicore machines becoming increasingly common, this might be
a key advantage.

Cheers,

Bob

---
Life is too short to be taken seriously.
Ole Nielsby
2006-07-11 19:54:29 UTC
Permalink
Robbert Haarman <***@inglorion.net> wrote:

> I wouldn't be surprised to see functional languages pick up
> popularity in the near future; the absence of state makes it
> much easier to run functional programs in a distributed
> environment than imperative ones, and with multicore
> machines becoming increasingly common, this might be
> a key advantage.

Generally, I agree.

However, one reason why "real programmers" stick with
imperative environments is, you can crack most bugs by
stepping through the code in a debugger.

Functional programming environments need to come up
with really good tools for pinning the little bugs in the
haystacks of "real programming" if it is to have any
deep impact.
Robbert Haarman
2006-07-11 20:22:57 UTC
Permalink
On Tue, Jul 11, 2006 at 09:54:29PM +0200, Ole Nielsby wrote:
>
> However, one reason why "real programmers" stick with
> imperative environments is, you can crack most bugs by
> stepping through the code in a debugger.

And this can't be done in functional languages?

> Functional programming environments need to come up
> with really good tools for pinning the little bugs in the
> haystacks of "real programming" if it is to have any
> deep impact.

My experience is that functional programming, in combination with safer
languages and APIs (w.r.t. type safety, bounds checking, injection,
etc.), eliminates a large chunk of bugs that occur in "real
programming". On the other hand, my experience with "real programming"
is minimal; I mostly write simple things, alone or with one or two other
people.

I think what's really holding back a great number of languages is the
aversion of change in the industry. There are good reasons for not
blindly adopting every language that comes along, but seeing how long it
has taken for features like garbage collection, object orientation, and
type safety to become commonplace, I can't help but think that the
industry is a bit too careful.

Bob

---
You are in a twisting maze of passages, all alike.
Ole Nielsby
2006-07-11 21:51:21 UTC
Permalink
FUT comp.lang.misc
(replies to this will go to comp.lang.misc only)

Robbert Haarman <***@inglorion.net> wrote:

> Ole Nielsby wrote:
>
>> However, one reason why "real programmers" stick with
>> imperative environments is, you can crack most bugs by
>> stepping through the code in a debugger.
>
> And this can't be done in functional languages?

Surely it can be done, but the execution order of fp languages
can be confusing.

>> Functional programming environments need to come up
>> with really good tools for pinning the little bugs in the
>> haystacks of "real programming" if it is to have any
>> deep impact.
>
> My experience is that functional programming, in combination
> with safer languages and APIs (w.r.t. type safety, bounds
> checking, injection, etc.), eliminates a large chunk of bugs
> that occur in "real programming". On the other hand, my
> experience with "real programming" is minimal; I mostly
> write simple things, alone or with one or two other people.

When writing alone or in pairs, you are able to keep certain
standards. In "real programming", you have to cope with
Beavis 'n Butthead code. Often, single-stepping is the only
way of finding out what is going on. Now, if the execution
order is quite different from the textual order, you could
have a really hard time.

> I think what's really holding back a great number of
> languages is the aversion of change in the industry.
> There are good reasons for not blindly adopting every
> language that comes along, but seeing how long it
> has taken for features like garbage collection, object
> orientation, and type safety to become commonplace,
> I can't help but think that the industry is a bit too careful.

Agree. "Mainstream" programming is a bit like a water pit
in the roof of a tent. The more water in the pit, the more the
pit sinks down, and the more water will run to the pit from
the surrounding areas. So many tools have developed
around imperative programming that "real programmers"
get drawn to it and perceive the alternatives as immature
and unfriendly. To get out of the pit, they'd have to climb
upwards, against the stream.

Programmers aren't like guppies or frogs. They cannot
jump to the next pit. They need a ladder to get up from
the pit - step by step, and so far, I don't think fp has
done to much to provide that.

At work, I've tried to connect the two ponds by
using a homebrew fp-style programming system
for writing VB6 analysis and refactoring tools.
Though several of the tools were quite successful and
have been integrated into the routines of maintaining
the VB6 project I wrote them for, this never stirred
any real interest in functional programming among
my collegues. The general consensus seems to be,
you can code anything in any language so let's just
stick with MS.

It doesn't seem to bother them that I, in this "toy
system" of mine, wrote useful stuff they simply
didn't know how to write in imperative languages.
goose
2006-07-12 10:12:21 UTC
Permalink
Robbert Haarman wrote:
> On Tue, Jul 11, 2006 at 09:54:29PM +0200, Ole Nielsby wrote:
> >
> > However, one reason why "real programmers" stick with
> > imperative environments is, you can crack most bugs by
> > stepping through the code in a debugger.
>
> And this can't be done in functional languages?
>
> > Functional programming environments need to come up
> > with really good tools for pinning the little bugs in the
> > haystacks of "real programming" if it is to have any
> > deep impact.
>
> My experience is that functional programming, in combination with safer
> languages and APIs (w.r.t. type safety, bounds checking, injection,
> etc.), eliminates a large chunk of bugs that occur in "real
> programming". On the other hand, my experience with "real programming"
> is minimal; I mostly write simple things, alone or with one or two other
> people.

My experience with "real programming" is extensive; I do it
full time and have done so for a number of years now. The
grandparent post *does* have a point wrt tools for functional
languages.

Sadly, the tools developers tend to develop for the largest
market; functional programming is not that market.

>
> I think what's really holding back a great number of languages is the
> aversion of change in the industry. There are good reasons for not
> blindly adopting every language that comes along, but seeing how long it
> has taken for features like garbage collection, object orientation, and
> type safety to become commonplace, I can't help but think that the
> industry is a bit too careful.
>

If I had more time, I'd disagree coherently; all I can do now
is point out that C# and Java are among the most popular and
have the biggest hype budget

goose,
Grzegorz Wróbel
2006-07-12 03:34:05 UTC
Permalink
Robbert Haarman wrote:

>>What I gather, the new thing is those user defined "statements", which
>>allows you to actually "develop your own language" by defining new syntax
>>statement.
>
>
> But Lisps have that, and so does Ocaml.
>

It is possible that the autor is either not aware of this (he compares his languages only to Ada, C++ and Java) or for some reasons he believes his kind of extension is unique.

Here is officual explanation why introducing this new language:
http://seed7.sourceforge.net/manual/intro.htm#Why_a_new_programming_language

However it would be interesting to hear what the autor has to say about that.

--
677265676F727940346E6575726F6E732E636F6D
Marcin 'Qrczak' Kowalczyk
2006-07-12 07:27:14 UTC
Permalink
Followup-To: comp.lang.misc

Grzegorz Wróbel </dev/***@localhost.localdomain> writes:

> Here is officual explanation why introducing this new language:
> http://seed7.sourceforge.net/manual/intro.htm#Why_a_new_programming_language

| There are several concepts which are new
|
| * Variables and constants must be initialized when they are declared.

Not new, see e.g. SML and OCaml.

| * Every expression has exactly one type. That means that overloaded
| functions are resolved with their actual parameters and not with
| the context of their call. (This is different to the overloading
| mechanism used by ADA)

If I understood what he means by this, this is true in most languages,
e.g. C++, SML.

| * With a syntax declaration new operators and statements can be defined.

Not new, see e.g. Lisp, Scheme, Dylan.

| * Not only the predefined operator symbols can be overloaded.
| Additionally it is possible to invent completely new operator
| symbols.

Not new, see e.g. Haskell.

| Several restrictions of other languages are released
|
| * There is no limitation in the length of an identifier and all
| characters of an identifier are significant.
|
| * Statements and parentheses can be nested without limitation in depth.
|
| * The number of parameters and local variables is not limited.
|
| * Strings can contain any characters (also the NUL character)
| This allows holding binary information in strings.
|
| * Although strings are not NUL terminated they have no size
| limitation. (Except there is no more memory)
|
| * String literals can have any length.
|
| * There is no limitation in the length of a source line.
|
| * There is no level limitation for nesting includes.

There are no such restrictions in most languages, e.g. Python and
Haskell have none of these when they are relevant (other mechanisms
are used instead of includes).

--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
goose
2006-07-12 09:48:36 UTC
Permalink
Grzegorz Wróbel wrote:
>

<snipped>

> Here is officual explanation why introducing this new language:
> http://seed7.sourceforge.net/manual/intro.htm#Why_a_new_programming_language
>
> However it would be interesting to hear what the autor has to say about that.
>

Seconded; I'm currently on a language binge and will gladly
give anything a bash, just to compare with my current choices;
so yes - I'd like to hear the author respond to this newsgroup
as well.

goose,
goose
2006-07-12 09:51:43 UTC
Permalink
Grzegorz Wróbel wrote:

<snipped>

>
> As to Lisp and it's "advantages"... well, it's a functional language. You know, all real software is done using imperative languages.
>

Ouch! :-)

goose,
btw: lisp is "functional" only when you
want it to be. I tend to use it as a
better OO system.
Grzegorz Wróbel
2006-07-12 11:02:21 UTC
Permalink
goose wrote:
> Ouch! :-)
>
> goose,
> btw: lisp is "functional" only when you
> want it to be. I tend to use it as a
> better OO system.
>

Yes, I realized after Robbert Haarman's reply. My short adventure with lisp was during my studies. We had one proffesor from Sweden, lisp maniac, minimalist and functional programming follower, so I remembered lisp as functional language. :)

--
677265676F727940346E6575726F6E732E636F6D
t***@gmx.at
2006-07-15 06:35:53 UTC
Permalink
Grzegorz Wróbel schrieb:
> What I gather, the new thing is those user defined "statements",
> which allows you to actually "develop your own language" by
> defining new syntax statement. Sound like a powerfull feature,
> but then if you think about the hell of going trough someone
> elses code... practically you would need to learn each programmers
> private language.

I would say the programmer is (as always) responsible to write
readable programs. The variable/type/function names and other
things chosen by the programmer can always lead to obfuscated code.

New statements are intendet to be used when writing librarys and
should not be used everywhere and all the time.

The possibility to define statements allows a more precise
language definition. As mentioned at another place in this thread:

The C++ for/while/if statements are described in the C++ manuals
using BNF and an english description. Seed7 statements can be
defined in Seed7. For example:

$ syntax expr: while.().do.().end.while is -> 25;

const proc: while (ref func boolean: condition) do
(ref proc: statement)
end while is func
begin
if condition then
statement;
while condition do
statement;
end while;
end if;
end func;

The syntax and semantic of a while statement is described
using an if statement and recursion. The implementation does
use a different implementation for performance reasons, but
this example shows the expressive power of Seed7.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
t***@gmx.at
2006-07-13 22:52:01 UTC
Permalink
goose wrote:
> Features of Seed7
> 1 User defined statements and operators.
> 2 Types are first class objects (Templates and generics can be
> defined easily without special syntax).
> 3 Predefined constructs like arrays or for-loops are declared in the
> language itself.
> 4 Object orientation
> 5 Strong typing
> 6 exception handling
> 7 overloading of procedures/functions/operators/statements
> 8 Various predefined types like resizable arrays, hashes, bitsets,
> structs, color, time, duration, etc.
> 9 Runs under linux and various unix versions. A windows version is
> under developent
> 10The interpreter and the example programs use the GPL license,
> while the runtime library uses the LGPL license.

> Well, lets take C++ and see how it compares:

1 AFAIK: C++ does allow overloading of existing operators but
not the invention of new operator symbols.
Additionally it is not possible to define new statements in C++.
2 Templates in C++ use the aTemplate<type1, type2> notation.
Seed7 does not need a special syntax for this. You can write
functions which take types as parameters. Such a function can
make declarations using a type parameters. Therefore templates
need no special syntax. The template mechanism in C++ is OK,
but types as parameters is better because no special syntax is
needed.
3 The C++ for/while/if statements are described in the C++ manuals
using BNF and an english description. Seed7 statements can be
defined in Seed7. For example:

$ syntax expr: while.().do.().end.while is -> 25;

const proc: while (ref func boolean: condition) do
(ref proc: statement)
end while is func
begin
if condition then
statement;
while condition do
statement;
end while;
end if;
end func;

The syntax and semantic of a while statement is described
using an if statement and recursion. The implementation does
use a different implementation for performance reasons, but
this example shows the expressive power of Seed7.

4 OO is in C++
5 C++ has various implicit type conversions. In Seed7 every
expression has exactly one type and no implicit conversions
take place. Implicit type conversions are a well known
source of errors.
6 C++ has exceptions
7 C++ has overloading of procedures, functions and operators,
but statements can not be overloaded.
8 The library functions of Seed7 will grow.
9 C++ and Seed7 are portable.
10 gcc

There are several features in Seed7 which are missing in C++
and it would not be easy add this features to C++.
Missing features of Seed7 compared to C++ can IMHO be easier
added.

> Lets see if Lisp has all these features:

1 AFAIK: Lisp uses lots of parentheses to form lists. In all
expressions the first element of the list is the function
name. The definition of the factorial function in lisp
would be (example from wikipedia):

(defun ! (n)
(cond ((= n 0) 1)
((> n 0) (* n (! (- n 1))))))

This function could be called with

(! 5)

AFAIK there is no concept of infix operators (with priority
and assoziativity) in Lisp. Lisp allows the definition of
new functions, but functions are not operators. The
description of an factorial operator in Seed7 would be:

$ syntax expr: . ! .() is -> 4;

const func integer: ! (in integer: n) is func
result
var integer: result is 1;
begin
if n > 0 then
result := n * !(n - 1);
end if;
end func;

This function could be called with

!5

In general Lisp does not know about operators and
overloading. Lisp statements (see cond of the example
above) use also the list syntax with lots of parentheses.
This means that user defined statements of Lisp have to
use the list notation and there is no possibility to
define a syntax for this statements.

2 The type concept does not exist in Lisp therefore
it is not possible to use types as parameters.

3 This is possible in Lisp

4 I do not know the details of CLOS

5 As mentioned before types does not exist in Lisp and
IMHO this is a bad thing.

I am to tired to answer the other points, but you see
my view is different.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-14 06:55:54 UTC
Permalink
Some corrections and clarifications regarding Lisp:

On Thu, Jul 13, 2006 at 03:52:01PM -0700, ***@gmx.at wrote:
> goose wrote:
> > Features of Seed7
> > 1 User defined statements and operators.
> > 2 Types are first class objects (Templates and generics can be
> > defined easily without special syntax).
> > 3 Predefined constructs like arrays or for-loops are declared in the
> > language itself.
> > 4 Object orientation
> > 5 Strong typing
> > 6 exception handling
> > 7 overloading of procedures/functions/operators/statements
> > 8 Various predefined types like resizable arrays, hashes, bitsets,
> > structs, color, time, duration, etc.
> > 9 Runs under linux and various unix versions. A windows version is
> > under developent
> > 10The interpreter and the example programs use the GPL license,
> > while the runtime library uses the LGPL license.
>
> > Lets see if Lisp has all these features:
>
> 1 AFAIK: Lisp uses lots of parentheses to form lists. In all
> expressions the first element of the list is the function
> name. The definition of the factorial function in lisp
> would be (example from wikipedia):
>
> <snip>
>
> In general Lisp does not know about operators and
> overloading. Lisp statements (see cond of the example
> above) use also the list syntax with lots of parentheses.
> This means that user defined statements of Lisp have to
> use the list notation and there is no possibility to
> define a syntax for this statements.

Common Lisp supports so-called read macros, which allow you to extend
the parser. These can and have been used to get it to support infix
arithmetic, including precedence. However, Lispers tend to favor the
consistency and simplicity of prefix syntax over compliance with
conventional math notation. However, if you want to, you can certainly
define your own statements and (infix) operators.

As for overloading; the math functions in Common Lisp work for various
types of number by default. It is possible to override them and
implement them for other types as well.

> 2 The type concept does not exist in Lisp therefore
> it is not possible to use types as parameters.

Types do exist in Common Lisp, although they are not first-class values.
However, you can get about the same effect as templates/generics by
defining a normal function: it will automatically work for any
compatible combination of types, without you having to specify which
types you want to pass in. If you wanted to completely emulate templates
in that you would have to create an instance of your template using
specific types, you could write a macro to do so.

For example, if you had, in C++:

template <typename T> max(T x, T y) {
return x > y ? x : y;
}

You could get the larger one of two integers by calling:

max<int>(3, 5);

In Common Lisp, you could write this as:

(defun max (x y) (if (> x y) x y))

(max 3 5)

although the standard already includes a definition of max that works
for one or more arguments...which would be somewhat complex to describe
in C++. How does Seed7 handle that, by the way?

One way to get closer to the C++ example would be to say:

(defmacro max (type x y)
`((lambda (x y) (the ,type (if (> x y) x y)))
(the ,type ,x) (the ,type ,y)))

(max integer 3 5)

The macro would, in this case, expand to

((lambda (x y) (the integer (if (> x y) x y)))
(the integer 3) (the integer 5))

which, in addition to returning the maximum of 3 and 5, asserts that 3,
5, and their maximum are all integers.

Of course, macros are much more powerful than this, and I would argue
that templates are a special, limited instance of macros.

> 4 I do not know the details of CLOS

CLOS has a very interesting and powerful approach to object-oriented
programming. It has classes and methods, but rather than associating
methods with classes (as the object systems in many contemporary
languages do), it associates them with generic functions. Among other
things, this means that (1) methods use the same syntax as functions,
and (2) the methods you can apply to instances of a class are not fixed
at method definition time (nor at any other time, actually).

Rather than completely explain CLOS here, I'm going to point interested
readers at Common Lisp the Language, 2nd edition, which can be found at
http://www.supelec.fr/docs/cltl/clm/clm.html, among other places. It
contains a description of Common Lisp, including CLOS.

> 5 As mentioned before types does not exist in Lisp and
> IMHO this is a bad thing.

Of course, Common Lisp does have types; only that type errors are not
detected until run time (although implementations often warn you if
types are determined to be incorrect at compile time). Although I feel
catching type errors at compile time is an advantage, to me it is not
worth the cost of having to explicitly declare types or be stuck with a
limited type system (as in C and older versions of Java).

> I am to tired to answer the other points, but you see
> my view is different.

Yes. In some cases, this is a matter of definitions, assumptions, or
fundamental values. For example, Common Lisp offers + as a normal
function, rather than an infix operator. Does this mean Common Lisp
loses a point for not allowing one to override the + infix operator?
With respect to object-orientation, the CLOS approach is different from
what many people take object-orientation to mean, and thus it has been
argued that Lisp doesn't support object oriented programming. Depending
on your definitions, this may be true or false.

Regards,

Bob

---
In a democracy, people get the government they deserve.
t***@gmx.at
2006-07-14 09:18:02 UTC
Permalink
Robbert Haarman wrote:
> For example, if you had, in C++:
>
> template <typename T> max(T x, T y) {
> return x > y ? x : y;
> }
>
> You could get the larger one of two integers by calling:
>
> max<int>(3, 5);
>
> In Common Lisp, you could write this as:
>
> (defun max (x y) (if (> x y) x y))
>
> (max 3 5)

This is a function declaration and no template is
involved.

> although the standard already includes a definition of max that works
> for one or more arguments...which would be somewhat complex to describe
> in C++. How does Seed7 handle that, by the way?

You declare a 'template' with:

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

const func aType: max (in aType: x, in aType: y) is func
result
var aType: result is aType.value;
begin
if x > y then
result := x;
else
result := y;
end if;
end func;

const func aType: max (in array aType: x) is func
result
var aType: result is aType.value;
local
var aType: y is aType.value;
begin
if length(x) >= 1 then
result := x[1];
for y range x do
if y > result then
result := y;
end if;
end for;
end if;
end func;

end func;

Then you instanciate the template with (for example):

declareMax(integer);
declareMax(char);
declareMax(float);
declareMax(time);

After that you can call the 'max' function with:

max('a', 'b')
max(3, 5)
max(1.2345, 3.1415)
max([](2, 3, 5, 7))
max([]('&', '*', '!', '+'))

Btw. Seed7 does not support variable size parameter lists
on purpose (this is a source of errors - see printf
statements), therefore an array is used instead.

> The macro would, in this case, expand to
>
> ((lambda (x y) (the integer (if (> x y) x y)))
> (the integer 3) (the integer 5))
>
> which, in addition to returning the maximum of 3 and 5,
> asserts that 3, 5, and their maximum are all integers.

Does it the type check at compiletime or runtime?
Seed7 does all type checks at compile time.

> Of course, Common Lisp does have types; only that type
> errors are not detected until run time

Type checks make much more sense when done at compile
time. This way lots of possible errors are avoided.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-14 10:21:23 UTC
Permalink
On Fri, Jul 14, 2006 at 02:18:02AM -0700, ***@gmx.at wrote:
> Robbert Haarman wrote:
> >
> > In Common Lisp, you could write this as:
> >
> > (defun max (x y) (if (> x y) x y))
> >
> > (max 3 5)
>
> This is a function declaration and no template is
> involved.

True, but depending on why you're using templates, this can be an
advantage. When programming in C++, I used templates to avoid code
duplication for functions that performed the same operations, but on
different types. In Lisp, I get that without having to use templates.

If you want to use the types you pass to templates to do compile time
type checking, you're lost in Common Lisp: the standard doesn't mandate
compile time type checking, and even many run time type checks are
optional. Having said that, many implementations will warn you at
compile time when your types aren't right. For example, in SBCL:

* (defun frobnitz () (+ 12 "aleph"))
; in: LAMBDA NIL
; (+ 12 "aleph")
; --> LOCALLY PROGN
; ==>
; (+ 12 "aleph")
;
; caught WARNING:
; Asserted type NUMBER conflicts with derived type
; (VALUES (SIMPLE-BASE-STRING 5) &OPTIONAL).
; See also:
; The SBCL Manual, Node "Handling of Types"
; compilation unit finished
; caught 1 WARNING condition

FROBNITZ

Here, the compiler is warning me that + expects to get a number, but I'm
passing it a string. This warning is given at compile time, before I've
even written any code that calls frobnitz.

> > although the standard already includes a definition of max that works
> > for one or more arguments...which would be somewhat complex to describe
> > in C++. How does Seed7 handle that, by the way?
>
> You declare a 'template' with:
>
> const proc: declareMax (in type: aType) is func
> begin
>
> const func aType: max (in aType: x, in aType: y) is func
> result
> var aType: result is aType.value;
> begin
> if x > y then
> result := x;
> else
> result := y;
> end if;
> end func;
>
> const func aType: max (in array aType: x) is func
> result
> var aType: result is aType.value;
> local
> var aType: y is aType.value;
> begin
> if length(x) >= 1 then
> result := x[1];
> for y range x do
> if y > result then
> result := y;
> end if;
> end for;
> end if;
> end func;
>
> end func;
>
> Then you instanciate the template with (for example):
>
> declareMax(integer);
> declareMax(char);
> declareMax(float);
> declareMax(time);
>
> After that you can call the 'max' function with:
>
> max('a', 'b')
> max(3, 5)
> max(1.2345, 3.1415)
> max([](2, 3, 5, 7))
> max([]('&', '*', '!', '+'))

Compare this with, say:

(defun maxx (n &rest xs)
(loop for x in xs do
(if (> x n) (setf n x)))
n)

and I guess you can see why I find Seed7 too verbose...

> Btw. Seed7 does not support variable size parameter lists
> on purpose (this is a source of errors - see printf
> statements), therefore an array is used instead.

In combinatios with your terse anonymous array syntax, I think this
works well enough. I don't really agree with your reasons, though: the
errors in printf aren't due to the variable number of arguments, but
rather to the format string which isn't checked against the arguments
that are provided. The same problem exists in Common Lisp, by the way,
although SBCL will give warnings, e.g.:

* (lambda () (format t "~a ~a~%" 'foo))
;
; caught WARNING:
; Too few arguments (1) to FORMAT "~a ~a~%": requires at least 2.
; See also:
; The ANSI Standard, Section 22.3.10.2
; compilation unit finished
; caught 1 WARNING condition

#<FUNCTION "#'(LAMBDA NIL (FORMAT T \"~a ~a~%\" ...))" {4808AA15}>

Still, the common case where you pass a number of arguments to a
function and they are all processed in order is not a source of errors,
and still very nice to have.

> > The macro would, in this case, expand to
> >
> > ((lambda (x y) (the integer (if (> x y) x y)))
> > (the integer 3) (the integer 5))
> >
> > which, in addition to returning the maximum of 3 and 5,
> > asserts that 3, 5, and their maximum are all integers.
>
> Does it the type check at compiletime or runtime?
> Seed7 does all type checks at compile time.

It depends what you mean by type check, really. Common Lisp
implementations are not required to check the asserted types AT ALL, but
SBCL will give you a warning at compile time:

; caught WARNING:
; Asserted type REAL conflicts with derived type (VALUES COMPLEX &OPTIONAL).
; See also:
; The SBCL Manual, Node "Handling of Types"

and an error at run time:

debugger invoked on a TYPE-ERROR in thread 13108:
The value 12 is not of type COMPLEX.

> > Of course, Common Lisp does have types; only that type
> > errors are not detected until run time
>
> Type checks make much more sense when done at compile
> time. This way lots of possible errors are avoided.

Yes, but it comes with a price. Depending on the type system, this price
can be rather high (e.g. in C, where you would have to define a new
function with a new name for performing the same operations on values of
different types, and all types have to be declared).

Of course, not doing compile time type checks comes with a price too:
finding out your types aren't right at run time isn't very nice,
especially if it's not the programmer discovering it but the customer.

Regards,

Bob

---
The early bird gets the worm, but the second mouse gets the cheese.
t***@gmx.at
2006-07-14 08:17:59 UTC
Permalink
Rob Thorpe wrote about Lisp:
> Within a statement you can define anything you want.
> You could write a form called "arith" for example that did normal
> arithmetic with precedence etc if you wanted.
>
> (arith 4 + 6 * 3)
>
> You could implement it with a macro so it expanded into normal code at
> compile time.

You don't get rid of the parantheses around the call of the
'arith' function.

> It is true to say that in lisp there is not associativity or
> precedence.

The 'arith' function has to interpret the precedence (execute * before
+ is executed) itself? This would be an interpreter written in Lisp.

> Since there are no operators there is no overloading.

You say it yourself: Lisp has no (infix) operators and therefore
no operator overloading.

> But you can define any syntax for statements you like, so long as you
> define a statement as everything inside a list after the first element.

As you say a Lisp 'statement' has to be written in list form, like

(cond ((= n 0) 1)
((> n 0) (* n (! (- n 1)))))

You don't get rid of the list notation with parentheses (Before the
first element of the 'statement' you have to write '(' and after the
last element of the 'statement' you have to write ')').

> This isn't that different to most languages with this capability where
> what you can define is everything from the first word to a terminator
> like ';'.

There is a big difference to

if n = 0 then
result := 1;
elsif n > 0 then
result := !(n - 1);
end if;

Defining new statements is not only a story about the definition
of the statement semantics (what Lisp is capable to do) but is
also about the statement syntax (which Lisp can only aproximate).

I know that you can define your 'arith' function (with interpreted
priority and assoziativity) and your user defined 'statements'
(with an approximation of the syntax using lots of
parentheses) in Lisp. But is the syntax check and the type
check done at compile time?

If you want to reuse the + operator to add 'colors', can you
just write something like (in Seed7):

const func color: (in color: col1) + (in color: col2) is func
result
var color: result is color.value;
begin
result.red_part := (col1.red_part + col2.red_part) div 2;
result.green_part := (col1.green_part + col2.green_part) div 2;
result.blue_part := (col1.blue_part + col2.blue_part) div 2;
end func;

and it just works?

> Lisp programmers tend to think the lack of precedence is a good thing
> at least for that language. Since in Lisp you have the ability to
> write macros at the level of the program tree, at this level it would
> be hard for the programmer to deal with precedence. (Or other things
> would have to be made hard to make it easy).

While Lisp has its reasons, I think that lack of precedence,
lack of overloading (In Lisp functions are identified with a
name) and the missing possibility to define the syntax of
new statements in Lisp is a weakness.

- Lisp does not have (infix) operators.
- There are no user defined operators (just functions).
- Overloading of operators does not exist.
- The statement syntax can not be defined in Lisp.

I suggest you take a closer look at Seed7. May be there are
things you like, and if not you can send me patches with
improvements. :-) This is open source everybody is welcome.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-14 09:41:21 UTC
Permalink
On Fri, Jul 14, 2006 at 01:17:59AM -0700, ***@gmx.at wrote:
> Rob Thorpe wrote about Lisp:
> > Within a statement you can define anything you want.
> > You could write a form called "arith" for example that did normal
> > arithmetic with precedence etc if you wanted.
> >
> > (arith 4 + 6 * 3)
> >
> > You could implement it with a macro so it expanded into normal code at
> > compile time.
>
> You don't get rid of the parantheses around the call of the
> 'arith' function.

But you could by using read macros. The reason people don't (and also
the reason people don't use infix arithmetic) is that it's unlispy; you
just don't write Lisp code that way. However, that doesn't mean it isn't
possible. You could probably implement a read macro that parsed C-like
syntax and converted it to Lisp code if you wanted to.

> > It is true to say that in lisp there is not associativity or
> > precedence.
>
> The 'arith' function has to interpret the precedence (execute * before
> + is executed) itself? This would be an interpreter written in Lisp.

No. Arith would be a macro, which means the translation is done at
compile time. At run time, it would be just like the user had written (+
4 (* 6 3)) to begin with.

> > Since there are no operators there is no overloading.
>
> You say it yourself: Lisp has no (infix) operators and therefore
> no operator overloading.

Depending on what you mean by that. There certainly is overloading in
Common Lisp; you can say

(defmethod foo ((x integer)) ...)

and

(defmethod foo ((x complex)) ...)

and get two versions of foo, one working on integers and another on
complex numbers. You could do the same for +, although it is a bit more
involved, because + isn't a generic function the way it's initially
defined, so you'd have to hide the previous definition first, then
introduce a new one.

You can still complain that + isn't an operator, but (1) I don't see why
you so badly want to have operators with associated special status in
your language (2) you can make it behave just like + in languages where
it is a special operator if you really want to, and (3) who says it's
not? just because it uses prefix notation like everything else doesn't
mean it isn't a special operator (in Scheme, for example, + is special
in the sense that it's undefined what happens if you try to redefine
it).

> > But you can define any syntax for statements you like, so long as you
> > define a statement as everything inside a list after the first element.

Actually, read macros lift that restriction.

> As you say a Lisp 'statement' has to be written in list form, like
>
> (cond ((= n 0) 1)
> ((> n 0) (* n (! (- n 1)))))

Or

(loop for i from 0 and for x in xs collecting (cons i x))

which doesn't look like it has Lots of Irritating Superflous
Parentheses, does it? (It doesn't do the same as the code above, by the
way.)

> You don't get rid of the list notation with parentheses (Before the
> first element of the 'statement' you have to write '(' and after the
> last element of the 'statement' you have to write ')').

Again, unless you use read macros to break this rule. And you don't
break the rule, because that would make the code harder to understand.

> > This isn't that different to most languages with this capability where
> > what you can define is everything from the first word to a terminator
> > like ';'.
>
> There is a big difference to
>
> if n = 0 then
> result := 1;
> elsif n > 0 then
> result := !(n - 1);
> end if;

Yes. And whether you prefer that or

(setf result
(cond
((= n 0) 1)
((> n 0) (not (- n 1)))))

(assuming that is what your code means), is a matter of, well,
preference. Probably, it's also influenced by what you're used to.

> Defining new statements is not only a story about the definition
> of the statement semantics (what Lisp is capable to do) but is
> also about the statement syntax (which Lisp can only aproximate).

Again, unless you use read macros.

> I know that you can define your 'arith' function (with interpreted
> priority and assoziativity) and your user defined 'statements'
> (with an approximation of the syntax using lots of
> parentheses) in Lisp.

You should know this is wrong by now.

> But is the syntax check and the type
> check done at compile time?

Syntax checks: yes.
Type checks: generally not, though many implementations will give you
warnings.

> If you want to reuse the + operator to add 'colors', can you
> just write something like (in Seed7):
>
> const func color: (in color: col1) + (in color: col2) is func
> result
> var color: result is color.value;
> begin
> result.red_part := (col1.red_part + col2.red_part) div 2;
> result.green_part := (col1.green_part + col2.green_part) div 2;
> result.blue_part := (col1.blue_part + col2.blue_part) div 2;
> end func;
>
> and it just works?

You can do this with any generic function. + isn't a generic function,
but you can redefine it to be. After that's done, you can write:

(defmethod + ((col1 color) (col2 color))
(make-color (/ (+ (color-red-part col1) (color-red-part col2)) 2)
(/ (+ (color-green-part col1) (color-green-part col2)) 2)
(/ (+ (color-blue-part col1) (color-blue-part col2)) 2)))

> While Lisp has its reasons, I think that lack of precedence,
> lack of overloading (In Lisp functions are identified with a
> name) and the missing possibility to define the syntax of
> new statements in Lisp is a weakness.
>
> - Lisp does not have (infix) operators.

Which is considered an advantage, because it simplifies the syntax of
the language. This makes macros easier to implement and understand.

> - There are no user defined operators (just functions).

I don't know what characteristic of operators you want that Lisp cannot
provide.

> - Overloading of operators does not exist.

Depends on your definition.

> - The statement syntax can not be defined in Lisp.

It can.

It's not like Lisp doesn't have any weaknesses, but I don't count the
things you mention to be among them. Probably, this is largely due to
you and I having different ideas about how things should work; it seems
that you insist a language must have infix operators, whereas I would
rather have uniform syntax. Also, you seem to have some misconceptions
about what is and what isn't possible in Lisp.

> I suggest you take a closer look at Seed7. May be there are
> things you like, and if not you can send me patches with
> improvements. :-) This is open source everybody is welcome.

I think you did a great job making Seed7 flexible and powerful. Still, I
probably wouldn't like programming in it, because it's syntax is too
verbose for my liking (although I guess this could be redefined using
syntax declarations), and the need to declare types everywhere.

Some things that might be interesting for you to investigate:

- Common Lisp Object System. It's very powerful and flexible, although
I find the class declaration syntax painfully verbose. A few macros
solve that problem, of course.

- Common Lisp's package system. Some people hate it, other people love
it. I only know it provides namespaces, mechanisms to prevent and
resolve name clashes, and mechanisms to hide symbols.

- Common Lisp's condition system. Like exceptions, but generally
offering more options for recovery, including an interactive
debugger.

- Common Lisp's numeric tower: arbitrary precission arithmetic,
rational and complex numbers, and all using a unified interface.

- Scheme's first class continuations (call/cc).

- First class, higher order, and anonymous functions (does Seed7 have
them?)

- Type inference (as in ML)

- Lazy evaluation (as in Haskell) or lazy data structures (e.g. as
discussed in "How to Add Laziness to a Strict Language Without Even
Being Odd")

- Parallel programming

- Distributed programming

Just some things that I find interesting. I don't know how much you have
looked into any of these.

Regards,

Bob

---
Q: Why is it that programmers always confuse Halloween with Christmas?
A: Because 31 OCT = 25 DEC.
t***@gmx.at
2006-07-14 10:51:42 UTC
Permalink
Robbert Haarman wrote:
> On Fri, Jul 14, 2006 at 01:17:59AM -0700, ***@gmx.at wrote:
> > Rob Thorpe wrote about Lisp:
> > > Within a statement you can define anything you want.
> > > You could write a form called "arith" for example that did normal
> > > arithmetic with precedence etc if you wanted.
> > >
> > > (arith 4 + 6 * 3)
> > >
> > > You could implement it with a macro so it expanded into normal code at
> > > compile time.
> >
> > You don't get rid of the parantheses around the call of the
> > 'arith' function.
>
> But you could by using read macros. The reason people don't (and also
> the reason people don't use infix arithmetic) is that it's unlispy; you
> just don't write Lisp code that way. However, that doesn't mean it isn't
> possible. You could probably implement a read macro that parsed C-like
> syntax and converted it to Lisp code if you wanted to.

Do the read macros all this in a type safe way?

> > > It is true to say that in lisp there is not associativity or
> > > precedence.
> >
> > The 'arith' function has to interpret the precedence (execute * before
> > + is executed) itself? This would be an interpreter written in Lisp.
>
> No. Arith would be a macro, which means the translation is done at
> compile time. At run time, it would be just like the user had written (+
> 4 (* 6 3)) to begin with.

Would the 'arith' macro take care of the operator precedence such that
'4 + 6 * 3' is '4 + (6 * 3)' and not '(4 + 6) * 3'?
What about '4 * 6 + 3' or
'2 ** 2 * 5 ** 2 + 3 ** 2 * 4 ** 2 = 6 ** 2 * 3 + 4 ** 2'?
Would the 'arith' macro do type checks at compile time?

> (defmethod foo ((x complex)) ...)

This is an overloaded function and not an operator.

> You can still complain that + isn't an operator, but (1) I don't see why
> you so badly want to have operators with associated special status in
> your language (2) you can make it behave just like + in languages where
> it is a special operator if you really want to, and (3) who says it's
> not? just because it uses prefix notation like everything else doesn't
> mean it isn't a special operator (in Scheme, for example, + is special
> in the sense that it's undefined what happens if you try to redefine
> it).

I want user definable infix operators with precedence and associativity
and the possibility to overload them. Seed7 provides just that.
Additionally the syntax, the semantic and the types are checked at
compile time. All the arguments about prefix notation make no
sense.

> Probably, it's also influenced by what you're used to.

There are many people which are used to Pascal, Ada, C, C++, C#, Java
statements which are based on keywords and/or curly braces.
Guess how many people use these languages and how many use a
Lisp variant.

There are also many people which like infix operators and
don't want prefix or postfix notation. Guess how many people
like infix operators and how many like a prefix or postfix notation.

I think that strong typing (Declaration with type, no implicit
type conversions, type checking at compile time) are important.

Seed7 does not try to be a perfect niche programming language.
It trys to look like mainstream programming languages, but
at the same time it trys to go byond them. This is at least
my vision.

> I think you did a great job making Seed7 flexible and powerful. Still, I
> probably wouldn't like programming in it, because it's syntax is too
> verbose for my liking (although I guess this could be redefined using
> syntax declarations), and the need to declare types everywhere.

As mentioned above: I am a strong typing fan, therefore
the type declarations are on purpose.

> Some things that might be interesting for you to investigate:

I will look at every source of inspiration.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-14 11:23:43 UTC
Permalink
On Fri, Jul 14, 2006 at 03:51:42AM -0700, ***@gmx.at wrote:
> Robbert Haarman wrote:
> > On Fri, Jul 14, 2006 at 01:17:59AM -0700, ***@gmx.at wrote:
> > >
> > > You don't get rid of the parantheses around the call of the
> > > 'arith' function.
> >
> > But you could by using read macros. The reason people don't (and also
> > the reason people don't use infix arithmetic) is that it's unlispy; you
> > just don't write Lisp code that way. However, that doesn't mean it isn't
> > possible. You could probably implement a read macro that parsed C-like
> > syntax and converted it to Lisp code if you wanted to.
>
> Do the read macros all this in a type safe way?

Macros don't concern themselves with values, and thus not with types.
Any type checking will be performed the same way as always, as if the
programmer had directly written the code the macros expand into. In
Common Lisp, type checking is not mandated (nor ruled out) by the
standard, so it is implementation-dependent.

> > > > It is true to say that in lisp there is not associativity or
> > > > precedence.
> > >
> > > The 'arith' function has to interpret the precedence (execute * before
> > > + is executed) itself? This would be an interpreter written in Lisp.
> >
> > No. Arith would be a macro, which means the translation is done at
> > compile time. At run time, it would be just like the user had written (+
> > 4 (* 6 3)) to begin with.
>
> Would the 'arith' macro take care of the operator precedence such that
> '4 + 6 * 3' is '4 + (6 * 3)' and not '(4 + 6) * 3'?
> What about '4 * 6 + 3' or
> '2 ** 2 * 5 ** 2 + 3 ** 2 * 4 ** 2 = 6 ** 2 * 3 + 4 ** 2'?

It all depends on how you implement the macro. You can write it to do
whatever you want.

> Would the 'arith' macro do type checks at compile time?

No. But the implementation might do type checking. See above.

> > (defmethod foo ((x complex)) ...)
>
> This is an overloaded function and not an operator.

Does it matter? What if functions and operators are one and the same?
What _is_ your definition of 'operator'?

> > You can still complain that + isn't an operator, but (1) I don't see why
> > you so badly want to have operators with associated special status in
> > your language (2) you can make it behave just like + in languages where
> > it is a special operator if you really want to, and (3) who says it's
> > not? just because it uses prefix notation like everything else doesn't
> > mean it isn't a special operator (in Scheme, for example, + is special
> > in the sense that it's undefined what happens if you try to redefine
> > it).
>
> I want user definable infix operators with precedence and associativity
> and the possibility to overload them. Seed7 provides just that.

Then either use one of the packages that provide these for Common Lisp,
or use a language that supports them out of the box.

> Additionally the syntax, the semantic and the types are checked at
> compile time.

If you want compile time type checking, Common Lisp is out. Simple as
that.

Semantic type checking at compile time, hmm. "I want the compiler to
verify that the program does what I want it to do." Yes, I would like
that, too.

> All the arguments about prefix notation make no sense.

That's a bit strong. Prefix notation has some advantages over a mixed
prefix-infix notation, and the other way around, too. Even postfix
notation can be advantegous. Which one is best for you depends on what
properties matter to you most.

> > Probably, it's also influenced by what you're used to.
>
> There are many people which are used to Pascal, Ada, C, C++, C#, Java
> statements which are based on keywords and/or curly braces.
> Guess how many people use these languages and how many use a
> Lisp variant.

Yes. And if the syntax of your language is the same, or very similar, to
what people are used to, they will find your syntax easier to learn than
a syntax they are not used to. That's an advantage. It doesn't mean that
such syntax is _better_.

At the end of the Middle Ages, most people believed the Earth was flat
and that the Sun revolved around it. Now, most people I know believe the
Earth is spherical and it revolves around the Sun. Just like with
syntax, either model works. It's just that if the Earth is spherical and
revolves around the Sun, a lot of observations that are difficult to
explain with the other model suddenly make a lot of sense. So maybe what
all these people in the Middle Ages believed wasn't the best model.
Maybe complex prefix-infix-with-precedence syntax isn't the best,
either.

> There are also many people which like infix operators and
> don't want prefix or postfix notation.

Fine. To each their own.

> Guess how many people like infix operators and how many like a prefix
> or postfix notation.

Enough people _prefer_ prefix notation that various infix notations for
Lisp have never taken off. Maybe there's a good reason for that. Maybe
lispers are just nuts. Or maybe everybody else is. At any rate, I'm not
about to deny anyone the syntax they prefer to use. And Lisp isn't
either: since you can modify the reader (programmatically; no need to go
and change the compiler source code), you can get it to swallow any
syntax you want and produce any code you want.

> I think that strong typing (Declaration with type, no implicit
> type conversions, type checking at compile time) are important.

Ok.

> Seed7 does not try to be a perfect niche programming language.
> It trys to look like mainstream programming languages, but
> at the same time it trys to go byond them. This is at least
> my vision.

I think it's great. And I think you're doing a good job at it. Keep it
up!

> As mentioned above: I am a strong typing fan, therefore
> the type declarations are on purpose.

Yes. I just don't like them, but that's me.

> > Some things that might be interesting for you to investigate:
>
> I will look at every source of inspiration.

Great! I hope you find the topics I presented interesting.

Regards,

Bob

---
The optimist proclaims that we live in the best of all possible worlds,
and the pessimist fears this is true.
goose
2006-07-14 14:11:31 UTC
Permalink
Robbert Haarman wrote:

<snipped>

> and that the Sun revolved around it. Now, most people I know believe the
> Earth is spherical and it revolves around the Sun. Just like with

Only "most" ?

goose,
discworld fan
Richard Heathfield
2006-07-14 14:21:00 UTC
Permalink
Robbert Haarman said:

<snip>

> At the end of the Middle Ages, most people believed the Earth was flat

Not if they lived in Yorkshire.

Seriously, most educated people knew perfectly well it was not flat, and
most educated people know that today, too. Those who were not educated -
the vast majority - may have believed it flat, or may never have considered
the matter at all. I suspect that this is still true today.

> and that the Sun revolved around it. Now, most people I know believe the
> Earth is spherical and it revolves around the Sun.

But it isn't and it doesn't. The Earth is an oblate spheroid, and both the
Sun and the Earth would revolve around their common centre of mass if they
were the only two bodies in the system, which they are not.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
j***@invalid.address
2006-07-14 14:31:04 UTC
Permalink
Richard Heathfield <***@invalid.invalid> writes:

> Robbert Haarman said:
>
> <snip>
>
> > At the end of the Middle Ages, most people believed the Earth was
> > flat
>
> Not if they lived in Yorkshire.
>
> Seriously, most educated people knew perfectly well it was not flat,
> and most educated people know that today, too. Those who were not
> educated - the vast majority - may have believed it flat, or may
> never have considered the matter at all. I suspect that this is
> still true today.
>
> > and that the Sun revolved around it. Now, most people I know
> > believe the Earth is spherical and it revolves around the Sun.
>
> But it isn't and it doesn't. The Earth is an oblate spheroid, and
> both the Sun and the Earth would revolve around their common centre
> of mass if they were the only two bodies in the system, which they
> are not.

But since they're not the only bodies in the system, the earth does,
in fact, revolve around the sun, right? If not, why do I have to mess
with daylight saving time?

Joe
Richard Heathfield
2006-07-14 15:38:41 UTC
Permalink
***@invalid.address said:

> Richard Heathfield <***@invalid.invalid> writes:
>

<snip>

>> The Earth is an oblate spheroid, and
>> both the Sun and the Earth would revolve around their common centre
>> of mass if they were the only two bodies in the system, which they
>> are not.
>
> But since they're not the only bodies in the system, the earth does,
> in fact, revolve around the sun, right?

No, it just means that the Earth's and Sun's orbits around that common
centre of mass are imperfect, because they are perturbed by the
gravitational attraction of other bodies in the system.

> If not, why do I have to mess with daylight saving time?

You don't. Well, I certainly don't. My system's clock is set to GMT.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
j***@invalid.address
2006-07-14 15:42:32 UTC
Permalink
Richard Heathfield <***@invalid.invalid> writes:

> ***@invalid.address said:
>
> > Richard Heathfield <***@invalid.invalid> writes:
> >
>
> <snip>
>
> >> The Earth is an oblate spheroid, and both the Sun and the Earth
> >> would revolve around their common centre of mass if they were the
> >> only two bodies in the system, which they are not.
> >
> > But since they're not the only bodies in the system, the earth does,
> > in fact, revolve around the sun, right?
>
> No, it just means that the Earth's and Sun's orbits around that common
> centre of mass are imperfect, because they are perturbed by the
> gravitational attraction of other bodies in the system.

So the earth doesn't revolve around the sun. How do things like
seasons happen then? Does the earth tip over the other way every six
months or so?

Just curious

Joe
Richard Heathfield
2006-07-14 15:54:24 UTC
Permalink
***@invalid.address said:

<snip>
>
> So the earth doesn't revolve around the sun.

Correct.

> How do things like seasons happen then?

Arrangements are made.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
John McCallum
2006-07-14 16:39:28 UTC
Permalink
***@invalid.address wrote:

> So the earth doesn't revolve around the sun. How do things like
> seasons happen then? Does the earth tip over the other way every six
> months or so?

:D

It might be worth considering where the centre of mass is, given that the
sun is >300000 times more massive than the earth.

Cheers,
--
John McCallum

For email, leave the web and we're not so small.
j***@invalid.address
2006-07-14 20:26:21 UTC
Permalink
John McCallum <***@itsy-bitsy.spider.web.com> writes:

> ***@invalid.address wrote:
>
> > So the earth doesn't revolve around the sun. How do things like
> > seasons happen then? Does the earth tip over the other way every six
> > months or so?
>
> :D
>
> It might be worth considering where the centre of mass is, given
> that the sun is >300000 times more massive than the earth.

Ok, so there's some kind of astronomical math involved that I'm not up
to. At the risk of belaboring this, does the earth not travel in an
orbit around the sun? Is it the word "revolve" that has the secret
meaning?

Thanks

Joe
Pascal Bourguignon
2006-07-14 20:59:59 UTC
Permalink
***@invalid.address writes:

> John McCallum <***@itsy-bitsy.spider.web.com> writes:
>
>> ***@invalid.address wrote:
>>
>> > So the earth doesn't revolve around the sun. How do things like
>> > seasons happen then? Does the earth tip over the other way every six
>> > months or so?
>>
>> :D
>>
>> It might be worth considering where the centre of mass is, given
>> that the sun is >300000 times more massive than the earth.
>
> Ok, so there's some kind of astronomical math involved that I'm not up
> to. At the risk of belaboring this, does the earth not travel in an
> orbit around the sun? Is it the word "revolve" that has the secret
> meaning?

ASTRONOMICAL Maths?


Given two points A and C of masses M[A] and M[C],
the barycentre C is the point at distances AB and BC
from the points A and C such as:

AB * M[B] = BC * M[C]


BC * M[C]
AB = -----------
M[A]

A = Sun
C = Earth
M[A] = 1.989e+30 kg
M[C] = 5.9736e+24 kg

BC = 147.09e9 m at the perihelie
BC = 152.10e9 m at the aphelie

147.09e9 * 5.9736e+24
Therefore AC = ----------------------- = 441758 m at the perihelie
1.989e+30


152.10e9 * 5.9736e+24
Therefore AC = ----------------------- = 456804 m at the apehelie
1.989e+30

Sun's equatorial radius is 695e6 m, therefore the barycenter of the
Earth-Sun system is well inside the Sun.


Exercise (easy): find on the web the perihelie and aphelie distances
Jupiter-Sun, and the mass of Jupiter, and compute the distance from
the center of the Sun of the barycenter of the Sun-Jupiter system.

Exercise (harder): compute the distance between the center of the Sun
and the barycenter of the whole Solar system, when all the planets are
aligned on the same radius.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"Specifications are for the weak and timid!"
j***@invalid.address
2006-07-14 21:39:52 UTC
Permalink
Pascal Bourguignon <***@informatimago.com> writes:

> ***@invalid.address writes:
>
> > John McCallum <***@itsy-bitsy.spider.web.com> writes:
> >
> >> ***@invalid.address wrote:
> >>
> >> > So the earth doesn't revolve around the sun. How do things like
> >> > seasons happen then? Does the earth tip over the other way every six
> >> > months or so?
> >>
> >> :D
> >>
> >> It might be worth considering where the centre of mass is, given
> >> that the sun is >300000 times more massive than the earth.
> >
> > Ok, so there's some kind of astronomical math involved that I'm not up
> > to. At the risk of belaboring this, does the earth not travel in an
> > orbit around the sun? Is it the word "revolve" that has the secret
> > meaning?
>
> ASTRONOMICAL Maths?

Ok, some kind of math that I'm not up to.

> Given two points A and C of masses M[A] and M[C],
> the barycentre C is the point at distances AB and BC
> from the points A and C such as:
>
> AB * M[B] = BC * M[C]
>
>
> BC * M[C]
> AB = -----------
> M[A]
>
> A = Sun
> C = Earth
> M[A] = 1.989e+30 kg
> M[C] = 5.9736e+24 kg
>
> BC = 147.09e9 m at the perihelie
> BC = 152.10e9 m at the aphelie
>
> 147.09e9 * 5.9736e+24
> Therefore AC = ----------------------- = 441758 m at the perihelie
> 1.989e+30
>
>
> 152.10e9 * 5.9736e+24
> Therefore AC = ----------------------- = 456804 m at the apehelie
> 1.989e+30
>
> Sun's equatorial radius is 695e6 m, therefore the barycenter of the
> Earth-Sun system is well inside the Sun.

So is that a "yes" or "no"?

Humor me for a moment. I'm not trying to be a pain in the ass, but I
think I'm asking a simple question and getting a truckload of facts in
response that are given in such a way that I think I'm being told I'm
wrong.

Sorry about my lack of math skills, but does all this really mean that
the earth does not travel in an orbit around the sun?

This is beginning to sound a bit like Zeno's paradox is being
expounded while the lion walks up and eats Zeno.

I know this isn't a programming question and I'll quit after this, I
promise.

Joe
Dr.Ruud
2006-07-14 21:47:22 UTC
Permalink
***@invalid.address schreef:

> does all this really mean that
> the earth does not travel in an orbit around the sun?

Not if you assume that earth is fixed in space, and the whole universe
wobbles and tumbles around it.

--
Affijn, Ruud

"Gewoon is een tijger."
Pascal Bourguignon
2006-07-14 22:55:06 UTC
Permalink
***@invalid.address writes:

>> Sun's equatorial radius is 695e6 m, therefore the barycenter of the
>> Earth-Sun system is well inside the Sun.
>
> So is that a "yes" or "no"?
>
> Humor me for a moment. I'm not trying to be a pain in the ass, but I
> think I'm asking a simple question and getting a truckload of facts in
> response that are given in such a way that I think I'm being told I'm
> wrong.

If we consider a universe containing only the Sun and the nine
planets, then we _could_ say that the planets revolve around the Sun.
But this is just by chance, because the mass of the Sun is so much
more than the mass of the planets. What happens actually, is that
all, planets and Sun, revolve around the barycenter of the system.

Now, if you consider in addition the Milky Way, since the Solar system
revolves around the Milky Way, neither the Sun nor the planet really
revolve even around the barycenter of the Solar system, since in any
period of time, the barycenter has moved in a direction out of the
ecliptic.

And the situation is even worse if you consider the whole universe,
since the Milky Way along our galatic group moves even faster toward
the big attractor, so the Solar system doesn't really revolve around
the center of the Milky Way.

So what we have, is chaotic helicoidal trajectories around helicoidal
trajectories.

The speed of the Earth relative to the Sun is about 30 km/s.
The speed of the Solar system relative to the Milky Way is about 220 km/s.
The speed of the Milky Way relative to the Great Attractor is about 600 km/s.

Since the direction of the movement of the Solar system forms an angle
of about 38 degree with the ecliptic, the movement of the Earth is
about 120 km/s up and between 130 km/s and 190 km/s in the ecliptic
plane, depending on the time of the year.

See this illustration:
http://www.orgonelab.org/graphics/MillerReich/SpiralDistances.jpg
from: http://www.orgonelab.org/MillerReich.htm

The Sun's path is itself such a helicoidal trajectory around the
center of the Milky Way, and the most probable, is that the trajectory
of the Milky Way is likewise too.


> Sorry about my lack of math skills, but does all this really mean that
> the earth does not travel in an orbit around the sun?

Well, saying that the Earth travels in an orbit around the Sun, is an
explication we'd tell to a 5 years old child. If you don't need more,
you can stay with it.


> This is beginning to sound a bit like Zeno's paradox is being
> expounded while the lion walks up and eats Zeno.
>
> I know this isn't a programming question and I'll quit after this, I
> promise.

--
__Pascal Bourguignon__ http://www.informatimago.com/

"Do not adjust your mind, there is a fault in reality"
-- on a wall many years ago in Oxford.
t***@gmx.at
2006-07-15 07:55:52 UTC
Permalink
Pascal Bourguignon wrote:
> The speed of the Earth relative to the Sun is about 30 km/s.
> The speed of the Solar system relative to the Milky Way is about 220 km/s.
> The speed of the Milky Way relative to the Great Attractor is about 600 km/s.

To come back to the main topic 'New Seed7 Release 2006-07-07':
I want to mention something from my initial mail

- A new example program (planets) was added.

The planets program (written in Seed7) can be used to
display information about the planets (The Milky Way and
the Great Attractor are not taken into account).

This program is not 'hi tech' and the user interface
is mouseless, but you can display the position of the
(inner and outer) planets on their way around the sun.

Horizontal cursor keys add or subtract a day, while the
vertical curser keys add or subtract a month.

May be someone helps to improve this or other example
programs...

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Lars
2006-07-18 11:58:29 UTC
Permalink
***@gmx.at wrote:
> - A new example program (planets) was added.
>
> The planets program (written in Seed7) can be used to
> display information about the planets (The Milky Way and
> the Great Attractor are not taken into account).

Can it compute the distance between the center of the Sun and the
barycenter of the whole Solar system, when all the planets are aligned
on the same radius? Or more generally, for any alignment? ;)
t***@gmx.at
2006-07-18 12:32:36 UTC
Permalink
Lars wrote:
> ***@gmx.at wrote:
> > - A new example program (planets) was added.
> >
> > The planets program (written in Seed7) can be used to
> > display information about the planets (The Milky Way and
> > the Great Attractor are not taken into account).
>
> Can it compute the distance between the center of the Sun and the
> barycenter of the whole Solar system, when all the planets are aligned
> on the same radius? Or more generally, for any alignment? ;)

No, but it can display the position of the inner or outer
planets at different dates. If you want to know the position of
the planets now, at your birthday or at some other date,
the planets program can show it.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Grzegorz Wróbel
2006-07-14 16:30:09 UTC
Permalink
***@invalid.address wrote:
>>But it isn't and it doesn't. The Earth is an oblate spheroid, and
>>both the Sun and the Earth would revolve around their common centre
>>of mass if they were the only two bodies in the system, which they
>>are not.
>
>
> But since they're not the only bodies in the system, the earth does,
> in fact, revolve around the sun, right? If not, why do I have to mess
> with daylight saving time?

Even if you took only all bodies in the solar system, they'd still revolve around their common centre of mass. But since mass of the sun is 99.9..% of the mass of our solar system, then the sun itself is quite qood approximation of that centre. And if you don't like a mess with daylight saving you can always move to live on the equator. :)

--
677265676F727940346E6575726F6E732E636F6D
Grzegorz Wróbel
2006-07-14 16:41:32 UTC
Permalink
Robbert Haarman wrote:
> Macros don't concern themselves with values, and thus not with types.
> Any type checking will be performed the same way as always, as if the
> programmer had directly written the code the macros expand into. In
> Common Lisp, type checking is not mandated (nor ruled out) by the
> standard, so it is implementation-dependent.

So are the macros in Lisp part of the language? In most languages macros are just wonders that are expanded inline by preprocessor before actual compilation.
So actually you can come to C++ and write macros here without type checking. But this is almost always bad idea, sophisticated macros not only bring a lot of dangers, but think also about the size of the generated code.

--
677265676F727940346E6575726F6E732E636F6D
Robbert Haarman
2006-07-14 17:18:36 UTC
Permalink
On Fri, Jul 14, 2006 at 06:41:32PM +0200, Grzegorz Wr?bel wrote:
>
> So are the macros in Lisp part of the language?

They are, in the sense that they are in the standard.

> In most languages macros are just wonders that are expanded inline by
> preprocessor before actual compilation.

I think that's what defines macros. What sets Common Lisp macros apart
from many other macros is that they are written in Common Lisp. This
means macros can do everything any Common Lisp program can do, including
calling functions defined in the same program.

Another aspects that sets them apart from macros in some other languages
is that Common Lisp macros won't alter the structure of the program
around them. A macro invocation is one s-expression, and its expansion
will still be one s-expression. Contrast this with, for example, C
macros, which can completely mess up the structure of your program.

> So actually you can come to C++ and write macros here without type
> checking.

I question the value of type checking on macros. Can you provide some
examples?

> But this is almost always bad idea, sophisticated macros not
> only bring a lot of dangers, but think also about the size of the
> generated code.

Well, if your macros generate a lot of code, then either they save you a
lot of work, or they are badly written. In the first case, macros are a
clear advantage; in the second case, I don't think macros are to blame.

Regards,

Bob

---
"UNIX was not designed to stop you from doing stupid things, because that
would also stop you from doing clever things."
--Doug Gwyn
Grzegorz Wróbel
2006-07-14 17:35:59 UTC
Permalink
Robbert Haarman wrote:

> I question the value of type checking on macros. Can you provide some
> examples?

That's what I meant. No type checking in macro.

>>But this is almost always bad idea, sophisticated macros not
>>only bring a lot of dangers, but think also about the size of the
>>generated code.
>
>
> Well, if your macros generate a lot of code, then either they save you a
> lot of work, or they are badly written. In the first case, macros are a
> clear advantage; in the second case, I don't think macros are to blame.

Well, the point is that in C++ I don't use macros at all. I use functions and templates. Even if there is a simple thing to do, which could be appropriate for the macro, I would rather use an inline function.

--
677265676F727940346E6575726F6E732E636F6D
Robbert Haarman
2006-07-14 18:16:49 UTC
Permalink
On Fri, Jul 14, 2006 at 07:35:59PM +0200, Grzegorz Wr?bel wrote:
> Robbert Haarman wrote:
>
> >I question the value of type checking on macros. Can you provide some
> >examples?
>
> That's what I meant. No type checking in macro.

I thought you said that no type checking in macros is a bad idea. I was
asking you to provide an example of how type checking in macros would
work, and why it would be a bad idea not to have it.

> Well, the point is that in C++ I don't use macros at all. I use functions
> and templates. Even if there is a simple thing to do, which could be
> appropriate for the macro, I would rather use an inline function.

In Common Lisp, you don't do everything using macros either. However,
there are things that macros can do that cannot be accomplished by the
other means provided. For example, suppose you wanted to define a new
conditional. One that I've defined is pred, which takes an expression
and a number of clauses, each containing a predicate and a body, where
the last clause may contain else for a predicate. The expression will be
evaluated, and the resulting value will be matched against each of the
predicates. The body after the first match will be executed, or the body
after else, if none of the predicates match. E.g:

(pred foo
(integerp (format t "integer"))
(stringp (format t "string"))
(else (format t "something-else")))

will print "int" if foo is an integer, "string" if foo is a string, and
"something else" if foo in neither an integer, nor a string. If pred had
been a function, all these clauses would be evaluated as function calls,
printing out "integer" and "string", and throwing an error because there
is no function named else, before the code of pred were even evaluated.

Another favorite example of mine: suppose you're making a library to
generate HTML. You are going to define a function for each tag, as
follows:

(defun html (attrs &rest content)
(concat 'string "<html" (transform-attrs attrs) ">"
(concat 'string content) "</html>"))

The idea should be clear. Now, it would be tedious to have to repeat
this code for every type of tag you want to define. So you could do

(defun html-tag (name attrs &rest content)
(concat 'string "<" name (transform-attrs attrs) ">"
(concat 'string content) "</" name ">"))

(defun html (attrs &rest content)
(apply #'html-tag `("html" attrs ,@content)))

Now the part you have to repeat for each tag is shorter. But you can get
it even shorter by using macros:

(defmacro define-html-tags (&rest names)
`(progn
,@(mapcar (lambda (name)
`(defun ,name (attrs &rest content)
(apply #'html-tag
`(,,(symbol-name name) attrs ,@content))
names)))

I haven't checked the code, so it may not work, but the idea is that the
macro gives you a defun like the last one above for every name that you
pass in. Now all you need to do is pass in the names of the tags for
which you want to define functions:

(define-html-tags html body p h1 h2 h3)

Now try doing that without macros!

Regards,

Bob

---
Albert Einstein, when asked to describe radio, replied: "You see, wire
telegraph is a kind of a very, very long cat. You pull his tail in New
York and his head is meowing in Los Angeles. Do you understand this?
And radio operates exactly the same way: you send signals here, they
receive them there. The only difference is that there is no cat."
Grzegorz Wróbel
2006-07-14 21:07:19 UTC
Permalink
Robbert Haarman wrote:
> On Fri, Jul 14, 2006 at 07:35:59PM +0200, Grzegorz Wr?bel wrote:
>
>>Robbert Haarman wrote:
>>
>>
>>>I question the value of type checking on macros. Can you provide some
>>>examples?
>>
>>That's what I meant. No type checking in macro.
>
> I thought you said that no type checking in macros is a bad idea. I was
> asking you to provide an example of how type checking in macros would
> work, and why it would be a bad idea not to have it.
>
That is, in my opinion one of disadvantages of macros (not the greatest though), but from your previous posts I understood you treat this as an advantage, 'cause you can treat macros as some sort of templates.

>
>>Well, the point is that in C++ I don't use macros at all. I use functions
>>and templates. Even if there is a simple thing to do, which could be
>>appropriate for the macro, I would rather use an inline function.
>
>
> In Common Lisp, you don't do everything using macros either. However,
> there are things that macros can do that cannot be accomplished by the
> other means provided. For example, suppose you wanted to define a new
> conditional. One that I've defined is pred, which takes an expression
> and a number of clauses, each containing a predicate and a body, where
> the last clause may contain else for a predicate. The expression will be
> evaluated, and the resulting value will be matched against each of the
> predicates. The body after the first match will be executed, or the body
> after else, if none of the predicates match. E.g:
>
> (pred foo
> (integerp (format t "integer"))
> (stringp (format t "string"))
> (else (format t "something-else")))
>
> will print "int" if foo is an integer, "string" if foo is a string, and
> "something else" if foo in neither an integer, nor a string. If pred had
> been a function, all these clauses would be evaluated as function calls,
> printing out "integer" and "string", and throwing an error because there
> is no function named else, before the code of pred were even evaluated.
>
> Another favorite example of mine: suppose you're making a library to
> generate HTML. You are going to define a function for each tag, as
> follows:
>
> (defun html (attrs &rest content)
> (concat 'string "<html" (transform-attrs attrs) ">"
> (concat 'string content) "</html>"))
>
> The idea should be clear. Now, it would be tedious to have to repeat
> this code for every type of tag you want to define. So you could do
>
> (defun html-tag (name attrs &rest content)
> (concat 'string "<" name (transform-attrs attrs) ">"
> (concat 'string content) "</" name ">"))
>
> (defun html (attrs &rest content)
> (apply #'html-tag `("html" attrs ,@content)))
>
> Now the part you have to repeat for each tag is shorter. But you can get
> it even shorter by using macros:
>
> (defmacro define-html-tags (&rest names)
> `(progn
> ,@(mapcar (lambda (name)
> `(defun ,name (attrs &rest content)
> (apply #'html-tag
> `(,,(symbol-name name) attrs ,@content))
> names)))
>
> I haven't checked the code, so it may not work, but the idea is that the
> macro gives you a defun like the last one above for every name that you
> pass in. Now all you need to do is pass in the names of the tags for
> which you want to define functions:
>
> (define-html-tags html body p h1 h2 h3)
>
> Now try doing that without macros!

If I wanted to write simple HTML generating library I would probably use 1 function and 1 enumerated type which would define keywords.

But let's go back to the macros. Take this classic C++ example:

#define MAX(x,y) ((x)>(y)?(x):(y))

and now call try to call it like that:
x=2;
y=2;
z=MAX(++x,y);

Such a simple thing and it reveals to be potentially dangerous compared to a function (or template).


Also I think you didn't get what I meant speaking about size of generated code using macros. I mean't overal size of your compiled program. If you had a large macro and in your program you would 'call' it, let's say, 1000 times then you'd have it expanded inline 1000 times in your compiled code! In case of a function you'd have it only once. And in case of template you'd have one body of it's code for each type, you used your template with.

Now, tell me macros are not to blame! :)


--
677265676F727940346E6575726F6E732E636F6D
Robbert Haarman
2006-07-14 22:39:27 UTC
Permalink
On Fri, Jul 14, 2006 at 11:07:19PM +0200, Grzegorz Wr?bel wrote:
> Robbert Haarman wrote:
> >On Fri, Jul 14, 2006 at 07:35:59PM +0200, Grzegorz Wr?bel wrote:
> >
> >>Robbert Haarman wrote:
> >>
> >>
> >>>I question the value of type checking on macros. Can you provide some
> >>>examples?
> >>
> >>That's what I meant. No type checking in macro.
> >
> >I thought you said that no type checking in macros is a bad idea. I was
> >asking you to provide an example of how type checking in macros would
> >work, and why it would be a bad idea not to have it.
> >
> That is, in my opinion one of disadvantages of macros (not the greatest
> though), but from your previous posts I understood you treat this as an
> advantage, 'cause you can treat macros as some sort of templates.

Sorry, but I still don't get it. What do templates have to do with it?
Sure, you can emulate C++ template behavior with Common Lisp macros, to
some extent, but that doesn't make macros and templates equivalent. Is
your complaint that my example emulation of C++ templates doesn't result
in compile time type checks?

> If I wanted to write simple HTML generating library I would probably use 1
> function and 1 enumerated type which would define keywords.

How would this function look, and how would you call it?

> But let's go back to the macros. Take this classic C++ example:
>
> #define MAX(x,y) ((x)>(y)?(x):(y))
>
> and now call try to call it like that:
> x=2;
> y=2;
> z=MAX(++x,y);
>
> Such a simple thing and it reveals to be potentially dangerous compared to
> a function (or template).

Which is because there is a flaw in the macro . The flaw is that the
macro expands x twice, thus resulting in two instances of ++x. In Common
Lisp, the same would occur if you defined max as

(defmacro max (x y) `(if (> ,x ,y) ,x ,y))

..which is why you don't define it that way. The most sensible way, in
this case, would be to define it as a function:

(defun max (x y) (if (> x y) x y))

Since function arguments are evaluated before the function is called,

(defvar x 2)
(defvar y 2)
(max (incf x) y)

would return 3, which is probably the intended result (disregarding, for
the sake of this discussion, the fact that max is a built-in function).

If you _really_ wanted to define it as a macro, you should write:

(defmacro max (x y)
(let ((my-x (gensym)) (my-y (gensym))
`(let ((,my-x ,x) (,my-y ,y))
(if (> ,my-x ,my-y) ,my-x ,my-y))))

which will create unique symbols for my-x and my-y, evaluate x and bind
the result to whatever symbol was generated for my-x, do the same for y,
and then run the comparison. An example:

(max (incf x) y)

could expand into

(let ((#G1 (incf x)) (#G2 y))
(if (> #G1 #G2) #G1 #G2))

As you can (hopefully) see, (incf x) is only evaluated once.

I don't know how to define an equivalent macro in portable C.

> Also I think you didn't get what I meant speaking about size of generated
> code using macros. I mean't overal size of your compiled program. If you
> had a large macro and in your program you would 'call' it, let's say, 1000
> times then you'd have it expanded inline 1000 times in your compiled code!

Yes. But keep in mind what macros are for: macros aren't functions,
macros are programs that write programs. So if you call a macro 1000
times, you will do so with different arguments, generating different
(but probably similar) code in each case. On each invocation, the macro
will do work for you, thus saving you time and effort.

Also, if you do

(loop for i from 1 to 1000 do (some-macro-that-generates-a-lot-of-code i))

this doesn't actually call that macro 1000 times: the macro is called
once, expanding into whatever lots of code it expands into, so the
compiled version of the loop will contain that code instead. That code
is then evaluated 1000 times, but it's only present in the executable
once.

> In case of a function you'd have it only once.

The comparison is that, with functions, you only write and the compiler
only generates it once, whereas you can call it many times. Each time
you use the function results in one function call. With a macro, you
write it once, and the compiler generates code once for every time you
use the macro. Each time you use it results in one instance of whatever
the macro exands into.

If you write macros like

(defmacro my-macro (func) ...lots of code... (,func ...) ... lots of code...)

this will be kind of a waste; you would have been better off using a
higher order function instead. But there are cases in which macros are
just what the doctor ordered.

> And in case of template you'd have one body of it's code for each
> type, you used your template with.

Similarly, macros give you one body of code for every instance where the
macro is used. Probably, it will have different parameters in each case.
If you find yourself using many invocations of the same macro with the
same parameters, perhaps you should abstract that part of your code a
bit more...maybe using another macro.

> Now, tell me macros are not to blame! :)

Ok. "macros are not to blame". If you cause your code to blow up
massively and unnecessarily, it's always your own fault. Macros are
great for saving you work: instead of repeating code, you have the
compiler generate that code for you. You don't generate larger
executables as a result; the result is exactly the same as if you had
repeatedly typed in the same code, only that you're done sooner. Sure,
you _can_ use macros to create huge code bloat; macros are a tool, and
any tool can be abused. Should we oppose hammers, because you can use
them to smash your fingers to pulp?

Regards,

Bob

---
And you needn't worry about your system going obsolete if it already is.
-- Eric Scigliano, about typewriters
Grzegorz Wróbel
2006-07-14 23:33:05 UTC
Permalink
Robbert Haarman wrote:

>>>>>I question the value of type checking on macros. Can you provide some
>>>>>examples?
>>>>
>>>>That's what I meant. No type checking in macro.
>>>
>>>I thought you said that no type checking in macros is a bad idea. I was
>>>asking you to provide an example of how type checking in macros would
>>>work, and why it would be a bad idea not to have it.
>>>
>>
>>That is, in my opinion one of disadvantages of macros (not the greatest
>>though), but from your previous posts I understood you treat this as an
>>advantage, 'cause you can treat macros as some sort of templates.
>
>
> Sorry, but I still don't get it. What do templates have to do with it?
> Sure, you can emulate C++ template behavior with Common Lisp macros, to
> some extent, but that doesn't make macros and templates equivalent. Is
> your complaint that my example emulation of C++ templates doesn't result
> in compile time type checks?

No complaint. I think, I simply don't understand your very first reply (the one a the top). What did you question and what exactly examples did you want? A macros with type checking?


> If you _really_ wanted to define it as a macro, you should write:

I wouldn't. I just gave it as example of one of the reasons why I'm not a follower of using macros. It's easy to write even a simple macro which will malfunction in certain cases, and it might not be easy to spot it.

> any tool can be abused. Should we oppose hammers, because you can use
> them to smash your fingers to pulp?

Not at all, but having an iron hammers should we still use wooden ones? In language I program most (C++) macros are not preffered way of doing things, that especially applies to function-like macros. And there are good reasons for that.

"The first rule about macros is: Don't use them unless you have to. Almost every macro demonstrates a flaw in the programming language, in the program, or in the programmer."

--
677265676F727940346E6575726F6E732E636F6D
goose
2006-07-14 22:51:24 UTC
Permalink
Grzegorz Wróbel wrote:
> Robbert Haarman wrote:
> > On Fri, Jul 14, 2006 at 07:35:59PM +0200, Grzegorz Wr?bel wrote:
> >
> >>Robbert Haarman wrote:
> >>
> >>
> >>>I question the value of type checking on macros. Can you provide some
> >>>examples?
> >>
> >>That's what I meant. No type checking in macro.
> >
> > I thought you said that no type checking in macros is a bad idea. I was
> > asking you to provide an example of how type checking in macros would
> > work, and why it would be a bad idea not to have it.
> >
> That is, in my opinion one of disadvantages of macros (not the greatest though), but from your previous posts I understood you treat this as an advantage, 'cause you can treat macros as some sort of templates.
>

Yes, basically. Although they are certainly more powerful than
C++ templates, this is mostly because of the lack of C++
not the advantage of macros.

<snipped>

> But let's go back to the macros. Take this classic C++ example:
>
> #define MAX(x,y) ((x)>(y)?(x):(y))
>
> and now call try to call it like that:
> x=2;
> y=2;
> z=MAX(++x,y);
>
> Such a simple thing and it reveals to be potentially dangerous compared to a function (or template).
>

Yes, all beginners are shown this example.
Yes, its a good example to demonstrate the danger.
Yes, its a bad practice and the reason that macros are usually
all UPPERCASE to warn users to beware of side-effects.

let me try to give you an example of how a
lisp macro will look in C++ (since you will have
trouble seeing the benefits if I give you working
lisp code :-)

Bear in mind that this is only an analagous
situation to lisp, this is not in fact lisp (nor C++)
code. I'm only trying to show lisp macros in C++ terms.

Lets say that as you program, you realise that you
are repeating the following pattern many times:

int array1[10], array2[20], array3[30];
...
for (int i=0; i<sizeof array1 / sizeof array1[0]; i++) {
fiddle_with (array1[i]);
}
...
for (int i=0; i<sizeof array2 / sizeof array2[0]; i++) {
faddle_on (array2[i]);
}
...
for (int i=0; i<sizeof array3 / sizeof array3[0]; i++) {
fuddle_by (array3[i]);
}

Now, if C++ supported lisp-type macros then you
could write a macro that looked /something/ like this:

#define-lisp-macro APPLY(array_name,&code_body) \
`for (int i=0; i < ,array_name / sizeof ,array_name[0]; i++) {\
,@code_body[i]; \
}

Once you do that, then you can replace the 3 for loops above
with this:

APPLY (array1, fiddle_with);
...
APPLY (array2, faddle_on);
...
APPLY (array3, fuddle_by);

Now the above is just an example of what you *cannot*
do with C++ (macros or templates), but that is done all
the time in lisp.

Does that make sense to you?

If you are going to counter "But you can do that with
a normal function if you just pass the length of the array",
then I have explained it badly.

For a more thorough example see my thoughts on this
at my website.
http://www.lelanthran.com/technical/computers/software/why_i_like_lisp.php

Lispers in particular might find inaccuracies on that page as I
am still learning the language, so I encourage lispers to visit
and mail me their criticisms.

While you're there, feel free to browse the rest of the site as well
:-).

>
> Also I think you didn't get what I meant speaking about size of generated code using macros. I mean't overal size of your compiled program. If you had a large macro and in your program you would 'call' it, let's say, 1000 times then you'd have it expanded inline 1000 times in your compiled code! In case of a function you'd have it only once. And in case of template you'd have one body of it's code for each type, you used your template with.
>
> Now, tell me macros are not to blame! :)
>

Well, look at it this way; in lisp macros do not replace functions.
So if a macro generated 1000 lines of code in your lisp program,
then it was 1000 lines that you did not have to write yourself :-)

If a function can do it for you in lisp, then you use a function; you
only use a macro when a function will not do.

goose,
lisp beginner
Brian Raiter
2006-07-15 01:09:31 UTC
Permalink
The problem with this particular thread of the conversation is that
Lisp macros and C++ macros are really very much unlike each other, so
much so that you're almost comparing apples and oranges.

"I don't like [C++] macros because they have ugly pitfalls and there's
very little you can do with them that you can't do more safely without
them."

"I like [Lisp] macros because they're an extremely flexible tool and
the language would be poorer and less readable without them."

Both statements are true, and have almost nothing to do with each
other.

b
Michael J. Fromberger
2006-07-14 20:39:29 UTC
Permalink
In article <e98hju$sah$***@nemesis.news.tpi.pl>,
Grzegorz Wrobel </dev/***@localhost.localdomain> wrote:

> In most languages macros are just wonders that are expanded inline by
> preprocessor before actual compilation.

I'm interested by your claim. In my experience, "most languages" lack
macros entirely. Apart from Lisp, the only languages I know of offhand
that possess macros are C, C++, and Dylan. There are undoubtedly
others, but you seem to be generalizing from C-style macros to the rest
of the programming world, and I'm not sure that's a safe generalization.

Cheers,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Grzegorz Wróbel
2006-07-14 21:21:09 UTC
Permalink
Michael J. Fromberger wrote:

> In article <e98hju$sah$***@nemesis.news.tpi.pl>,
> Grzegorz Wrobel </dev/***@localhost.localdomain> wrote:
>
>
>>In most languages macros are just wonders that are expanded inline by
>>preprocessor before actual compilation.
>
>
> I'm interested by your claim. In my experience, "most languages" lack
> macros entirely. Apart from Lisp, the only languages I know of offhand
> that possess macros are C, C++, and Dylan. There are undoubtedly
> others, but you seem to be generalizing from C-style macros to the rest
> of the programming world, and I'm not sure that's a safe generalization.

Well, there is Assembler yet :). And from the context, by "most languages" here I meant "most languages that do have macros" if it wasn't obvious. I would have even said all (because I always thought that's the definition of macro - ie that it is expanded inline by the preprocesor) but since one of the interlocutors in this thread presented Lisp macros as an equivalent of templates I thought it was something more advanced.

--
677265676F727940346E6575726F6E732E636F6D
Brian Raiter
2006-07-15 00:36:48 UTC
Permalink
> So is that a "yes" or "no"?

Maybe if you took a moment to look up "barycenter", you'd understand
the previous better.

> Humor me for a moment. I'm not trying to be a pain in the ass, but I
> think I'm asking a simple question and getting a truckload of facts in
> response that are given in such a way that I think I'm being told I'm
> wrong.

Well, to be precise, ...

> Sorry about my lack of math skills, but does all this really mean
> that the earth does not travel in an orbit around the sun?

... this statement is not precise enough to warrant an unequivocal
yes.

In short:

The sun, and earth, and everything else under consideration, revolve
around an imaginary point, which is sort of the "average" of all the
mass of the solar system. This point is called the "barycenter".
Naturally, it is not a fixed point, but wobbled around as the various
masses of the solar system move about.

If you're still confused, just go here:

http://en.wikipedia.org/wiki/Center_of_mass#Barycenter

and be enlightened.

b
goose
2006-07-14 14:06:20 UTC
Permalink
Robbert Haarman wrote:
> On Fri, Jul 14, 2006 at 01:17:59AM -0700, ***@gmx.at wrote:

<snipped>

> > If you want to reuse the + operator to add 'colors', can you
> > just write something like (in Seed7):
> >
> > const func color: (in color: col1) + (in color: col2) is func
> > result
> > var color: result is color.value;
> > begin
> > result.red_part := (col1.red_part + col2.red_part) div 2;
> > result.green_part := (col1.green_part + col2.green_part) div 2;
> > result.blue_part := (col1.blue_part + col2.blue_part) div 2;
> > end func;
> >
> > and it just works?
>
> You can do this with any generic function. + isn't a generic function,
> but you can redefine it to be. After that's done, you can write:
>
> (defmethod + ((col1 color) (col2 color))
> (make-color (/ (+ (color-red-part col1) (color-red-part col2)) 2)
> (/ (+ (color-green-part col1) (color-green-part col2)) 2)
> (/ (+ (color-blue-part col1) (color-blue-part col2)) 2)))
>

Actually, I'd rather do something like

(defun average (&rest values)
(let ((result 0))
(dolist (num values)
(setf result (+ num result)))
(setf result (/ result (length values)))
result))

(defmethod + ((col1 color) (col2 color))
(make-color
(average (red col1) (red col2))
(average (green col1) (green col2))
(average (blue col1) (blue col2))))

On the offchance I may actually need to average something
else someday and it makes "+" more readable.

Turning "+" above into a function which takes
an unlimited number of arguments is left as an
exercise to the reader (human, not macro :-)


goose,
Robbert Haarman
2006-07-14 15:01:43 UTC
Permalink
On Fri, Jul 14, 2006 at 07:06:20AM -0700, goose wrote:
> Robbert Haarman wrote:
> >
> > (defmethod + ((col1 color) (col2 color))
> > (make-color (/ (+ (color-red-part col1) (color-red-part col2)) 2)
> > (/ (+ (color-green-part col1) (color-green-part col2)) 2)
> > (/ (+ (color-blue-part col1) (color-blue-part col2)) 2)))
> >
>
> Actually, I'd rather do something like
>
> (defun average (&rest values)
> (let ((result 0))
> (dolist (num values)
> (setf result (+ num result)))
> (setf result (/ result (length values)))
> result))
>
> (defmethod + ((col1 color) (col2 color))
> (make-color
> (average (red col1) (red col2))
> (average (green col1) (green col2))
> (average (blue col1) (blue col2))))
>
> On the offchance I may actually need to average something
> else someday and it makes "+" more readable.

Me too, but I was staying close to what Thomas provided.

By the way, why not:

(defun average (&rest values)
(/ (apply #'+ values) (length values)))

?

> Turning "+" above into a function which takes
> an unlimited number of arguments is left as an
> exercise to the reader (human, not macro :-)

Heh. I can't resist...but it's not as easy as I first thought:
apparently, you can't specialize on the type of the &rest parameters in
Common Lisp. Here's my best attempt (although I would shorten it with
macros):

(defmethod + ((col color) &rest colors)
(if (every colorp colors)
(make-color
(apply #'average (cons
(color-red-part col)
(mapcar #'color-red-part colors)))
(apply #'average (cons
(color-green-part col)
(mapcar #'color-green-part colors)))
(apply #'average (cons
(color-blue-part col)
(mapcar #'color-blue-part colors))))
(call-next-method)))

It first tests if all the arguments in colors actually are colors, if
so, it creates a color whose components are the average of all colors
given, otherwise it gives up and calls call-next-method.

Regards,

Bob

---
That that is is that that is not not, that is, not that that is not.
goose
2006-07-14 18:39:11 UTC
Permalink
Robbert Haarman wrote:
> On Fri, Jul 14, 2006 at 07:06:20AM -0700, goose wrote:

<snipped>

> By the way, why not:
>
> (defun average (&rest values)
> (/ (apply #'+ values) (length values)))
>
> ?

Err, because I hadn't learned that yet :-)

>
> > Turning "+" above into a function which takes
> > an unlimited number of arguments is left as an
> > exercise to the reader (human, not macro :-)
>
> Heh. I can't resist...but it's not as easy as I first thought:

Me neither; I couldn't even find a solution in the five
minutes I had to look at it; so your solution wins
by default :-)


goose,
By kind; I'm still only learning lisp
goose
2006-07-14 13:07:29 UTC
Permalink
***@gmx.at wrote:
> goose wrote:

<snipped>

> > Lets see if Lisp has all these features:
>
> 1 AFAIK: Lisp uses lots of parentheses to form lists. In all

How does this in any way invalidate what lisp supports?

> expressions the first element of the list is the function
> name. The definition of the factorial function in lisp
> would be (example from wikipedia):
>
> (defun ! (n)
> (cond ((= n 0) 1)
> ((> n 0) (* n (! (- n 1))))))
>
> This function could be called with
>
> (! 5)
>
> AFAIK there is no concept of infix operators (with priority
> and assoziativity) in Lisp.

There isn't; this is generally considered to be a /good/
thing, not a bad thing.

> Lisp allows the definition of
> new functions, but functions are not operators. The

And how is this difference in significant in any way?
IOW, when I write "+" (operator) and "+" (function)
why is the operator automatically better than the function?

> description of an factorial operator in Seed7 would be:
>
> $ syntax expr: . ! .() is -> 4;
>
> const func integer: ! (in integer: n) is func
> result
> var integer: result is 1;
> begin
> if n > 0 then
> result := n * !(n - 1);
> end if;
> end func;
>
> This function could be called with
>
> !5
>
> In general Lisp does not know about operators and
> overloading.

Yes, it does; see above for my operator/function question;
it'll overload functions.

> Lisp statements (see cond of the example
> above) use also the list syntax with lots of parentheses.

Why is this a bad thing?

> This means that user defined statements of Lisp have to
> use the list notation and there is no possibility to
> define a syntax for this statements.

You can modify the reader macro(s) and/or the readtable
(IIRC) to write all your code like seed7 for example.

>
> 2 The type concept does not exist in Lisp therefore
> it is not possible to use types as parameters.

It is not needed; if you *really* must have types
you can, although IIRC the standard specifies runtime types
only I've not met a lisp implementation that won't
issue warnings at compile-time.

>
> 3 This is possible in Lisp
>
> 4 I do not know the details of CLOS
>
> 5 As mentioned before types does not exist in Lisp and
> IMHO this is a bad thing.

see above.

>
> I am to tired to answer the other points, but you see
> my view is different.
>

I do see that; I did attempt to design my own language
a little while ago. After looking at what the current
offerings include I decided that I might as well just
reimplement an existing language (and have been annoying
everyone on this newsgroup since :-).

All the language designers before me have already had
major insight into languages and tools which I am only
now getting.

For example, it seems to me that you didn't have a bash
at lisp before starting your language design. If you had,
you may have taken the way lisp handles types a step
further instead of handling types in a more traditional
but less powerful manner.

If you had a look at haskell before starting design
then you might've combined lisp syntax (very consistent)
with haskell way of defining functions (and or lazy
evaluation).

e.g. haskell factorial function:

fact 0 = 1
fact n | n > 0 = fact n - 1

Neat, eh :-) ?

That beats both lisp and seed7 for readability
and expressiveness :-)

Combining lisp syntax and haskell
goodness should result (well, for me anyway) in:
(defun fact (0) 1)
(defun fact ((n | (> n 0))) (fact (- n 1)))

Now, obviously some people won't like that, but
for me it combines maximum consistency with
maximum expressiveness.

If you have seen erlang (a little on the heavy
side for me personally but YMMV) you may have included
/primitives/ to allow concurrent processing
as well as rethought why exceptions/error-handling
is needed and/or used for.

There are a few things from each language that are
desirable; if you /don't want/ comparisons of your new
baby (seed7) with all existing languages, then perhaps
you should specify on the seed7 homepage that this
language is favourably comparable to other imperative
languages like Java, C++, etc but was not designed
to compete featurewise with other languages (lisp
haskell, smalltalk, etc).

HTH

goose,
t***@gmx.at
2006-07-14 21:26:14 UTC
Permalink
goose schrieb:
> ***@gmx.at wrote:
> > AFAIK there is no concept of infix operators (with priority
> > and assoziativity) in Lisp.
>
> There isn't; this is generally considered to be a /good/
> thing, not a bad thing.

This advocacy discussion leads nowhere. Different languages
have different design principles. The design principles of
Lisp are totally different from the design principles of Seed7.
This principles lead to different goals and different views
about good and bad things. Some of the design principles of
Seed7 are:

- It is an imperative programming language.
- Everything must declared before it is used.
- Every expression has just one type.
- There are no implicit type conversions.
- Traditional statements as in Pascal, Ada, C.
- Infix operators with priority and assoziativity
- functions (operators, statements) can be overloaded.
- It is possible to declare statements.
- ...

Based on this axioms:

- Expressions with infix operators are good.
- Compile time checking is good.
- ...

It is absolut impossible to convince me that this are
bad things.

Lisp has different design prinziples and other good
and bad things. The comparison has different points:

Mandatory compile time type checks vs.
Optional (runtime or compile time) type checking.

Expressions like in Pascal, Ada, C, Java vs.
Everything is an S-Expression.

Infix operators vs. Prefix operators

Macros (like in C/C++) should not be used vs.
Macros as normal element of the language.

Lots and lots of situations where you can compare
apples to oranges...

> I do see that; I did attempt to design my own language
> a little while ago. After looking at what the current
> offerings include I decided that I might as well just
> reimplement an existing language (and have been annoying
> everyone on this newsgroup since :-).
>
> All the language designers before me have already had
> major insight into languages and tools which I am only
> now getting.
>
> For example, it seems to me that you didn't have a bash
> at lisp before starting your language design.

Years ago I did a look at Lisp and IMHO the design
principles of Lisp differ fundamentally from the Seed7
ones. Therefore Seed7 is not an extension of Lisp.

> If you had,
> you may have taken the way lisp handles types a step
> further instead of handling types in a more traditional
> but less powerful manner.

I treat types in the traditional way on purpose.
IMHO mandatory compile time type checks are a HUGE
advantage in big applications. The arguments for this
decision can be found at many places in the internet
and I don't want to repeat them here. Please do not try
to convince me (You will fail. Try to convince Linus
that monolitic kernels are bad and microkernels are
good. Your chances for this are better. If you succeed
and Linus is convinced come back and you will fail
aggain).

> If you had a look at haskell before starting design
> then you might've combined lisp syntax (very consistent)
> with haskell way of defining functions (and or lazy
> evaluation).
>
> e.g. haskell factorial function:
>
> fact 0 = 1
> fact n | n > 0 = fact n - 1
>
> Neat, eh :-) ?

What about this:

const type: piece is new enum
SQUARE_BLOCK, I_BAR, S_ZIGZAG, Z_ZIGZAG, GAMMA_KNEE, L_KNEE,
T_BRANCH
end enum;

const color: color (SQUARE_BLOCK) is dark_blue;
const color: color (I_BAR) is dark_red;
const color: color (S_ZIGZAG) is light_green;
const color: color (Z_ZIGZAG) is light_cyan;
const color: color (GAMMA_KNEE) is light_gray;
const color: color (L_KNEE) is dark_magenta;
const color: color (T_BRANCH) is brown;

const func color: color (ref piece param) is DYNAMIC;

The expression

color(myColor)

delivers the corresponding color for a tetris piece.

> There are a few things from each language that are
> desirable;

There are always 'nice to have' features in other
languages. Programming language features have also
fashions. Seed7 does not want to support every
en vogue feature. But in general Seed7 trys to provide
a framework which should allow to gather features
from different programming languages. These features
need to match the design principles of Seed7.

> this language is favourably comparable to other
> imperative languages like Java, C++,

Seed7 wants to compete with languages like C, C++,
Java, etc. These languages are used a lot and for big
programs in most areas. There is a long way to go...

You can compare Seed7 with any other programming
language, but 'apple to oranges' comparisons make
no reason.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Rob Thorpe
2006-07-17 01:17:55 UTC
Permalink
***@gmx.at wrote:
> goose schrieb:
> > ***@gmx.at wrote:
> > > AFAIK there is no concept of infix operators (with priority
> > > and assoziativity) in Lisp.
> >
> > There isn't; this is generally considered to be a /good/
> > thing, not a bad thing.
>
> This advocacy discussion leads nowhere.

I don't know, I've learnt a lot about the rotation of the earth. And I
think others have learnt a lot about lisp.

> It is absolut impossible to convince me that this are
> bad things.

Rather than speaking of convincing people, it would be more useful if
you told us the reasons for your decisions. People are more likely to
be interested in what you say if you have data as well as opinions.
t***@gmx.at
2006-07-17 08:35:43 UTC
Permalink
Rob Thorpe schrieb:
> ***@gmx.at wrote:
> > goose schrieb:
> > > ***@gmx.at wrote:
> > > > AFAIK there is no concept of infix operators (with priority
> > > > and assoziativity) in Lisp.
> > >
> > > There isn't; this is generally considered to be a /good/
> > > thing, not a bad thing.
> >
> > This advocacy discussion leads nowhere.
>
> I don't know, I've learnt a lot about the rotation of the earth.

I was refering to advocacy discussions like:

- Are infix operators (with priority and assoziativity) a
good thing, or should everything be based on functions.

- Is mandatory compiletime type checking a good thing, or
is it better when there are only runtime type checks.

> Rather than speaking of convincing people, it would be more useful if
> you told us the reasons for your decisions.

I don't think it is possible to convince 'hard core' fans of any
language or paradigma. I can try to give some of the reasoning
behind my design decisions:

- Infix operators have a long tradition in mathematics
and related areas. The mainstream programming languages
use infix operators also. Since Seed7 wants to be near the
mainstream it uses infix operators also.

- Tiny programs and scripts can be written faster when you
omit declarations (with types). Although Seed7 is intended
to be used for scripts, it is also intended to be used for
big programs, therefore rules of professional program development
are used. There are studies that errors are more expensive
when they are found later in the software development process.
Therefore it is important to find errors as early as possible.
Mandatory compiletime type checking is a method to find
a certain class of errors earlier.

=== The philosophy of Seed7 ===
In the beginning of the 80s I had the idea of a general
preprocessor or language. One of the ideas was, that it
should be possible to use features of other programming
languages in Seed7 (at that time I called it Master).

Taken this idea to the extreme: You import the FORTRAN
library and the rest of your program is written in FORTRAN.
For Pascal, Cobol, Ada, ... it should work the same.

As I said, this was the extreme. In general I wanted to
have a frame programming language which would allow
stealing features (constructs) from other programming
languages.

It soon turned out that there are many features which
are considerd outdated (Like columns with special
meanings like in old FORTRAN). I decided to omit such
features. Therefore it is not possible to emulate
languages with such features.

An important point is: The syntax and the semantic
of a feature should be provided. But I wanted not to
do in in the way a compiler generator works.

New features should be provided in the same way as
you declare functions (since infix operators and
statements are functions with special syntax).

There have been several steps which lead to the current
Seed7 which I plan to explain at the homepage.

Programming languages change over time. New features
are invented and compiler writers include new
features in the compiler.

In general: The people who write compilers make the
innovations. The idea of Seed7 is to give this power
to the programmers.

So Seed7 is about 'Power to the People'. If you share
this vision you are invited to help.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-17 09:37:18 UTC
Permalink
On Mon, Jul 17, 2006 at 01:35:43AM -0700, ***@gmx.at wrote:
> Rob Thorpe schrieb:
> > ***@gmx.at wrote:
> > > goose schrieb:
> > > > ***@gmx.at wrote:
> > > > > AFAIK there is no concept of infix operators (with priority
> > > > > and assoziativity) in Lisp.
> > > >
> > > > There isn't; this is generally considered to be a /good/
> > > > thing, not a bad thing.
> > >
> > > This advocacy discussion leads nowhere.
> >
> > I don't know, I've learnt a lot about the rotation of the earth.
>
> I was refering to advocacy discussions like:
>
> - Are infix operators (with priority and assoziativity) a
> good thing, or should everything be based on functions.
>
> - Is mandatory compiletime type checking a good thing, or
> is it better when there are only runtime type checks.

I think it can be very useful to discuss these issues, provided that
people really _think_ about what the others are saying, rather than
just try to convince the rest of the world. Many people assume that
there is One True Way to do these things, often because they've only
heard one side of the story. I firmly believe that there are advantages
to both approaches to the above issues, and discussing about them can
open people's eyes.

> > Rather than speaking of convincing people, it would be more useful if
> > you told us the reasons for your decisions.
>
> I don't think it is possible to convince 'hard core' fans of any
> language or paradigma.

But you don't have to. You should be content when you've given
reasonable people something to think about.

> I can try to give some of the reasoning behind my design decisions:
>
> - Infix operators have a long tradition in mathematics
> and related areas. The mainstream programming languages
> use infix operators also. Since Seed7 wants to be near the
> mainstream it uses infix operators also.

Sounds perfectly good to me.

> - Tiny programs and scripts can be written faster when you
> omit declarations (with types). Although Seed7 is intended
> to be used for scripts, it is also intended to be used for
> big programs, therefore rules of professional program development
> are used. There are studies that errors are more expensive
> when they are found later in the software development process.
> Therefore it is important to find errors as early as possible.
> Mandatory compiletime type checking is a method to find
> a certain class of errors earlier.

This sounds like you're ignoring the possibilities of type inference and
weak typing. Type inference lets the compiler figure out types, without
you having specified them, thus allowing compile-time type checking and
optimization, without any extra effort from the programmer. Weak typing
detects possible type errors at compile time, but gives warnings instead
of rejecting the program. Depending on your type system, your type
checker might reject some programs that would never fail to work if they
were allowed to run. If that's the case, weak typing offers you to go
ahead and run the program anyway (as in dynamic typing), while it still
offers you the opportunity to catch errors at compile time (as in static
typing).

Now, let me make one thing perfectly clear: I'm not trying to convince
you that you _should_ use type inference and weak typing. I'm just
pointing out the possibilities, and their advantages. It's your
language; you decide.

Regards,

Bob

---
Perilous to all of us are the devices of an art deeper than we ourselves
possess.
-- Gandalf the Grey [J.R.R. Tolkien, "Lord of the Rings"]
t***@gmx.at
2006-07-17 11:00:21 UTC
Permalink
Robbert Haarman wrote:
> On Mon, Jul 17, 2006 at 01:35:43AM -0700, ***@gmx.at wrote:
> > - Tiny programs and scripts can be written faster when you
> > omit declarations (with types). Although Seed7 is intended
> > to be used for scripts, it is also intended to be used for
> > big programs, therefore rules of professional program development
> > are used. There are studies that errors are more expensive
> > when they are found later in the software development process.
> > Therefore it is important to find errors as early as possible.
> > Mandatory compiletime type checking is a method to find
> > a certain class of errors earlier.
>
> This sounds like you're ignoring the possibilities of type inference and
> weak typing. Type inference lets the compiler figure out types, without
> you having specified them, thus allowing compile-time type checking and
> optimization, without any extra effort from the programmer.

I know about type inference. Type inference is not a system which works
100% of the time (except you reduce it to very primitive examples).
If you omit declarations (with types) the types can not always be
determined. The redundancy you get from type declarations and
mandatory type checks makes your program safer.

Seed7 expressions have always one type and there are no implicit type
conversions. This leads to a very simple and crystal clear system to
decide which of the overloaded functions needs to be called.
That is a big advantage: It makes reading the program easier.
Complicated (and hard to remember) automatic type conversion rules
like in Algol68, C and C++ are not needed. Complicated rules
which (template) function is called are also not necessary.

Type inference would save you a little typing but would make the whole
language more complicated (for the compiler/interpreter and for the
human reader).

Since Seed7 is an extendable programming language which
claims to allow the definition of features in a wide range:
You could declare 'const' and 'var' declaration statements
which use type inference (from the initial value) in Seed7.
This are the primitive cases of type inference I mentioned
above (Variable or constant declaration with initialisation).

> Weak typing
> detects possible type errors at compile time, but gives warnings instead
> of rejecting the program. Depending on your type system, your type
> checker might reject some programs that would never fail to work if they
> were allowed to run.

This sounds strange because: When a good type system rejects a program
it would fail (crash or produce garbadge) at some point (which might be
called just once every 100000 Years). At least in Seed7 the type
system only 'rejects' buggy programs. Btw. the Seed7 interpreter always
trys to execute a program (independend of the number of errors).

If you really need different types at runtime:
Use object orientation. You have an 'interface' which promises
functionality (in Seed7 this are the 'DYNAMIC' functions) and
you have the actual methods in the classes. And belive me:
Object orientation is much more powerful and better designed
than weak typing.

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-17 17:03:48 UTC
Permalink
On Mon, Jul 17, 2006 at 04:00:21AM -0700, ***@gmx.at wrote:
> Robbert Haarman wrote:
> > On Mon, Jul 17, 2006 at 01:35:43AM -0700, ***@gmx.at wrote:
> > > - Tiny programs and scripts can be written faster when you
> > > omit declarations (with types). Although Seed7 is intended
> > > to be used for scripts, it is also intended to be used for
> > > big programs, therefore rules of professional program development
> > > are used. There are studies that errors are more expensive
> > > when they are found later in the software development process.
> > > Therefore it is important to find errors as early as possible.
> > > Mandatory compiletime type checking is a method to find
> > > a certain class of errors earlier.
> >
> > This sounds like you're ignoring the possibilities of type inference and
> > weak typing. Type inference lets the compiler figure out types, without
> > you having specified them, thus allowing compile-time type checking and
> > optimization, without any extra effort from the programmer.
>
> I know about type inference. Type inference is not a system which works
> 100% of the time (except you reduce it to very primitive examples).

How do you mean? Type inference seems to work just fine in various
variants of ML...

> If you omit declarations (with types) the types can not always be
> determined.

That depends on your type system.

> The redundancy you get from type declarations and mandatory type
> checks makes your program safer.

I don't see that. A type inferencer could try to infer a safe typing for
your program, and reject it if no such typing were found. This would be
every bit as safe as type declarations.

> Type inference would save you a little typing but would make the whole
> language more complicated (for the compiler/interpreter and for the
> human reader).

I don't see that it makes the language more complicated for the human
reader. As a human, I care about what the program does to my values, not
necessarily what types they are. But then, I mostly program in
dynamically typed languages. Still, the amount of work involved in
explicit type declarations can be substantial, especially in a
programming style that uses lots of small functions.

> Since Seed7 is an extendable programming language which
> claims to allow the definition of features in a wide range:
> You could declare 'const' and 'var' declaration statements
> which use type inference (from the initial value) in Seed7.

On the other hand, that would be going against the nature of the
language; the intent is for the language to have explicitly declared
types everywhere.

> This are the primitive cases of type inference I mentioned
> above (Variable or constant declaration with initialisation).

These are _very_ primitive. Type inference can go much further than
that.

> > Weak typing
> > detects possible type errors at compile time, but gives warnings instead
> > of rejecting the program. Depending on your type system, your type
> > checker might reject some programs that would never fail to work if they
> > were allowed to run.
>
> This sounds strange because: When a good type system rejects a program
> it would fail (crash or produce garbadge) at some point (which might be
> called just once every 100000 Years).

Not all type systems are that good.

> At least in Seed7 the type system only 'rejects' buggy programs.

Buggy by what definition? By the definition that it won't work with
Seed7's type system? Or buggy by the definition that it couldn't work at
all?

For example, a function that took, as an argument, a list containing a
string, then an integer, then a string, then an integer, etc. and
printed out the first string, a colon, a space, the first integer, a
newline, and so on for the second up to the last string and integer
would be rejected by many static type systems. Arguably, it's bad style.
But it would work fine under a dynamic type system. Is it a correct
program? By what definition? Would Seed7 accept it?

> Btw. the Seed7 interpreter always trys to execute a program
> (independend of the number of errors).

So the program has different semantics when interpreted than when
compiled?

> If you really need different types at runtime:
> Use object orientation. You have an 'interface' which promises
> functionality (in Seed7 this are the 'DYNAMIC' functions) and
> you have the actual methods in the classes. And belive me:
> Object orientation is much more powerful and better designed
> than weak typing.

It's also orthogonal. Object orientation is a programming paradigm; weak
typing is a type system. You can have object orientation with or without
weak typing, and the other way around.

And what about your interfaces? Do you have to declare them or does the
compiler figure out what methods need to be supported? If I have a
method like

foo(x) {
print(x);
fiddle(x);
}

will I have to declare what interface x implements? Or will the compiler
figure that any x goes, as long as at least the print and fiddle methods
are defined for it? I guess that, in line with Seed7's focus on explicit
typing, interfaces will need to be declared, and you need to declare the
interfaces of the values your functions accept. This is fine, but it
does mean that if you have multiple interfaces that include a print
method and a fiddle method, you will also have to define multiple foo
functions.

Regards,

Bob

---
"Thou shalt not follow the Null Pointer, for at it's end Madness and Chaos lie."
Jerry Coffin
2006-07-17 18:06:21 UTC
Permalink
In article <***@morgenes.shire.sytes.net>,
***@inglorion.net says...

[ ... ]

> > I know about type inference. Type inference is not a system which works
> > 100% of the time (except you reduce it to very primitive examples).
>
> How do you mean? Type inference seems to work just fine in various
> variants of ML...

It usually works quite well in ML -- but in the worst case, it has
exponential complexity. Though it's quite uncommon, a minor change in
an ML program can suddenly slow compilation _substantially_.

> > The redundancy you get from type declarations and mandatory type
> > checks makes your program safer.
>
> I don't see that. A type inferencer could try to infer a safe typing for
> your program, and reject it if no such typing were found. This would be
> every bit as safe as type declarations.

Type inferencing has some limitations -- or at least most current
implementations do, at any rate. For one example of a system that
pushes the limits, consider Generic Haskell. For one example, see:

http://www.cs.uu.nl/~johanj/DGP2005/alexey.pdf

I'm certainly not prepared to say the limitations are all that
terrible, but they definitely exist.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Marcin 'Qrczak' Kowalczyk
2006-07-17 19:11:21 UTC
Permalink
Followup-To: comp.lang.misc

Jerry Coffin <***@taeus.com> writes:

>> How do you mean? Type inference seems to work just fine in various
>> variants of ML...
>
> It usually works quite well in ML -- but in the worst case, it has
> exponential complexity. Though it's quite uncommon, a minor change
> in an ML program can suddenly slow compilation _substantially_.

This happens only for artificially constructed programs where types
have exponential size (the same program with explicitly specified
types would be exponentially larger). This is not a problem in
practice.

--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
t***@gmx.at
2006-07-17 20:16:24 UTC
Permalink
Robbert Haarman wrote:
> On Mon, Jul 17, 2006 at 04:00:21AM -0700, ***@gmx.at wrote:
> > Robbert Haarman wrote:
> > > On Mon, Jul 17, 2006 at 01:35:43AM -0700, ***@gmx.at wrote:
> > > > - Tiny programs and scripts can be written faster when you
> > > > omit declarations (with types). Although Seed7 is intended
> > > > to be used for scripts, it is also intended to be used for
> > > > big programs, therefore rules of professional program development
> > > > are used. There are studies that errors are more expensive
> > > > when they are found later in the software development process.
> > > > Therefore it is important to find errors as early as possible.
> > > > Mandatory compiletime type checking is a method to find
> > > > a certain class of errors earlier.
> > >
> > > This sounds like you're ignoring the possibilities of type inference and
> > > weak typing. Type inference lets the compiler figure out types, without
> > > you having specified them, thus allowing compile-time type checking and
> > > optimization, without any extra effort from the programmer.
> >
> > I know about type inference. Type inference is not a system which works
> > 100% of the time (except you reduce it to very primitive examples).
>
> How do you mean? Type inference seems to work just fine in various
> variants of ML...

When ML uses type inference - good. Seed7 will not do that.
Once and for all: Seed7 is not ML, Haskell or Lisp. Seed7 can take
over concepts of other programming languages, but the basic
language will be a typesafe one with compiletime type checking.
I have stated my reasons why I consider mandatory compiletime type
checking a good thing. I have stated why I consider type inference
a bad thing.

Ever heard of the KISS principle. Seed7 has a simple concept:

Seed7 expressions have always one type and there are no implicit
type conversions.

I don't think that type inference rules can be described that simple.
And don't say 'do what I mean'. I am speaking of implementable rules.

> > The redundancy you get from type declarations and mandatory type
> > checks makes your program safer.
>
> I don't see that. A type inferencer could try to infer a safe typing for
> your program, and reject it if no such typing were found. This would be
> every bit as safe as type declarations.

Have you ever written such a type inferencer?

The Seed7 type system leads to a very simple and crystal clear
system to decide which of the overloaded functions needs to be called.
That is a big advantage: It makes reading the program easier.
Complicated (and hard to remember) automatic type conversion rules
like in Algol68, C and C++ are not needed. Complicated rules
which (template) function is called are also not necessary.
A simple concept is also easier to implement and the propability
that the implementation contains errors is lower.

> I don't see that it makes the language more complicated for the human
> reader. As a human, I care about what the program does to my values, not
> necessarily what types they are.

When the types are wrong you could get garbage when your type system
thinks that it makes sense.

> But then, I mostly program ...

Just a questions: What was the biggest program you had to deal with.
All this wonderful 'do what I mean' concepts work for small programs.
But when a 'do what I mean' concept fails you are lost in a jungle.
Think of big projects with many people working on the same
program for years. What languages are used for such programs.
Think over it. Not toy or Mikey Mouse projects. A commercial or
a big open source program. For most of this big programs
a language with static type checking is used. You can always
argue that most people are stupid. But maybe the people decide
for languages with mandatory compiletime type checking for a reason.

> > Since Seed7 is an extendable programming language which
> > claims to allow the definition of features in a wide range:
> > You could declare 'const' and 'var' declaration statements
> > which use type inference (from the initial value) in Seed7.
>
> On the other hand, that would be going against the nature of the
> language; the intent is for the language to have explicitly declared
> types everywhere.

You must destinguish between the basic language (without type
inference) and what could be declared as new statements.
The 'const' and 'var' declarations are just statements.
Therefore new declaration statements (which take the type
from the initialisation value) could be declared.

> > > Weak typing
> > > detects possible type errors at compile time, but gives warnings instead
> > > of rejecting the program. Depending on your type system, your type
> > > checker might reject some programs that would never fail to work if they
> > > were allowed to run.
> >
> > This sounds strange because: When a good type system rejects a program
> > it would fail (crash or produce garbage) at some point (which might be
> > called just once every 100000 Years).
>
> Not all type systems are that good.

Well a type system with mandatory compiletime type checks is that good.
And this is the absolute minimum I want to accept.

> > At least in Seed7 the type system only 'rejects' buggy programs.
>
> Buggy by what definition? By the definition that it won't work with
> Seed7's type system? Or buggy by the definition that it couldn't work at
> all?

As I already said: I consider programs that crash as buggy.
But more important I consider also programs that produce garbage
as buggy.

>
> For example, a function that took, as an argument, a list containing a
> string, then an integer, then a string, then an integer, etc. and
> printed out the first string, a colon, a space, the first integer, a
> newline, and so on for the second up to the last string and integer
> would be rejected by many static type systems. Arguably, it's bad style.
> But it would work fine under a dynamic type system. Is it a correct
> program? By what definition? Would Seed7 accept it?

What you really have is an array of structs. Every struct consists of
two elements: a string and an integer. In Seed7 it would look like:

const type: myPair is new struct
var string: name is "";
var integer: number is 0;
end struct;

const proc: myFunc (in array myPair: myList) is func
local
var integer: index is 0;
begin
for index range 1 to length myList do
writeln(myList[index].name <& ": " <& myList[index].number);
end for;
end func;

> > Btw. the Seed7 interpreter always trys to execute a program
> > (independend of the number of errors).
>
> So the program has different semantics when interpreted than when
> compiled?

No. - The compiler is not finished. But in principle the interpreter
should not execute programms with errors.

> And what about your interfaces? Do you have to declare them or does the
> compiler figure out what methods need to be supported?

As I prefere explicit things and don't like guesswork: You have to
declare an interface.

I try to answer you last question with my own example.

Seed7 has sets. Sets are implemented as abstract data types.
an abstract data type is a function which has a type as result.
You can just write 'set of integer' or 'set of char' and a function
with the head

const func type: set of (in type: baseType) is func

is executed and produces a set type. The sets are implemented as
bitsets based on 'set of integer'. Basically 'set of baseType' makes
sense when a baseType value can be converted to an integer
(with the 'ord' function). So when you write 'set of float' you
get a compiletime error because floats have no 'ord' functon.
(I plan to implement sets of types without 'ord' function to
use lists but for now you get just an error).

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-18 14:24:06 UTC
Permalink
On Mon, Jul 17, 2006 at 01:16:24PM -0700, ***@gmx.at wrote:
>
> When ML uses type inference - good. Seed7 will not do that.
> Once and for all: Seed7 is not ML, Haskell or Lisp. Seed7 can take
> over concepts of other programming languages, but the basic
> language will be a typesafe one with compiletime type checking.

That sounds like you're saying type inference precludes compile time
type checking. It doesn't. ML uses type inference, but checks types at
compile time.

> I have stated why I consider type inference a bad thing.

Yes, but I think you're mistaken. You stated that type inference doesn't
work all the time. You still haven't explained what you mean by that. As
I said before, type inference seems to work just fine in various ML
dialtects.

> I don't think that type inference rules can be described that simple.

I guess type inference is indeed somewhat more complex than checking
explicitly specified types. However, I wonder how much that would really
matter, on top of everything that Seed7 already does. And not having to
specify types saves your users work. So it might still be worth
implementing. The KISS principle is fine and well, but it doesn't mean
you can add absolutely no helpful features.

> > > The redundancy you get from type declarations and mandatory type
> > > checks makes your program safer.
> >
> > I don't see that. A type inferencer could try to infer a safe typing for
> > your program, and reject it if no such typing were found. This would be
> > every bit as safe as type declarations.
>
> Have you ever written such a type inferencer?

As a matter of fact, no. But other people have done just that. See
Haskell, Ocaml, Standard ML, ...

> > I don't see that it makes the language more complicated for the human
> > reader. As a human, I care about what the program does to my values, not
> > necessarily what types they are.
>
> When the types are wrong you could get garbage when your type system
> thinks that it makes sense.

Yes, but I am not asking you to adopt a type system that thinks the
types make sense when they are wrong.

> > But then, I mostly program ...
>
> Just a questions: What was the biggest program you had to deal with.
> All this wonderful 'do what I mean' concepts work for small programs.
> But when a 'do what I mean' concept fails you are lost in a jungle.

I am not talking about "do what I mean". I'm personally not a fan of the
computer trying to guess at what I meant. But type inference is not
that. Type inference is about determining what types would be valid for
the given program, and rejecting the program if no such types are found.
If you want to make the types explicit, you could even write a program
that automatically inserted the inferred types for you. You get all the
benefits of type annotations, but without having to write them all.

> Think of big projects with many people working on the same
> program for years. What languages are used for such programs.

Err...all manner of languages. Large projects have been written in Perl
and PHP and Common Lisp, none of which require type annotations, or
check them. I'm not saying all of these are very maintainable, but the
same is true for many large projects using Java or C.

> Think over it. Not toy or Mikey Mouse projects. A commercial or
> a big open source program. For most of this big programs
> a language with static type checking is used. You can always
> argue that most people are stupid. But maybe the people decide
> for languages with mandatory compiletime type checking for a reason.

Indeed. My hypothesis is that people choose a language mainly because of
familiarity and because it's what everybody else uses. These are
perfectly good reasons, but they don't say anything about how good the
language is.

> > > Since Seed7 is an extendable programming language which
> > > claims to allow the definition of features in a wide range:
> > > You could declare 'const' and 'var' declaration statements
> > > which use type inference (from the initial value) in Seed7.
> >
> > On the other hand, that would be going against the nature of the
> > language; the intent is for the language to have explicitly declared
> > types everywhere.
>
> You must destinguish between the basic language (without type
> inference) and what could be declared as new statements.
> The 'const' and 'var' declarations are just statements.
> Therefore new declaration statements (which take the type
> from the initialisation value) could be declared.

I'm not denying that this is the case, but I am saying it would go
against the nature of the language. The nature of the language is that
types are declared explicitly. Changing that so that types are inferred,
rather than declared, gives the language a very different feel. Just
like you _can_ write Java programs where all classes have only public
fields and no methods, and all your methods are defined as static
methods of your main class. It's possible, but it goes against the way
Java programs are normally written.

> > > > Weak typing
> > > > detects possible type errors at compile time, but gives warnings instead
> > > > of rejecting the program. Depending on your type system, your type
> > > > checker might reject some programs that would never fail to work if they
> > > > were allowed to run.
> > >
> > > This sounds strange because: When a good type system rejects a program
> > > it would fail (crash or produce garbage) at some point (which might be
> > > called just once every 100000 Years).
> >
> > Not all type systems are that good.
>
> Well a type system with mandatory compiletime type checks is that good.

Sorry, but that makes no sense. Having mandatory compile time checks
does _not_ imply that you don't reject working programs in the type
checker. Actually, compile time checks are a necessary condition for
rejecting programs based on typing.

> > > At least in Seed7 the type system only 'rejects' buggy programs.
> >
> > Buggy by what definition? By the definition that it won't work with
> > Seed7's type system? Or buggy by the definition that it couldn't work at
> > all?
>
> As I already said: I consider programs that crash as buggy.
> But more important I consider also programs that produce garbage
> as buggy.

Ok, so let's consider:

foo = 12;
print_int(foo);
foo = "lalala";
print_string(foo);

This program wouldn't crash, nor would it produce garbage. Athough foo
is used both as an integer and as a string, the program never applies an
integer operation to a string or vice versa. So it's not buggy by your
definition. Does your type checker accept it?

> > For example, a function that took, as an argument, a list containing a
> > string, then an integer, then a string, then an integer, etc. and
> > printed out the first string, a colon, a space, the first integer, a
> > newline, and so on for the second up to the last string and integer
> > would be rejected by many static type systems. Arguably, it's bad style.
> > But it would work fine under a dynamic type system. Is it a correct
> > program? By what definition? Would Seed7 accept it?
>
> What you really have is an array of structs. Every struct consists of
> two elements: a string and an integer. In Seed7 it would look like:

No. That's what Seed7 _requires_ me to have, because it would reject the
program I originally had in mind - even though it's perfectly safe to
execute.

> > And what about your interfaces? Do you have to declare them or does the
> > compiler figure out what methods need to be supported?
>
> As I prefere explicit things and don't like guesswork: You have to
> declare an interface.

Ok. When can I declare these interfaces? Do I have to list all
implemented interfaces at type definition time (as in Java), or can I
define interfaces whenever I want?

Regards,

Bob

---
The following statement is not true. The previous statement is true.
t***@gmx.at
2006-07-18 16:30:16 UTC
Permalink
Robbert Haarman wrote:
> On Mon, Jul 17, 2006 at 01:16:24PM -0700, ***@gmx.at wrote:
> > > > The redundancy you get from type declarations and mandatory type
> > > > checks makes your program safer.
> > >
> > > I don't see that. A type inferencer could try to infer a safe typing for
> > > your program, and reject it if no such typing were found. This would be
> > > every bit as safe as type declarations.
> >
> > Have you ever written such a type inferencer?
>
> As a matter of fact, no. But other people have done just that. See
> Haskell, Ocaml, Standard ML, ...

To use mandatory compiletime type checking is a design decision.
To use explicit types and no type inference is also a design decision.
The analyze phase of the interpreter is optimized for performance.
A type inferencer would have to go forward and backward the whole
program which would slow the analyze phase down.

> > > > > Weak typing
> > > > > detects possible type errors at compile time, but gives warnings instead
> > > > > of rejecting the program. Depending on your type system, your type
> > > > > checker might reject some programs that would never fail to work if they
> > > > > were allowed to run.
> > > >
> > > > This sounds strange because: When a good type system rejects a program
> > > > it would fail (crash or produce garbage) at some point (which might be
> > > > called just once every 100000 Years).
> > >
> > > Not all type systems are that good.
> >
> > Well a type system with mandatory compiletime type checks is that good.
>
> Sorry, but that makes no sense. Having mandatory compile time checks
> does _not_ imply that you don't reject working programs in the type
> checker. Actually, compile time checks are a necessary condition for
> rejecting programs based on typing.

Don't fear that working programs can be rejected. Usually
a typing error is very easy to fix. It is better to be
on the save side (never accept buggy programs).

> > > > At least in Seed7 the type system only 'rejects' buggy programs.
> > >
> > > Buggy by what definition? By the definition that it won't work with
> > > Seed7's type system? Or buggy by the definition that it couldn't work at
> > > all?
> >
> > As I already said: I consider programs that crash as buggy.
> > But more important I consider also programs that produce garbage
> > as buggy.
>
> Ok, so let's consider:
>
> foo = 12;
> print_int(foo);
> foo = "lalala";
> print_string(foo);

So Seed7 would reject this program. It is hard to rewrite
this program such that a mandatory compile time type check
accepts it. :-)

> > > For example, a function that took, as an argument, a list containing a
> > > string, then an integer, then a string, then an integer, etc. and
> > > printed out the first string, a colon, a space, the first integer, a
> > > newline, and so on for the second up to the last string and integer
> > > would be rejected by many static type systems. Arguably, it's bad style.
> > > But it would work fine under a dynamic type system. Is it a correct
> > > program? By what definition? Would Seed7 accept it?
> >
> > What you really have is an array of structs. Every struct consists of
> > two elements: a string and an integer. In Seed7 it would look like:
>
> No. That's what Seed7 _requires_ me to have, because it would reject the
> program I originally had in mind - even though it's perfectly safe to
> execute.

I looked at your description and made a design. Your describe an
array of structs but then you insist that it is just a list of
elements. You can view any data as stream of bytes. But in most
cases it makes sense to structure your data. This is what I did.

> > > And what about your interfaces? Do you have to declare them or does the
> > > compiler figure out what methods need to be supported?
> >
> > As I prefere explicit things and don't like guesswork: You have to
> > declare an interface.
>
> Ok. When can I declare these interfaces? Do I have to list all
> implemented interfaces at type definition time (as in Java), or can I
> define interfaces whenever I want?

It is possible to define interfaces whenever you want.

And Now for Something Completely Different.

The following template function declares 'for' statements:

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

const proc: for (inout aType: variable) range
(in aType: low) to (in aType: high) do
(in proc: statements)
end for is func
begin
variable := low;
if variable <= high then
statements;
while variable < high do
incr(variable);
statements;
end while;
end if;
end func;

end func;

FOR_DECLS(char);
FOR_DECLS(boolean);

The body of the 'FOR_DECLS' function contains a declaration of
the 'for' statement for the type aType. Calling 'FOR_DECLS'
with char and boolean as parameter creates corresponding
declarations of 'for' statements. The example above is a
simplified part of the standard Seed7 library "seed7_05.s7i".

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-18 17:40:30 UTC
Permalink
On Tue, Jul 18, 2006 at 09:30:16AM -0700, ***@gmx.at wrote:
> Robbert Haarman wrote:
> > On Mon, Jul 17, 2006 at 01:16:24PM -0700, ***@gmx.at wrote:
> > > > > The redundancy you get from type declarations and mandatory type
> > > > > checks makes your program safer.
> > > >
> > > > I don't see that. A type inferencer could try to infer a safe typing for
> > > > your program, and reject it if no such typing were found. This would be
> > > > every bit as safe as type declarations.
> > >
> > > Have you ever written such a type inferencer?
> >
> > As a matter of fact, no. But other people have done just that. See
> > Haskell, Ocaml, Standard ML, ...
>
> To use mandatory compiletime type checking is a design decision.
> To use explicit types and no type inference is also a design decision.
> The analyze phase of the interpreter is optimized for performance.
> A type inferencer would have to go forward and backward the whole
> program which would slow the analyze phase down.

Well, it's not that bad in practice. Again, see Ocaml. Besides, this
isn't what we were discussing; you claimed that explicit types make your
programs safer, and I disputed that claim. See above.

> > > > > This sounds strange because: When a good type system rejects a program
> > > > > it would fail (crash or produce garbage) at some point (which might be
> > > > > called just once every 100000 Years).
> > > >
> > > > Not all type systems are that good.
> > >
> > > Well a type system with mandatory compiletime type checks is that good.
> >
> > Sorry, but that makes no sense. Having mandatory compile time checks
> > does _not_ imply that you don't reject working programs in the type
> > checker. Actually, compile time checks are a necessary condition for
> > rejecting programs based on typing.
>
> Don't fear that working programs can be rejected. Usually
> a typing error is very easy to fix. It is better to be
> on the save side (never accept buggy programs).

Ok, well, as I've said before, I think your choices are alright; I'm
just finding fault with your reasoning. The type checkers employed by
most statically typed languages are both an underapproximation and an
overapproximation of valid programs; they reject programs that would
have worked fine had no type checking been performed (as in some of the
examples I've provided) , and they accept programs that don't do what
they should do (e.g. if you add instead of subtracting, the types would
still be the same, but the results would be wrong). You claimed your
type checker would reject programs only if they would crash or produce
garbage; I disputed that claim. I'm not saying your type checker isn't
any good, I'm saying you should be realistic about exactly how good it
is.

> > > > > At least in Seed7 the type system only 'rejects' buggy programs.
> > > >
> > > > Buggy by what definition? By the definition that it won't work with
> > > > Seed7's type system? Or buggy by the definition that it couldn't work at
> > > > all?
> > >
> > > As I already said: I consider programs that crash as buggy.
> > > But more important I consider also programs that produce garbage
> > > as buggy.
> >
> > Ok, so let's consider:
> >
> > foo = 12;
> > print_int(foo);
> > foo = "lalala";
> > print_string(foo);
>
> So Seed7 would reject this program. It is hard to rewrite
> this program such that a mandatory compile time type check
> accepts it. :-)

My point exactly. Seed7 rejects the program, even though it doesn't
crash or produce garbage, and thus, by your definition, isn't buggy. Not
that rejecting this program is a Bad Thing, but it means your type
checker isn't as great as you said it was.

> > > > For example, a function that took, as an argument, a list containing a
> > > > string, then an integer, then a string, then an integer, etc. and
> > > > printed out the first string, a colon, a space, the first integer, a
> > > > newline, and so on for the second up to the last string and integer
> > > > would be rejected by many static type systems. Arguably, it's bad style.
> > > > But it would work fine under a dynamic type system. Is it a correct
> > > > program? By what definition? Would Seed7 accept it?
> > >
> > > What you really have is an array of structs. Every struct consists of
> > > two elements: a string and an integer. In Seed7 it would look like:
> >
> > No. That's what Seed7 _requires_ me to have, because it would reject the
> > program I originally had in mind - even though it's perfectly safe to
> > execute.
>
> I looked at your description and made a design. Your describe an
> array of structs but then you insist that it is just a list of
> elements. You can view any data as stream of bytes. But in most
> cases it makes sense to structure your data. This is what I did.

But you missed the point. The point is not that my program is badly
designed the way I specified it, the point is that Seed7 rejects it,
even though it doesn't crash or produce garbage. Again, this is not a
Bad Thing, but you said that Seed7 doesn't do that.

> It is possible to define interfaces whenever you want.

Great!

> And Now for Something Completely Different.
>
> The following template function declares 'for' statements:
>
> const proc: FOR_DECLS (in type: aType) is func
> begin
>
> const proc: for (inout aType: variable) range
> (in aType: low) to (in aType: high) do
> (in proc: statements)
> end for is func
> begin
> variable := low;
> if variable <= high then
> statements;
> while variable < high do
> incr(variable);
> statements;
> end while;
> end if;
> end func;
>
> end func;

Reading this, and knowing Common Lisp, I have to wonder:

What happens if, say, the code in statements referse to variable, low,
or high? So, if I write:

var integer: high is 0;
var integer: variable is 0;
for i range 0 to 10 do
high := high + i;
end for;

What will the expansion of that loop look like, and how will it behave?

Regards,

Bob

---
> Those who do not study history are doomed to repeat it

Yes, and those who do study history are doomed to watch in frustration
as it is unwittingly repeated by those who do not :-)

-- jonadab on Slashdot
t***@gmx.at
2006-07-18 19:04:48 UTC
Permalink
Robbert Haarman wrote:
> On Tue, Jul 18, 2006 at 09:30:16AM -0700, ***@gmx.at wrote:
> > Robbert Haarman wrote:
> > > On Mon, Jul 17, 2006 at 01:16:24PM -0700, ***@gmx.at wrote:
> > > > > > The redundancy you get from type declarations and mandatory type
> > > > > > checks makes your program safer.
> > > > >
> > > > > I don't see that. A type inferencer could try to infer a safe typing for
> > > > > your program, and reject it if no such typing were found. This would be
> > > > > every bit as safe as type declarations.
> > > >
> > > > Have you ever written such a type inferencer?
> > >
> > > As a matter of fact, no. But other people have done just that. See
> > > Haskell, Ocaml, Standard ML, ...
> >
> > To use mandatory compiletime type checking is a design decision.
> > To use explicit types and no type inference is also a design decision.
> > The analyze phase of the interpreter is optimized for performance.
> > A type inferencer would have to go forward and backward the whole
> > program which would slow the analyze phase down.
>
> Well, it's not that bad in practice. Again, see Ocaml. Besides, this
> isn't what we were discussing; you claimed that explicit types make your
> programs safer, and I disputed that claim. See above.

The additional safety comes from the redundancy. For example:
The Seed7 literals for integers, floats and strings are different.
For example 1.0 and 3.1415 are float literals, while 1 and 31415
are integer literals and "1" and "3.1415" are string literals.
A program fragment like:

var integer: num is 0;

const proc: setZero (inOut integer: i) is func
begin
i := "0.0";
end func;

...
setZero(num);
write(num);
...

would be rejected, while a program fragment like

var: num; # Initialisation ommited for demonstation purposes

const proc: setZero (inOut: i) is func
begin
i := "0,0";
end func;

...
setZero(num);
write(num);
...

would (with a type inferencer) assume that i is of type string.
When there is no RTTI, to detect this error at runtime, the second
program could produce garbage.

> > > > > > This sounds strange because: When a good type system rejects a program
> > > > > > it would fail (crash or produce garbage) at some point (which might be
> > > > > > called just once every 100000 Years).
> > > > >
> > > > > Not all type systems are that good.
> > > >
> > > > Well a type system with mandatory compiletime type checks is that good.
> > >
> > > Sorry, but that makes no sense. Having mandatory compile time checks
> > > does _not_ imply that you don't reject working programs in the type
> > > checker. Actually, compile time checks are a necessary condition for
> > > rejecting programs based on typing.
> >
> > Don't fear that working programs can be rejected. Usually
> > a typing error is very easy to fix. It is better to be
> > on the save side (never accept buggy programs).
>
> Ok, well, as I've said before, I think your choices are alright; I'm
> just finding fault with your reasoning. The type checkers employed by
> most statically typed languages are both an underapproximation and an
> overapproximation of valid programs; they reject programs that would
> have worked fine had no type checking been performed (as in some of the
> examples I've provided) , and they accept programs that don't do what
> they should do (e.g. if you add instead of subtracting, the types would
> still be the same, but the results would be wrong). You claimed your
> type checker would reject programs only if they would crash or produce
> garbage; I disputed that claim. I'm not saying your type checker isn't
> any good, I'm saying you should be realistic about exactly how good it
> is.

The Seed7 type system does not catch all buggy programs.
Seed7 is sooo good, it even allows you to write buggy programs. :-)
Seed7 could be compiled to C. There is no RTTI in C, this is
another reason to have a mandatory compile time type check.
OTOH Seed7 has types which carry a RTTI. This types are used
for OO programming.

> > > > > > At least in Seed7 the type system only 'rejects' buggy programs.
> > > > >
> > > > > Buggy by what definition? By the definition that it won't work with
> > > > > Seed7's type system? Or buggy by the definition that it couldn't work at
> > > > > all?
> > > >
> > > > As I already said: I consider programs that crash as buggy.
> > > > But more important I consider also programs that produce garbage
> > > > as buggy.
> > >
> > > Ok, so let's consider:
> > >
> > > foo = 12;
> > > print_int(foo);
> > > foo = "lalala";
> > > print_string(foo);
> >
> > So Seed7 would reject this program. It is hard to rewrite
> > this program such that a mandatory compile time type check
> > accepts it. :-)
>
> My point exactly. Seed7 rejects the program, even though it doesn't
> crash or produce garbage, and thus, by your definition, isn't buggy. Not
> that rejecting this program is a Bad Thing, but it means your type
> checker isn't as great as you said it was.

I think that rejecting such programs as above is not a big loss.
In general: Normally it is bad program design to use one variable
for different purposes (even if the purposes have the same type).

> > And Now for Something Completely Different.
> >
> > The following template function declares 'for' statements:
> >
> > const proc: FOR_DECLS (in type: aType) is func
> > begin
> >
> > const proc: for (inout aType: variable) range
> > (in aType: low) to (in aType: high) do
> > (in proc: statements)
> > end for is func
> > begin
> > variable := low;
> > if variable <= high then
> > statements;
> > while variable < high do
> > incr(variable);
> > statements;
> > end while;
> > end if;
> > end func;
> >
> > end func;
>
> Reading this, and knowing Common Lisp, I have to wonder:
>
> What happens if, say, the code in statements referse to variable, low,
> or high? So, if I write:
>
> var integer: high is 0;
> var integer: variable is 0;
> for i range 0 to 10 do
> high := high + i;
> end for;
>
> What will the expansion of that loop look like, and how will it behave?

I turned your example into a program which i wrote in the file
tst22.sd7:

-----------------------------------------------------------------
$ include "seed7_05.s7i";

$ syntax expr: .myFor.().range.().to.().do.().end.for is -> 25;

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

const proc: myFor (inout aType: variable) range
(in aType: low) to (in aType: high) do
(in proc: statements)
end for is func
begin
variable := low;
if variable <= high then
statements;
while variable < high do
incr(variable);
statements;
end while;
end if;
end func;

end func;

MY_FOR_DECL(integer);

const proc: main is func
local
var integer: i is 0;
var integer: high is 0;
var integer: variable is 0;
begin
myFor i range 0 to 10 do
high := high + i;
end for;
writeln(high);
end func;
-----------------------------------------------------------------

Then I started the hi interpreter:

***@penguin:~/seed7_5/prg$ ./hi tst22
HI INTERPRETER Version 4.5.934 Copyright (c) 1990-2006 Thomas Mertes
252 syntax.s7i
3013 seed7_05.s7i
37 tst22.sd7
3302 lines total
30018 lines per second
1402312 bytes
55
***@penguin:~/seed7_5/prg$

You see: It just works

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Robbert Haarman
2006-07-18 19:27:21 UTC
Permalink
On Tue, Jul 18, 2006 at 12:04:48PM -0700, ***@gmx.at wrote:
> Robbert Haarman wrote:
> >
> > Well, it's not that bad in practice. Again, see Ocaml. Besides, this
> > isn't what we were discussing; you claimed that explicit types make your
> > programs safer, and I disputed that claim. See above.
>
> The additional safety comes from the redundancy. For example:
> The Seed7 literals for integers, floats and strings are different.
> For example 1.0 and 3.1415 are float literals, while 1 and 31415
> are integer literals and "1" and "3.1415" are string literals.
> A program fragment like:
>
> var integer: num is 0;
>
> const proc: setZero (inOut integer: i) is func
> begin
> i := "0.0";
> end func;
>
> ...
> setZero(num);
> write(num);
> ...
>
> would be rejected, while a program fragment like
>
> var: num; # Initialisation ommited for demonstation purposes
>
> const proc: setZero (inOut: i) is func
> begin
> i := "0,0";
> end func;
>
> ...
> setZero(num);
> write(num);
> ...
>
> would (with a type inferencer) assume that i is of type string.
> When there is no RTTI, to detect this error at runtime, the second
> program could produce garbage.

No, because any place where num is used as anything not compatible with
string, this would be detected at compile time. If there isn't such a
place, the program will run fine.

> > > The following template function declares 'for' statements:
> > >
> > > const proc: FOR_DECLS (in type: aType) is func
> > > begin
> > >
> > > const proc: for (inout aType: variable) range
> > > (in aType: low) to (in aType: high) do
> > > (in proc: statements)
> > > end for is func
> > > begin
> > > variable := low;
> > > if variable <= high then
> > > statements;
> > > while variable < high do
> > > incr(variable);
> > > statements;
> > > end while;
> > > end if;
> > > end func;
> > >
> > > end func;
> >
> > Reading this, and knowing Common Lisp, I have to wonder:
> >
> > What happens if, say, the code in statements referse to variable, low,
> > or high? So, if I write:
> >
> > var integer: high is 0;
> > var integer: variable is 0;
> > for i range 0 to 10 do
> > high := high + i;
> > end for;
> >
> > What will the expansion of that loop look like, and how will it behave?
>
> I turned your example into a program which i wrote in the file
> tst22.sd7:
>
> -----------------------------------------------------------------
> $ include "seed7_05.s7i";
>
> $ syntax expr: .myFor.().range.().to.().do.().end.for is -> 25;
>
> const proc: MY_FOR_DECL (in type: aType) is func
> begin
>
> const proc: myFor (inout aType: variable) range
> (in aType: low) to (in aType: high) do
> (in proc: statements)
> end for is func
> begin
> variable := low;
> if variable <= high then
> statements;
> while variable < high do
> incr(variable);
> statements;
> end while;
> end if;
> end func;
>
> end func;
>
> MY_FOR_DECL(integer);
>
> const proc: main is func
> local
> var integer: i is 0;
> var integer: high is 0;
> var integer: variable is 0;
> begin
> myFor i range 0 to 10 do
> high := high + i;
> end for;
> writeln(high);
> end func;
> -----------------------------------------------------------------
>
> Then I started the hi interpreter:
>
> ***@penguin:~/seed7_5/prg$ ./hi tst22
> HI INTERPRETER Version 4.5.934 Copyright (c) 1990-2006 Thomas Mertes
> 252 syntax.s7i
> 3013 seed7_05.s7i
> 37 tst22.sd7
> 3302 lines total
> 30018 lines per second
> 1402312 bytes
> 55
> ***@penguin:~/seed7_5/prg$
>
> You see: It just works

Alright, good job! :-) So how does the compiler prevent the two
variables named high from clashing? What if you _want_ them to clash?

Regards,

Bob

---
That that is is that that is not not.
t***@gmx.at
2006-07-18 20:26:42 UTC
Permalink
Robbert Haarman wrote:
> On Tue, Jul 18, 2006 at 12:04:48PM -0700, ***@gmx.at wrote:
> > Robbert Haarman wrote:
> > >
> > > Well, it's not that bad in practice. Again, see Ocaml. Besides, this
> > > isn't what we were discussing; you claimed that explicit types make your
> > > programs safer, and I disputed that claim. See above.
> >
> > The additional safety comes from the redundancy. For example:
> > The Seed7 literals for integers, floats and strings are different.
> > For example 1.0 and 3.1415 are float literals, while 1 and 31415
> > are integer literals and "1" and "3.1415" are string literals.
> > A program fragment like:
> >
> > var integer: num is 0;
> >
> > const proc: setZero (inOut integer: i) is func
> > begin
> > i := "0.0";
> > end func;
> >
> > ...
> > setZero(num);
> > write(num);
> > ...
> >
> > would be rejected, while a program fragment like
> >
> > var: num; # Initialisation ommited for demonstation purposes
> >
> > const proc: setZero (inOut: i) is func
> > begin
> > i := "0,0";
> > end func;
> >
> > ...
> > setZero(num);
> > write(num);
> > ...
> >
> > would (with a type inferencer) assume that i is of type string.
> > When there is no RTTI, to detect this error at runtime, the second
> > program could produce garbage.
>
> No, because any place where num is used as anything not compatible with
> string, this would be detected at compile time. If there isn't such a
> place, the program will run fine.

I assumed that the write function is overloaded to work for
integers and strings. Such that the program fragment:

var string: num is "";

const proc: setZero (inOut string: i) is func
begin
i := "0.0";
end func;

...
setZero(num);
write(num);
...

would also be a legal program. In the inferencer example, the
type of the parameter 'i' can only be determined from the
assignment i := "0.0"; (in this case from a string). Therefore
the inferencer would assume that setZero has a string parameter.
There is no place "where num is used as anything not compatible
with string". Or does the inferencer need more then one hint?

> > > > The following template function declares 'for' statements:
> > > >
> > > > const proc: FOR_DECLS (in type: aType) is func
> > > > begin
> > > >
> > > > const proc: for (inout aType: variable) range
> > > > (in aType: low) to (in aType: high) do
> > > > (in proc: statements)
> > > > end for is func
> > > > begin
> > > > variable := low;
> > > > if variable <= high then
> > > > statements;
> > > > while variable < high do
> > > > incr(variable);
> > > > statements;
> > > > end while;
> > > > end if;
> > > > end func;
> > > >
> > > > end func;
> > >
> > > Reading this, and knowing Common Lisp, I have to wonder:
> > >
> > > What happens if, say, the code in statements referse to variable, low,
> > > or high? So, if I write:
> > >
> > > var integer: high is 0;
> > > var integer: variable is 0;
> > > for i range 0 to 10 do
> > > high := high + i;
> > > end for;
> > >
> > > What will the expansion of that loop look like, and how will it behave?
> >
> > I turned your example into a program which i wrote in the file
> > tst22.sd7:
> >
> > -----------------------------------------------------------------
> > $ include "seed7_05.s7i";
> >
> > $ syntax expr: .myFor.().range.().to.().do.().end.for is -> 25;
> >
> > const proc: MY_FOR_DECL (in type: aType) is func
> > begin
> >
> > const proc: myFor (inout aType: variable) range
> > (in aType: low) to (in aType: high) do
> > (in proc: statements)
> > end for is func
> > begin
> > variable := low;
> > if variable <= high then
> > statements;
> > while variable < high do
> > incr(variable);
> > statements;
> > end while;
> > end if;
> > end func;
> >
> > end func;
> >
> > MY_FOR_DECL(integer);
> >
> > const proc: main is func
> > local
> > var integer: i is 0;
> > var integer: high is 0;
> > var integer: variable is 0;
> > begin
> > myFor i range 0 to 10 do
> > high := high + i;
> > end for;
> > writeln(high);
> > end func;
> > -----------------------------------------------------------------
> >
> > Then I started the hi interpreter:
> >
> > ***@penguin:~/seed7_5/prg$ ./hi tst22
> > HI INTERPRETER Version 4.5.934 Copyright (c) 1990-2006 Thomas Mertes
> > 252 syntax.s7i
> > 3013 seed7_05.s7i
> > 37 tst22.sd7
> > 3302 lines total
> > 30018 lines per second
> > 1402312 bytes
> > 55
> > ***@penguin:~/seed7_5/prg$
> >
> > You see: It just works
>
> Alright, good job! :-) So how does the compiler prevent the two
> variables named high from clashing? What if you _want_ them to clash?

Parameters like local variables belong to the local namespace of the
function. Therefore the two variables named 'high' are distinct
(as the two variables named 'variable'). One 'high' is local to 'main'
while the other is local to the 'integer' variant of 'myFor'.
If you would declare a 'myFor' loop for 'char' with:

MY_FOR_DECL(char);

you would have a third 'high' variable local to the 'char' variant
of 'myFor'. Instead of declaring the 'myFor' loop for chars with
'MY_FOR_DECL' you could also declare it this way:

const proc: myFor (inout char: variable) range
(in char: low) to (in char: high) do
(in proc: statements)
end for is func
begin
variable := low;
if variable <= high then
statements;
while variable < high do
incr(variable);
statements;
end while;
end if;
end func;

> What if you _want_ them to clash?

I am not sure what you mean with this.
In the declaration of the 'myFor' statement you could use global
variables instead of the local parameters. In that case you
would see strange effects if you modify one of these variables
(in the statements between 'do' and 'end') when calling the loop.
You see: Seed7 allows you to shoot yoursef in the foot. :-)

Greetings Thomas Mertes

Seed7 Homepage: http://seed7.sourceforge.net
Project page: http://sourceforge.net/projects/seed7
Gerry Quinn
2006-07-17 11:16:15 UTC
Permalink
In article <***@morgenes.shire.sytes.net>,
***@inglorion.net says...
> On Mon, Jul 17, 2006 at 01:35:43AM -0700, ***@gmx.at wrote:
> > Rob Thorpe schrieb:
> > > ***@gmx.at wrote:
> > > > goose schrieb:
> > > > > ***@gmx.at wrote:
> > > > > > AFAIK there is no concept of infix operators (with priority
> > > > > > and assoziativity) in Lisp.
> > > > >
> > > > > There isn't; this is generally considered to be a /good/
> > > > > thing, not a bad thing.
> > > >
> > > > This advocacy discussion leads nowhere.
> > >
> > > I don't know, I've learnt a lot about the rotation of the earth.
> >
> > I was refering to advocacy discussions like:
> >
> > - Are infix operators (with priority and assoziativity) a
> > good thing, or should everything be based on functions.
> >
> > - Is mandatory compiletime type checking a good thing, or
> > is it better when there are only runtime type checks.
>
> I think it can be very useful to discuss these issues, provided that
> people really _think_ about what the others are saying, rather than
> just try to convince the rest of the world. Many people assume that
> there is One True Way to do these things, often because they've only
> heard one side of the story. I firmly believe that there are advantages
> to both approaches to the above issues, and discussing about them can
> open people's eyes.
>
> > > Rather than speaking of convincing people, it would be more useful if
> > > you told us the reasons for your decisions.
> >
> > I don't think it is possible to convince 'hard core' fans of any
> > language or paradigma.
>
> But you don't have to. You should be content when you've given
> reasonable people something to think about.
>
> > I can try to give some of the reasoning behind my design decisions:
> >
> > - Infix operators have a long tradition in mathematics
> > and related areas. The mainstream programming languages
> > use infix operators also. Since Seed7 wants to be near the
> > mainstream it uses infix operators also.
>
> Sounds perfectly good to me.
>
> > - Tiny programs and scripts can be written faster when you
> > omit declarations (with types). Although Seed7 is intended
> > to be used for scripts, it is also intended to be used for
> > big programs, therefore rules of professional program development
> > are used. There are studies that errors are more expensive
> > when they are found later in the software development process.
> > Therefore it is important to find errors as early as possible.
> > Mandatory compiletime type checking is a method to find
> > a certain class of errors earlier.
>
> This sounds like you're ignoring the possibilities of type inference and
> weak typing. Type inference lets the compiler figure out types, without
> you having specified them, thus allowing compile-time type checking and
> optimization, without any extra effort from the programmer. Weak typing
> detects possible type errors at compile time, but gives warnings instead
> of rejecting the program. Depending on your type system, your type
> checker might reject some programs that would never fail to work if they
> were allowed to run. If that's the case, weak typing offers you to go
> ahead and run the program anyway (as in dynamic typing), while it still
> offers you the opportunity to catch errors at compile time (as in static
> typing).
>
> Now, let me make one thing perfectly clear: I'm not trying to convince
> you that you _should_ use type inference and weak typing. I'm just
> pointing out the possibilities, and their advantages. It's your
> language; you decide.

It seems to me that he has decided, and that the above commentary
ignores the fact that weak typing will still miss some errors that
static typing will find.

It would be easy to modify C to use 'weak typing'. Just make it
compile anyway if there is a type mismatch. On typical PC hardware,
every type boils down to 'data at address' anyway, no? So all types
are interconvertible.

Would this be good?

- Gerry Quinn
Robbert Haarman
2006-07-17 17:19:27 UTC
Permalink
On Mon, Jul 17, 2006 at 12:16:15PM +0100, Gerry Quinn wrote:
>
> It seems to me that he has decided, and that the above commentary
> ignores the fact that weak typing will still miss some errors that
> static typing will find.

I don't think that's true. Given the same program, static typing and
weak typing can find exactly the same errors, using the same algorithm.
The only difference is that weak typing would allow you to continue
anyway (and shoot yourself in the foot), whereas strong typing would not
(possibly rejecting an otherwise working program).

> It would be easy to modify C to use 'weak typing'. Just make it
> compile anyway if there is a type mismatch. On typical PC hardware,
> every type boils down to 'data at address' anyway, no? So all types
> are interconvertible.
>
> Would this be good?

At least you would get rid of all of those casts. That is, until you
wanted to get rid of the warnings. But retrofitting weak typing on an
overtly typed language is different from designing a new language with
weak typing. In combination with inferred types, for example, the
warnings that weak typing gives you convey helpful information: the
compiler couldn't infer a valid typing for some part of your program.
This means that either the compiler isn't smart enough, or you made a
mistake. Either way, you'll want to fix things, if only to get rid of
that pesky warning. If you don't get any warnings, valid types were
inferred for your program, and it's safe to run (as far as types go, of
course).

Regards,

Bob

---
The one thing that is more frustrating than things breaking
is things breaking without you having done anything.
Gerry Quinn
2006-07-18 10:15:28 UTC
Permalink
In article <***@morgenes.shire.sytes.net>,
***@inglorion.net says...
> On Mon, Jul 17, 2006 at 12:16:15PM +0100, Gerry Quinn wrote:
> >
> > It seems to me that he has decided, and that the above commentary
> > ignores the fact that weak typing will still miss some errors that
> > static typing will find.
>
> I don't think that's true. Given the same program, static typing and
> weak typing can find exactly the same errors, using the same algorithm.
> The only difference is that weak typing would allow you to continue
> anyway (and shoot yourself in the foot), whereas strong typing would not
> (possibly rejecting an otherwise working program).

Weak typing can't find errors where type A is used incorrectly as type
B, but the incorrect use is formally valid. These are not necessarily
language errors (or maybe they are language errors when the data takes
certain values), but they are program errors.

Unsigned and signed ints are seamlessly interconverted by C. A
language that prevented this would give error messages that would annoy
people used to C, but would also find some errors that C would not.

> > It would be easy to modify C to use 'weak typing'. Just make it
> > compile anyway if there is a type mismatch. On typical PC hardware,
> > every type boils down to 'data at address' anyway, no? So all types
> > are interconvertible.
> >
> > Would this be good?
>
> At least you would get rid of all of those casts. That is, until you
> wanted to get rid of the warnings. But retrofitting weak typing on an
> overtly typed language is different from designing a new language with
> weak typing. In combination with inferred types, for example, the
> warnings that weak typing gives you convey helpful information: the
> compiler couldn't infer a valid typing for some part of your program.
> This means that either the compiler isn't smart enough, or you made a
> mistake. Either way, you'll want to fix things, if only to get rid of
> that pesky warning. If you don't get any warnings, valid types were
> inferred for your program, and it's safe to run (as far as types go, of
> course).

But I don't think 'as far as types go' is equivalent to 'as far as
static typing protects'.

- Gerry Quinn
Robbert Haarman
2006-07-18 14:03:32 UTC
Permalink
On Tue, Jul 18, 2006 at 11:15:28AM +0100, Gerry Quinn wrote:
>
> Weak typing can't find errors where type A is used incorrectly as type
> B,

Why not?

> but the incorrect use is formally valid.

How can it be "formally valid" and "incorrect" at the same time? How do
you mean?

> These are not necessarily language errors (or maybe they are language
> errors when the data takes certain values), but they are program
> errors.

I agree that weak typing cannot find _all_ program errors, any more than
static typing can.

> Unsigned and signed ints are seamlessly interconverted by C. A
> language that prevented this would give error messages that would annoy
> people used to C, but would also find some errors that C would not.

It depends. C compilers can and do give warnings when possibly
incompatible int types are intermixed. Some compilers (at least gcc) can
also convert these warnings into errors. But weak typing can apply to
more than just int types: anything that results in a type error under
static typing would result in a warning under weak typing.

> But I don't think 'as far as types go' is equivalent to 'as far as
> static typing protects'.

What else does static typing check, besides types?

Regards,

Bob

---
I can't remember the last time I forgot something.
Gerry Quinn
2006-07-19 09:42:18 UTC
Permalink
In article <***@morgenes.shire.sytes.net>,
***@inglorion.net says...
> On Tue, Jul 18, 2006 at 11:15:28AM +0100, Gerry Quinn wrote:
> >
> > Weak typing can't find errors where type A is used incorrectly as type
> > B,
>
> Why not?
>
> > but the incorrect use is formally valid.
>
> How can it be "formally valid" and "incorrect" at the same time? How do
> you mean?

Rob Thorpe has answered better than I could. One of them is more
likely to conform to the specifications in the brain of the programmer.

> > These are not necessarily language errors (or maybe they are language
> > errors when the data takes certain values), but they are program
> > errors.
>
> I agree that weak typing cannot find _all_ program errors, any more than
> static typing can.

But with static typing, the program is specified more accurately.
Therefore it will find errors that violate specifications that are
unstated under weak typing.

So maybe the question is, how much specification is good? The C stable
of languages certainly don't go the whole way with specification, given
the automatic promotion of the various int types. Doing away with that
might be an interesting experiment. It would certainly find *some*
bugs of types that we've all created from time to time.

> > Unsigned and signed ints are seamlessly interconverted by C. A
> > language that prevented this would give error messages that would annoy
> > people used to C, but would also find some errors that C would not.
>
> It depends. C compilers can and do give warnings when possibly
> incompatible int types are intermixed. Some compilers (at least gcc) can
> also convert these warnings into errors. But weak typing can apply to
> more than just int types: anything that results in a type error under
> static typing would result in a warning under weak typing.

It's easier to specify a type than check every warning. If the
argument is only about errors versus warnings, weak typing has already
lost IMO.

Sure, C/C++ programmers get used to having to live with a few warnings,
but these should be exceptional cases rather than a normal constituent
of released software.

> > But I don't think 'as far as types go' is equivalent to 'as far as
> > static typing protects'.
>
> What else does static typing check, besides types?

Nothing - but its types go further.

If I go to dinner with Bill Gates, we can each order as much as our
wallets will bear, but that doen't meant he can't order more than me!

- Gerry Quinn
Rob Thorpe
2006-07-17 21:20:32 UTC
Permalink
***@gmx.at wrote:
> Rob Thorpe schrieb:
> > ***@gmx.at wrote:
> > > goose schrieb:
> > > > ***@gmx.at wrote:
> > > > > AFAIK there is no concept of infix operators (with priority
> > > > > and assoziativity) in Lisp.
> > > >
> > > > There isn't; this is generally considered to be a /good/
> > > > thing, not a bad thing.
> > >
> > > This advocacy discussion leads nowhere.
> >
> > I don't know, I've learnt a lot about the rotation of the earth.
>
> I was refering to advocacy discussions like:
>
> - Are infix operators (with priority and assoziativity) a
> good thing, or should everything be based on functions.
>
> - Is mandatory compiletime type checking a good thing, or
> is it better when there are only runtime type checks.
>
> > Rather than speaking of convincing people, it would be more useful if
> > you told us the reasons for your decisions.
>
> I don't think it is possible to convince 'hard core' fans of any
> language or paradigma. I can try to give some of the reasoning
> behind my design decisions:

I'm not sure its impossible, but I agree that it's difficult. If
advocates of static typing came up with convincing empirical evidence
that it is helpful for all programming then I would be convinced.

The thing to remember though is that far more people read usenet than
post. The people posting here are mainly those who have made up their
minds quite strongly, but I expect many of those listening will not
have done.
goose
2006-07-19 09:03:35 UTC
Permalink
Rob Thorpe wrote:

<snipped>
>
> The thing to remember though is that far more people read usenet than
> post.

<grin>
Also, many of those who do post frequently
dispense with the reading part as well :-)

goose,
Continue reading on narkive:
Loading...