From: Neo
Subject: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105377133.853915.78010@f14g2000cwb.googlegroups.com>
I am trying to write a scripting language for a small experimental db.
Its current syntax is quite limited. I was hoping to make it more
flexible by following LISP syntax. Does LISP encode a sequence of
statements as follows:

// Current scripting syntax.
Command1 param1 param2;
Command2 params...;
Command3 params...;

// Would this be the equivalent LISP Syntax?
(Command1 param1 param2)
(Command2 params...)
(Command3 params...)

Why does begining a statement with a marker, in addition to ending it
with a marker, make it more flexible?

From: ·········@gmail.com
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105381088.730176.327660@c13g2000cwb.googlegroups.com>
With that sort of really simple syntax, adding parens isn't going to
make any significant difference except making it easier to parse with
READ. However, when you want to do fancier things, Lisp can really be
useful.

For example, most databases have some procedural language to do fancy
manipulation of the information without requiring an external program.
Suppose that you had a table with one row of numbers and you wanted to
fill another row with those numbers doubled. You could use the
database's procedural language to do that.

But these languages are hard to make. Would you like to write a new
programming language? Would you then like to write a compiler for
speed? Would you use garbage collection? What data types would you
allow? Or you could just add some functions and macros to Lisp and use
it as your extension language. You would get the power of a mature
language and the speed of a good compiler. You could define some new
control structures to make Lisp's semantics closer to what you would
want for a database manipulation language. And you need Lisp syntax for
this.

That's just one example, but the lesson is that Lisp's syntax is only
really useful for non-trivial things.

-Peter Scott
From: Neo
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105470645.754288.234360@z14g2000cwz.googlegroups.com>
> You could define some new control structures to make Lisp's semantics
> closer to what you would want for a database manipulation language.

True, but I enjoy the process of tinkering rather than the final result
in this case. Below is an example of the rudimentary script's ability.
What would be its approximate equivalent in LISP?

// Create items in directory to classify things.
(CREATE *gender.item ~in = dir)
(CREATE *person.item ~in = dir)

// Create a person named John who is male.
(CREATE *john.cls = person)
(CREATE john.gender = +male)

// Create a person named Mary who is female.
(CREATE *mary.cls = person)
(CREATE mary.gender = +female)

// Create John likes Mary.
(CREATE *like.cls = verb)
(CREATE john.like = mary)

// Find gender of person that John likes.
// Finds female.
(SELECT (john.like=%).gender=%)
From: ·········@gmail.com
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105484556.495157.325770@z14g2000cwz.googlegroups.com>
It looks like your database is just objects with configurable slots and
a scripting language. The biggest part is the scripting language and
its syntax, and if you reduced that to Lisp syntax, it would seem so
trivial that you would want to extend its abilities.

