This is ridiculous
Posted: Fri Oct 01, 2004 10:54 am
The name "newLISP" would suggest that it builds on old Lisp experience, but in fact it ignores Lisp history and uses rules which have been tried and rejected as bad ideas, like dynamic scoping by default.
"Excepting symbols and built-in primitives, each object is referenced only once in the system and is always passed by value." - This implies that a recursive function which conses an element on each iteration to a growing list, or even descends a list by iterating 'rest', has O(N^2) complexity, or worse if elements themselves are big.
This also makes impractical to create graphs of mutable objects: you can't refer to a part of it for further modification because it will be implicitly copied. IMHO this very fact makes it not a Lisp at all. Every Lisp, and in fact most modern languages, pass objects by reference and collect unreachable garbage. In every Lisp you can look at the rest/cdr/tail of a list without copying it.
"Many of newLISP's built-in functions are polymorphic in type, accepting a variety - and sometimes all - data types and thereby greatly reducing the total number of different functions and syntactic forms necessary to be learned and implemented." - Except arithmetic, where it would make the most sense. Not just the defaults are limited, but there are no arithmetic operators which do the right thing (return an exact answer when possible).
No wonder why correctly behaving arithmetic is not provided: having only fixed-range integers, without even checking for overflow, and floats, is pathetic. This set of types just can't exactly represent 1/10 nor the size of my hard drive in bytes. Is it Lisp or C?
cons which does a completely different thing depending on whether the second argument is a list is stupid. If there are improper lists, then fine - make it an error if it's not a list. But making a two-element list *except* when the second argument was a list makes absolutely no sense, because if you rely on cons making a two-element list, you will badly surprised if the second argument happens to be a list. There is no context where you really want either this or that, in all cases you statically know which behavior you want, so it makes no sense to put them both in one function. I bet that the two-element behavior of cons is not used in practice, because it's not robust.
A hash table is associated with a global variable. What?! I can't make a list of hash tables without inventing unique names for them? This applies to objects as well. Is it Lisp or Tcl?
The implementation of hash tables is interesting:
> (load "modules/hash.lsp")
true
> (HASH:make 'h)
h
> (h:put "(" 'open)
open
> (h:get ")")
open
...Huh?!
"Unless otherwise specified for a function, an index greater than N-1 returns the last element, and an index less than -N returns the first when in lists, but out of bounds indices in arrays will cause an error message." - long live the consistency. I see no purpose in returning the last element of a list when the index is too large - it will just mask programming errors.
"constant: Works exactly like set but protects the symbol from subsequent modification. A symbol set with constant can only be modified again using constant." - Funny, a constant which is not constant.
"If num is supplied, dec always returns the result as floating point even for integer input arguments." - Why?
"If the expression in exp evaluates to a string, it will be replicated int-n times in a string and returned. For any other type in exp a list of int-n of the evaluation of exp is returned." - How to make a list with N references to the given string (sorry, N copies of the string)? Again an inconsistent behavior which doesn't make sense - if you want to make a list using dup, ensure that the element is *not* a string, because you will get a different thing in this case.
A similar problem is inherent in flat. The documentation says: "To convert a list back to an array apply flat to the list". It will break if the array is supposed to contain lists as some elements. These operations which do a particular thing for almost all values, *except* when values are of a particular type, are just misdesigned.
"get-char: Gets a character from an address specified in int-address." - An address represented in 32 bits? So it will not work on 64-bit machines. What a pity. C used to almost unify pointers with integers about 30 years ago.
File handles represented as ints and I/O operations using system calls directly, with no buffering? I knew that this is C 30 years ago.
In general, I'm disgusted. There is some work in wrapping C library functions, but the core language design, number and list processing is awful. The name newLisp is misleading: it's not a Lisp and it's not modern. It tries hard to have neither garbage collection nor pointers, which implies that pointers must be simulated using unique constants which denote globally accessible structures, as if it was Tcl or ancient Fortran. It throws away the progress made in programming language design in the last 30 years.
"Excepting symbols and built-in primitives, each object is referenced only once in the system and is always passed by value." - This implies that a recursive function which conses an element on each iteration to a growing list, or even descends a list by iterating 'rest', has O(N^2) complexity, or worse if elements themselves are big.
This also makes impractical to create graphs of mutable objects: you can't refer to a part of it for further modification because it will be implicitly copied. IMHO this very fact makes it not a Lisp at all. Every Lisp, and in fact most modern languages, pass objects by reference and collect unreachable garbage. In every Lisp you can look at the rest/cdr/tail of a list without copying it.
"Many of newLISP's built-in functions are polymorphic in type, accepting a variety - and sometimes all - data types and thereby greatly reducing the total number of different functions and syntactic forms necessary to be learned and implemented." - Except arithmetic, where it would make the most sense. Not just the defaults are limited, but there are no arithmetic operators which do the right thing (return an exact answer when possible).
No wonder why correctly behaving arithmetic is not provided: having only fixed-range integers, without even checking for overflow, and floats, is pathetic. This set of types just can't exactly represent 1/10 nor the size of my hard drive in bytes. Is it Lisp or C?
cons which does a completely different thing depending on whether the second argument is a list is stupid. If there are improper lists, then fine - make it an error if it's not a list. But making a two-element list *except* when the second argument was a list makes absolutely no sense, because if you rely on cons making a two-element list, you will badly surprised if the second argument happens to be a list. There is no context where you really want either this or that, in all cases you statically know which behavior you want, so it makes no sense to put them both in one function. I bet that the two-element behavior of cons is not used in practice, because it's not robust.
A hash table is associated with a global variable. What?! I can't make a list of hash tables without inventing unique names for them? This applies to objects as well. Is it Lisp or Tcl?
The implementation of hash tables is interesting:
> (load "modules/hash.lsp")
true
> (HASH:make 'h)
h
> (h:put "(" 'open)
open
> (h:get ")")
open
...Huh?!
"Unless otherwise specified for a function, an index greater than N-1 returns the last element, and an index less than -N returns the first when in lists, but out of bounds indices in arrays will cause an error message." - long live the consistency. I see no purpose in returning the last element of a list when the index is too large - it will just mask programming errors.
"constant: Works exactly like set but protects the symbol from subsequent modification. A symbol set with constant can only be modified again using constant." - Funny, a constant which is not constant.
"If num is supplied, dec always returns the result as floating point even for integer input arguments." - Why?
"If the expression in exp evaluates to a string, it will be replicated int-n times in a string and returned. For any other type in exp a list of int-n of the evaluation of exp is returned." - How to make a list with N references to the given string (sorry, N copies of the string)? Again an inconsistent behavior which doesn't make sense - if you want to make a list using dup, ensure that the element is *not* a string, because you will get a different thing in this case.
A similar problem is inherent in flat. The documentation says: "To convert a list back to an array apply flat to the list". It will break if the array is supposed to contain lists as some elements. These operations which do a particular thing for almost all values, *except* when values are of a particular type, are just misdesigned.
"get-char: Gets a character from an address specified in int-address." - An address represented in 32 bits? So it will not work on 64-bit machines. What a pity. C used to almost unify pointers with integers about 30 years ago.
File handles represented as ints and I/O operations using system calls directly, with no buffering? I knew that this is C 30 years ago.
In general, I'm disgusted. There is some work in wrapping C library functions, but the core language design, number and list processing is awful. The name newLisp is misleading: it's not a Lisp and it's not modern. It tries hard to have neither garbage collection nor pointers, which implies that pointers must be simulated using unique constants which denote globally accessible structures, as if it was Tcl or ancient Fortran. It throws away the progress made in programming language design in the last 30 years.