Is a lisp with only functional parentheses possible?

Started by newdep, August 18, 2009, 03:13:35 PM

Previous topic - Next topic

cormullion

#15
This example is proposed in the sweet-expression scenario (http://www.dwheeler.com/readable/version02.html">//http://www.dwheeler.com/readable/version02.html):


NewLisp

NewLisp is "Lisp-like, general purpose scripting language", with an implementation released under the GPL.
Original Lisp

Here is a sample from their Code patterns document:
    (dolist (file-name (3 (main-args)))
        (set 'file (open file-name "read"))
        (println "file ---> " file-name)
        (while (read-line file)
            (if (find (main-args 2) (current-line) 0)
            (write-line)))
        (close file))

This is the original formatting. It's a little misleading; the write-line is actually inside the "if", not a sibling of it. Yet another example of how formatting can mislead a reader, when humans use it but computers don't.

Infix is not Default (Version 0.2)

Same thing, with sweet-expressions:

    dolist (file-name (3 (main-args)))
        set 'file open(file-name "read")
        println "file ---> " file-name
        while read-line(file)
            if find(main-args(2) current-line() 0)
              write-line()
        close file


Presumably someone can write something that does the necessary transformations...



I like his work, and his approach. But he didn't convince me that Lisp syntax is intrinsicially harder to read, given the same amount of familiarity with it that he allows programmers to have with other languages. (Ie years of training in mathematics, Basic and C-style function calling, etc.)


QuoteThe fact that so many people are compelled to find a "fix" to Lisp syntax indicates to me that there is a problem...



Quote Here's the problem: for most software developers, programs written solely using s-expressions are hard to read, and they will only voluntarily use programming languages that allow, at least optionally, a more common notation. This is particularly true for the usual infix operations (+, <, and so on). People who use Lisp-based languages all the time eventually learn, but not everyone wants to use them all the time, and even developers who are comfortable with programs in s-expression notation need to share their work with others.


QuoteLisp's syntax looks genuinely hostile to most "normal programmers".


He's mainly arguing, I think, that programmers in C-style languages would prefer to have Lisp-like features available using their preferred syntax forms. That's great, and you should always use a language you feel comfortable with.



Personally I still find the lisp style clearer, and think this:


find(main-args(2) current-line() 0)

is not as good as this:


(find (main-args 2) (current-line) 0)

But I suppose I'm completely brainwashed by now... :)

linli

#16
It seems that quite a lot of people(including me) do not like the parentheses of lisp, because it is unnatural, hard to read or whatever else, but currently do we have a better replacement for it? Have a look at the syntax of C-family languages or PL/SQL, they are all trying to be natural, in the end, they have to use different syntactical rules for different things.Personally, I found this sucks! It is too complicated. In addition, if you make any tiny mistake, the complier or interpreter will not accept your code at all! This is why I believe that any kind of "natural" syntaxes suck for programming languages.

Natural languages are good for communications between human beings because we are intelligent, we can correct small mistakes, but computers can not do it and natural languages are so complicated that it is very very easy to make mistakes, programming languages that try to be natural just increase unnecessary complexity. So unless some one finds some other parenthesis-less syntax that still preserve the same simplicity of lisp's syntax, we should not touch it.

m i c h a e l

#17
Attempts to remove the parentheses from Lisp, both big (like Dylan in the '90s) and small (such as Sweet-expressions today) have assumed the problem was with the parenthesis itself, instead of the prejudice of non-Lisp programmers against it. Like all differences we encounter for the first time, they can seem strange or even alien. With exposure and interaction, however, we begin to see beyond the differences to behold the essence of something. Most experienced Lisp programmers say the same thing: they no longer see the parentheses. But even this seems to suggest they're better left unnoticed.



I love the humble parenthesis. The simple beauty of it belies its power. Those who would be ashamed of parentheses have yet to understand them.



m i c h a e l

Lutz

#18
Changes to the traditional parenthesis syntax in LISP may not be compatible with the program equals data paradigm. E.g.:


(set 'lst '( (foo x y) (bar q p) ) )

should this be translated into:


(set 'lst '( foo(x y) bar(q p) ) )

or not? Imagine something like this:


(dolist (e lst) (println (eval e)))

is following the first line. This would fail on the sweet-expression translation. I suppose one would not transform quoted expressions. But how many more examples could be constructed needing more complex rules to guide the transformation process?



Like Scheme, newLISP has one namespace and the operator part of a list expression is evaluated. 'foo' and 'bar' may or may not be user-defined or built-in functions. It may not be possible to find out until runtime.



Although Sweet Expressions could be introduced into newLISP they would then either exclude certain programmatic manipulations of program expressions as data or create ambiguities which can only be resolved introducing more complex transformation rules.

TedWalther

#19
Quote from: "Lutz"Changes to the traditional parenthesis syntax in LISP may not be compatible with the program equals data paradigm. E.g.:


(set 'lst '( (foo x y) (bar q p) ) )

should this be translated into:


(set 'lst '( foo(x y) bar(q p) ) )

or not? Imagine something like this:


(dolist (e lst) (println (eval e)))

is following the first line. This would fail on the sweet-expression translation. I suppose one would not transform quoted expressions. But how many more examples could be constructed needing more complex rules to guide the transformation process?



Like Scheme, newLISP has one namespace and the operator part of a list expression is evaluated. 'foo' and 'bar' may or may not be user-defined or built-in functions. It may not be possible to find out until runtime.



Although Sweet Expressions could be introduced into newLISP they would then either exclude certain programmatic manipulations of program expressions as data or create ambiguities which can only be resolved introducing more complex transformation rules.


Or, if we get reader macros, sweet expressions will be transformed to standard newlisp, at which point all standard manipulations will apply.  The onus of cleverness will be on the function creator.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

newdep

#20
I think that 'less' parentheses only make newlisp more complex regarding  quick reading and understanding..I do like though the thought of 'simplyfing'code by the use of "reader macro's".. That could make the language indeed intresting...





(push 'd [ a b c ] -1 ) -> (a b c d )

or

(set 'lst '( (foo x y) (bar q p) ) )

--> (set 'lst [[ foo x y ][ bar q p ]] )

-----> (set 'lst _ foo x y _ bar q p _ )

or

(begin.......) ->  [.........]

'(............) -> [..........]

(setq X...) ->  [ X .... ]

(define (X) (...) ) ->  [ (X) (...) ]




...still thinking...
-- (define? (Cornflakes))

TedWalther

#21
Quote from: "newdep"I think that 'less' parentheses only make newlisp more complex regarding  quick reading and understanding..I do like though the thought of 'simplyfing'code by the use of "reader macro's".. That could make the language indeed intresting...




With reader macros we could embed languages within languages within languages.



Imagine the following code:


Quote
(add-reader-macro 'c-lang)

(add-reader-macro 'sql-lang)

(add-reader-macro 'html-lang)



(println "hi")



(C

printf("foo%d",1);

i++;

)



(sql

SELECT * FROM ,(amb "table1" "table2")

)



(html

<h1>foo</h1>

,(generate-some-tables))

)


With read macros, someone could implement the , and ,@ quasi-quote operators from Common Lisp.  If they really wanted them.  Lutz has made a good case they aren't necessary.  But with reader macros they could be expanded from their short form into good newlisp style anyway.  Even ' could be implemented as a reader macro, and in most LISP's, is.



In the examples above, I assumed that each minilanguage included a comma escape to let you insert the output of a newlisp expression.  This allows for endless recursive embedding of languages, C within newlisp within SQL within newlisp within python within newlisp...  And all without any of the usual headaches we get when doing escaping.  I've been doing php/html/javascript/sql in my dayjob, and I can honestly say the interactions between the four formats causes a lot of headaches.  If only they were all written in newlisp with reader macros, they could be mingled and nested within each other safely, to any depth desired, without all sorts of wierd escaping rules.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

newdep

#22
...I realy do like the sound of this and Im currious on How far this could

be taken inside coding.. this would be nice...
-- (define? (Cornflakes))

Kazimir Majorinc

#23
I think reader macros make writing code (programming) more friendly, but writing code that processes code (metaprogramming) more difficult.



I do not think that "one who does not want to use reader macros shouldn't use them" is enough. What would happen if someone writes useful library that uses reader macros? Programmers will start to use it. Theoretically, we can remember both new syntax and how it translates into normal Lisp, but in reality, our minds are finite, especially for those who program Newlisp on and off - so we'd start using Lisp as any other language, without understanding how to process code.



This practice would, in turn, influence future development of the language. Although Lutz makes decisions, these are made on the base of the perceived problems and discussions by other programmers.



I could admit that finally, it is not known whether metaprogramming is good idea and that I only believe it is good idea. The failure of Lisp dialects to establish itself as a mainstream language is not a good sign, but recently it appears that Ruby users practice metaprogramming alot. Anycase, metaprogramming is differentia specifica of Lisp; if it is bad idea, Lisp itself is failure. And if it is good idea, it is comparative advantage of Lisp that should be promoted and not discouraged.



From my point of view, following syntax looks OK:


(load "c-lang")
(load "sql-lang")
(load "html-lang")

(println "hi")

(C "printf("foo%d",1);
    i++;"
)

(sql (append "SELECT * FROM" (amb ""table1""  ""table2"")))

(html (append "<h1>foo</h1>"
              (generate-some-tables))
)


I understand why Ted likes his syntax better. Back while I used PLT Scheme, I used °s-expr instead of (println 's-expr "=" s-expr) equivalent. Good for debugging. Reader macros can be fun. But, Ted can implement his own, private preprocessor - on that way, whole thing is interesting and challenging private experiment, and not a language policy.


(preprocess
   (add-reader-macro 'c-lang)
   (add-reader-macro 'sql-lang)
   (add-reader-macro 'html-lang)

   (println "hi")

   (C printf("foo%d",1);
      i++;))


(I'll publish this post at my blog)
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

TedWalther

#24
Kazimir, how would I implement preprocess function without reimplementing all of the newlisp language?  To have that type of recursion, the ability to slip back and forth between different languages, requires the ability to read in a newlisp expression, as with read-expr... but to do it recursively, as with a nested list that contains a mini-language at some level, the macro hooks have to be in the reader.



reader macros can be done efficiently and the concept is fairly simple; you pass the stream object to the reader macro, then the reader macro will tell you if it matched or not, and will optionally return a value, and will leave the stream in some modified state, generally just leaving the pointer past the end of the expression that was read in.  If the reader macro succeeded, then there is no need for further evaluation.  If no reader macro succeeds, then the default implementation, which parses standard newlisp, is used.  But in every case, the reader macro returns valid newlisp expressions.



Again, how would one write the preprocessor function you speak of, without having to reimplement the entire newlisp syntax parser in newlisp?  It will be a lot easier to slightly modify the reader to incorporate reader macros.



Ted


Quote from: "Kazimir Majorinc"I think reader macros make writing code (programming) more friendly, but writing code that processes code (metaprogramming) more difficult.



I do not think that "one who does not want to use reader macros shouldn't use them" is enough. What would happen if someone writes useful library that uses reader macros? Programmers will start to use it. Theoretically, we can remember both new syntax and how it translates into normal Lisp, but in reality, our minds are finite, especially for those who program Newlisp on and off - so we'd start using Lisp as any other language, without understanding how to process code.



This practice would, in turn, influence future development of the language. Although Lutz makes decisions, these are made on the base of the perceived problems and discussions by other programmers.



I could admit that finally, it is not known whether metaprogramming is good idea and that I only believe it is good idea. The failure of Lisp dialects to establish itself as a mainstream language is not a good sign, but recently it appears that Ruby users practice metaprogramming alot. Anycase, metaprogramming is differentia specifica of Lisp; if it is bad idea, Lisp itself is failure. And if it is good idea, it is comparative advantage of Lisp that should be promoted and not discouraged.



From my point of view, following syntax looks OK:


(load "c-lang")
(load "sql-lang")
(load "html-lang")

(println "hi")

(C "printf("foo%d",1);
    i++;"
)

(sql (append "SELECT * FROM" (amb ""table1""  ""table2"")))

(html (append "<h1>foo</h1>"
              (generate-some-tables))
)


I understand why Ted likes his syntax better. Back while I used PLT Scheme, I used °s-expr instead of (println 's-expr "=" s-expr) equivalent. Good for debugging. Reader macros can be fun. But, Ted can implement his own, private preprocessor - on that way, whole thing is interesting and challenging private experiment, and not a language policy.


(preprocess
   (add-reader-macro 'c-lang)
   (add-reader-macro 'sql-lang)
   (add-reader-macro 'html-lang)

   (println "hi")

   (C printf("foo%d",1);
      i++;))


(I'll publish this post at my blog)
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

Kazimir Majorinc

#25
I don't get it.



Could you write short example of the code you'd like to write, it is possible with reader macro, but not with your own preprocess function?
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

TedWalther

#26
Quote from: "Kazimir Majorinc"I don't get it.



Could you write short example of the code you'd like to write, it is possible with reader macro, but not with your own preprocess function?


Let's be clear.  I could do anything I want with my own preprocess function.  But every time the newLISP syntax changes, I would have to update it.  I would have to duplicate the code by re-implementing the newLISP syntax parser.



The purpose of read macros is to avoid that overhead; use the build in reader where you can.  Also, as a standard part of the language, I wouldn't have to make my pre-process binary replace newlisp as the standard binary.



read macros should be fairly simple to implement (in the larger scheme of things).  I'm not familiar enough with newLISP internals to bang this out quickly, but I"m guessing Lutz could have a rough cut working in 8 hours or so.  (purely a guess from the poking around I did do)



It would work like the current macros do, but operate on the input character stream rather than on an already existing parse tree.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

Elica

#27
If the idea of reducing the number of (...)'s is to make the source code easier to read by not-lispers, then you must also consider solutions which affect the IDE (or the editor) without changing anything in the language.



For example, an editor that helps with the (..)'s might solve most of the problems. Here are few options:



- changing font size/color/background

- adding graphical elements (like the box in Boxer)

- collapsing/expanding nodes and subnodes

- etc. etc.



This would keep the language pure and will move all human-computer interfacing problems to be solved by the GUI or IDE.



So, a key question is whether you like an ASCII-only solution, or you would be happy with other solutions too. For ASCII solutions the most feasible might be using macros or preprocessing.

TedWalther

#28
Quote from: "Elica"If the idea of reducing the number of (...)'s is to make the source code easier to read by not-lispers, then you must also consider solutions which affect the IDE (or the editor) without changing anything in the language.



For example, an editor that helps with the (..)'s might solve most of the problems. Here are few options:



- changing font size/color/background

- adding graphical elements (like the box in Boxer)

- collapsing/expanding nodes and subnodes

- etc. etc.



This would keep the language pure and will move all human-computer interfacing problems to be solved by the GUI or IDE.



So, a key question is whether you like an ASCII-only solution, or you would be happy with other solutions too. For ASCII solutions the most feasible might be using macros or preprocessing.


That is an interesting concept.  Someone could implement it as an emacs "mode"; the text view would be sweet expressions, but underneath emacs would be storing everything as proper newLISP.



This brings us around to the ColorFORTH concept that compilation happens in the editor, word by word.  Full circle.  I knew Chuck Moore was LISPy at heart (and he even admitted it in person)
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

newdep

#29
Im still thinking about simplify..

And indeed an overlay-editor or a color mix is a very nice way to do this...

(so are all programming languages overlaying Assembly anyway ;-)





Getting back to newLISP though... I think that newlisp can be simplified by starting to look at its functions..



I.e. the predicates...



Using predicates one must test those against xx by use of an extra function..It isnt smart by itself..



But what if they where able to include the test-case them selfs..?



This is my preference:

(integer? (integer "1") (println "yes"))

or

(integer? (integer "1") (println "yes") (println "no"))


But instead we must now write ->

(when (integer? (integer "1")) (println "yes"))



The "when" is not needed here, integer? is already testing...

if the predicate was smart enought to deal with everything within its

test argument...Rewriting this saves parentheses and a 'test function..



...still thinking...
-- (define? (Cornflakes))