SELECT (john.like=%).gender=%)
becomes
(gender (like john))
or possibly, if you wanted to get very fancy and give John a list of
people he can like,
(mapcar #'gender (people-liked-by john))

And then you can define functions or macros so you can write stuff like
this:

(defperson john :gender 'male :likes 'mary)
(defperson mary :gender 'female)

You like it?

-Peter
From: drewc
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <o2ZEd.53054$8l.3944@pd7tw1no>
Neo wrote:

[...]
> in this case. Below is an example of the rudimentary script's ability.
> What would be its approximate equivalent in LISP?

There is nothing stopping you from implemeting the syntax you describe 
as a macro. "LISP" has no built in database support, so there is not 
really an "equivalent" in Lisp.

That being said, you could do this in CLSQL syntax.


> 
> // Create items in directory to classify things.
> (CREATE *gender.item ~in = dir)
> (CREATE *person.item ~in = dir)

(connect '("dir"))

(def-view-class person ()
   ((name :accessor name :initarg :name :type string)
    (gender-id :accessor gender-id :initarg :gender-id :type int)
    (gender :accessor gender :db-kind :join
            :db-info (:join-class gender
                      :home-key gender-id
		     :foreign-key gender-id))))

(def-view-class gender ()
   ((gender-id :accessor gender-id :initarg :gender-id :type int)
    (name :accessor name :initarg name :type)
    (persons :accessor persons :db-kind :join
             :db-info (:join-class person
                       :home-key gender-id
                       :foreign-key gender-id
                       :set t))))	

(dolist (view '(gender person))
  (create-view-from-class view))

(defparameter female (make-instance 'gender
                        :gender-id 1
                        :name "Female"))

(defparameter male (make-instance 'gender
                        :gender-id 2
                        :name "Male"))

> 
> // Create a person named John who is male.
> (CREATE *john.cls = person)
> (CREATE john.gender = +male)

(defparameter john (make-instance 'person :gender-id 2 :name 'john))

> 
> // Create a person named Mary who is female.
> (CREATE *mary.cls = person)
> (CREATE mary.gender = +female)

(defparameter mary (make-instance 'person :gender-id 1 :name 'mary))

> 
> // Create John likes Mary.
> (CREATE *like.cls = verb)
> (CREATE john.like = mary)

(def-view-class likes ()
  ((like-er-name :accessor :like-er-name
		:initarg :like-er-name
		:type string)
  (like-ee-name :accessor :like-ee-name
		:initarg :like-ee-name
		:type string)
  (liked :accessor liked :db-kind :join
          :db-info (:join-class person
                    :home-key like-ee-name
                    :foreign-key name
                    :set nil))))

(create-view-from-class likes)

(defparameter j-likes-m (make-instance 'likes
                          :like-er-name (name john)
                          :like-ee-name (name mary))

(dolist (i '(john mary j-likes-m))
  (update-records-from-instance i))

> 
> // Find gender of person that John likes.
> // Finds female.
> (SELECT (john.like=%).gender=%)

(name (gender (liked
  (caar
   (select 'likes :where [= [slot-value john 'name]
                            [slot-value likes 'like-er-name])))))

=> "Female"



Not as terse as your version, but there would be nothing stopping you 
from implementing your macros on top of cl-sql view classes. I do that 
sort of thing frequently.

drewc
From: Frank Buss
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <cruedl$a4u$1@newsreader2.netcologne.de>
"Neo" <········@hotmail.com> wrote:

> Why does begining a statement with a marker, in addition to ending it
> with a marker, make it more flexible?

one reason is, that you always know, where a command starts:

(command (command-which-returns-something arg1_1) arg2 arg3)

If you don't mark it, it will be difficult for you (perhaps not for the 
compiler) to see, if "command-which-returns-something" is a command or a 
variable.

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Andreas Thiele
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <crugrd$kk8$04$1@news.t-online.com>
"Frank Buss" <··@frank-buss.de> schrieb im Newsbeitrag
·················@newsreader2.netcologne.de...
> "Neo" <········@hotmail.com> wrote:
>
> > Why does begining a statement with a marker, in addition to ending it
> > with a marker, make it more flexible?
>
> one reason is, that you always know, where a command starts:
>
> (command (command-which-returns-something arg1_1) arg2 arg3)
>
> If you don't mark it, it will be difficult for you (perhaps not for the
> compiler) to see, if "command-which-returns-something" is a command or a
> variable.
>
> --
> Frank Bu�, ··@frank-buss.de
> http://www.frank-buss.de, http://www.it4-systems.de

... and as you can see in Franks example, you can arbitrary nest 'commands'.

Andreas
From: Neo
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105467824.581905.287660@f14g2000cwb.googlegroups.com>
>>> Why does begining a statement with "("...make it more flexible?
>>
>> one reason is, that you always know, where a command starts:
>> (command (command-which-returns-something arg1_1) arg2 arg3)
>
> you can arbitrary nest 'commands'

Thanks, you were right, surrounding the statements with parentheses
does make the script processing easier especially if a parameter is
another command; however it gets confusing to read. What is the
advantage of the following LISP coding style versus that of C? Why is
crunching everything on one line an advantage? Does LISP allow the
equivalent C style?

// LISP style
F2 ( a  b  F1( ) )

// C style
var1 = F1( );
F2 (a b var1);
From: Cameron MacKinnon
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <14adnblz45e80XncRVn-vQ@golden.net>
> Thanks, you were right, surrounding the statements with parentheses
> does make the script processing easier especially if a parameter is
> another command; however it gets confusing to read. What is the
> advantage of the following LISP coding style versus that of C?

If you're writing your language in Lisp and it uses S expressions, you 
get to use Lisp's parser for free - access to it is built into the 
language. Contrast this with C, which provides no standardized way of 
interfacing with your C compiler's parser, which isn't generally 
customizable or present in your program's runtime image anyway.

A typical compiler construction text for a C or Pascal like language 
spends about the first 1/3 of the book teaching you how to create 
grammars, parseable grammars, efficiently parseable grammars...
From: Kenny Tilton
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <ERVEd.41551$Yh2.19021654@twister.nyc.rr.com>
Neo wrote:
>>>>Why does begining a statement with "("...make it more flexible?
>>>
>>>one reason is, that you always know, where a command starts:
>>>(command (command-which-returns-something arg1_1) arg2 arg3)
>>
>>you can arbitrary nest 'commands'
> 
> 
> Thanks, you were right, surrounding the statements with parentheses
> does make the script processing easier especially if a parameter is
> another command; however it gets confusing to read.

Only if you have never read it before (your case). After a few weeks you 
will not even see the parens, you will be looking at the indentation. 
That, by the way, is supplied by the editor. If you write a lot of 
original code and like to refactor, make a mental note from now on as to 
how much time you spend manually re-indenting. And when I say automatic, 
I do not mean the editor has a command to "indent selection one tab". I 
mean it will take a completely butchered 100-line function and reindent 
the whole thing intelligently in one command. hellasweet.

> What is the
> advantage of the following LISP coding style versus that of C? Why is
> crunching everything on one line an advantage? Does LISP allow the
> equivalent C style?
> 
> // LISP style
> F2 ( a  b  F1( ) )
> 
> // C style
> var1 = F1( );
> F2 (a b var1);
> 

I hate putting things on one line. Tho in this case I would write:

      (f2 a b (f1))

When things get hairier, you will see:

      (f-this-that-and-the-other
         (yowza-lokke-there a)
         (o-mi-god b)))

When your C code gets hairier, ick, you end up with all these local 
variables which add their own complexity (room for bugs, mostly) and 
make the code less readable because now I have to mentally inventory 
them and keep track of what must be bound to what.

Mind you, I see a /lot/ of Lisp code that looks more like C code because 
it uses temp vars and a sequence of "commands" to get a job done, but 
that just means they have not swallowed the Lisp red pill, they have it 
under their tongue.

kt

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Neo
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105481460.708009.322340@f14g2000cwb.googlegroups.com>
>When things get hairier, you will see:
>     (f-this-that-and-the-other
>        (yowza-lokke-there a)
>        (o-mi-god b))

Thanks, didn't realize an indentation scheme would make such a
difference in making things readable.

> variables which add their own complexity (room for bugs, mostly) and
> make the code less readable because now I have to mentally inventory
> them and keep track of what must be bound to what

Aren't the negatives of intermediate variables offset in some cases by
increasing readability. If a variable is like the title of a paragraph,
doesn't it give a quick summary without reading the whole paragraph?
From: Kenny Tilton
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <GDZEd.57810$ld2.20246311@twister.nyc.rr.com>
Neo wrote:

>>When things get hairier, you will see:
>>    (f-this-that-and-the-other
>>       (yowza-lokke-there a)
>>       (o-mi-god b))
> 
> 
> Thanks, didn't realize an indentation scheme would make such a
> difference in making things readable.

The great thing for me was that I had been an indentation-junkie anyway 
from COBOL, Basic, and C, so you can imagine my delight when I got to 
Lisp and the smart editors doing it for me. Right there I got a 
significant productivity boost since I refactor so much.

> 
> 
>>variables which add their own complexity (room for bugs, mostly) and
>>make the code less readable because now I have to mentally inventory
>>them and keep track of what must be bound to what
> 
> 
> Aren't the negatives of intermediate variables offset in some cases by
> increasing readability. If a variable is like the title of a paragraph,
> doesn't it give a quick summary without reading the whole paragraph?

Two things. Sadly, in my experience, every opportunity to name a 
variable or a function is taken as an opportunity by programmers to 
mislead the reader by picking a godawful name, the worst ones being so 
very close to the right name. (The truly awful names at least advertise 
their awfulness, wherease the almost-right ones are well-disguised trip 
wires.)

Second, sounds like we are talking about a situation in which a function 
has bitten off more than the reader can chew. Many times that 
intermediate variable gets used only once in the rest of the code. In 
that case, the code defining the temp variable probably can be defined 
as a useful external function, called concisely within the larger 
function. Then when reading the larger function, I probably do not need 
to know the details of that external function, almost by definition. 
That external function serves to divide and conquer the source which 
once overstuffed the original.

Usually this external function will prove useful elsewhere, or evolve 
into one after some refactoring when a second use is found. if not, we 
have the glory of FLET or LABELS, which lets on achieve the same result 
while at once making clear that these functions are highly specific to 
the enclosing function, but allow one to preserve the functional style 
in which the semantic tree is not disguised (when you stop to dump a 
result into a temporary variable to be used later, you use the visual 
connection of seeing the form in the place where it is used -- you have 
to do that mental linking back to the code assigned to the temp 
variable, no matter how well it is named.

that's how I think about code, anyway.

kt


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Pascal Bourguignon
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <87wtujeqfo.fsf@thalassa.informatimago.com>
"Neo" <········@hotmail.com> writes:

> >>> Why does begining a statement with "("...make it more flexible?
> >>
> >> one reason is, that you always know, where a command starts:
> >> (command (command-which-returns-something arg1_1) arg2 arg3)
> >
> > you can arbitrary nest 'commands'
> 
> Thanks, you were right, surrounding the statements with parentheses
> does make the script processing easier especially if a parameter is
> another command; however it gets confusing to read. What is the
> advantage of the following LISP coding style versus that of C? Why is
> crunching everything on one line an advantage? Does LISP allow the
> equivalent C style?
> 
> // LISP style
> F2 ( a  b  F1( ) )
> 
> // C style
> var1 = F1( );
> F2 (a b var1);


(f2 a b (f1))

(setf var1 (f1))
(f2 a b var1)
 

There is a draft standard for sexps: 

    http://theory.lcs.mit.edu/~rivest/sexp.txt
    http://theory.lcs.mit.edu/~rivest/sexp.html
    http://sexpr.sourceforge.net/refman/

and other standards apply, where the parentheses go (f a b), 
not f(a b), eg.:

    ANSI CL1994 X3.226-1994
    ISO/IEC 13816:1997


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
From: Kaz Kylheku
Subject: Re: Newbie ?: Consequtive Command Lines
Date: 
Message-ID: <1105482216.260022.54860@f14g2000cwb.googlegroups.com>
Neo wrote:
> I am trying to write a scripting language for a small experimental
db.
> Its current syntax is quite limited. I was hoping to make it more
> flexible by following LISP syntax. Does LISP encode a sequence of
> statements as follows:
>
> // Current scripting syntax.
> Command1 param1 param2;
> Command2 params...;
> Command3 params...;
>
> // Would this be the equivalent LISP Syntax?
> (Command1 param1 param2)
> (Command2 params...)
> (Command3 params...)
>
> Why does begining a statement with a marker, in addition to ending it
> with a marker, make it more flexible?

The full answer to this question is involved and touches on various
branches of programming language design.

There are flexibilities in the Lisp language, and most of them don't
have to do with the parentheses.

What the parenthesized syntax does is simplify the implementation of
the pieces which are traditionally quite difficult.

Lisp notation can be much more completely processed by a scanner which
is scarcely more complex then a typical lexical analyzer for most
typical programming languages.

The output of a lexical analyzer is typically a linear sequence of
tokens. These must be fed into some parser, typically a LR(1)
shift-reduce state machine, which recognizes a deeper syntax among the
tokens, based on a phrase-structure grammar.

The output of the Lisp reader is a polymorphic data structure which is
ready for semantic analysis. No parsing (of the above type) is needed,
because all constituent pieces of the expressions can be readily
retrieved by their position in a nested list.

Those other languages like Java and C also have nested lists. In fact,
they have more than one syntax for lists, and they are recognized
within that parser. Let's take examples from C:

long int x(unsigned long x, struct foo y)
{
long z = y.memb, w = z + x;
foo(x, y);
bar(x, z);
}

Why this is nothing but nested lists, but the syntax is ad hoc!

long int

is known as a declaration-specifier list. Then within the parentheses
of the function definition, we have a parameter list, each of which has
its own declaration-specifier list.

In the declaration:

long x = y.memb, w = z + x;

the keyword long is a declaration specifier-qualifier list. This is
followed by a comma-separated list of declarators, which are
x = y.memb and w = z + x. Lists list, everywhere lists! the function
body itself is a brace-enclosed list containing semicolon-terminated
declarations and statements.

What's different about LISP is that its design explicitly recognizes
that a language is made up of lists of heterogeneous items such as
symbols and string literals and numbers. A single written
representation is selected for representing a list, and you program
with that. So your parser just has to be able to parse nested lists.
Moreover, you can get rid of infix operators and replace them by lists
as well, so there is no need for an operator precedence expression
grammar.

Now this leads to flexibility because the lack of hard-coded special
cases in the grammar, and the use of arbitrary nested lists, means that
your scanner can handle *any* syntax. That is to say, any abstract
syntax tree can be readily represented in printed form as a
parenthesized list. Your scanner will accept that syntax, and return
the correct data structure. All that is left for you is to write the
missing pieces of the back-end to handle that data structure and give
it some kind of meaning.

In Common Lisp, users can write such back-ends in Lisp itself; they are
called macros. Macros are called upon to handle the extended syntax,
hooked to a symbol, perform some arbitrary analysis on there and return
a translated data structure which is substituted in its place and
perhaps subject to more macro processing.