Syntax Suggestions

Started by Jeremy Dunn, October 16, 2004, 10:15:54 AM

Previous topic - Next topic

Jeremy Dunn

I like this language a lot but hey, everyone thinks they have a good idea and I'm no different. So I would like to suggest some ideas that could be useful for reducing expression size.



1. LISTS



Lists are written like (list a b c) or even '(a b c) but it might also be good to allow us to write ( a b c) and dispense with the extra symbols altogether. In this case if there is at least one space after the left parenthesis then it is considered to be a list.



2. BOOLEAN FUNCTIONS



I'm glad to see that newLISP ends its boolean func names with "?" instead of "p". Let us go one further and have the boolean act as its own if/then conditional if you end the function name with "??". For instance,



(if (= x 3) 4 5) could be (=?? x 3 4 5)



All the arguments are collected together and the last two arguments are the "then" and "else" part of the statement. If there is no "else" condition then we can stuff it with a + sign as in



(if (= x 3) 4) becomes (=?? x 3 4 +)



Use ~ as a prefix to represent the "not" function so that we can write



(if (not (zero? x)) a b) as (~zero?? x a b)



This technique could save us a lot of parentheses and get rid of 90% of those "if" statements. Note that this would allow writing a "cond" statement in an explicit form if one wished. For instance



(cond

  ((= x 3) A)

  ((zero? y) B)

  (true C)

)



would be



(=?? x 3 A

  (zero?? y B C))



3. NESTED FUNCTIONS



Suppose we have the statement (sqrt (abs (sin (tan x)))), this kind of nesting often occurs. How about allowing us to write this as



(sqrt abs sin tan | x) ?



The vertical slash separates the nested item from the function names that are nesting around it.



4. NUMBERS as FUNCTIONS



This is a bit esoteric but hear me out. I would like to see the ability to treat numbers as functions and make newLISP even more of a functional language. What do I mean? I suggest a function that generates a complex number. This would have the form



(c <real digit list><real expon><imag digit list><imag expon><base>)



If the number base is not supplied it defaults to 10.

If exponents are not supplied they default to being equal to the number of digits in the digit list before them.

If a digit list is not supplied it defaults to '(0).

Negative bases, digits and exponents are all allowed.



With these rules here are some examples of numbers:



23 -> (c '(2 3))

-4 -> (c '(-4))

12.34 -> (c '(1 2 3 4) 2)

-12.34 -> (c '(-1 -2 -3 -4) 2)

1.3e3 -> (c '(1 3) 4)    one notes the exponent is 1 larger

56i -> (c nil nil '(5 6))

0.78i -> (c nil nil '(7 8) 0)

1.2+8.3i -> (c '(1 2) 1 '(8 3) 1)

3AB base 12 (c '(3 10 11) nil nil nil 12)



The point here is not to demand that everyone start writing their numbers this way but to allow them to in those cases where the person wants total control of the number down to the digits and the base. This might not seem important but I think people will find clever things to do with it. This function will of course output a list with all the parts of the complex number. The math functions will have to be rewritten to take this list as input as well as the standard format numbers. There should also be two other functions



(numeric-output-standard)

(numeric-output-complex)



These would act as toggles to decide how the math functions are going to output their results, as normal numbers or complex number lists. When the user writes (numeric-output-complex) all the functions will return complex lists until they call (numeric-output-standard) again. The default is standard of course.



We also need conversion between standard and complex numbers with

(standardtocomplex n)

(complextostandard n)



So   (standardtocomplex 1.2) -> ((1 2) 1 (0) 1 10)

and (complextostandard ((1 2) 1 (0) 1 10)) -> 1.2



5. NUMERIC CONDITIONAL STATEMENTS



I would like to suggest adding two numeric condtional statements that I have found extremely handy to have. First



(<=> x y A B C)



This statement means:

 If (< x y) return the evaluation of A

 If (= x y) return the evaluation of B

 If (> x y) return the evaluation of C



And second,



(signcond x A B C)



This is similar to the first function but means

 If x is negative return the evaluation of A

 If x is zero return the evaluation of B

 If x is positive return the evaluation C



Well I am probably wearing out my welcome with too many suggestions but I look forward to the commentary.

HPW

#1
newLISP was shouted often strange and exotic by the LISP community.



It is different in some aspects, but stays on a fundamental base found in much other Lisp's.



Some of your suggestion could be done by the user himself, others would look really different to old lisp's. This is of cource a matter of taste.



So for my taste, some of your suggestions I find them less clear to read (Ok for traditional lisp-users).

I am not a language designer or purist, so I only can speak as a lisp-user who like the current newLISP very much.



Just my 2 cents (euro)!

;-)
Hans-Peter

Lutz

#2
The nice thing about LISP and Scheme is, that the syntax rules are very simple : the first list member is the functor/operator and the rest are the parameters/arguments. The only difference between LISP and Scheme/newLISP is that Scheme and newLISP evaluate the first list member first before applying it to the parameters:



;; newLISP and Scheme evaluate the operator part first (other LISPs don't):

((if (> A B) + *) A B)

;; in this example A and B are added if A > B else multiplied


Most of Jeremy's suggestions could be implemented by defining functions or macros for it, i.e:



(define (<=> x y A B C)
   (if
    (< x y) A
    (= x y) B
    (> x y) C))

(<=> 3 4 10 20 30) => 10
(<=> 4 4 10 20 30) => 20
(<=> 5 4 10 20 30) => 30


In newLISP you also have the possibility to redefine the built-in functions using 'constant'. Doing this and using functions and macros, you can completely tailor a language to your own taste, which is the reason people use these kind of languages in the first place, because they let you define your own language appropiate to the problem area you are developing in.



Lutz

eddier

#3
I dont like typing much either. For non cgi programs, I've redone many of the commands by adding the following to my init.lsp.



(constant (global 'const) constant)
(constant (global 'df) define)
(constant (global 'dm) define-macro)
(constant (global 'ap) apply)
(constant (global 'filt) filter)
(constant (global 'car) first)
(constant (global 'cdr) rest)
(constant (global 'cat) append)
(constant (global 'fmt) format)
(constant (global 'pr) print)
(constant (global 'prn) println)
(constant (global 'len) length)
(constant (global 'int) integer)
(constant (global 'int?) integer?)
(constant (global 'str) string)
(constnat (global 'str?) string?)
(constant (global 'sym) symbol)
(constant (global 'sym?) symbol?)

(define-macro (--) (map (fn (n) (set n (- (eval n) 1))) (args)))
(constant (global '--))

(define-macro (++) (map (fn (n) (set n (+ (eval n) 1))) (args)))
(constant (global '++))

(define-macro (=0?) (ap = (args)))
(constant (global '=0?))

(define (red f L) (ap f L 2))
(constant (global 'red))

(define (caar L) (car (car L)))
(constant (global 'caar))

(define (cadr L) (car (cdr L)))
(constant (global 'cadr))

(define (cdar L) (cdr (car L)))
(constant (global 'cdar))
.
.
.


Eddie

Jeremy Dunn

#4
Quote from: "Lutz"The nice thing about LISP and Scheme is, that the syntax rules are very simple : the first list member is the functor/operator and the rest are the parameters/arguments. The only difference between LISP and Scheme/newLISP is that Scheme and newLISP evaluate the first list member first before applying it to the parameters:



;; newLISP and Scheme evaluate the operator part first (other LISPs don't):

((if (> A B) + *) A B)

;; in this example A and B are added if A > B else multiplied


Most of Jeremy's suggestions could be implemented by defining functions or macros for it, i.e:



(define (<=> x y A B C)
   (if
    (< x y) A
    (= x y) B
    (> x y) C))

(<=> 3 4 10 20 30) => 10
(<=> 4 4 10 20 30) => 20
(<=> 5 4 10 20 30) => 30


In newLISP you also have the possibility to redefine the built-in functions using 'constant'. Doing this and using functions and macros, you can completely tailor a language to your own taste, which is the reason people use these kind of languages in the first place, because they let you define your own language appropiate to the problem area you are developing in.



Lutz


Please forgive my poor AutoLISP addled brain, I am having to learn a new way to think here. Your example has a statement that in purest form is

(if a b c d e f). I thought an if statement can have only 3 arguments. I take it it keeps grabbing them and interprets it as (if a b (if c d (if e f)))? But I thought all the other functions left associate as in

(fn (fn (fn a b) c) d) is if an exception or am I just lost?

Lutz

#5
The new if-syntax with multiple conditions was added after a AutoLisp person argued for  a 'cond' with less parenthesis. I thought he had a point, and this is how 'if' with multiple conditions was added, and in reality it's not an 'if' using it this way, but rather a 'cond'.



There are other AutoLisp things in newLISP like i.e. 'set/setq' with mutliple sets of arguments. I have never worked with AutoLisp, but it seems they did some things right. Some say it is (or was ;-) ) the most popular LISP today. So they must have done things to learn from. Perhaps like newLISP they tried to be 'practical' and they certainly had to be so as an extension language for a popular application like Autocad.



Lutz

HPW

#6
>So they must have done things to learn from. Perhaps like newLISP they tried to be 'practical'



In the early autolisp-days they were really 'practical'! They invented really practical function driven by the autocad community. And they made 'DCL' as a powerfull GUI geometry manager (some similarity with TK) in a lispy way. Generating GUI's and code morphing on the fly. Very powerfull and easy for it's time. Now they go with the masses (MS) and left Lisp/DCL as it is. (Still usefull but no modern touch)



newLISP is more powerfull in it's LISP base, but you have to choose the right GUI enviroment to get the same power and flexibility. Fortunatly we have now several choices for this.



As always: Choose the right tool to get the job done!

;-)
Hans-Peter

Lutz

#7
Yes, we have now different GUI possibilities to choose from, mainly Tcl/Tk and GTK. An then of course there are solutions like NeoBook or VB, where newLISP just runs as a backend doing the non-gui stuff.



What we don't have is a possibility to write GUIs in newLISP. What one could do is take the Tcl/Tk or GTK-server solution and put a newLISP layer on top of it. Personally I probably would refer GTK, because it seems they will develop further than Tcl/Tk, which is getting a little bit stale, i.e. antialiased fonts, transparency etc. At the moment I think only Java Swing has all that stuff, but i think its coming to GTK too, if not already there? On the other side GTK is complexer to install on Win-32 machines (two installs). The nice think about Tcl/Tk is that you can deliver everything in one file.



Lutz

pjot

#8
Quote
At the moment I think only Java Swing has all that stuff, but i think its coming to GTK too, if not already there?


Indeed it's already in GTK 2.x. Also the Windows port of GTK 2.x supports anti-aliased fonts and theming, but the anti-aliasing will only show in WinXP, since earlier Windows versions do not support ClearType.



The development of GTK is very active right now; but being a Unix GUI solution, it seems that the 2-install problem will remain...

Lutz

#9
Are you planning a Mac OSX GTK-Server version? I think GTK is available there? I always found Mac OSX porting pretty simple as it is so close to BSD. I do all my stuff for the Mac on cf.sourceforge.net.



Lutz

Lutz

#10
I just was re-reading Jeremy's post about complex numbers. Are you aware of Eddie's rational numbers library? You can find it here: http://www.newlisp.org/index.cgi?Code_Contributions">http://www.newlisp.org/index.cgi?Code_Contributions or here: http://www.newlisp.org/code/rational.lsp.txt">http://www.newlisp.org/code/rational.lsp.txt



Perhaps somebody can write something similar for complex numbers. There is one pair of functions in newLISP already, which can take complex numbers: 'fft' and 'ifft'.



Lutz

pjot

#11
The GTK-port for OSX is mentioned to be "pre-alpha". It is an unstable port which, according to the website, is still not very suitable to compile with. Also, it is only GTK 1.x which is ported currently, the latest version being 0.7 dated 25/5/2004:



http://gtk-osx.sourceforge.net/">http://gtk-osx.sourceforge.net/



...so GTK 2.x is unavailable - unfortunately... :-(



I also need to buy a Mac, but that's of minor importance; I always wanted to have one... :-)

newdep

#12
Pjot i have a Mac Classic II on my Attic... Its a Beauty ;-)
-- (define? (Cornflakes))

Jeremy Dunn

#13
Read up on "if" yesterday. I can see that I will have to reread every command to make sure I don't miss out on all the new features. I have started writing both a math and geometry library. Complex numbers will be included plus some number theory and other things. But it will take a while to write and test everything of course.



AutoLISP is popular simply because there are a lot of CAD users out there. I would jump ship in an instant if Autodesk would have brains enough to replace it with something like newLISP. We don't even have optional arguments! I think the Autodesk programmers are deliberately leaving it inadequate to force us into VB. The problem is that most of the users like LISP so much that they connive ways to get around using VB, Autodesk just doesn't get that most of us despise having to write programs in VB and don't want the headache of having to learn ObjectARX.