Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Lisp with XML concrete syntax

27 views
Skip to first unread message

Eric Marsden

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
Quoting from <URL:http://www.w3.org/TR/xexpr/>:

In many applications of XML, there is a requirement for using XML
in conjunction with a scripting language. Many times, this results
in a scripting language such as JavaScript being bound within the
XML content (like the <script> tag). XEXPR is a scripting language
that uses XML as its primary syntax, making it easily embeddable
in an XML document. In addition, XEXPR takes a functional
approach, and hence maps well onto the syntax of XML.

here is an example of the scripting language with the buzz-enabled
syntax:

,----
| <define name="factorial" args="x">
| <define name="iterator" args="product counter max">
| <if>
| <gt><counter/><max/></gt>
| <product/>
| <iterator>
| <multiply><counter/><product/></multiply>
| <add><counter/>1</add>
| <max/>
| </iterator>
| </if>
| </define>
|
| <iterator>1 1 <x/></iterator>
| </define>
`----

--
Eric Marsden <URL:http://www.laas.fr/~emarsden/>

Rainer Joswig

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
In article <wzisnoi...@mail.dotcom.fr>, Eric Marsden
<emar...@mail.dotcom.fr> wrote:

A barf bag, quick...

--
Rainer Joswig, Hamburg, Germany
Email: mailto:jos...@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/

Michael Livshin

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
Eric Marsden <emar...@mail.dotcom.fr> writes:

> | <define name="factorial" args="x">
> | <define name="iterator" args="product counter max">
> | <if>
> | <gt><counter/><max/></gt>
> | <product/>
> | <iterator>
> | <multiply><counter/><product/></multiply>
> | <add><counter/>1</add>
> | <max/>
> | </iterator>
> | </if>
> | </define>
> |
> | <iterator>1 1 <x/></iterator>
> | </define>

I propose we call this "the mOdeRn syntax".

how long till there's a Mozilla-based volonteer project to support
this?

*gag*

--
(only legal replies to this address are accepted)

This code is a piece of crap! You have no honor!
-- Klingon Programmer

Erik Naggum

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
* Eric Marsden <emar...@mail.dotcom.fr>

| here is an example of the scripting language with the buzz-enabled
| syntax:
|
| ,----
| | <define name="factorial" args="x">
| | <define name="iterator" args="product counter max">
| | <if>
| | <gt><counter/><max/></gt>
| | <product/>
| | <iterator>
| | <multiply><counter/><product/></multiply>
| | <add><counter/>1</add>
| | <max/>
| | </iterator>
| | </if>
| | </define>
| |
| | <iterator>1 1 <x/></iterator>
| | </define>
| `----

Wow! This is almost like watching sports on TV. You just know that
those guys out there are generally in a lot of pain, seem to overcome
it, at least while everyone's watching them and while the money from
sponsors keep coming in, and are delightfully soon to be replaced by
somebody else in a little _more_ pain. Bring out the beer, this can
get _fun_!

XML -- till death do us parse.

#:Erik
--
Solution to U.S. Presidential Election Crisis 2000:
Let Texas secede from the Union and elect George W. Bush their
very first President. All parties, states would rejoice.

Geoff Summerhayes

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
How about:

<define name="factorial">
<dup/>1<neq/><if><dup/>1<minus/><recurse/><multiply/></if>
</define>

What can I say, I hate typing. In XML, RPN is kind of nice.

Geoff


"Eric Marsden" <emar...@mail.dotcom.fr> wrote in message
news:wzisnoi...@mail.dotcom.fr...


> ,----
> | <define name="factorial" args="x">
> | <define name="iterator" args="product counter max">
> | <if>
> | <gt><counter/><max/></gt>
> | <product/>
> | <iterator>
> | <multiply><counter/><product/></multiply>
> | <add><counter/>1</add>
> | <max/>
> | </iterator>
> | </if>
> | </define>
> |
> | <iterator>1 1 <x/></iterator>
> | </define>
> `----
>

Marc Battyani

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to

"Eric Marsden" <emar...@mail.dotcom.fr> wrote in message
news:wzisnoi...@mail.dotcom.fr...
> Quoting from <URL:http://www.w3.org/TR/xexpr/>:
>
> In many applications of XML, there is a requirement for using XML
> in conjunction with a scripting language. Many times, this results
> in a scripting language such as JavaScript being bound within the
> XML content (like the <script> tag). XEXPR is a scripting language
> that uses XML as its primary syntax, making it easily embeddable
> in an XML document. In addition, XEXPR takes a functional
> approach, and hence maps well onto the syntax of XML.
>
> here is an example of the scripting language with the buzz-enabled
> syntax:
>
> ,----
> | <define name="factorial" args="x">
> | <define name="iterator" args="product counter max">
> | <if>
> | <gt><counter/><max/></gt>
> | <product/>
> | <iterator>
> | <multiply><counter/><product/></multiply>
> | <add><counter/>1</add>
> | <max/>
> | </iterator>
> | </if>
> | </define>
> |
> | <iterator>1 1 <x/></iterator>
> | </define>

So brilliant, I hope they patented it. ;-)

I first thought it was a joke as it is a good conclusion to a recent thread
(http://www.deja.com/getdoc.xp?AN=638290840 ) but it seems real.

They went even farther than the jokes. A good example of how reality always
surpass fiction...

Marc

Tom Breton

unread,
Nov 23, 2000, 10:54:57 PM11/23/00
to
Eric Marsden <emar...@mail.dotcom.fr> writes:

> `----

The thing that's most unLisp is that you can't start a listform with
an arbitrary head. Everything has to be pre-defined in the dtd. Eg,
there's no:

(flet
((foo () ...))

(foo))

--
Visit this site to make your views known: www.AlGoreLost.org
Tom Breton, http://world.std.com/~tob
Not using "gh" 1997-2000. http://world.std.com/~tob/ugh-free.html
Some vocal people in cll make frequent, hasty personal attacks, but if
you killfile them cll becomes usable.

Valeriy E. Ushakov

unread,
Nov 24, 2000, 3:29:09 PM11/24/00
to
Tom Breton <t...@world.std.com> wrote:

>> ,----
>> | <define name="factorial" args="x">

> The thing that's most unLisp is that you can't start a listform with
> an arbitrary head. Everything has to be pre-defined in the dtd.

Hey, that's XML. They don't care about DTDs...

(You don't even have to bring FLET to discussion, the "define" above
demonstrates it already.)

PS: Actually the MetaHTML (www.metahtml.org) was released in 1996
(IIRC) and it uses less tags. Prepare your bard bags)...

<define-tag splashy-bars start end step>
<while <not <gt end start>>>
<hr width=<get-var start>%>
<set-var start=<sub start step>>
</while>
</define-tag>

SY, Uwe
--
u...@ptc.spbu.ru | Zu Grunde kommen
http://www.ptc.spbu.ru/~uwe/ | Ist zu Grunde gehen

Bob Bane

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
The really sad thing about this is that they clearly don't have a clue
as to what a lexical scope is, or decent instincts for writing
tail-recursive code. The Common Lisp equivalent to their XML concrete
is:

(defun factorial (x)
(labels ((iterator (product counter max)
(if (> counter max)
product
(iterator (* counter product)
(+ counter 1)
max)))
(iterator 1 1 x)))

which could be written better as:

(defun factorial (x)
(labels ((iterator (product counter)
(if (> counter x)
product
(iterator (* counter product)
(+ counter 1))))
(iterator 1 1)))

Or better yet:

(defun factorial (x)
(labels ((iterator (product counter)
(if (<= counter 0)
product
(iterator (* counter product)
(- counter 1))))
(iterator 1 x)))

Once again, proof that nothing has been learned in the last 40 years of
computer science.

--
Remove obvious stuff to e-mail me.
Bob Bane

Hannah Schroeter

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
Hello!

In article <3A2282F2...@removeme.gst.com>,
Bob Bane <ba...@removeme.gst.com> wrote:
>[...]

>(defun factorial (x)
> (labels ((iterator (product counter)
> (if (<= counter 0)
> product
> (iterator (* counter product)
> (- counter 1))))
> (iterator 1 x)))

And why not

(defun factorial (x &optional (ac 1))
(if (<= x 1)
ac
(factorial (1- x) (* ac x))))

Kind regards,

Hannah.

Bob Bane

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
A depressingly direct example of:

Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C
or Fortran
program contains an ad-hoc, informally-specified bug-ridden slow
implementation of
half of Common Lisp."

See http://philip.greenspun.com/research/index.html

Joe Marshall

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
han...@schlund.de (Hannah Schroeter) writes:

1. Factorial is function of 1 argument, not two.

2. It may add an additional conditional test at the beginning of the
call.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----

Kent M Pitman

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
Joe Marshall <j...@content-integrity.com> writes:

> han...@schlund.de (Hannah Schroeter) writes:
>
> [...]


> > And why not
> >
> > (defun factorial (x &optional (ac 1))
> > (if (<= x 1)
> > ac
> > (factorial (1- x) (* ac x))))
>

> 1. Factorial is function of 1 argument, not two. [...]

Well, yes, but one argument factorial is not tail recursive, like its
two argument friend is.


Joe Marshall

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to

Sure it is. The one-argument factorial can simply tail recurse onto
its two-argument friend (with the appropriate argument).

I was saying that *semantically* that you may wish to avoid using
optional arguments as iteration state because they give the impression
that there is an additional `user-specified' parameter that usually
defaulted. In this case, the function no longer computes the
factorial of its first argument if you override the second. It would
most likely be an error to provide the second argument anywhere but in
that one recursive call.

Geoff Summerhayes

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
I don't see the problem. For example, just call it factorial-aux, lose the
&optional and
(defun factorial(x) <--interface
(factorial-aux x 1)) <--tail-recursion

or ...

Geoff

"Joe Marshall" <j...@content-integrity.com> wrote in message
news:d7fhw0...@content-integrity.com...

glauber

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
In article <t25mvu2...@corp.supernews.com>,

"Geoff Summerhayes" <sNuOmS...@hNoOtSmPaAiMl.com> wrote:
> I don't see the problem. For example, just call it factorial-aux, lose the
> &optional and
> (defun factorial(x) <--interface
> (factorial-aux x 1)) <--tail-recursion

and scope factorial-aux so it's only visible inside factorial, and you're
protected.

--
Glauber Ribeiro
thegl...@my-deja.com http://www.myvehiclehistoryreport.com
"Opinions stated are my own and not representative of Experian"


Sent via Deja.com http://www.deja.com/
Before you buy.

Janis Dzerins

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
glauber <thegl...@my-deja.com> writes:

> In article <t25mvu2...@corp.supernews.com>,
> "Geoff Summerhayes" <sNuOmS...@hNoOtSmPaAiMl.com> wrote:
> > I don't see the problem. For example, just call it factorial-aux, lose the
> > &optional and
> > (defun factorial(x) <--interface
> > (factorial-aux x 1)) <--tail-recursion
>
> and scope factorial-aux so it's only visible inside factorial, and you're
> protected.

And then we're back at where we started 6 articles ago:

Bob Bane wrote:
>(defun factorial (x)
> (labels ((iterator (product counter)
> (if (<= counter 0)
> product
> (iterator (* counter product)
> (- counter 1))))
> (iterator 1 x)))

Janis Dzerins
--
Ever feel like life was a game and you had the wrong instruction book?

Erik Naggum

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
* Hannah Schroeter

| And why not
|
| (defun factorial (x &optional (ac 1))
| (if (<= x 1)
| ac
| (factorial (1- x) (* ac x))))

There are many good reasons not to do tail-call merging for calls to
global, user-defined functions. The function is conceptually distinct
from the name, and while few people do it, you could copy the function
over to a different symbol, and do something else with the old symbol.
You _should_ expect to see it call the function in the old symbol, as
that is the defined semantics of Common Lisp function calls. It also
helps debugging and numerous other common tasks not to confuse symbol
with function named by symbol.

Local functions have no such restrictions, of course, being part of
the function itself rather than depend on the symbol for its meaning.

I consider the above code fragment tantamount to using dynamic binding
simply out of tradition. The optional argument is another sign of old
design and should be considered abuse of a language feature today.

Tim Bradshaw

unread,
Dec 2, 2000, 3:00:00 AM12/2/00
to
* Erik Naggum wrote:

> There are many good reasons not to do tail-call merging for calls to
> global, user-defined functions. The function is conceptually distinct
> from the name, and while few people do it, you could copy the function
> over to a different symbol, and do something else with the old symbol.
> You _should_ expect to see it call the function in the old symbol, as
> that is the defined semantics of Common Lisp function calls. It also
> helps debugging and numerous other common tasks not to confuse symbol
> with function named by symbol.

Is this right? From the hyperspec (3.2.2.3):

Within a function named F, the compiler may (but is not required
to) assume that an apparent recursive call to a function named F
refers to the same definition of F, unless that function has been
declared notinline. The consequences of redefining such a
recursively defined function F while it is executing are
undefined.

Which I read as meanind that within a definition like:

.. no NOTINLINE declaration for F ...

(defun f (...)
... no intervening local function bindings for F ...
... no intervening NOTINLINE declarations for F ...
(f ...)
...)

the recursive call to F can safely be assumed to be a call to the F
defined by the DEFUN.

However I may not have read carefully enough, or I may have
misunderstood what you are saying.

--tim

Kent M Pitman

unread,
Dec 2, 2000, 3:00:00 AM12/2/00
to
Tim Bradshaw <t...@cley.com> writes:

>
> * Erik Naggum wrote:
>
> > There are many good reasons not to do tail-call merging for calls to
> > global, user-defined functions. The function is conceptually distinct
> > from the name, and while few people do it, you could copy the function
> > over to a different symbol, and do something else with the old symbol.
> > You _should_ expect to see it call the function in the old symbol, as
> > that is the defined semantics of Common Lisp function calls. It also
> > helps debugging and numerous other common tasks not to confuse symbol
> > with function named by symbol.
>

> Is this right? From the hyperspec (3.2.2.3): [...]


> the recursive call to F can safely be assumed to be a call to the F
> defined by the DEFUN.
>
> However I may not have read carefully enough, or I may have
> misunderstood what you are saying.

Both of you are using slightly confusing language, IMO.

Tim, you're right that the compiler is permitted to optimize tail calls
in the way you describe. But it is not required to. Hence, you cannot
expect it to.

Erik, I think when you say "You _should_ expect" you're confusing him,
since you're using the English word "should expect", which has the
formal standards meaning "must not expect". That is, anything that
doesn't say "must" isn't required and therefore should not be expected. :-)

The standard's wording is correct as to expectation:

Within a function named F, the compiler may (but is not required
to) assume that an apparent recursive call to a function named F
refers to the same definition of F,

That is, you can't really expect anything. It just encourages you not
to send a bug report in either case...


Tim Bradshaw

unread,
Dec 2, 2000, 3:00:00 AM12/2/00
to
* Kent M Pitman wrote:

> Tim, you're right that the compiler is permitted to optimize tail calls
> in the way you describe. But it is not required to. Hence, you cannot
> expect it to.

I agree, and I'm sorry for vagueness. What I really meant is that
if you do something like this (assuming no NOTINLINE declarations &
reasonable stack limits &c)


;;; in a file which is compiled & loaded
(defun f (n)
(if (zerop n)
(end-the-world :now t)
(f (- n 1))))

(defun f-caller ()
(f 2))

;;; in a file which is compiled and loaded after the above
(defvar *f-fn* (symbol-function 'f))

(setf (symbol-function 'f)
#'(lambda (n)
(declare (ignore n))
(format t "~&The world has not ended~%")))

(defun f-fn-caller ()
(funcall *f-fn* 2))

Then you can not assume anything at all about whether either a call to
F-CALLER or F-FN-CALLER will cause END-THE-WORLD to be called. In
particular you can not assume that it will *not* be called.

I hope that's right. I guess the elaborateness of the example
demonstrates how fiddly the concepts are...

--tim

Kent M Pitman

unread,
Dec 2, 2000, 3:00:00 AM12/2/00
to
Tim Bradshaw <t...@cley.com> writes:

> [big code example omitted]


> Then you can not assume anything at all about whether either a call to
> F-CALLER or F-FN-CALLER will cause END-THE-WORLD to be called. In
> particular you can not assume that it will *not* be called.
>
> I hope that's right. I guess the elaborateness of the example
> demonstrates how fiddly the concepts are...

Right. I think the primary guarantee you get is that you can do:

(defmacro autoload (fn file)
(check-type fn symbol "a function name")
(check-type file (or string pathname) "a filename")
`(defun ,fn (&rest args)
(declare (notinline ,fn))
(let ((,fn #',fn))
(load ,file)
(when (eq ,fn #'fn)
(error "Definition of ~S not found in ~A."
',fn ',file))
(apply #',fn args))))

or things like that where you don't want the compiler to get confused
and think you're a wayward Scheme programmer setting up an infinite loop.
That is, it's for self-defining and self-redefining functions.
For efficiency, of course, I'd probably do this particular task I used
above as a closure instead, as in:

(defun autoloader (function file)
#'(lambda (&rest args)
(let ((function (symbol-function fn)))
(load file)
(let ((new (symbol-function fn)))
(when (eq new function)
(error "Definition of ~S not found in ~A." function file))
(apply new args)))))

(defmacro autoload (fn file)
(check-type fn symbol "a function name")
(check-type file (or string pathname) "a filename")
`(progn (setf (symbol-function ',fn) (autoloader ',fn ',file))
',fn))

But then, of course, the NOTINLINE issue wouldn't come up and this would
have been a lousy example. Ah well.

What? Did I *test* the above code? Not me... Just for illustration. No
warranty (as if there would be one otherwise--ha,ha). Caveat emptor. ...

0 new messages